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