From: Matti Tahvonen Date: Fri, 16 Nov 2007 11:21:24 +0000 (+0000) Subject: refactored default icons, now uses ThemeResources properly and renders without captio... X-Git-Tag: 6.7.0.beta1~5555 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6b6257f93b0620cc9ff60f8e22e83342322070f9;p=vaadin-framework.git refactored default icons, now uses ThemeResources properly and renders without caption text svn changeset:2845/svn branch:trunk --- diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Caption.java b/src/com/itmill/toolkit/terminal/gwt/client/Caption.java index 0669524de8..a07d1871c2 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Caption.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Caption.java @@ -4,134 +4,146 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.PopupPanel; +import com.itmill.toolkit.terminal.gwt.client.ui.Icon; public class Caption extends HTML { - public static final String CLASSNAME = "i-caption"; - - private Paintable owner; - - private Element errorIndicatorElement; - - private Element icon; - - private Element captionText; - - private ErrorMessage errorMessage; - - /* Caption must be attached to a Paintable */ - private Caption() { - }; - - public Caption(Paintable component) { - super(); - owner = component; - setStyleName(CLASSNAME); - } - - public void updateCaption(UIDL uidl) { - setVisible(!uidl.getBooleanAttribute("invisible")); - - if (uidl.hasAttribute("error")) { - UIDL errorUidl = uidl.getErrors(); - - if (errorIndicatorElement == null) { - errorIndicatorElement = DOM.createDiv(); - DOM.setElementProperty(errorIndicatorElement, "className", - "i-errorindicator"); - DOM.insertChild(getElement(), errorIndicatorElement, 0); - } - if (errorMessage == null) - errorMessage = new ErrorMessage(); - errorMessage.updateFromUIDL(errorUidl); - - } else if (errorIndicatorElement != null) { - DOM.setStyleAttribute(errorIndicatorElement, "display", "none"); - } - - if (uidl.hasAttribute("icon")) { - if (icon == null) { - icon = DOM.createImg(); - DOM.appendChild(getElement(), icon); - } - DOM.setElementAttribute(icon, "src", uidl - .getStringAttribute("icon")); - } else { - if (icon != null) - DOM.removeChild(getElement(), icon); - } - - if (uidl.hasAttribute("caption")) { - if (captionText == null) { - captionText = DOM.createSpan(); - DOM.appendChild(getElement(), captionText); - } - DOM.setInnerText(captionText, uidl.getStringAttribute("caption")); - } else { - // TODO should span also be removed - } - - if (uidl.hasAttribute("description")) { - if (captionText != null) { - DOM.setElementProperty(captionText, "title", uidl - .getStringAttribute("description")); - } else { - setTitle(uidl.getStringAttribute("description")); - } - } - - } - - public void onBrowserEvent(Event event) { - Element target = DOM.eventGetTarget(event); - if (errorIndicatorElement != null - && DOM.compare(target, errorIndicatorElement)) { - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEOVER: - showErrorMessage(); - break; - case Event.ONMOUSEOUT: - hideErrorMessage(); - break; - case Event.ONCLICK: - ApplicationConnection.getConsole().log( - DOM.getInnerHTML(errorMessage.getElement())); - default: - break; - } - } - } - - private void hideErrorMessage() { - if (errorMessage != null) { - errorMessage.hide(); - } - } - - private void showErrorMessage() { - if (errorMessage != null) { - errorMessage.showAt(errorIndicatorElement); - } - } - - public static boolean isNeeded(UIDL uidl) { - if (uidl.getStringAttribute("caption") != null) - return true; - if (uidl.hasAttribute("error")) - return true; - - // TODO Description ?? - - return false; - } - - /** - * Returns Paintable for which this Caption belongs to. - * - * @return owner Widget - */ - public Paintable getOwner() { - return owner; - } + public static final String CLASSNAME = "i-caption"; + + private Paintable owner; + + private Element errorIndicatorElement; + + private Icon icon; + + private Element captionText; + + private ErrorMessage errorMessage; + + private ApplicationConnection client; + + /* Caption must be attached to a Paintable */ + private Caption() { + }; + + public Caption(Paintable component, ApplicationConnection client) { + super(); + this.client = client; + owner = component; + setStyleName(CLASSNAME); + } + + public void updateCaption(UIDL uidl) { + setVisible(!uidl.getBooleanAttribute("invisible")); + + if (uidl.hasAttribute("error")) { + UIDL errorUidl = uidl.getErrors(); + + if (errorIndicatorElement == null) { + errorIndicatorElement = DOM.createDiv(); + DOM.setElementProperty(errorIndicatorElement, "className", + "i-errorindicator"); + DOM.insertChild(getElement(), errorIndicatorElement, 0); + } + if (errorMessage == null) { + errorMessage = new ErrorMessage(); + } + errorMessage.updateFromUIDL(errorUidl); + + } else if (errorIndicatorElement != null) { + DOM.setStyleAttribute(errorIndicatorElement, "display", "none"); + } + + if (uidl.hasAttribute("icon")) { + if (icon == null) { + icon = new Icon(client); + + DOM.appendChild(getElement(), icon.getElement()); + } + icon.setUri(uidl.getStringAttribute("icon")); + } else { + if (icon != null) { + DOM.removeChild(getElement(), icon.getElement()); + icon = null; + } + + } + + if (uidl.hasAttribute("caption")) { + if (captionText == null) { + captionText = DOM.createSpan(); + DOM.appendChild(getElement(), captionText); + } + DOM.setInnerText(captionText, uidl.getStringAttribute("caption")); + } else { + // TODO should span also be removed + } + + if (uidl.hasAttribute("description")) { + if (captionText != null) { + DOM.setElementProperty(captionText, "title", uidl + .getStringAttribute("description")); + } else { + setTitle(uidl.getStringAttribute("description")); + } + } + + } + + public void onBrowserEvent(Event event) { + Element target = DOM.eventGetTarget(event); + if (errorIndicatorElement != null + && DOM.compare(target, errorIndicatorElement)) { + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEOVER: + showErrorMessage(); + break; + case Event.ONMOUSEOUT: + hideErrorMessage(); + break; + case Event.ONCLICK: + ApplicationConnection.getConsole().log( + DOM.getInnerHTML(errorMessage.getElement())); + default: + break; + } + } + } + + private void hideErrorMessage() { + if (errorMessage != null) { + errorMessage.hide(); + } + } + + private void showErrorMessage() { + if (errorMessage != null) { + errorMessage.showAt(errorIndicatorElement); + } + } + + public static boolean isNeeded(UIDL uidl) { + if (uidl.getStringAttribute("caption") != null) { + return true; + } + if (uidl.hasAttribute("error")) { + return true; + } + if (uidl.hasAttribute("icon")) { + return true; + } + + // TODO Description ?? + + return false; + } + + /** + * Returns Paintable for which this Caption belongs to. + * + * @return owner Widget + */ + public Paintable getOwner() { + return owner; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/CaptionWrapper.java b/src/com/itmill/toolkit/terminal/gwt/client/CaptionWrapper.java index a4e05f0283..5b61a40ecd 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/CaptionWrapper.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/CaptionWrapper.java @@ -5,24 +5,24 @@ import com.google.gwt.user.client.ui.Widget; public class CaptionWrapper extends FlowPanel { - public static final String CLASSNAME = "i-captionwrapper"; - Caption caption; - Paintable widget; + public static final String CLASSNAME = "i-captionwrapper"; + Caption caption; + Paintable widget; - public CaptionWrapper(Paintable toBeWrapped) { - caption = new Caption(toBeWrapped); - add(caption); - widget = toBeWrapped; - add((Widget) widget); - setStyleName(CLASSNAME); - } + public CaptionWrapper(Paintable toBeWrapped, ApplicationConnection client) { + caption = new Caption(toBeWrapped, client); + add(caption); + widget = toBeWrapped; + add((Widget) widget); + setStyleName(CLASSNAME); + } - public void updateCaption(UIDL uidl) { - caption.updateCaption(uidl); - setVisible(!uidl.getBooleanAttribute("invisible")); - } + public void updateCaption(UIDL uidl) { + caption.updateCaption(uidl); + setVisible(!uidl.getBooleanAttribute("invisible")); + } - public Paintable getPaintable() { - return widget; - } + public Paintable getPaintable() { + return widget; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java index b8e2da7e8b..3924f1ba5e 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java @@ -23,399 +23,406 @@ import com.itmill.toolkit.terminal.gwt.client.Util; * */ public class ICustomLayout extends ComplexPanel implements Paintable, - Container, ContainerResizedListener { - - /** Location-name to containing element in DOM map */ - private HashMap locationToElement = new HashMap(); - - /** Location-name to contained widget map */ - private HashMap locationToWidget = new HashMap(); - - /** Widget to captionwrapper map */ - private HashMap widgetToCaptionWrapper = new HashMap(); - - /** Currently rendered style */ - String currentTemplate; - - /** Unexecuted scripts loaded from the template */ - private String scripts = ""; - - /** Paintable ID of this paintable */ - private String pid; - - private ApplicationConnection client; - - public ICustomLayout() { - setElement(DOM.createDiv()); - DOM.setStyleAttribute(getElement(), "height", "100%"); - } - - /** - * Sets widget to given location. - * - * If location already contains a widget it will be removed. - * - * @param widget - * Widget to be set into location. - * @param location - * location name where widget will be added - * - * @throws IllegalArgumentException - * if no such location is found in the layout. - */ - public void setWidget(Widget widget, String location) { - - if (widget == null) - return; - - // If no given location is found in the layout, and exception is throws - Element elem = (Element) locationToElement.get(location); - if (elem == null && hasTemplate()) { - throw new IllegalArgumentException("No location " + location - + " found"); - } - - // Get previous widget - Widget previous = (Widget) locationToWidget.get(location); - // NOP if given widget already exists in this location - if (previous == widget) - return; - remove(previous); - - // if template is missing add element in order - if (!hasTemplate()) - elem = getElement(); - - // Add widget to location - super.add(widget, elem); - locationToWidget.put(location, widget); - } - - /** Update the layout from UIDL */ - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - // Client manages general cases - if (client.updateComponent(this, uidl, false)) - return; - - // Update PID - pid = uidl.getId(); - if (!hasTemplate()) { - // Update HTML template only once - initializeHTML(uidl, client); - } - - // Evaluate scripts - eval(scripts); - scripts = null; - - // For all contained widgets - for (Iterator i = uidl.getChildIterator(); i.hasNext();) { - UIDL uidlForChild = (UIDL) i.next(); - if (uidlForChild.getTag().equals("location")) { - String location = uidlForChild.getStringAttribute("name"); - Widget child = client.getWidget(uidlForChild.getChildUIDL(0)); - try { - setWidget(child, location); - ((Paintable) child).updateFromUIDL(uidlForChild - .getChildUIDL(0), client); - } catch (IllegalArgumentException e) { - // If no location is found, this component is not visible - } - } - } - - iLayout(); - } - - /** Initialize HTML-layout. */ - private void initializeHTML(UIDL uidl, ApplicationConnection client) { - - String newTemplate = uidl.getStringAttribute("template"); - - // Get the HTML-template from client - String template = client - .getResource("layouts/" + newTemplate + ".html"); - if (template == null) { - template = "Layout file layouts/" - + newTemplate - + ".html is missing. Components will be drawn for debug purposes."; - } else { - currentTemplate = newTemplate; - } - - // Connect body of the template to DOM - template = extractBodyAndScriptsFromTemplate(template); - DOM.setInnerHTML(getElement(), template); - - // Remap locations to elements - locationToElement.clear(); - scanForLocations(getElement()); - - // Remap image srcs in layout - Widget parent = getParent(); - while (parent != null && !(parent instanceof IView)) - parent = parent.getParent(); - if (parent != null && ((IView) parent).getTheme() != null) { - String prefix; - if(uriEndsWithSlash()) { - prefix = "../ITMILL/themes/"; - } else { - prefix = "ITMILL/themes/"; - } - prefixImgSrcs(getElement(), prefix - + ((IView) parent).getTheme() + "/layouts/"); - } else { - throw (new IllegalStateException( - "Could not find IView; maybe updateFromUIDL() was called before attaching the widget?")); - } - - publishResizedFunction(DOM.getFirstChild(getElement())); - - } - - private native boolean uriEndsWithSlash() /*-{ - var path = $wnd.location.pathname; - if(path.charAt(path.length - 1) == "/") - return true; - return false; - }-*/; - - private boolean hasTemplate() { - if (currentTemplate == null) - return false; - else - return true; - } - - /** Collect locations from template */ - private void scanForLocations(Element elem) { - - String location = getLocation(elem); - if (location != null) { - locationToElement.put(location, elem); - DOM.setInnerHTML(elem, ""); - } else { - int len = DOM.getChildCount(elem); - for (int i = 0; i < len; i++) { - scanForLocations(DOM.getChild(elem, i)); - } - } - } - - /** Get the location attribute for given element */ - private static native String getLocation(Element elem) /*-{ - return elem.getAttribute("location"); - }-*/; - - /** Evaluate given script in browser document */ - private static native void eval(String script) /*-{ - try { - if (script != null) - eval("{ var document = $doc; var window = $wnd; "+ script + "}"); - } catch (e) { - } - }-*/; - - /** Prefix all img tag srcs with given prefix. */ - private static native void prefixImgSrcs(Element e, String srcPrefix) /*-{ - try { - var divs = e.getElementsByTagName("img"); - var base = "" + $doc.location; - var l = base.length-1; - while (l >= 0 && base.charAt(l) != "/") l--; - base = base.substring(0,l+1); - for (var i = 0; i < divs.length; i++) { - var div = divs[i]; - var src = div.getAttribute("src"); - if (src.indexOf(base) == 0) div.setAttribute("src",base + srcPrefix + src.substring(base.length)); - else if (src.indexOf("http") != 0) div.setAttribute("src",srcPrefix + src); - } - } catch (e) { alert(e + " " + srcPrefix);} - }-*/; - - /** - * Extract body part and script tags from raw html-template. - * - * Saves contents of all script-tags to private property: scripts. Returns - * contents of the body part for the html without script-tags. Also replaces - * all _UID_ tags with an unique id-string. - * - * @param html - * Original HTML-template received from server - * @return html that is used to create the HTMLPanel. - */ - private String extractBodyAndScriptsFromTemplate(String html) { - - // Replace UID:s - html = html.replaceAll("_UID_", pid + "__"); - - // Exctract script-tags - scripts = ""; - int endOfPrevScript = 0; - int nextPosToCheck = 0; - String lc = html.toLowerCase(); - String res = ""; - int scriptStart = lc.indexOf(" 0) { - res += html.substring(endOfPrevScript, scriptStart); - scriptStart = lc.indexOf(">", scriptStart); - int j = lc.indexOf("", scriptStart); - scripts += html.substring(scriptStart + 1, j) + ";"; - nextPosToCheck = endOfPrevScript = j + "".length(); - scriptStart = lc.indexOf("", startOfBody) + 1; - int endOfBody = lc.indexOf("", startOfBody); - if (endOfBody > startOfBody) - res = html.substring(startOfBody, endOfBody); - else - res = html.substring(startOfBody); - } - - return res; - } - - protected void onAttach() { - super.onAttach(); - } - - /** Replace child components */ - public void replaceChildComponent(Widget from, Widget to) { - String location = getLocation(from); - if (location == null) - throw new IllegalArgumentException(); - setWidget(to, location); - } - - /** Does this layout contain given child */ - public boolean hasChildComponent(Widget component) { - return locationToWidget.containsValue(component); - } - - /** Update caption for given widget */ - public void updateCaption(Paintable component, UIDL uidl) { - CaptionWrapper wrapper = (CaptionWrapper) widgetToCaptionWrapper - .get(component); - if (Caption.isNeeded(uidl)) { - if (wrapper == null) { - String loc = getLocation((Widget) component); - super.remove((Widget) component); - wrapper = new CaptionWrapper(component); - super.add(wrapper, (Element) locationToElement.get(loc)); - widgetToCaptionWrapper.put(component, wrapper); - } - wrapper.updateCaption(uidl); - } else { - if (wrapper != null) { - String loc = getLocation((Widget) component); - super.remove(wrapper); - super.add((Widget) wrapper.getPaintable(), - (Element) locationToElement.get(loc)); - widgetToCaptionWrapper.remove(component); - } - } - } - - /** Get the location of an widget */ - public String getLocation(Widget w) { - for (Iterator i = locationToWidget.keySet().iterator(); i.hasNext();) { - String location = (String) i.next(); - if (locationToWidget.get(location) == w) - return location; - } - return null; - } - - /** Removes given widget from the layout */ - public boolean remove(Widget w) { - client.unregisterPaintable((Paintable) w); - String location = getLocation(w); - if (location != null) - locationToWidget.remove(location); - CaptionWrapper cw = (CaptionWrapper) widgetToCaptionWrapper.get(w); - if (cw != null) { - widgetToCaptionWrapper.remove(w); - return super.remove(cw); - } else if (w != null) - return super.remove(w); - return false; - } - - /** Adding widget without specifying location is not supported */ - public void add(Widget w) { - throw new UnsupportedOperationException(); - } - - /** Clear all widgets from the layout */ - public void clear() { - super.clear(); - locationToWidget.clear(); - widgetToCaptionWrapper.clear(); - } - - public void iLayout() { - if (!iLayoutJS(DOM.getFirstChild(getElement()))) { - Util.runDescendentsLayout(this); - } - } - - /** - * This method is published to JS side with the same name into first DOM - * node of custom layout. This way if one implements some resizeable - * containers in custom layout he/she can notify children after resize. - */ - public void notifyChildrenOfSizeChange() { - Util.runDescendentsLayout(this); - } - - public void onDetach() { - detachResizedFunction(DOM.getFirstChild(getElement())); - } - - private native void detachResizedFunction(Element element) - /*-{ - element.notifyChildrenOfSizeChange = null; - }-*/; - - private native void publishResizedFunction(Element element) - /*-{ - var self = this; - element.notifyChildrenOfSizeChange = function() { - self.@com.itmill.toolkit.terminal.gwt.client.ui.ICustomLayout::notifyChildrenOfSizeChange()(); - }; - }-*/; - - /** - * In custom layout one may want to run layout functions made with - * JavaScript. This function tests if one exists (with name "iLayoutJS" in - * layouts first DOM node) and runs if it. Return value is used to determine - * is children needs to be notified of size changes. - * - * @param el - * @return true if layout function was run and it returned true. - */ - private native boolean iLayoutJS(Element el) - /*-{ - if(el && el.iLayoutJS) { - try { - el.iLayoutJS(); - return true; - } catch (e) { - return false; - } - } else { - return false; - } - }-*/; + Container, ContainerResizedListener { + + /** Location-name to containing element in DOM map */ + private HashMap locationToElement = new HashMap(); + + /** Location-name to contained widget map */ + private HashMap locationToWidget = new HashMap(); + + /** Widget to captionwrapper map */ + private HashMap widgetToCaptionWrapper = new HashMap(); + + /** Currently rendered style */ + String currentTemplate; + + /** Unexecuted scripts loaded from the template */ + private String scripts = ""; + + /** Paintable ID of this paintable */ + private String pid; + + private ApplicationConnection client; + + public ICustomLayout() { + setElement(DOM.createDiv()); + DOM.setStyleAttribute(getElement(), "height", "100%"); + } + + /** + * Sets widget to given location. + * + * If location already contains a widget it will be removed. + * + * @param widget + * Widget to be set into location. + * @param location + * location name where widget will be added + * + * @throws IllegalArgumentException + * if no such location is found in the layout. + */ + public void setWidget(Widget widget, String location) { + + if (widget == null) { + return; + } + + // If no given location is found in the layout, and exception is throws + Element elem = (Element) locationToElement.get(location); + if (elem == null && hasTemplate()) { + throw new IllegalArgumentException("No location " + location + + " found"); + } + + // Get previous widget + Widget previous = (Widget) locationToWidget.get(location); + // NOP if given widget already exists in this location + if (previous == widget) { + return; + } + remove(previous); + + // if template is missing add element in order + if (!hasTemplate()) { + elem = getElement(); + } + + // Add widget to location + super.add(widget, elem); + locationToWidget.put(location, widget); + } + + /** Update the layout from UIDL */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + this.client = client; + // Client manages general cases + if (client.updateComponent(this, uidl, false)) { + return; + } + + // Update PID + pid = uidl.getId(); + if (!hasTemplate()) { + // Update HTML template only once + initializeHTML(uidl, client); + } + + // Evaluate scripts + eval(scripts); + scripts = null; + + // For all contained widgets + for (Iterator i = uidl.getChildIterator(); i.hasNext();) { + UIDL uidlForChild = (UIDL) i.next(); + if (uidlForChild.getTag().equals("location")) { + String location = uidlForChild.getStringAttribute("name"); + Widget child = client.getWidget(uidlForChild.getChildUIDL(0)); + try { + setWidget(child, location); + ((Paintable) child).updateFromUIDL(uidlForChild + .getChildUIDL(0), client); + } catch (IllegalArgumentException e) { + // If no location is found, this component is not visible + } + } + } + + iLayout(); + } + + /** Initialize HTML-layout. */ + private void initializeHTML(UIDL uidl, ApplicationConnection client) { + + String newTemplate = uidl.getStringAttribute("template"); + + // Get the HTML-template from client + String template = client + .getResource("layouts/" + newTemplate + ".html"); + if (template == null) { + template = "Layout file layouts/" + + newTemplate + + ".html is missing. Components will be drawn for debug purposes."; + } else { + currentTemplate = newTemplate; + } + + // Connect body of the template to DOM + template = extractBodyAndScriptsFromTemplate(template); + DOM.setInnerHTML(getElement(), template); + + // Remap locations to elements + locationToElement.clear(); + scanForLocations(getElement()); + + // Remap image srcs in layout + Widget parent = getParent(); + while (parent != null && !(parent instanceof IView)) { + parent = parent.getParent(); + } + if (parent != null && ((IView) parent).getTheme() != null) { + String prefix; + if (uriEndsWithSlash()) { + prefix = "../ITMILL/themes/"; + } else { + prefix = "ITMILL/themes/"; + } + prefixImgSrcs(getElement(), prefix + ((IView) parent).getTheme() + + "/layouts/"); + } else { + throw (new IllegalStateException( + "Could not find IView; maybe updateFromUIDL() was called before attaching the widget?")); + } + + publishResizedFunction(DOM.getFirstChild(getElement())); + + } + + private native boolean uriEndsWithSlash() /*-{ + var path = $wnd.location.pathname; + if(path.charAt(path.length - 1) == "/") + return true; + return false; + }-*/; + + private boolean hasTemplate() { + if (currentTemplate == null) { + return false; + } else { + return true; + } + } + + /** Collect locations from template */ + private void scanForLocations(Element elem) { + + String location = getLocation(elem); + if (location != null) { + locationToElement.put(location, elem); + DOM.setInnerHTML(elem, ""); + } else { + int len = DOM.getChildCount(elem); + for (int i = 0; i < len; i++) { + scanForLocations(DOM.getChild(elem, i)); + } + } + } + + /** Get the location attribute for given element */ + private static native String getLocation(Element elem) /*-{ + return elem.getAttribute("location"); + }-*/; + + /** Evaluate given script in browser document */ + private static native void eval(String script) /*-{ + try { + if (script != null) + eval("{ var document = $doc; var window = $wnd; "+ script + "}"); + } catch (e) { + } + }-*/; + + /** Prefix all img tag srcs with given prefix. */ + private static native void prefixImgSrcs(Element e, String srcPrefix) /*-{ + try { + var divs = e.getElementsByTagName("img"); + var base = "" + $doc.location; + var l = base.length-1; + while (l >= 0 && base.charAt(l) != "/") l--; + base = base.substring(0,l+1); + for (var i = 0; i < divs.length; i++) { + var div = divs[i]; + var src = div.getAttribute("src"); + if (src.indexOf(base) == 0) div.setAttribute("src",base + srcPrefix + src.substring(base.length)); + else if (src.indexOf("http") != 0) div.setAttribute("src",srcPrefix + src); + } + } catch (e) { alert(e + " " + srcPrefix);} + }-*/; + + /** + * Extract body part and script tags from raw html-template. + * + * Saves contents of all script-tags to private property: scripts. Returns + * contents of the body part for the html without script-tags. Also replaces + * all _UID_ tags with an unique id-string. + * + * @param html + * Original HTML-template received from server + * @return html that is used to create the HTMLPanel. + */ + private String extractBodyAndScriptsFromTemplate(String html) { + + // Replace UID:s + html = html.replaceAll("_UID_", pid + "__"); + + // Exctract script-tags + scripts = ""; + int endOfPrevScript = 0; + int nextPosToCheck = 0; + String lc = html.toLowerCase(); + String res = ""; + int scriptStart = lc.indexOf(" 0) { + res += html.substring(endOfPrevScript, scriptStart); + scriptStart = lc.indexOf(">", scriptStart); + int j = lc.indexOf("", scriptStart); + scripts += html.substring(scriptStart + 1, j) + ";"; + nextPosToCheck = endOfPrevScript = j + "".length(); + scriptStart = lc.indexOf("", startOfBody) + 1; + int endOfBody = lc.indexOf("", startOfBody); + if (endOfBody > startOfBody) { + res = html.substring(startOfBody, endOfBody); + } else { + res = html.substring(startOfBody); + } + } + + return res; + } + + /** Replace child components */ + public void replaceChildComponent(Widget from, Widget to) { + String location = getLocation(from); + if (location == null) { + throw new IllegalArgumentException(); + } + setWidget(to, location); + } + + /** Does this layout contain given child */ + public boolean hasChildComponent(Widget component) { + return locationToWidget.containsValue(component); + } + + /** Update caption for given widget */ + public void updateCaption(Paintable component, UIDL uidl) { + CaptionWrapper wrapper = (CaptionWrapper) widgetToCaptionWrapper + .get(component); + if (Caption.isNeeded(uidl)) { + if (wrapper == null) { + String loc = getLocation((Widget) component); + super.remove((Widget) component); + wrapper = new CaptionWrapper(component, client); + super.add(wrapper, (Element) locationToElement.get(loc)); + widgetToCaptionWrapper.put(component, wrapper); + } + wrapper.updateCaption(uidl); + } else { + if (wrapper != null) { + String loc = getLocation((Widget) component); + super.remove(wrapper); + super.add((Widget) wrapper.getPaintable(), + (Element) locationToElement.get(loc)); + widgetToCaptionWrapper.remove(component); + } + } + } + + /** Get the location of an widget */ + public String getLocation(Widget w) { + for (Iterator i = locationToWidget.keySet().iterator(); i.hasNext();) { + String location = (String) i.next(); + if (locationToWidget.get(location) == w) { + return location; + } + } + return null; + } + + /** Removes given widget from the layout */ + public boolean remove(Widget w) { + client.unregisterPaintable((Paintable) w); + String location = getLocation(w); + if (location != null) { + locationToWidget.remove(location); + } + CaptionWrapper cw = (CaptionWrapper) widgetToCaptionWrapper.get(w); + if (cw != null) { + widgetToCaptionWrapper.remove(w); + return super.remove(cw); + } else if (w != null) { + return super.remove(w); + } + return false; + } + + /** Adding widget without specifying location is not supported */ + public void add(Widget w) { + throw new UnsupportedOperationException(); + } + + /** Clear all widgets from the layout */ + public void clear() { + super.clear(); + locationToWidget.clear(); + widgetToCaptionWrapper.clear(); + } + + public void iLayout() { + if (!iLayoutJS(DOM.getFirstChild(getElement()))) { + Util.runDescendentsLayout(this); + } + } + + /** + * This method is published to JS side with the same name into first DOM + * node of custom layout. This way if one implements some resizeable + * containers in custom layout he/she can notify children after resize. + */ + public void notifyChildrenOfSizeChange() { + Util.runDescendentsLayout(this); + } + + public void onDetach() { + detachResizedFunction(DOM.getFirstChild(getElement())); + } + + private native void detachResizedFunction(Element element) + /*-{ + element.notifyChildrenOfSizeChange = null; + }-*/; + + private native void publishResizedFunction(Element element) + /*-{ + var self = this; + element.notifyChildrenOfSizeChange = function() { + self.@com.itmill.toolkit.terminal.gwt.client.ui.ICustomLayout::notifyChildrenOfSizeChange()(); + }; + }-*/; + + /** + * In custom layout one may want to run layout functions made with + * JavaScript. This function tests if one exists (with name "iLayoutJS" in + * layouts first DOM node) and runs if it. Return value is used to determine + * is children needs to be notified of size changes. + * + * @param el + * @return true if layout function was run and it returned true. + */ + private native boolean iLayoutJS(Element el) + /*-{ + if(el && el.iLayoutJS) { + try { + el.iLayoutJS(); + return true; + } catch (e) { + return false; + } + } else { + return false; + } + }-*/; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java index fe1fffd497..7aa87bfc1e 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java @@ -16,64 +16,66 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; */ public class IFormLayout extends FlexTable implements Container { - HashMap componentToCaption = new HashMap(); - private ApplicationConnection client; + HashMap componentToCaption = new HashMap(); + private ApplicationConnection client; - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + this.client = client; - if (client.updateComponent(this, uidl, false)) - return; + if (client.updateComponent(this, uidl, false)) { + return; + } - int i = 0; - for (Iterator it = uidl.getChildIterator(); it.hasNext(); i++) { - prepareCell(i, 1); - UIDL childUidl = (UIDL) it.next(); - Paintable p = (Paintable) client.getWidget(childUidl); - Caption c = (Caption) componentToCaption.get(p); - if (c == null) { - c = new Caption(p); - componentToCaption.put(p, c); - } - Paintable oldComponent = (Paintable) getWidget(i, 1); - if (oldComponent == null) { - setWidget(i, 1, (Widget) p); - } else if (oldComponent != p) { - client.unregisterPaintable(oldComponent); - setWidget(i, 1, (Widget) p); - } - setWidget(i, 0, c); - p.updateFromUIDL(childUidl, client); - } - i++; - while (getRowCount() > i) { - Paintable p = (Paintable) getWidget(i, 1); - client.unregisterPaintable(p); - componentToCaption.remove(p); - removeRow(i); - } - } + int i = 0; + for (Iterator it = uidl.getChildIterator(); it.hasNext(); i++) { + prepareCell(i, 1); + UIDL childUidl = (UIDL) it.next(); + Paintable p = (Paintable) client.getWidget(childUidl); + Caption c = (Caption) componentToCaption.get(p); + if (c == null) { + c = new Caption(p, client); + componentToCaption.put(p, c); + } + Paintable oldComponent = (Paintable) getWidget(i, 1); + if (oldComponent == null) { + setWidget(i, 1, (Widget) p); + } else if (oldComponent != p) { + client.unregisterPaintable(oldComponent); + setWidget(i, 1, (Widget) p); + } + setWidget(i, 0, c); + p.updateFromUIDL(childUidl, client); + } + i++; + while (getRowCount() > i) { + Paintable p = (Paintable) getWidget(i, 1); + client.unregisterPaintable(p); + componentToCaption.remove(p); + removeRow(i); + } + } - public boolean hasChildComponent(Widget component) { - return componentToCaption.containsKey(component); - } + public boolean hasChildComponent(Widget component) { + return componentToCaption.containsKey(component); + } - public void replaceChildComponent(Widget oldComponent, Widget newComponent) { - int i; - for (i = 0; i < getRowCount(); i++) { - if (oldComponent == getWidget(i, 1)) { - Caption newCap = new Caption((Paintable) newComponent); - setWidget(i, 0, newCap); - setWidget(i, 1, newComponent); - client.unregisterPaintable((Paintable) oldComponent); - break; - } - } - } + public void replaceChildComponent(Widget oldComponent, Widget newComponent) { + int i; + for (i = 0; i < getRowCount(); i++) { + if (oldComponent == getWidget(i, 1)) { + Caption newCap = new Caption((Paintable) newComponent, client); + setWidget(i, 0, newCap); + setWidget(i, 1, newComponent); + client.unregisterPaintable((Paintable) oldComponent); + break; + } + } + } - public void updateCaption(Paintable component, UIDL uidl) { - Caption c = (Caption) componentToCaption.get(component); - if (c != null) - c.updateCaption(uidl); - } + public void updateCaption(Paintable component, UIDL uidl) { + Caption c = (Caption) componentToCaption.get(component); + if (c != null) { + c.updateCaption(uidl); + } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java index 69645e047d..e532e8b79f 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java @@ -14,86 +14,91 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class IGridLayout extends FlexTable implements Paintable, Container { - /** Widget to captionwrapper map */ - private HashMap widgetToCaptionWrapper = new HashMap(); - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - if (client.updateComponent(this, uidl, false)) - return; - - clear(); - if (uidl.hasAttribute("caption")) - setTitle(uidl.getStringAttribute("caption")); - int row = 0, column = 0; - - ArrayList detachdedPaintables = new ArrayList(); - - for (Iterator i = uidl.getChildIterator(); i.hasNext();) { - UIDL r = (UIDL) i.next(); - if ("gr".equals(r.getTag())) { - row++; - column = 0; - for (Iterator j = r.getChildIterator(); j.hasNext();) { - UIDL c = (UIDL) j.next(); - if ("gc".equals(c.getTag())) { - column++; - int w; - if (c.hasAttribute("w")) { - w = c.getIntAttribute("w"); - } else - w = 1; - ((FlexCellFormatter) getCellFormatter()).setColSpan( - row, column, w); - - UIDL u = c.getChildUIDL(0); - if (u != null) { - Widget child = client.getWidget(u); - prepareCell(row, column); - Widget oldChild = getWidget(row, column); - if (child != oldChild) { - if (oldChild != null) { - CaptionWrapper cw = (CaptionWrapper) oldChild; - detachdedPaintables.add(cw.getPaintable()); - widgetToCaptionWrapper.remove(oldChild); - } - CaptionWrapper wrapper = new CaptionWrapper( - (Paintable) child); - setWidget(row, column, wrapper); - widgetToCaptionWrapper.put(child, wrapper); - } - ((Paintable) child).updateFromUIDL(u, client); - } - column += w - 1; - } - } - } - } - - // for loop detached widgets and unregister them unless they are - // attached (case of widget which is moved to another cell) - for (Iterator it = detachdedPaintables.iterator(); it.hasNext();) { - Widget w = (Widget) it.next(); - if (!w.isAttached()) - client.unregisterPaintable((Paintable) w); - } - } - - public boolean hasChildComponent(Widget component) { - if (widgetToCaptionWrapper.containsKey(component)) - return true; - return false; - } - - public void replaceChildComponent(Widget oldComponent, Widget newComponent) { - // TODO Auto-generated method stub - - } - - public void updateCaption(Paintable component, UIDL uidl) { - CaptionWrapper wrapper = (CaptionWrapper) widgetToCaptionWrapper - .get(component); - wrapper.updateCaption(uidl); - } + /** Widget to captionwrapper map */ + private HashMap widgetToCaptionWrapper = new HashMap(); + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + if (client.updateComponent(this, uidl, false)) { + return; + } + + clear(); + if (uidl.hasAttribute("caption")) { + setTitle(uidl.getStringAttribute("caption")); + } + int row = 0, column = 0; + + ArrayList detachdedPaintables = new ArrayList(); + + for (Iterator i = uidl.getChildIterator(); i.hasNext();) { + UIDL r = (UIDL) i.next(); + if ("gr".equals(r.getTag())) { + row++; + column = 0; + for (Iterator j = r.getChildIterator(); j.hasNext();) { + UIDL c = (UIDL) j.next(); + if ("gc".equals(c.getTag())) { + column++; + int w; + if (c.hasAttribute("w")) { + w = c.getIntAttribute("w"); + } else { + w = 1; + } + ((FlexCellFormatter) getCellFormatter()).setColSpan( + row, column, w); + + UIDL u = c.getChildUIDL(0); + if (u != null) { + Widget child = client.getWidget(u); + prepareCell(row, column); + Widget oldChild = getWidget(row, column); + if (child != oldChild) { + if (oldChild != null) { + CaptionWrapper cw = (CaptionWrapper) oldChild; + detachdedPaintables.add(cw.getPaintable()); + widgetToCaptionWrapper.remove(oldChild); + } + CaptionWrapper wrapper = new CaptionWrapper( + (Paintable) child, client); + setWidget(row, column, wrapper); + widgetToCaptionWrapper.put(child, wrapper); + } + ((Paintable) child).updateFromUIDL(u, client); + } + column += w - 1; + } + } + } + } + + // for loop detached widgets and unregister them unless they are + // attached (case of widget which is moved to another cell) + for (Iterator it = detachdedPaintables.iterator(); it.hasNext();) { + Widget w = (Widget) it.next(); + if (!w.isAttached()) { + client.unregisterPaintable((Paintable) w); + } + } + } + + public boolean hasChildComponent(Widget component) { + if (widgetToCaptionWrapper.containsKey(component)) { + return true; + } + return false; + } + + public void replaceChildComponent(Widget oldComponent, Widget newComponent) { + // TODO Auto-generated method stub + + } + + public void updateCaption(Paintable component, UIDL uidl) { + CaptionWrapper wrapper = (CaptionWrapper) widgetToCaptionWrapper + .get(component); + wrapper.updateCaption(uidl); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java index 17cef81ea2..8ffb34ef0a 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java @@ -25,411 +25,421 @@ import com.itmill.toolkit.terminal.gwt.client.Util; */ public abstract class IOrderedLayout extends ComplexPanel implements Container { - public static final String CLASSNAME = "i-orderedlayout"; - - public static final int ORIENTATION_VERTICAL = 0; - public static final int ORIENTATION_HORIZONTAL = 1; - - int orientationMode = ORIENTATION_VERTICAL; - - protected HashMap componentToCaption = new HashMap(); - - protected ApplicationConnection client; - - /** - * Contains reference to Element where Paintables are wrapped. Normally a TR - * or a TBODY element. - */ - protected Element childContainer; - - /* - * Elements that provides the Layout interface implementation. - */ - protected Element size; - protected Element margin; - - protected Element topMargin = null; - protected Element bottomMargin = null; - - private static final String structure = "
"; - - public IOrderedLayout(int orientation) { - orientationMode = orientation; - constructDOM(); - setStyleName(CLASSNAME); - } - - protected void constructDOM() { - size = DOM.createDiv(); - DOM.setInnerHTML(size, structure); - margin = DOM.getFirstChild(size); - Element tBody = DOM.getFirstChild(DOM.getFirstChild(margin)); - if (orientationMode == ORIENTATION_HORIZONTAL) { - childContainer = DOM.createTR(); - DOM.appendChild(tBody, childContainer); - } else - childContainer = tBody; - setElement(size); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - this.client = client; - - // Ensure correct implementation - if (client.updateComponent(this, uidl, false)) - return; - - // Set size - if (uidl.hasAttribute("width")) { - setWidth(uidl.getStringAttribute("width")); - DOM.setStyleAttribute(DOM.getFirstChild(margin), "width", "100%"); - } else { - setWidth(""); - DOM.setStyleAttribute(DOM.getFirstChild(margin), "width", ""); - } - if (uidl.hasAttribute("height")) { - setHeight(uidl.getStringAttribute("height")); - // TODO override setHeight() method and move these there - DOM.setStyleAttribute(margin, "height", "100%"); - DOM.setStyleAttribute(DOM.getFirstChild(margin), "height", "100%"); - } else { - setHeight(""); - DOM.setStyleAttribute(margin, "height", ""); - DOM.setStyleAttribute(DOM.getFirstChild(margin), "height", ""); - } - - ArrayList uidlWidgets = new ArrayList(); - for (Iterator it = uidl.getChildIterator(); it.hasNext();) { - UIDL uidlForChild = (UIDL) it.next(); - Widget child = client.getWidget(uidlForChild); - uidlWidgets.add(child); - } - - ArrayList oldWidgets = getPaintables(); - - Iterator oldIt = oldWidgets.iterator(); - Iterator newIt = uidlWidgets.iterator(); - Iterator newUidl = uidl.getChildIterator(); - - Widget oldChild = null; - while (newIt.hasNext()) { - Widget child = (Widget) newIt.next(); - UIDL childUidl = (UIDL) newUidl.next(); - - if (oldChild == null && oldIt.hasNext()) { - // search for next old Paintable which still exists in layout - // and delete others - while (oldIt.hasNext()) { - oldChild = (Widget) oldIt.next(); - // now oldChild is an instance of Paintable - if (uidlWidgets.contains(oldChild)) - break; - else { - removePaintable((Paintable) oldChild); - oldChild = null; - } - } - } - if (oldChild == null) { - // we are adding components to layout - add(child); - } else if (child == oldChild) { - // child already attached and updated - oldChild = null; - } else if (hasChildComponent(child)) { - // current child has been moved, re-insert before current - // oldChild - // TODO this might be optimized by moving only container element - // to correct position - removeCaption(child); - int index = getWidgetIndex(oldChild); - if (componentToCaption.containsKey(oldChild)) - index--; - remove(child); - this.insert(child, index); - } else { - // insert new child before old one - int index = getWidgetIndex(oldChild); - insert(child, index); - } - ((Paintable) child).updateFromUIDL(childUidl, client); - } - // remove possibly remaining old Paintable object which were not updated - while (oldIt.hasNext()) { - oldChild = (Widget) oldIt.next(); - Paintable p = (Paintable) oldChild; - if (!uidlWidgets.contains(p)) - removePaintable(p); - } - - // Handle component alignments - handleAlignments(uidl); - - // Handle layout margins - handleMargins(uidl); - - } - - /** - * Retuns a list of Paintables currently rendered in layout - * - * @return list of Paintable objects - */ - protected ArrayList getPaintables() { - ArrayList al = new ArrayList(); - Iterator it = iterator(); - while (it.hasNext()) { - Widget w = (Widget) it.next(); - if (w instanceof Paintable) - al.add(w); - } - return al; - } - - /** - * Removes Paintable from DOM and its reference from ApplicationConnection. - * - * Also removes Paintable's Caption if one exists - * - * @param p - * Paintable to be removed - */ - public boolean removePaintable(Paintable p) { - Caption c = (Caption) componentToCaption.get(p); - if (c != null) { - componentToCaption.remove(c); - remove(c); - } - client.unregisterPaintable(p); - return remove((Widget) p); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.gwt.client.Layout#replaceChildComponent(com.google.gwt.user.client.ui.Widget, - * com.google.gwt.user.client.ui.Widget) - */ - public void replaceChildComponent(Widget from, Widget to) { - client.unregisterPaintable((Paintable) from); - Caption c = (Caption) componentToCaption.get(from); - if (c != null) { - remove(c); - componentToCaption.remove(c); - } - int index = getWidgetIndex(from); - if (index >= 0) { - remove(index); - insert(to, index); - } - } - - protected void insert(Widget w, int beforeIndex) { - if (w instanceof Caption) { - Caption c = (Caption) w; - // captions go into same container element as their - // owners - Element container = DOM.getParent(((UIObject) c.getOwner()) - .getElement()); - Element captionContainer = DOM.createDiv(); - DOM.insertChild(container, captionContainer, 0); - insert(w, captionContainer, beforeIndex, false); - } else { - Element wrapper = createWidgetWrappper(); - DOM.insertChild(childContainer, wrapper, beforeIndex); - insert(w, getWidgetContainerFromWrapper(wrapper), beforeIndex, - false); - } - } - - protected Element getWidgetContainerFromWrapper(Element wrapper) { - switch (orientationMode) { - case ORIENTATION_HORIZONTAL: - return wrapper; - default: - return DOM.getFirstChild(wrapper); - } - } - - /** - * creates an Element which will contain child widget - */ - protected Element createWidgetWrappper() { - Element td = DOM.createTD(); - // DOM.setStyleAttribute(td, "overflow", "hidden"); - switch (orientationMode) { - case ORIENTATION_HORIZONTAL: - return td; - default: - Element tr = DOM.createTR(); - DOM.appendChild(tr, td); - return tr; - } - } - - public boolean hasChildComponent(Widget component) { - return getWidgetIndex(component) >= 0; - } - - public void updateCaption(Paintable component, UIDL uidl) { - - Caption c = (Caption) componentToCaption.get(component); - - if (Caption.isNeeded(uidl)) { - if (c == null) { - int index = getWidgetIndex((Widget) component); - c = new Caption(component); - insert(c, index); - componentToCaption.put(component, c); - } - c.updateCaption(uidl); - } else { - if (c != null) { - remove(c); - componentToCaption.remove(component); - } - } - } - - public void removeCaption(Widget w) { - Caption c = (Caption) componentToCaption.get(w); - if (c != null) { - this.remove(c); - componentToCaption.remove(w); - } - } - - public void add(Widget w) { - Element wrapper = createWidgetWrappper(); - DOM.appendChild(childContainer, wrapper); - super.add(w, orientationMode == ORIENTATION_HORIZONTAL ? wrapper : DOM - .getFirstChild(wrapper)); - } - - public boolean remove(int index) { - return remove(getWidget(index)); - } - - public boolean remove(Widget w) { - Element wrapper = DOM.getParent(w.getElement()); - boolean removed = super.remove(w); - if (removed) { - if (!(w instanceof Caption)) { - DOM.removeChild(childContainer, - orientationMode == ORIENTATION_HORIZONTAL ? wrapper - : DOM.getParent(wrapper)); - } - return true; - } - return false; - } - - public Widget getWidget(int index) { - return getChildren().get(index); - } - - public int getWidgetCount() { - return getChildren().size(); - } - - public int getWidgetIndex(Widget child) { - return getChildren().indexOf(child); - } - - protected void handleMargins(UIDL uidl) { - // Modify layout margins - String marginClasses = ""; - MarginInfo margins = new MarginInfo(uidl.getIntAttribute("margins")); - - // Top margin - if (margins.hasTop()) { - marginClasses += " " + StyleConstants.LAYOUT_MARGIN_TOP; - if (topMargin == null) { - // We need to insert a new row in to the table - topMargin = createWidgetWrappper(); - DOM.appendChild(getWidgetContainerFromWrapper(topMargin), DOM - .createDiv()); - DOM.setElementProperty(topMargin, "className", CLASSNAME - + "-toppad"); - if (orientationMode == ORIENTATION_HORIZONTAL) { - DOM.setElementAttribute(DOM.getFirstChild(topMargin), - "colspan", "" + getPaintables().size()); - } - DOM.insertChild(childContainer, topMargin, 0); - } - } else { - if (topMargin != null) - DOM.removeChild(childContainer, DOM - .getFirstChild(childContainer)); - topMargin = null; - } - - // Right margin - if (margins.hasRight()) - marginClasses += " " + StyleConstants.LAYOUT_MARGIN_RIGHT; - - // Bottom margin - if (margins.hasBottom()) { - marginClasses += " " + StyleConstants.LAYOUT_MARGIN_BOTTOM; - if (bottomMargin == null) { - // We need to insert a new row in to the table - bottomMargin = createWidgetWrappper(); - DOM.appendChild(getWidgetContainerFromWrapper(bottomMargin), - DOM.createDiv()); - DOM.setElementProperty(bottomMargin, "className", CLASSNAME - + "-bottompad"); - if (orientationMode == ORIENTATION_HORIZONTAL) { - DOM.setElementAttribute(DOM.getFirstChild(bottomMargin), - "colspan", "" + getPaintables().size()); - } - DOM.appendChild(childContainer, bottomMargin); - } - } else { - if (bottomMargin != null) - DOM.removeChild(childContainer, DOM.getChild(childContainer, - DOM.getChildCount(childContainer) - 1)); - bottomMargin = null; - } - - // Left margin - if (margins.hasLeft()) - marginClasses += " " + StyleConstants.LAYOUT_MARGIN_LEFT; - - // Add - DOM.setElementProperty(margin, "className", marginClasses); - } - - protected void handleAlignments(UIDL uidl) { - // Component alignments as a comma separated list. - // See com.itmill.toolkit.terminal.gwt.client.ui.AlignmentInfo.java for - // possible values. - int[] alignments = uidl.getIntArrayAttribute("alignments"); - int alignmentIndex = 0; - // Insert alignment attributes - Iterator it = getPaintables().iterator(); - while (it.hasNext()) { - - // Calculate alignment info - AlignmentInfo ai = new AlignmentInfo(alignments[alignmentIndex++]); - - Element td = DOM.getParent(((Widget) it.next()).getElement()); - if (Util.isIE()) { - DOM.setElementAttribute(td, "vAlign", ai - .getVerticalAlignment()); - } else { - DOM.setStyleAttribute(td, "verticalAlign", ai - .getVerticalAlignment()); - } - // TODO use one-cell table to implement horizontal alignments - if (Util.isIE()) { - DOM.setElementAttribute(td, "align", ai - .getHorizontalAlignment()); - } else { - DOM.setStyleAttribute(td, "textAlign", ai - .getHorizontalAlignment()); - } - } - } + public static final String CLASSNAME = "i-orderedlayout"; + + public static final int ORIENTATION_VERTICAL = 0; + public static final int ORIENTATION_HORIZONTAL = 1; + + int orientationMode = ORIENTATION_VERTICAL; + + protected HashMap componentToCaption = new HashMap(); + + protected ApplicationConnection client; + + /** + * Contains reference to Element where Paintables are wrapped. Normally a TR + * or a TBODY element. + */ + protected Element childContainer; + + /* + * Elements that provides the Layout interface implementation. + */ + protected Element size; + protected Element margin; + + protected Element topMargin = null; + protected Element bottomMargin = null; + + private static final String structure = "
"; + + public IOrderedLayout(int orientation) { + orientationMode = orientation; + constructDOM(); + setStyleName(CLASSNAME); + } + + protected void constructDOM() { + size = DOM.createDiv(); + DOM.setInnerHTML(size, structure); + margin = DOM.getFirstChild(size); + Element tBody = DOM.getFirstChild(DOM.getFirstChild(margin)); + if (orientationMode == ORIENTATION_HORIZONTAL) { + childContainer = DOM.createTR(); + DOM.appendChild(tBody, childContainer); + } else { + childContainer = tBody; + } + setElement(size); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + this.client = client; + + // Ensure correct implementation + if (client.updateComponent(this, uidl, false)) { + return; + } + + // Set size + if (uidl.hasAttribute("width")) { + setWidth(uidl.getStringAttribute("width")); + DOM.setStyleAttribute(DOM.getFirstChild(margin), "width", "100%"); + } else { + setWidth(""); + DOM.setStyleAttribute(DOM.getFirstChild(margin), "width", ""); + } + if (uidl.hasAttribute("height")) { + setHeight(uidl.getStringAttribute("height")); + // TODO override setHeight() method and move these there + DOM.setStyleAttribute(margin, "height", "100%"); + DOM.setStyleAttribute(DOM.getFirstChild(margin), "height", "100%"); + } else { + setHeight(""); + DOM.setStyleAttribute(margin, "height", ""); + DOM.setStyleAttribute(DOM.getFirstChild(margin), "height", ""); + } + + ArrayList uidlWidgets = new ArrayList(); + for (Iterator it = uidl.getChildIterator(); it.hasNext();) { + UIDL uidlForChild = (UIDL) it.next(); + Widget child = client.getWidget(uidlForChild); + uidlWidgets.add(child); + } + + ArrayList oldWidgets = getPaintables(); + + Iterator oldIt = oldWidgets.iterator(); + Iterator newIt = uidlWidgets.iterator(); + Iterator newUidl = uidl.getChildIterator(); + + Widget oldChild = null; + while (newIt.hasNext()) { + Widget child = (Widget) newIt.next(); + UIDL childUidl = (UIDL) newUidl.next(); + + if (oldChild == null && oldIt.hasNext()) { + // search for next old Paintable which still exists in layout + // and delete others + while (oldIt.hasNext()) { + oldChild = (Widget) oldIt.next(); + // now oldChild is an instance of Paintable + if (uidlWidgets.contains(oldChild)) { + break; + } else { + removePaintable((Paintable) oldChild); + oldChild = null; + } + } + } + if (oldChild == null) { + // we are adding components to layout + add(child); + } else if (child == oldChild) { + // child already attached and updated + oldChild = null; + } else if (hasChildComponent(child)) { + // current child has been moved, re-insert before current + // oldChild + // TODO this might be optimized by moving only container element + // to correct position + removeCaption(child); + int index = getWidgetIndex(oldChild); + if (componentToCaption.containsKey(oldChild)) { + index--; + } + remove(child); + this.insert(child, index); + } else { + // insert new child before old one + int index = getWidgetIndex(oldChild); + insert(child, index); + } + ((Paintable) child).updateFromUIDL(childUidl, client); + } + // remove possibly remaining old Paintable object which were not updated + while (oldIt.hasNext()) { + oldChild = (Widget) oldIt.next(); + Paintable p = (Paintable) oldChild; + if (!uidlWidgets.contains(p)) { + removePaintable(p); + } + } + + // Handle component alignments + handleAlignments(uidl); + + // Handle layout margins + handleMargins(uidl); + + } + + /** + * Retuns a list of Paintables currently rendered in layout + * + * @return list of Paintable objects + */ + protected ArrayList getPaintables() { + ArrayList al = new ArrayList(); + Iterator it = iterator(); + while (it.hasNext()) { + Widget w = (Widget) it.next(); + if (w instanceof Paintable) { + al.add(w); + } + } + return al; + } + + /** + * Removes Paintable from DOM and its reference from ApplicationConnection. + * + * Also removes Paintable's Caption if one exists + * + * @param p + * Paintable to be removed + */ + public boolean removePaintable(Paintable p) { + Caption c = (Caption) componentToCaption.get(p); + if (c != null) { + componentToCaption.remove(c); + remove(c); + } + client.unregisterPaintable(p); + return remove((Widget) p); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.gwt.client.Layout#replaceChildComponent(com.google.gwt.user.client.ui.Widget, + * com.google.gwt.user.client.ui.Widget) + */ + public void replaceChildComponent(Widget from, Widget to) { + client.unregisterPaintable((Paintable) from); + Caption c = (Caption) componentToCaption.get(from); + if (c != null) { + remove(c); + componentToCaption.remove(c); + } + int index = getWidgetIndex(from); + if (index >= 0) { + remove(index); + insert(to, index); + } + } + + protected void insert(Widget w, int beforeIndex) { + if (w instanceof Caption) { + Caption c = (Caption) w; + // captions go into same container element as their + // owners + Element container = DOM.getParent(((UIObject) c.getOwner()) + .getElement()); + Element captionContainer = DOM.createDiv(); + DOM.insertChild(container, captionContainer, 0); + insert(w, captionContainer, beforeIndex, false); + } else { + Element wrapper = createWidgetWrappper(); + DOM.insertChild(childContainer, wrapper, beforeIndex); + insert(w, getWidgetContainerFromWrapper(wrapper), beforeIndex, + false); + } + } + + protected Element getWidgetContainerFromWrapper(Element wrapper) { + switch (orientationMode) { + case ORIENTATION_HORIZONTAL: + return wrapper; + default: + return DOM.getFirstChild(wrapper); + } + } + + /** + * creates an Element which will contain child widget + */ + protected Element createWidgetWrappper() { + Element td = DOM.createTD(); + // DOM.setStyleAttribute(td, "overflow", "hidden"); + switch (orientationMode) { + case ORIENTATION_HORIZONTAL: + return td; + default: + Element tr = DOM.createTR(); + DOM.appendChild(tr, td); + return tr; + } + } + + public boolean hasChildComponent(Widget component) { + return getWidgetIndex(component) >= 0; + } + + public void updateCaption(Paintable component, UIDL uidl) { + + Caption c = (Caption) componentToCaption.get(component); + + if (Caption.isNeeded(uidl)) { + if (c == null) { + int index = getWidgetIndex((Widget) component); + c = new Caption(component, client); + insert(c, index); + componentToCaption.put(component, c); + } + c.updateCaption(uidl); + } else { + if (c != null) { + remove(c); + componentToCaption.remove(component); + } + } + } + + public void removeCaption(Widget w) { + Caption c = (Caption) componentToCaption.get(w); + if (c != null) { + this.remove(c); + componentToCaption.remove(w); + } + } + + public void add(Widget w) { + Element wrapper = createWidgetWrappper(); + DOM.appendChild(childContainer, wrapper); + super.add(w, orientationMode == ORIENTATION_HORIZONTAL ? wrapper : DOM + .getFirstChild(wrapper)); + } + + public boolean remove(int index) { + return remove(getWidget(index)); + } + + public boolean remove(Widget w) { + Element wrapper = DOM.getParent(w.getElement()); + boolean removed = super.remove(w); + if (removed) { + if (!(w instanceof Caption)) { + DOM.removeChild(childContainer, + orientationMode == ORIENTATION_HORIZONTAL ? wrapper + : DOM.getParent(wrapper)); + } + return true; + } + return false; + } + + public Widget getWidget(int index) { + return getChildren().get(index); + } + + public int getWidgetCount() { + return getChildren().size(); + } + + public int getWidgetIndex(Widget child) { + return getChildren().indexOf(child); + } + + protected void handleMargins(UIDL uidl) { + // Modify layout margins + String marginClasses = ""; + MarginInfo margins = new MarginInfo(uidl.getIntAttribute("margins")); + + // Top margin + if (margins.hasTop()) { + marginClasses += " " + StyleConstants.LAYOUT_MARGIN_TOP; + if (topMargin == null) { + // We need to insert a new row in to the table + topMargin = createWidgetWrappper(); + DOM.appendChild(getWidgetContainerFromWrapper(topMargin), DOM + .createDiv()); + DOM.setElementProperty(topMargin, "className", CLASSNAME + + "-toppad"); + if (orientationMode == ORIENTATION_HORIZONTAL) { + DOM.setElementAttribute(DOM.getFirstChild(topMargin), + "colspan", "" + getPaintables().size()); + } + DOM.insertChild(childContainer, topMargin, 0); + } + } else { + if (topMargin != null) { + DOM.removeChild(childContainer, DOM + .getFirstChild(childContainer)); + } + topMargin = null; + } + + // Right margin + if (margins.hasRight()) { + marginClasses += " " + StyleConstants.LAYOUT_MARGIN_RIGHT; + } + + // Bottom margin + if (margins.hasBottom()) { + marginClasses += " " + StyleConstants.LAYOUT_MARGIN_BOTTOM; + if (bottomMargin == null) { + // We need to insert a new row in to the table + bottomMargin = createWidgetWrappper(); + DOM.appendChild(getWidgetContainerFromWrapper(bottomMargin), + DOM.createDiv()); + DOM.setElementProperty(bottomMargin, "className", CLASSNAME + + "-bottompad"); + if (orientationMode == ORIENTATION_HORIZONTAL) { + DOM.setElementAttribute(DOM.getFirstChild(bottomMargin), + "colspan", "" + getPaintables().size()); + } + DOM.appendChild(childContainer, bottomMargin); + } + } else { + if (bottomMargin != null) { + DOM.removeChild(childContainer, DOM.getChild(childContainer, + DOM.getChildCount(childContainer) - 1)); + } + bottomMargin = null; + } + + // Left margin + if (margins.hasLeft()) { + marginClasses += " " + StyleConstants.LAYOUT_MARGIN_LEFT; + } + + // Add + DOM.setElementProperty(margin, "className", marginClasses); + } + + protected void handleAlignments(UIDL uidl) { + // Component alignments as a comma separated list. + // See com.itmill.toolkit.terminal.gwt.client.ui.AlignmentInfo.java for + // possible values. + int[] alignments = uidl.getIntArrayAttribute("alignments"); + int alignmentIndex = 0; + // Insert alignment attributes + Iterator it = getPaintables().iterator(); + while (it.hasNext()) { + + // Calculate alignment info + AlignmentInfo ai = new AlignmentInfo(alignments[alignmentIndex++]); + + Element td = DOM.getParent(((Widget) it.next()).getElement()); + if (Util.isIE()) { + DOM + .setElementAttribute(td, "vAlign", ai + .getVerticalAlignment()); + } else { + DOM.setStyleAttribute(td, "verticalAlign", ai + .getVerticalAlignment()); + } + // TODO use one-cell table to implement horizontal alignments + if (Util.isIE()) { + DOM.setElementAttribute(td, "align", ai + .getHorizontalAlignment()); + } else { + DOM.setStyleAttribute(td, "textAlign", ai + .getHorizontalAlignment()); + } + } + } }