001: /*
002: * Copyright 2000,2005 wingS development team.
003: *
004: * This file is part of wingS (http://wingsframework.org).
005: *
006: * wingS is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU Lesser General Public License
008: * as published by the Free Software Foundation; either version 2.1
009: * of the License, or (at your option) any later version.
010: *
011: * Please see COPYING for the complete licence.
012: */
013: package org.wings.plaf.css;
014:
015: import org.apache.commons.logging.Log;
016: import org.apache.commons.logging.LogFactory;
017: import org.wings.plaf.Update;
018: import org.wings.*;
019: import org.wings.event.SRequestListener;
020: import org.wings.event.SRequestEvent;
021: import org.wings.externalizer.AbstractExternalizeManager;
022: import org.wings.externalizer.ExternalizeManager;
023: import org.wings.dnd.DragAndDropManager;
024: import org.wings.header.*;
025: import org.wings.io.Device;
026: import org.wings.io.StringBuilderDevice;
027: import org.wings.plaf.CGManager;
028: import org.wings.plaf.Update.Handler;
029: import org.wings.plaf.css.InternalFrameCG.AddWindowUpdate;
030: import org.wings.plaf.css.InternalFrameCG.RemoveWindowUpdate;
031: import org.wings.plaf.css.script.OnPageRenderedScript;
032: import org.wings.resource.ClassPathResource;
033: import org.wings.resource.ReloadResource;
034: import org.wings.resource.ResourceManager;
035: import org.wings.resource.UpdateResource;
036: import org.wings.resource.ResourceNotFoundException;
037: import org.wings.script.*;
038: import org.wings.session.*;
039:
040: import javax.swing.*;
041:
042: import java.io.IOException;
043: import java.util.*;
044: import java.awt.event.KeyEvent;
045: import java.awt.event.InputEvent;
046:
047: /**
048: * <code>CmsFrameCG<code>.
049: * <p/>
050: * User: rrd
051: * Date: 10.08.2007
052: * Time: 16:43:09
053: *
054: * @author rrd
055: * @version $Id
056: */
057: public class CmsFrameCG implements org.wings.plaf.FrameCG {
058:
059: private static final long serialVersionUID = 1L;
060:
061: private final static Log log = LogFactory.getLog(FrameCG.class);
062:
063: /**
064: * The default DOCTYPE enforcing standard (non-quirks mode) in all current browsers. Please be aware, that
065: * changing the DOCTYPE may change the way how browser renders the generate document i.e. esp. the CSS
066: * attribute inheritance does not work correctly on <code>table</code> elements.
067: * See i.e. http://www.ericmeyeroncss.com/bonus/render-mode.html
068: */
069: public final static String STRICT_DOCTYPE = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" "
070: + "\"http://www.w3.org/TR/REC-html40/strict.dtd\">";
071:
072: /**
073: * The HTML DOCTYPE setting all browsers to Quirks mode. We need this to force IE to use the correct box
074: * rendering model. It's the only browser you cannot reconfigure via a CSS tag.
075: */
076: public final static String QUIRKS_DOCTYPE = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">";
077:
078: /**
079: * Lookup for a property Stylesheet.BROWSERNAME to know fitting stylesheets
080: */
081: private static final String PROPERTY_STYLESHEET = "Stylesheet.";
082: private static final String BROWSER_DEFAULT = "default";
083:
084: private String documentType = STRICT_DOCTYPE;
085:
086: protected final List<Header> headers = new ArrayList<Header>();
087:
088: /**
089: * Should the returned HTML page start with the <?xml version="1.0" encoding="...">.
090: * This has effects which rendering mode the browsers will choose (quirks/strict)
091: */
092: private Boolean renderXmlDeclaration = Boolean.FALSE;
093:
094: private final List<Script> compressedHeaders = new ArrayList<Script>();
095: private final Map<Script, Script[]> debugReplacementJsHeaders = new HashMap<Script, Script[]>();
096: private final List<Script> debugAddonJsHeaders = new ArrayList<Script>();
097: private final String[] firebugResources = new String[] {
098: Utils.HTML_DEBUG_FIREBUGLITE, Utils.CSS_DEBUG_FIREBUGLITE,
099: Utils.IMG_DEBUG_FIREBUGLITE_ERROR,
100: Utils.IMG_DEBUG_FIREBUGLITE_WARN,
101: Utils.IMG_DEBUG_FIREBUGLITE_INFO };
102:
103: private boolean debugJs = false;
104:
105: // JS_YUI_UTILITIES = aggregate: yahoo, dom, event, connection, animation, dragdrop, element
106: final Script yuiUtilities = Utils
107: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_UTILITIES);
108: final Script yuiContainer = Utils
109: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_CONTAINER);
110: final Script wingsAll = Utils
111: .createExternalizedJSHeaderFromProperty(Utils.JS_WINGS_ALL);
112:
113: {
114: compressedHeaders.add(yuiUtilities);
115: compressedHeaders.add(yuiContainer);
116: compressedHeaders.add(wingsAll);
117: debugReplacementJsHeaders
118: .put(
119: yuiUtilities,
120: new Script[] {
121: Utils
122: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_YAHOO_DEBUG),
123: Utils
124: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_DOM_DEBUG),
125: Utils
126: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_EVENT_DEBUG),
127: Utils
128: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_CONNECTION_DEBUG),
129: Utils
130: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_ANIMATION_DEBUG),
131: Utils
132: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_DRAGDROP_DEBUG),
133: Utils
134: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_ELEMENT_DEBUG) });
135: debugReplacementJsHeaders
136: .put(
137: yuiContainer,
138: new Script[] { Utils
139: .createExternalizedJSHeaderFromProperty(Utils.JS_YUI_CONTAINER_DEBUG) });
140: debugReplacementJsHeaders
141: .put(
142: wingsAll,
143: new Script[] { Utils
144: .createExternalizedJSHeaderFromProperty(Utils.JS_WINGS_ALL_DEBUG) });
145:
146: debugAddonJsHeaders
147: .add(Utils
148: .createExternalizedJSHeaderFromProperty(Utils.JS_DEBUG_FIREBUGLITE));
149: // HTML, CSS and Images for firebuglite
150: ExternalizeManager extMgr = SessionManager.getSession()
151: .getExternalizeManager();
152: for (int i = 0; i < firebugResources.length; i++) {
153: String classPath = (String) ResourceManager.getObject(
154: firebugResources[i], String.class);
155: ClassPathResource res = new ClassPathResource(classPath);
156: String string = extMgr.externalize(res,
157: AbstractExternalizeManager.GLOBAL);
158: }
159: }
160:
161: /**
162: * Initialize properties from config
163: */
164: public CmsFrameCG() {
165: final CGManager manager = SessionManager.getSession()
166: .getCGManager();
167: final String userDocType = (String) manager.getObject(
168: "FrameCG.userDocType", String.class);
169: final Boolean userRenderXmlDecl = (Boolean) manager.getObject(
170: "FrameCG.renderXmlDeclaration", Boolean.class);
171:
172: if (userDocType != null) {
173: setDocumentType(userDocType);
174: }
175:
176: if (userRenderXmlDecl != null) {
177: setRenderXmlDeclaration(userRenderXmlDecl);
178: }
179:
180: // Add CSS headers of YUI components which should be included in every frames by default
181: // (DO use files under "yui/assets" and DO NOT use those under "yui/<component>/assets")
182: headers
183: .add(Utils
184: .createExternalizedCSSHeaderFromProperty(Utils.CSS_YUI_ASSETS_CONTAINER));
185: // Common hack to externalize YUI's 'sprite.png' which contains most (if not all) images of the SAM skin
186: new SResourceIcon((String) ResourceManager.getObject(
187: Utils.IMG_YUI_ASSETS_SPRITE, String.class)).getId();
188:
189: // Add DWR headers
190: headers.add(new JavaScriptHeader("../dwr/engine.js"));
191: headers.add(new JavaScriptHeader("../dwr/util.js"));
192:
193: // Common hack to externalize the ugly .htc-file for dealing with form buttons in IE
194: new ClassPathResource("org/wings/plaf/css/formbutton.htc",
195: "text/x-component").getId();
196: }
197:
198: public void installCG(final SComponent comp) {
199: final SFrame component = (SFrame) comp;
200:
201: // Add dynamic resources to the frame
202: ReloadResource reloadResource = new ReloadResource(component);
203: component.addDynamicResource(reloadResource);
204: UpdateResource updateResource = new UpdateResource(component);
205: component.addDynamicResource(updateResource);
206:
207: // Externalize update resource
208: component.getDynamicResource(UpdateResource.class).getId();
209:
210: final JavaScriptDOMListener handleClicks = new JavaScriptDOMListener(
211: JavaScriptEvent.ON_CLICK, "wingS.util.handleBodyClick",
212: comp);
213: final JavaScriptDOMListener storeFocusFF = new JavaScriptDOMListener(
214: JavaScriptEvent.ON_FOCUS, "wingS.util.storeFocus", comp);
215: final JavaScriptDOMListener storeFocusIE = new JavaScriptDOMListener(
216: JavaScriptEvent.ON_ACTIVATE, "wingS.util.storeFocus",
217: comp);
218:
219: // Add script listeners to the frame
220: component.addScriptListener(handleClicks);
221: component
222: .addScriptListener(Utils.isMSIE(component) ? storeFocusIE
223: : storeFocusFF);
224:
225: SessionHeaders.getInstance().registerHeaders(0, headers);
226: SessionHeaders.getInstance().registerHeaders(0,
227: compressedHeaders);
228: SessionHeaders.getInstance().registerHeaders(
229: getBrowserStylesheets());
230:
231: new InputMapRequestListener(component);
232: }
233:
234: class InputMapRequestListener {
235: SFrame frame;
236:
237: public InputMapRequestListener(SFrame frame) {
238: this .frame = frame;
239: frame.putClientProperty("InputMapRequestListener", this );
240:
241: frame.getSession().addRequestListener(
242: new SRequestListener() {
243: public void processRequest(SRequestEvent e) {
244: if (e.getType() == SRequestEvent.DELIVER_START
245: && InputMapRequestListener.this .frame
246: .getDynamicResources()
247: .contains(
248: e
249: .getRequestedResource()
250: .getObject())) {
251: boolean changeDetected = false;
252:
253: Set<SComponent> components = InputMapRequestListener.this .frame
254: .getGlobalInputMapComponents();
255:
256: for (SComponent component : components) {
257: boolean visible = component
258: .isRecursivelyVisible();
259: if (!Boolean
260: .valueOf(visible)
261: .equals(
262: component
263: .getClientProperty("visible"))) {
264: component.putClientProperty(
265: "visible", visible);
266: changeDetected |= true;
267: }
268: }
269: for (SComponent component : components) {
270: if (checkForChange(
271: component,
272: SComponent.WHEN_FOCUSED_OR_ANCESTOR_OF_FOCUSED_COMPONENT)) {
273: changeDetected |= true;
274: }
275: if (checkForChange(
276: component,
277: SComponent.WHEN_IN_FOCUSED_FRAME)) {
278: changeDetected |= true;
279: }
280: }
281: if (changeDetected) {
282: String script = strokes(components);
283: InputMapRequestListener.this .frame
284: .getSession()
285: .getScriptManager()
286: .addScriptListener(
287: new JavaScriptListener(
288: null, null,
289: script));
290: }
291: }
292: }
293: });
294: }
295:
296: private boolean checkForChange(SComponent component,
297: int condition) {
298: InputMap inputMap = component.getInputMap(condition);
299: if (inputMap != null && inputMap.size() > 0) {
300: if (!(inputMap instanceof VersionedInputMap)) {
301: inputMap = new VersionedInputMap(inputMap);
302: component.setInputMap(condition, inputMap);
303: component.putClientProperty("inputMapVersion"
304: + condition, -1);
305: }
306:
307: final VersionedInputMap versionedInputMap = (VersionedInputMap) inputMap;
308: final Integer inputMapVersion = (Integer) component
309: .getClientProperty("inputMapVersion"
310: + condition);
311: if (inputMapVersion == null
312: || versionedInputMap.getVersion() != inputMapVersion) {
313: component
314: .putClientProperty("inputMapVersion"
315: + condition, versionedInputMap
316: .getVersion());
317: return true;
318: }
319: }
320: return false;
321: }
322: }
323:
324: protected String strokes(Set<SComponent> components) {
325: if (components == null)
326: return null;
327:
328: StringBuilder builder = new StringBuilder();
329: builder.append("var wk = wingS.keyboard;");
330: builder.append("var kss = wk.keyStrokes = [];");
331: builder.append("var ks = wingS.keyboard.KeyStroke;\n");
332: for (SComponent component : components) {
333: if (component.isRecursivelyVisible()) {
334: appendStrokes(
335: builder,
336: component,
337: SComponent.WHEN_FOCUSED_OR_ANCESTOR_OF_FOCUSED_COMPONENT,
338: component
339: .getInputMap(SComponent.WHEN_FOCUSED_OR_ANCESTOR_OF_FOCUSED_COMPONENT));
340: appendStrokes(
341: builder,
342: component,
343: SComponent.WHEN_IN_FOCUSED_FRAME,
344: component
345: .getInputMap(SComponent.WHEN_IN_FOCUSED_FRAME));
346: }
347: }
348: return builder.toString();
349: }
350:
351: private void appendStrokes(StringBuilder builder,
352: SComponent component, int condition, InputMap inputMap) {
353: KeyStroke[] keyStrokes = inputMap.keys();
354: if (keyStrokes != null) {
355: for (int i = 0; i < keyStrokes.length; i++) {
356: KeyStroke keyStroke = keyStrokes[i];
357: Object binding = inputMap.get(keyStroke);
358:
359: switch (keyStroke.getKeyEventType()) {
360: case KeyEvent.KEY_PRESSED:
361: builder.append("kss.push(new ks('");
362: builder.append(component.getName());
363: builder.append("',");
364: builder
365: .append(condition == SComponent.WHEN_FOCUSED_OR_ANCESTOR_OF_FOCUSED_COMPONENT ? "!0"
366: : "!1");
367: builder.append(",'");
368: builder.append(binding);
369: builder.append("',");
370: builder.append(keyStroke.getKeyCode());
371: builder.append(',');
372: builder
373: .append((keyStroke.getModifiers() & InputEvent.SHIFT_DOWN_MASK) != 0 ? "!0"
374: : "!1");
375: builder.append(',');
376: builder
377: .append((keyStroke.getModifiers() & InputEvent.CTRL_DOWN_MASK) != 0 ? "!0"
378: : "!1");
379: builder.append(',');
380: builder
381: .append((keyStroke.getModifiers() & InputEvent.ALT_DOWN_MASK) != 0 ? "!0"
382: : "!1");
383: builder.append("));\n");
384: break;
385: case KeyEvent.KEY_TYPED:
386: break;
387: case KeyEvent.KEY_RELEASED:
388: break;
389: }
390: }
391: }
392: }
393:
394: /**
395: * Externalizes the style sheet(s) for this session. Look up according style sheet file name in
396: * org.wings.plaf.css.properties file under Stylesheet.BROWSERNAME. The style sheet is loaded from
397: * the class path.
398: *
399: * @return a list of externalized browser specific stylesheet headers
400: */
401: private List<Header> getBrowserStylesheets() {
402: Session session = SessionManager.getSession();
403: final CGManager cgManager = session.getCGManager();
404: final String browserName = session.getUserAgent()
405: .getBrowserType().getShortName();
406:
407: String cssClassPaths = (String) cgManager.getObject(
408: PROPERTY_STYLESHEET + browserName, String.class);
409: if (cssClassPaths == null) {
410: cssClassPaths = (String) cgManager
411: .getObject(PROPERTY_STYLESHEET + BROWSER_DEFAULT,
412: String.class);
413: }
414:
415: List<Header> browserStylesheets = new ArrayList<Header>();
416: StringTokenizer tokenizer = new StringTokenizer(cssClassPaths,
417: ",");
418: while (tokenizer.hasMoreTokens()) {
419: browserStylesheets
420: .add(Utils.createExternalizedCSSHeader(tokenizer
421: .nextToken()));
422: }
423:
424: return browserStylesheets;
425: }
426:
427: /**
428: * Uninstall renderer (i.e. other to apply other renderer).
429: */
430: public void uninstallCG(final SComponent comp) {
431: final SFrame component = (SFrame) comp;
432:
433: component.removeDynamicResource(ReloadResource.class);
434: component.removeDynamicResource(UpdateResource.class);
435:
436: SessionHeaders.getInstance().deregisterHeaders(headers);
437: }
438:
439: public void componentChanged(SComponent c) {
440: }
441:
442: public void write(final Device device, final SComponent component)
443: throws IOException {
444: final SFrame frame = (SFrame) component;
445:
446: String strokes = strokes(frame.getGlobalInputMapComponents());
447: if (strokes != null)
448: component
449: .getSession()
450: .getScriptManager()
451: .addScriptListener(
452: new JavaScriptListener(null, null, strokes));
453:
454: if (!frame.isVisible())
455: return;
456: else
457: frame.fireRenderEvent(SComponent.START_RENDERING);
458:
459: Session session = SessionManager.getSession();
460: final String language = session.getLocale().getLanguage();
461: final String title = frame.getTitle();
462: final String encoding = session.getCharacterEncoding();
463:
464: // <?xml version="1.0" encoding="...">
465: if (renderXmlDeclaration == null || renderXmlDeclaration) {
466: device.print("<?xml version=\"1.0\" encoding=\"");
467: Utils.write(device, encoding);
468: device.print("\"?>\n");
469: }
470:
471: // <!DOCTYPE HTML PUBLIC ... >
472: Utils.writeRaw(device, documentType);
473: device.print("\n");
474:
475: // <html> tag
476: device
477: .print("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"");
478: Utils.write(device, language);
479: device.print("\" lang=\"");
480: Utils.write(device, language);
481: device.print("\">\n");
482:
483: // <head> tag
484: device.print("<head>");
485: if (title != null) {
486: device.print("<title>");
487: Utils.write(device, title);
488: device.print("</title>\n");
489: }
490:
491: // Character set encoding, the default is typically utf-8.
492: device
493: .print("<meta http-equiv=\"Content-type\" content=\"text/html; charset=");
494: Utils.write(device, encoding);
495: device.print("\"/>\n");
496:
497: /* Insert version and compile time. Since the Version Class is generated on compile time,
498: * build errors in SDK's are quite normal. Just run the Version.java ant task.
499: */
500: device
501: .print("<meta http-equiv=\"Generator\" content=\"wingS v");
502: device.print(Version.getVersion());
503: device.print(" (http://wingsframework.org) - built on: ");
504: device.print(Version.getCompileTime());
505: device.print("\" />\n");
506:
507: // Render all headers
508: boolean isDebug = frame.isDebugJs();
509: if (isDebug) {
510: for (Script debugAddon : debugAddonJsHeaders) {
511: ((Renderable) debugAddon).write(device);
512: device.print("\n");
513: }
514: }
515: for (Object next : frame.getHeaders()) {
516: if (next instanceof Renderable) {
517: try {
518: if (isDebug && getDebugHeaders(next) != null) {
519: // Render uncompressed headers
520: Script[] debugHeaders = getDebugHeaders(next);
521: for (Script debugHeader : debugHeaders) {
522: if (debugHeader instanceof Renderable) {
523: ((Renderable) debugHeader)
524: .write(device);
525: } else {
526: Utils.write(device, debugHeader
527: .toString());
528: }
529: }
530: } else {
531: // Render compressed headers
532: ((Renderable) next).write(device);
533: }
534: } catch (ResourceNotFoundException e) {
535: log
536: .error(
537: "Unable to deliver inlined renderable",
538: e);
539: }
540: } else {
541: Utils.write(device, next.toString());
542: }
543: device.print("\n");
544: }
545:
546: // Focus management. Put focus in selected object.
547: if (frame.getFocus() != null) {
548: String script = "wingS.util.requestFocus('"
549: + frame.getFocus().getName() + "');";
550: ScriptManager.getInstance().addScriptListener(
551: new OnPageRenderedScript(script));
552: }
553:
554: device.print("</head>\n");
555: device.print("<body");
556: Utils.writeEvents(device, frame, null);
557: Utils.writeAllAttributes(device, frame);
558: device.print(">\n");
559:
560: // Write contents of the frame
561: if (frame.isVisible()) {
562: Utils.createExternalizedJSHeaderFromProperty(
563: Utils.JS_ETC_WZ_TOOLTIP).write(device);
564: device.print("\n");
565:
566: // Write components
567: frame.getLayout().write(device);
568:
569: // Write menus
570: device.print("\n\n<div id=\"wings_menues\">\n");
571: Set menues = frame.getSession().getMenuManager().getMenues(
572: frame);
573: for (Iterator i = menues.iterator(); i.hasNext();) {
574: SComponent menuItem = (SComponent) i.next();
575: menuItem.putClientProperty("popup", Boolean.TRUE);
576: menuItem.write(device);
577: menuItem.putClientProperty("popup", null);
578: }
579: device.print("\n</div>\n\n");
580:
581: DragAndDropManager dndManager = frame.getSession()
582: .getDragAndDropManager();
583: dndManager.getCG().write(device, dndManager);
584:
585: handleScripts(device, frame);
586: }
587:
588: device.print("</body>\n</html>\n");
589:
590: component.fireRenderEvent(SComponent.DONE_RENDERING);
591: }
592:
593: /**
594: * @param next
595: * @return
596: */
597: private Script[] getDebugHeaders(Object next) {
598: if (debugReplacementJsHeaders.containsKey(next)) {
599: return debugReplacementJsHeaders.get(next);
600: } else {
601: return null;
602: }
603: }
604:
605: protected void handleScripts(Device device, SComponent component)
606: throws IOException {
607: final SFrame frame = (SFrame) component;
608: final ScriptManager scriptManager = frame.getSession()
609: .getScriptManager();
610: final SToolTipManager tooltipManager = SToolTipManager
611: .sharedInstance();
612:
613: // hand script listeners of frame to script manager
614: scriptManager.addScriptListeners(frame.getScriptListeners());
615:
616: device.print("<script type=\"text/javascript\">\n");
617:
618: // print all scripts
619: writeGlobalInitScript(device, frame);
620: device.print("\n");
621: writeTooltipInitScript(device, tooltipManager);
622: device.print("\n");
623: ScriptListener[] scriptListeners = scriptManager
624: .getScriptListeners();
625: for (int i = 0; i < scriptListeners.length; ++i) {
626: if (scriptListeners[i].getScript() != null) {
627: device.print(scriptListeners[i].getScript())
628: .print("\n");
629: }
630: }
631: scriptManager.clearScriptListeners();
632:
633: device.print("</script>\n");
634: }
635:
636: private void writeGlobalInitScript(Device out, SFrame frame)
637: throws IOException {
638: Map<String, Object> initConfig = new HashMap<String, Object>();
639: initConfig.put("eventEpoch", frame.getEventEpoch());
640: initConfig.put("reloadResource", frame.getDynamicResource(
641: ReloadResource.class).getURL().toString());
642: initConfig.put("updateResource", frame.getDynamicResource(
643: UpdateResource.class).getURL().toString());
644: initConfig.put("updateEnabled", frame.isUpdateEnabled());
645: initConfig.put("updateCursor", Utils.mapToJsObject(frame
646: .getUpdateCursor()));
647: initConfig.put("autoAdjustLayout", Utils.mapToJsObject(frame
648: .getAutoAdjustLayout()));
649: final String logLevel = frame.getLogLevel();
650: if (logLevel != null && !"".equals(logLevel)) {
651: initConfig.put("loglevel", logLevel);
652: }
653:
654: out.print("wingS.global.init(");
655: Utils.mapToJsObject(initConfig).write(out);
656: out.print(");");
657: }
658:
659: private void writeTooltipInitScript(Device out,
660: SToolTipManager tooltipManager) throws IOException {
661: out.print("wingS.tooltip.init(");
662: out.print(tooltipManager.getInitialDelay()).print(",");
663: out.print(tooltipManager.getDismissDelay()).print(",");
664: out.print(tooltipManager.isFollowMouse()).print(");");
665: }
666:
667: public String getDocumentType() {
668: return documentType;
669: }
670:
671: public void setDocumentType(String documentType) {
672: this .documentType = documentType;
673: }
674:
675: /**
676: * @return The current rendered DOCTYPE of this document. {@link #STRICT_DOCTYPE}
677: */
678: public Boolean getRenderXmlDeclaration() {
679: return renderXmlDeclaration;
680: }
681:
682: /**
683: * Sets should the returned HTML page start with the <?xml version="1.0" encoding="...">.
684: * This has effects which rendering mode the browsers will choose (quirks/strict)
685: *
686: * @param renderXmlDeclaration should the returned HTML page start with the <?xml version="1.0" encoding="...">.
687: */
688: public void setRenderXmlDeclaration(Boolean renderXmlDeclaration) {
689: this .renderXmlDeclaration = renderXmlDeclaration;
690: }
691:
692: public Update getComponentUpdate(SComponent component) {
693: return null;
694: }
695:
696: public Update getAddHeaderUpdate(SFrame frame, int index,
697: Object header) {
698: if (header instanceof Script)
699: return new HeaderScriptUpdate(frame, true, (Script) header,
700: index);
701: else if (header instanceof Link)
702: return new HeaderLinkUpdate(frame, true, (Link) header,
703: index);
704: else
705: return null;
706: }
707:
708: public Update getAddHeaderUpdate(SFrame frame, Object header) {
709: if (header instanceof Script)
710: return new HeaderScriptUpdate(frame, true, (Script) header);
711: else if (header instanceof Link)
712: return new HeaderLinkUpdate(frame, true, (Link) header);
713: else
714: return null;
715: }
716:
717: public Update getRemoveHeaderUpdate(SFrame frame, Object header) {
718: if (header instanceof Script)
719: // Removing script headers asynchronously would indeed
720: // detach the according header, however, the functions
721: // contained in the according files are not unloaded.
722: // If unloading functions is desired, it might be a good
723: // idea to RETURN 'NULL' here. This would create a
724: // component update of the frame which in turn would
725: // force a complete page reload and function unloading.
726: return new HeaderScriptUpdate(frame, false, (Script) header);
727: else if (header instanceof Link)
728: return new HeaderLinkUpdate(frame, false, (Link) header);
729: else
730: return null;
731: }
732:
733: public Update getEpochUpdate(SFrame frame, String epoch) {
734: return new EpochUpdate(frame, epoch);
735: }
736:
737: public Update getFocusUpdate(SFrame frame, SComponent focus) {
738: return new FocusUpdate(frame, focus);
739: }
740:
741: public Update getUpdateEnabledUpdate(SFrame frame, boolean enabled) {
742: return new UpdateEnabledUpdate(frame, enabled);
743: }
744:
745: protected class HeaderScriptUpdate extends AbstractUpdate {
746:
747: private Boolean add;
748: private Script script;
749: private Integer index;
750:
751: public HeaderScriptUpdate(SComponent component, boolean add,
752: Script script) {
753: super (component);
754: this .add = add;
755: this .script = script;
756: }
757:
758: public HeaderScriptUpdate(SComponent component, boolean add,
759: Script script, int index) {
760: this (component, add, script);
761: this .index = index;
762: }
763:
764: public int getPriority() {
765: return 5;
766: }
767:
768: public Handler getHandler() {
769: UpdateHandler handler = new UpdateHandler("headerScript");
770: handler.addParameter(add);
771: handler.addParameter(script.getURL().toString());
772: handler.addParameter(script.getType());
773: if (index != null)
774: handler.addParameter(index);
775: return handler;
776: }
777:
778: public boolean equals(Object object) {
779: if (this == object)
780: return true;
781: if (!super .equals(object))
782: return false;
783: if (!script.equals(((HeaderScriptUpdate) object).script))
784: return false;
785:
786: return true;
787: }
788:
789: }
790:
791: protected class HeaderLinkUpdate extends AbstractUpdate {
792:
793: private Boolean add;
794: private Link link;
795: private Integer index;
796:
797: public HeaderLinkUpdate(SComponent component, boolean add,
798: Link link) {
799: super (component);
800: this .add = add;
801: this .link = link;
802: }
803:
804: public HeaderLinkUpdate(SComponent component, boolean add,
805: Link link, int index) {
806: this (component, add, link);
807: this .index = index;
808: }
809:
810: public int getPriority() {
811: return 5;
812: }
813:
814: public Handler getHandler() {
815: UpdateHandler handler = new UpdateHandler("headerLink");
816: handler.addParameter(add);
817: handler.addParameter(link.getURL().toString());
818: handler.addParameter(link.getType());
819: if (link.getRel() != null || link.getRev() != null
820: || link.getTarget() != null || index != null)
821: handler.addParameter(link.getRel());
822: if (link.getRev() != null || link.getTarget() != null
823: || index != null)
824: handler.addParameter(link.getRev());
825: if (link.getTarget() != null || index != null)
826: handler.addParameter(link.getTarget());
827: if (index != null)
828: handler.addParameter(index);
829:
830: return handler;
831: }
832:
833: public boolean equals(Object object) {
834: if (this == object)
835: return true;
836: if (!super .equals(object))
837: return false;
838: if (!link.equals(((HeaderLinkUpdate) object).link))
839: return false;
840:
841: return true;
842: }
843:
844: }
845:
846: protected class EpochUpdate extends AbstractUpdate {
847:
848: private String epoch;
849:
850: public EpochUpdate(SComponent component, String epoch) {
851: super (component);
852: this .epoch = epoch;
853: }
854:
855: public int getPriority() {
856: return 0;
857: }
858:
859: public Handler getHandler() {
860: UpdateHandler handler = new UpdateHandler("epoch");
861: handler.addParameter(epoch);
862: return handler;
863: }
864:
865: }
866:
867: protected class FocusUpdate extends AbstractUpdate {
868:
869: private SComponent focus;
870:
871: public FocusUpdate(SComponent component, SComponent focus) {
872: super (component);
873: this .focus = focus;
874: }
875:
876: public int getPriority() {
877: return 0;
878: }
879:
880: public Handler getHandler() {
881: UpdateHandler handler = new UpdateHandler("focus");
882: handler.addParameter(focus.getName());
883: return handler;
884: }
885:
886: }
887:
888: protected class UpdateEnabledUpdate extends AbstractUpdate {
889:
890: private Boolean enabled;
891:
892: public UpdateEnabledUpdate(SComponent component, boolean enabled) {
893: super (component);
894: this .enabled = Boolean.valueOf(enabled);
895: }
896:
897: public Handler getHandler() {
898: UpdateHandler handler = new UpdateHandler("updateEnabled");
899: handler.addParameter(enabled);
900: return handler;
901: }
902:
903: }
904:
905: /**
906: * {@inheritDoc}
907: */
908: public Update getAddWindowUpdate(SContainer container,
909: SWindow window) {
910: return new AddWindowUpdate(container, window);
911: }
912:
913: protected class AddWindowUpdate extends AbstractUpdate {
914:
915: private SWindow window;
916:
917: public AddWindowUpdate(SContainer container, SWindow window) {
918: super (container);
919: this .window = window;
920: }
921:
922: @Override
923: public int getPriority() {
924: return Integer.MAX_VALUE;
925: }
926:
927: public Handler getHandler() {
928: UpdateHandler handler = new UpdateHandler("addWindow");
929: handler.addParameter(component.getName());
930: handler.addParameter("<div id=\"" + window.getName()
931: + "\"/>");
932: return handler;
933: }
934: }
935:
936: public Update getRemoveWindowUpdate(final SContainer container,
937: final SWindow window) {
938: return new RemoveWindowUpdate(container, window);
939: }
940:
941: protected class RemoveWindowUpdate extends AbstractUpdate {
942:
943: private SWindow window;
944:
945: public RemoveWindowUpdate(final SContainer container,
946: final SWindow window) {
947: super (container);
948: this .window = window;
949: }
950:
951: public Handler getHandler() {
952: UpdateHandler handler = new UpdateHandler("removeWindow");
953: handler.addParameter(window.getName());
954: return handler;
955: }
956: }
957: }
|