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;
+ }
}
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;
+ }
}
*
*/
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 = "<em>Layout file layouts/"
- + newTemplate
- + ".html is missing. Components will be drawn for debug purposes.</em>";
- } 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("<script", nextPosToCheck);
- while (scriptStart > 0) {
- res += html.substring(endOfPrevScript, scriptStart);
- scriptStart = lc.indexOf(">", scriptStart);
- int j = lc.indexOf("</script>", scriptStart);
- scripts += html.substring(scriptStart + 1, j) + ";";
- nextPosToCheck = endOfPrevScript = j + "</script>".length();
- scriptStart = lc.indexOf("<script", nextPosToCheck);
- }
- res += html.substring(endOfPrevScript);
-
- // Extract body
- html = res;
- lc = html.toLowerCase();
- int startOfBody = lc.indexOf("<body");
- if (startOfBody < 0) {
- res = html;
- } else {
- res = "";
- startOfBody = lc.indexOf(">", startOfBody) + 1;
- int endOfBody = lc.indexOf("</body>", 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 = "<em>Layout file layouts/"
+ + newTemplate
+ + ".html is missing. Components will be drawn for debug purposes.</em>";
+ } 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("<script", nextPosToCheck);
+ while (scriptStart > 0) {
+ res += html.substring(endOfPrevScript, scriptStart);
+ scriptStart = lc.indexOf(">", scriptStart);
+ int j = lc.indexOf("</script>", scriptStart);
+ scripts += html.substring(scriptStart + 1, j) + ";";
+ nextPosToCheck = endOfPrevScript = j + "</script>".length();
+ scriptStart = lc.indexOf("<script", nextPosToCheck);
+ }
+ res += html.substring(endOfPrevScript);
+
+ // Extract body
+ html = res;
+ lc = html.toLowerCase();
+ int startOfBody = lc.indexOf("<body");
+ if (startOfBody < 0) {
+ res = html;
+ } else {
+ res = "";
+ startOfBody = lc.indexOf(">", startOfBody) + 1;
+ int endOfBody = lc.indexOf("</body>", 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;
+ }
+ }-*/;
}
*/
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);
+ }
+ }
}
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);
+ }
}
*/
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 = "<div><table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"table-layout:fixed;\"><tbody></tbody></table></div>";
-
- 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 = "<div><table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"table-layout:fixed;\"><tbody></tbody></table></div>";
+
+ 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());
+ }
+ }
+ }
}