123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- package com.itmill.toolkit.terminal.gwt.client.ui;
-
- import java.util.HashMap;
- import java.util.Iterator;
-
- import com.google.gwt.user.client.DOM;
- import com.google.gwt.user.client.Element;
- import com.google.gwt.user.client.ui.ComplexPanel;
- import com.google.gwt.user.client.ui.Widget;
- import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
- import com.itmill.toolkit.terminal.gwt.client.Caption;
- import com.itmill.toolkit.terminal.gwt.client.CaptionWrapper;
- import com.itmill.toolkit.terminal.gwt.client.Layout;
- import com.itmill.toolkit.terminal.gwt.client.Paintable;
- import com.itmill.toolkit.terminal.gwt.client.UIDL;
-
- /**
- * Custom Layout implements complext layouting defined with HTML template.
- *
- * @author IT Mill
- *
- */
- public class ICustomLayout extends ComplexPanel implements Paintable, Layout {
-
- /** 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 currentStyle;
-
- /** 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());
- }
-
- /**
- * 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) {
- 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);
-
- // 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();
-
- // Update HTML template if needed
- updateHTML(uidl, client);
-
- // 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
- }
- }
- }
- }
-
- /** Update implementing HTML-layout if needed. */
- private void updateHTML(UIDL uidl, ApplicationConnection client) {
-
- // Update only if style has changed
- String newStyle = uidl.getStringAttribute("style");
- if (currentStyle != null && currentStyle.equals(newStyle))
- return;
-
- // Get the HTML-template from client
- String template = client.getResource("layout/" + newStyle + ".html");
- if (template == null) {
- template = "Layout file layout/" + newStyle + ".html is missing.";
- } else {
- currentStyle = newStyle;
- }
-
- // 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 IWindow))
- parent = parent.getParent();
- if (parent != null && ((IWindow) parent).getTheme() != null)
- ;
- prefixImgSrcs(getElement(), "../theme/" + ((IWindow) parent).getTheme()
- + "/layout/");
- }
-
- /** 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");
- }-*/;
-
- /** Scripts are evaluated when the document has been rendered */
- protected void onLoad() {
- super.onLoad();
- // Evaluate scripts only once
- if (scripts != null) {
- eval(scripts);
- scripts = null;
- }
- }
-
- /** Evaluate given script in browser document */
- private static native void eval(String script) /*-{
- try {
- 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);}
- }-*/;
-
- /**
- * Exctract 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(Widget component, UIDL uidl) {
- CaptionWrapper wrapper = (CaptionWrapper) widgetToCaptionWrapper.get(component);
- if (Caption.isNeeded(uidl)) {
- if (wrapper == null) {
- String loc = getLocation(component);
- super.remove(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(component);
- super.remove(wrapper);
- super.add(wrapper.getWidget(), (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
- return super.remove(w);
- }
-
- /** 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();
- }
- }
|