import java.util.Iterator;
import java.util.Vector;
-import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.HasFocus;
import com.google.gwt.user.client.ui.HasWidgets;
-import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.itmill.toolkit.terminal.gwt.client.ui.ContextMenu;
import com.itmill.toolkit.terminal.gwt.client.ui.IView;
private ContextMenu contextMenu = null;
- private IView view = new IView();
+ private IView view;
public ApplicationConnection(WidgetSet widgetSet) {
this.widgetSet = widgetSet;
}
makeUidlRequest("repaintAll=1");
-
+
// TODO remove hardcoded id name
- RootPanel.get("itmtk-ajax-window").add(view);
+ view = new IView("itmtk-ajax-window");
+
}
public static Console getConsole() {
--- /dev/null
+package com.itmill.toolkit.terminal.gwt.client;
+
+/**
+ * ContainerResizedListener interface is useful for Widgets that support
+ * relative sizes and who need some additional sizing logic.
+ */
+public interface ContainerResizedListener {
+ /**
+ * This function is run when container box has been resized. Object
+ * implementing ContainerResizedListener is responsible to call the same
+ * function on its ancestors that implement NeedsLayout in case their
+ * container has resized. runAnchestorsLayout(HasWidgets parent) function
+ * from Util class may be a good helper for this.
+ */
+ public void iLayout();
+}
import com.itmill.toolkit.terminal.gwt.client.ui.ICustomLayout;
import com.itmill.toolkit.terminal.gwt.client.ui.IDateFieldCalendar;
import com.itmill.toolkit.terminal.gwt.client.ui.IEmbedded;
+import com.itmill.toolkit.terminal.gwt.client.ui.IExpandLayout;
import com.itmill.toolkit.terminal.gwt.client.ui.IFilterSelect;
import com.itmill.toolkit.terminal.gwt.client.ui.IForm;
import com.itmill.toolkit.terminal.gwt.client.ui.IFormLayout;
import com.itmill.toolkit.terminal.gwt.client.ui.ITwinColSelect;
import com.itmill.toolkit.terminal.gwt.client.ui.IUnknownComponent;
import com.itmill.toolkit.terminal.gwt.client.ui.IUpload;
-import com.itmill.toolkit.terminal.gwt.client.ui.IView;
import com.itmill.toolkit.terminal.gwt.client.ui.IWindow;
public class DefaultWidgetSet implements WidgetSet {
} else if ("com.itmill.toolkit.terminal.gwt.client.ui.IButton"
.equals(className)) {
return new IButton();
- } else if ("com.itmill.toolkit.terminal.gwt.client.ui.IView"
- .equals(className)) {
- // TODO remove IView?
- return new IView();
} else if ("com.itmill.toolkit.terminal.gwt.client.ui.IWindow"
.equals(className)) {
return new IWindow();
} else if ("com.itmill.toolkit.terminal.gwt.client.ui.IProgressIndicator"
.equals(className)) {
return new IProgressIndicator();
+ } else if ("com.itmill.toolkit.terminal.gwt.client.ui.IExpandLayout"
+ .equals(className)) {
+ return new IExpandLayout();
}
return new IUnknownComponent();
return "com.itmill.toolkit.terminal.gwt.client.ui.ISplitPanelVertical";
} else if ("progressindicator".equals(tag)) {
return "com.itmill.toolkit.terminal.gwt.client.ui.IProgressIndicator";
+ } else if ("expandlayout".equals(tag)) {
+ return "com.itmill.toolkit.terminal.gwt.client.ui.IExpandLayout";
}
return "com.itmill.toolkit.terminal.gwt.client.ui.IUnknownComponent";
package com.itmill.toolkit.terminal.gwt.client;
+import java.util.Iterator;
+
import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.HasWidgets;
+import com.google.gwt.user.client.ui.Widget;
public class Util {
el.oncontextmenu = null;
}-*/;
+ /**
+ * Traverses recursively ancestors until ContainerResizedListener child widget is found.
+ * They will delegate it futher if needed.
+ * @param container
+ */
+ public static void runAnchestorsLayout(HasWidgets container) {
+ Iterator childWidgets = container.iterator();
+ while (childWidgets.hasNext()) {
+ Widget child = (Widget) childWidgets.next();
+ if (child instanceof ContainerResizedListener) {
+ ((ContainerResizedListener) child).iLayout();
+ } else if (child instanceof HasWidgets) {
+ HasWidgets childContainer = (HasWidgets) child;
+ runAnchestorsLayout(childContainer);
+ }
+ }
+ }
}
--- /dev/null
+package com.itmill.toolkit.terminal.gwt.client.ui;
+
+import java.util.ArrayList;
+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.Widget;
+import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
+import com.itmill.toolkit.terminal.gwt.client.ContainerResizedListener;
+import com.itmill.toolkit.terminal.gwt.client.Paintable;
+import com.itmill.toolkit.terminal.gwt.client.UIDL;
+import com.itmill.toolkit.terminal.gwt.client.Util;
+
+/**
+ * TODO make this work horizontally
+ *
+ * @author IT Mill Ltd
+ */
+public class IExpandLayout extends IOrderedLayout implements ContainerResizedListener {
+
+ private Widget expandedWidget;
+ private UIDL expandedWidgetUidl;
+
+ public IExpandLayout() {
+ super(IOrderedLayout.ORIENTATION_VERTICAL);
+ }
+
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ this.client = client;
+
+ // Ensure correct implementation
+ if (client.updateComponent(this, uidl, false))
+ return;
+
+ String h = uidl.getStringAttribute("height");
+ setHeight(h);
+ String w = uidl.getStringAttribute("width");
+ setWidth(w);
+
+ ArrayList uidlWidgets = new ArrayList();
+ for (Iterator it = uidl.getChildIterator(); it.hasNext();) {
+ UIDL cellUidl = (UIDL) it.next();
+ Widget child = client.getWidget(cellUidl.getChildUIDL(0));
+ uidlWidgets.add(child);
+ if (cellUidl.hasAttribute("expanded")) {
+ expandedWidget = child;
+ expandedWidgetUidl = cellUidl.getChildUIDL(0);
+ }
+ }
+
+ 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()).getChildUIDL(0);
+ 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);
+ }
+ if (child != expandedWidget)
+ ((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);
+ }
+
+ iLayout();
+
+ /*
+ * Expanded widget is updated after layout function so it has its
+ * container fixed at the moment of updateFromUIDL.
+ */
+ ((Paintable) expandedWidget).updateFromUIDL(expandedWidgetUidl, client);
+
+ }
+
+ public void iLayout() {
+// ApplicationConnection.getConsole().log("EL layouting...");
+ Element expandedElement = DOM.getParent(expandedWidget.getElement());
+ String origDisplay = DOM.getStyleAttribute(expandedElement, "display");
+ DOM.setStyleAttribute(expandedElement, "display", "none");
+
+ // add temp element to make some measurements
+ Element meter = createWidgetWrappper();
+ DOM.setStyleAttribute(meter, "overflow", "hidden");
+ DOM.setStyleAttribute(meter, "height", "1px");
+ DOM.appendChild(childContainer, meter);
+ int usedSpace = DOM.getElementPropertyInt(meter, "offsetTop")
+ - DOM.getElementPropertyInt(DOM.getFirstChild(childContainer),
+ "offsetTop");
+// ApplicationConnection.getConsole().log("EL h" + getOffsetHeight());
+// ApplicationConnection.getConsole().log("EL h" + getOffsetHeight());
+ int freeSpace = getOffsetHeight() - usedSpace;
+
+ DOM.setStyleAttribute(expandedElement,
+ "height", freeSpace + "px");
+
+ DOM.setStyleAttribute(expandedElement, "display", origDisplay);
+
+ DOM.removeChild(childContainer, meter);
+
+ // TODO save previous size and only propagate if really changed
+ Util.runAnchestorsLayout(this);
+ }
+
+}
int orientationMode = ORIENTATION_VERTICAL;
- private HashMap componentToCaption = new HashMap();
+ protected HashMap componentToCaption = new HashMap();
- private ApplicationConnection client;
+ protected ApplicationConnection client;
/**
* Contains reference to Element where Paintables are wrapped. For horizontal
* layout this is TR and for vertical DIV.
*/
- private Element childContainer;
+ protected Element childContainer;
public IOrderedLayout(int orientation) {
orientationMode = orientation;
setStyleName(CLASSNAME);
}
- private void constructDOM() {
+ protected void constructDOM() {
switch (orientationMode) {
case ORIENTATION_HORIZONTAL:
Element table = DOM.createTable();
*
* @return list of Paintable objects
*/
- private ArrayList getPaintables() {
+ protected ArrayList getPaintables() {
ArrayList al = new ArrayList();
Iterator it = iterator();
while (it.hasNext()) {
}
}
- private void insert(Widget w, int beforeIndex) {
+ protected void insert(Widget w, int beforeIndex) {
if (w instanceof Caption) {
Caption c = (Caption) w;
// captions go into same container element as their
/**
* creates an Element which will contain child widget
*/
- private Element createWidgetWrappper() {
+ protected Element createWidgetWrappper() {
switch (orientationMode) {
case ORIENTATION_HORIZONTAL:
return DOM.createTD();
package com.itmill.toolkit.terminal.gwt.client.ui;
-import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.HorizontalSplitPanel;
-import com.google.gwt.user.client.ui.HorizontalSplitPanelImages;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.google.gwt.user.client.ui.VerticalSplitPanel;
-import com.google.gwt.user.client.ui.VerticalSplitPanelImages;
+import com.google.gwt.user.client.Event;
+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.ContainerResizedListener;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
+import com.itmill.toolkit.terminal.gwt.client.Util;
-public class ISplitPanel extends SimplePanel implements Paintable {
+public class ISplitPanel extends ComplexPanel implements Paintable, ContainerResizedListener {
public static final String CLASSNAME = "i-splitpanel";
+
public static final int ORIENTATION_HORIZONTAL = 0;
public static final int ORIENTATION_VERTICAL = 1;
-
+
+ private static final int SPLITTER_SIZE = 8;
+
private int orientation;
- private HorizontalSplitPanel sph;
- private VerticalSplitPanel spv;
private Widget firstChild;
private Widget secondChild;
-
+
+ private Element wrapper = DOM.createDiv();
+ private Element firstContainer = DOM.createDiv();
+ private Element secondContainer = DOM.createDiv();
+ private Element splitter = DOM.createDiv();
+
+ private boolean resizing;
+
+ private int origX;
+
+ private int origY;
+
+ private int origMouseX;
+
+ private int origMouseY;
+
public ISplitPanel() {
this(ORIENTATION_HORIZONTAL);
}
-
+
public ISplitPanel(int orientation) {
- super();
+ setElement(DOM.createDiv());
+ setStyleName(CLASSNAME);
+ constructDom();
setOrientation(orientation);
+ setSplitPosition("50%");
+ DOM.sinkEvents(splitter, Event.MOUSEEVENTS);
+ }
+
+ protected void constructDom() {
+ DOM.appendChild(getElement(), wrapper);
+ DOM.setStyleAttribute(wrapper, "position", "relative");
+ DOM.setStyleAttribute(wrapper, "width", "100%");
+ DOM.setStyleAttribute(wrapper, "height", "100%");
+
+ DOM.appendChild(wrapper, splitter);
+ DOM.appendChild(wrapper, secondContainer);
+ DOM.appendChild(wrapper, firstContainer);
+
+ DOM.setStyleAttribute(splitter, "position", "absolute");
+ DOM.setStyleAttribute(secondContainer, "position", "absolute");
+ DOM.setElementProperty(splitter, "className", "splitter");
+ DOM.setStyleAttribute(splitter, "background", "cyan");
+
+ DOM.setStyleAttribute(firstContainer, "overflow", "hidden");
+ DOM.setStyleAttribute(secondContainer, "overflow", "hidden");
+
}
-
+
private void setOrientation(int orientation) {
this.orientation = orientation;
- if(orientation == ORIENTATION_HORIZONTAL) {
- this.sph = new HorizontalSplitPanel((HorizontalSplitPanelImages) GWT.create(com.itmill.toolkit.terminal.gwt.client.ui.HorizontalSplitPanelImages.class));
- this.sph.setStyleName(CLASSNAME+"-horizontal");
- // Ugly work-around to allow more advanced styling (GWT's heavy use of TABLE-elements is restricting)
- Element handle = DOM.getChild(DOM.getChild(this.sph.getElement(), 0), 1);
- DOM.setElementAttribute(handle, "className", CLASSNAME+"-handle");
- this.setWidget(sph);
- if(spv != null) {
- // TODO cleanup contained widgets
- this.spv = null;
- }
+ if (orientation == ORIENTATION_HORIZONTAL) {
+ DOM.setStyleAttribute(splitter, "height", "100%");
+ DOM.setStyleAttribute(splitter, "width", SPLITTER_SIZE + "px");
+ DOM.setStyleAttribute(firstContainer, "height", "100%");
+ DOM.setStyleAttribute(secondContainer, "height", "100%");
} else {
- this.spv = new VerticalSplitPanel((VerticalSplitPanelImages) GWT.create(com.itmill.toolkit.terminal.gwt.client.ui.VerticalSplitPanelImages.class));
- this.spv.setStyleName(CLASSNAME+"-vertical");
- // Ugly work-around to allow more advanced styling (GWT's heavy use of TABLE-elements is restricting)
- Element handle = DOM.getChild(DOM.getChild(this.spv.getElement(), 0), 1);
- DOM.setElementAttribute(handle, "className", CLASSNAME+"-handle");
- this.setWidget(spv);
- if(sph != null) {
- // TODO cleanup contained widgets
- this.sph = null;
- }
+ DOM.setStyleAttribute(splitter, "width", "100%");
+ DOM.setStyleAttribute(splitter, "height", SPLITTER_SIZE + "px");
+ DOM.setStyleAttribute(firstContainer, "width", "100%");
+ DOM.setStyleAttribute(secondContainer, "width", "100%");
}
}
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
client.updateComponent(this, uidl, true);
-
- setSplitPosition(uidl.getStringAttribute("position"));
-
+
setWidth(uidl.getStringAttribute("width"));
setHeight(uidl.getStringAttribute("height"));
-
-
- Paintable newFirstChild = (Paintable) client.getWidget(uidl.getChildUIDL(0));
- Paintable newSecondChild = (Paintable) client.getWidget(uidl.getChildUIDL(1));
- if(firstChild != newFirstChild) {
- if(firstChild != null)
+
+ setSplitPosition(uidl.getStringAttribute("position"));
+
+ Paintable newFirstChild = (Paintable) client.getWidget(uidl
+ .getChildUIDL(0));
+ Paintable newSecondChild = (Paintable) client.getWidget(uidl
+ .getChildUIDL(1));
+ if (firstChild != newFirstChild) {
+ if (firstChild != null)
client.unregisterPaintable((Paintable) firstChild);
setFirstWidget((Widget) newFirstChild);
}
- if(secondChild != newSecondChild) {
- if(secondChild != null)
+ if (secondChild != newSecondChild) {
+ if (secondChild != null)
client.unregisterPaintable((Paintable) secondChild);
setSecondWidget((Widget) newSecondChild);
}
newFirstChild.updateFromUIDL(uidl.getChildUIDL(0), client);
newSecondChild.updateFromUIDL(uidl.getChildUIDL(1), client);
}
-
+
private void setSplitPosition(String pos) {
- if(orientation == ORIENTATION_HORIZONTAL) {
- this.sph.setSplitPosition(pos);
+ if (orientation == ORIENTATION_HORIZONTAL) {
+ DOM.setStyleAttribute(splitter, "left", pos);
} else {
- this.spv.setSplitPosition(pos);
+ DOM.setStyleAttribute(splitter, "top", pos);
}
+ iLayout();
+ }
+
+ /*
+ * Calculates absolutely positioned container places/sizes (non-Javadoc)
+ *
+ * @see com.itmill.toolkit.terminal.gwt.client.NeedsLayout#layout()
+ */
+ public void iLayout() {
+ int wholeSize;
+ int pixelPosition;
+ switch (orientation) {
+ case ORIENTATION_HORIZONTAL:
+ wholeSize = DOM.getElementPropertyInt(wrapper, "clientWidth");
+ pixelPosition = DOM.getElementPropertyInt(splitter, "offsetLeft");
+
+ DOM
+ .setStyleAttribute(firstContainer, "width", pixelPosition
+ + "px");
+ DOM.setStyleAttribute(secondContainer, "width", (wholeSize
+ - pixelPosition - SPLITTER_SIZE)
+ + "px");
+ DOM.setStyleAttribute(secondContainer, "left",
+ (pixelPosition + SPLITTER_SIZE) + "px");
+
+ break;
+ case ORIENTATION_VERTICAL:
+ wholeSize = DOM.getElementPropertyInt(wrapper, "clientHeight");
+ pixelPosition = DOM.getElementPropertyInt(splitter, "offsetTop");
+
+ DOM.setStyleAttribute(firstContainer, "height", pixelPosition
+ + "px");
+ DOM.setStyleAttribute(secondContainer, "height", (wholeSize
+ - pixelPosition - SPLITTER_SIZE)
+ + "px");
+ DOM.setStyleAttribute(secondContainer, "top",
+ (pixelPosition + SPLITTER_SIZE) + "px");
+
+ default:
+
+ break;
+ }
+
+ Util.runAnchestorsLayout(this);
}
private void setFirstWidget(Widget w) {
- firstChild = w;
- if(orientation == ORIENTATION_HORIZONTAL) {
- this.sph.setLeftWidget(w);
- } else {
- this.spv.setTopWidget(w);
+ if (firstChild != null) {
+ firstChild.removeFromParent();
}
+ super.add(w, firstContainer);
+ firstChild = w;
}
-
+
private void setSecondWidget(Widget w) {
- secondChild = w;
- if(orientation == ORIENTATION_HORIZONTAL) {
- this.sph.setRightWidget(w);
- } else {
- this.spv.setBottomWidget(w);
+ if (secondChild != null) {
+ secondChild.removeFromParent();
}
+ super.add(w, secondContainer);
+ secondChild = w;
}
public void setHeight(String height) {
super.setHeight(height);
- if(orientation == ORIENTATION_HORIZONTAL) {
- sph.setHeight(height);
- } else {
- spv.setHeight(height);
- }
}
public void setWidth(String width) {
super.setWidth(width);
- if(orientation == ORIENTATION_HORIZONTAL) {
- sph.setWidth(width);
- } else {
- spv.setWidth(width);
+ }
+
+ public void onBrowserEvent(Event event) {
+ switch (DOM.eventGetType(event)) {
+ case Event.ONMOUSEMOVE:
+ if (resizing) {
+ onMouseMove(event);
+ }
+ break;
+ case Event.ONMOUSEDOWN:
+ onMouseDown(event);
+ break;
+ case Event.ONMOUSEUP:
+ onMouseUp(event);
+ break;
}
}
-
+
+ public void onMouseDown(Event event) {
+ resizing = true;
+ DOM.setCapture(getElement());
+ origX = DOM.getAbsoluteLeft(splitter);
+ origY = DOM.getAbsoluteTop(splitter);
+ origMouseX = DOM.eventGetClientX(event);
+ origMouseY = DOM.eventGetClientY(event);
+ DOM.eventCancelBubble(event, true);
+ DOM.eventPreventDefault(event);
+ }
+
+ public void onMouseEnter(Widget sender) {
+ }
+
+ public void onMouseLeave(Widget sender) {
+ }
+
+ public void onMouseMove(Event event) {
+ switch (orientation) {
+ case ORIENTATION_HORIZONTAL:
+ int x = DOM.eventGetClientX(event);
+ onHorizontalMouseMove(x);
+ break;
+ case ORIENTATION_VERTICAL:
+ default:
+ int y = DOM.eventGetClientY(event);
+ onVerticalMouseMove(y);
+ break;
+ }
+ iLayout();
+ }
+
+ private void onHorizontalMouseMove(int x) {
+ int newX = origX + x - origMouseX;
+ if (newX < 0)
+ newX = 0;
+ if (newX + SPLITTER_SIZE > getOffsetWidth())
+ newX = getOffsetWidth() - SPLITTER_SIZE;
+ DOM.setStyleAttribute(splitter, "left", newX + "px");
+ }
+
+ private void onVerticalMouseMove(int y) {
+ int newY = origY + y - origMouseY;
+ if (newY < 0)
+ newY = 0;
+
+ if (newY + SPLITTER_SIZE > getOffsetHeight())
+ newY = getOffsetHeight() - SPLITTER_SIZE;
+ DOM.setStyleAttribute(splitter, "top", newY + "px");
+ }
+
+ public void onMouseUp(Event event) {
+ onMouseMove(event);
+ resizing = false;
+ DOM.releaseCapture(getElement());
+ }
+
}
import com.itmill.toolkit.terminal.gwt.client.Util;
/**
- * TODO dump GWT's Tree implementation and use Toolkit 4 style
- * TODO update node close/opens to server (even if no content fetch is needed)
+ * TODO dump GWT's Tree implementation and use Toolkit 4 style TODO update node
+ * close/opens to server (even if no content fetch is needed)
*
* DOM structure
- *
+ *
*/
public class ITree extends Tree implements Paintable {
-
+
public static final String CLASSNAME = "i-tree";
Set selectedIds = new HashSet();
String paintableId;
private boolean selectable;
private boolean multiselect;
-
+
private HashMap keyToNode = new HashMap();
-
+
/**
- * This map contains captions and icon urls for
- * actions like:
- * * "33_c" -> "Edit"
- * * "33_i" -> "http://dom.com/edit.png"
+ * This map contains captions and icon urls for actions like: * "33_c" ->
+ * "Edit" * "33_i" -> "http://dom.com/edit.png"
*/
private HashMap actionMap = new HashMap();
private boolean immediate;
-
public ITree() {
super();
setStyleName(CLASSNAME);
}
-
+
private void updateActionMap(UIDL c) {
Iterator it = c.getChildIterator();
- while(it.hasNext()) {
+ while (it.hasNext()) {
UIDL action = (UIDL) it.next();
String key = action.getStringAttribute("key");
String caption = action.getStringAttribute("caption");
actionMap.put(key + "_c", caption);
- if(action.hasAttribute("icon")) {
+ if (action.hasAttribute("icon")) {
// TODO need some uri handling ??
actionMap.put(key + "_i", action.getStringAttribute("icon"));
}
}
-
+
}
-
+
public String getActionCaption(String actionKey) {
return (String) actionMap.get(actionKey + "_c");
}
-
+
public String getActionIcon(String actionKey) {
return (String) actionMap.get(actionKey + "_i");
}
-
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
// Ensure correct implementation and let container manage caption
if (client.updateComponent(this, uidl, true))
return;
-
+
this.client = client;
-
- if(uidl.hasAttribute("partialUpdate")) {
+
+ if (uidl.hasAttribute("partialUpdate")) {
handleUpdate(uidl);
return;
}
-
+
this.paintableId = uidl.getId();
-
+
this.immediate = uidl.hasAttribute("immediate");
-
+
clear();
for (Iterator i = uidl.getChildIterator(); i.hasNext();) {
- UIDL childUidl = (UIDL)i.next();
- if("actions".equals(childUidl.getTag())){
+ UIDL childUidl = (UIDL) i.next();
+ if ("actions".equals(childUidl.getTag())) {
updateActionMap(childUidl);
continue;
}
String selectMode = uidl.getStringAttribute("selectmode");
selectable = selectMode != null;
multiselect = "multi".equals(selectMode);
-
+
addTreeListener(new TreeListener() {
-
+
public void onTreeItemStateChanged(TreeItem item) {
if (item instanceof TreeNode) {
TreeNode tn = (TreeNode) item;
- if(item.getState()) {
- if(!tn.isChildrenLoaded()) {
+ if (item.getState()) {
+ if (!tn.isChildrenLoaded()) {
String key = tn.key;
- ITree.this.client.updateVariable(paintableId, "expand", new String[] {key}, true);
+ ITree.this.client.updateVariable(paintableId,
+ "expand", new String[] { key }, true);
}
} else {
// TODO collapse
}
}
}
-
+
public void onTreeItemSelected(TreeItem item) {
TreeNode n = ((TreeNode) item);
- if (!selectable) return;
+ if (!selectable)
+ return;
String key = n.key;
if (key != null) {
- if(selectedIds.contains(key) && multiselect) {
+ if (selectedIds.contains(key) && multiselect) {
selectedIds.remove(key);
n.setISelected(false);
} else {
selectedIds.add(key);
n.setISelected(true);
}
- ITree.this.client.updateVariable(ITree.this.paintableId, "selected", selectedIds.toArray(), immediate);
+ ITree.this.client.updateVariable(ITree.this.paintableId,
+ "selected", selectedIds.toArray(), immediate);
}
}
-
+
});
-
+
selectedIds = uidl.getStringArrayVariableAsSet("selected");
-
+
}
-
+
private void handleUpdate(UIDL uidl) {
- TreeNode rootNode = (TreeNode) keyToNode.get(uidl.getStringAttribute("rootKey"));
- if(rootNode != null) {
+ TreeNode rootNode = (TreeNode) keyToNode.get(uidl
+ .getStringAttribute("rootKey"));
+ if (rootNode != null) {
rootNode.renderChildNodes(uidl.getChildIterator());
}
-
+
}
private class TreeNode extends TreeItem implements ActionOwner {
-
+
String key;
-
+
boolean isLeaf = false;
-
+
private String[] actionKeys = null;
private boolean childrenLoaded;
-
+
public TreeNode() {
super();
attachContextMenuEvent(getElement());
}
-
+
public void remove() {
Util.removeContextMenuEvent(getElement());
super.remove();
}
public void setSelected(boolean selected) {
- if(!selected && !ITree.this.multiselect) {
+ if (!selected && !ITree.this.multiselect) {
this.setISelected(false);
}
super.setSelected(selected);
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
this.setText(uidl.getStringAttribute("caption"));
key = uidl.getStringAttribute("key");
-
+
keyToNode.put(key, this);
-
- if(uidl.hasAttribute("al"))
+
+ if (uidl.hasAttribute("al"))
actionKeys = uidl.getStringArrayAttribute("al");
-
- if(uidl.getTag().equals("node")) {
+
+ if (uidl.getTag().equals("node")) {
isLeaf = false;
- if(uidl.getChidlCount() == 0) {
+ if (uidl.getChidlCount() == 0) {
TreeNode childTree = new TreeNode();
childTree.setText("Loading...");
childrenLoaded = false;
} else {
isLeaf = true;
}
-
- if(uidl.getBooleanAttribute("expanded") && !getState()) {
+
+ if (uidl.getBooleanAttribute("expanded") && !getState()) {
setState(true);
}
-
+
setSelected(uidl.getBooleanAttribute("selected"));
-
+
}
-
+
private void renderChildNodes(Iterator i) {
removeItems();
while (i.hasNext()) {
- UIDL childUidl = (UIDL)i.next();
- if("actions".equals(childUidl.getTag())) {
+ UIDL childUidl = (UIDL) i.next();
+ if ("actions".equals(childUidl.getTag())) {
updateActionMap(childUidl);
continue;
}
}
childrenLoaded = true;
}
-
+
public boolean isChildrenLoaded() {
return childrenLoaded;
}
public Action[] getActions() {
- if(actionKeys == null)
+ if (actionKeys == null)
return new Action[] {};
Action[] actions = new Action[actionKeys.length];
for (int i = 0; i < actions.length; i++) {
String actionKey = actionKeys[i];
- TreeAction a = new TreeAction(this, String.valueOf(key), actionKey);
+ TreeAction a = new TreeAction(this, String.valueOf(key),
+ actionKey);
a.setCaption(getActionCaption(actionKey));
a.setIconUrl(getActionIcon(actionKey));
actions[i] = a;
public String getPaintableId() {
return paintableId;
}
-
+
/**
- * Adds/removes IT Mill Toolkit spesific style name.
- * (GWT treenode does not support multiselects)
+ * Adds/removes IT Mill Toolkit spesific style name. (GWT treenode does
+ * not support multiselects)
*
* @param selected
*/
public void setISelected(boolean selected) {
setStyleName(getElement(), "i-tree-node-selected", selected);
}
-
+
public void showContextMenu(Event event) {
- if(actionKeys != null) {
+ if (actionKeys != null) {
int left = DOM.eventGetClientX(event);
int top = DOM.eventGetClientY(event);
top += Window.getScrollTop();
}
DOM.eventCancelBubble(event, true);
}
-
- private native void attachContextMenuEvent(Element el) /*-{
+
+ private native void attachContextMenuEvent(Element el)
+ /*-{
var node = this;
el.oncontextmenu = function(e) {
if(!e)
return false;
};
}-*/;
-
+
}
}
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.WindowResizeListener;
import com.google.gwt.user.client.ui.KeyboardListenerCollection;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
+import com.itmill.toolkit.terminal.gwt.client.Util;
/**
*
*/
-public class IView extends SimplePanel implements Paintable {
+public class IView extends SimplePanel implements Paintable, WindowResizeListener {
+ private static final String CLASSNAME = "i-view";
+
private String theme;
private Paintable layout;
private ShortcutActionHandler actionHandler;
- public IView() {
+ public IView(String elementId) {
super();
+ setStyleName(CLASSNAME);
DOM.sinkEvents(getElement(), Event.ONKEYDOWN);
+
+ RootPanel.get(elementId).add(this);
+
+ Window.addWindowResizeListener(this);
}
public String getTheme() {
}
}
+ public void onWindowResized(int width, int height) {
+ Util.runAnchestorsLayout(this);
+ }
+
}
+html, body {
+ margin:0;
+ padding:0;
+ height:100%;
+}
+
#itmtk-ajax-window {\r
background: #e9eced;\r
font-family: "Trebuchet MS", geneva, helvetica, arial, tahoma, verdana, sans-serif;\r
color: #464f52;\r
font-size: 12px;\r
line-height: 18px;\r
+ height:100%;
+}
+
+.i-view {
+ height:100%;
}\r
\r
input, select, textarea, button {\r
@import "splitpanel/splitpanel.css";\r
@import "select/filterselect.css";\r
@import "progressindicator/progressindicator.css";
-\r
+@import "expandlayout/expandlayout.css";\r
--- /dev/null
+package com.itmill.toolkit.tests;
+
+import com.itmill.toolkit.Application;
+import com.itmill.toolkit.ui.*;
+
+public class TestForApplicationLayoutThatUsesWholeBrosersSpace extends
+ Application {
+
+ Window main = new Window("Windowing test");
+
+ ExpandLayout rootLayout;
+
+ SplitPanel firstLevelSplit;
+
+ public void init() {
+ setMainWindow(main);
+
+ rootLayout = new ExpandLayout();
+ main.setLayout(rootLayout);
+
+ rootLayout.addComponent(new Label("header"));
+
+ firstLevelSplit = new SplitPanel();
+
+ SplitPanel secondSplitPanel = new SplitPanel(
+ SplitPanel.ORIENTATION_HORIZONTAL);
+ secondSplitPanel.setFirstComponent(new Label("left"));
+
+ ExpandLayout topRight = new ExpandLayout();
+ topRight.addComponent(new Label("topright header"));
+
+ Table t = TestForTablesInitialColumnWidthLogicRendering.getTestTable(4, 100);
+ t.setWidth(100);
+ t.setWidthUnits(Table.UNITS_PERCENTAGE);
+ t.setHeight(100);
+ t.setHeightUnits(Table.UNITS_PIXELS);
+ topRight.addComponent(t);
+ topRight.expand(t);
+
+ topRight.addComponent(new Label("topright footer"));
+
+ secondSplitPanel.setSecondComponent(topRight);
+
+
+ ExpandLayout el = new ExpandLayout();
+ el.addComponent(new Label("B\9a\9a"));
+
+ firstLevelSplit.setFirstComponent(secondSplitPanel);
+ firstLevelSplit.setSecondComponent(el);
+
+ rootLayout.addComponent(firstLevelSplit);
+ rootLayout.expand(firstLevelSplit);
+
+ rootLayout.addComponent(new Label("footer"));
+
+ }
+
+}
}
- public Table getTestTable(int cols, int rows) {
+ public static Table getTestTable(int cols, int rows) {
Table t = new Table();
t.setColumnCollapsingAllowed(true);
for(int i = 0; i < cols; i++) {
--- /dev/null
+package com.itmill.toolkit.ui;
+
+import java.util.Iterator;
+
+import com.itmill.toolkit.terminal.PaintException;
+import com.itmill.toolkit.terminal.PaintTarget;
+import com.itmill.toolkit.terminal.Sizeable;
+
+/**
+ * TODO finish documentation
+ *
+ * our layouts (except custom layout of course) don't currently work at all with
+ * relative widths. This layout tries to cope with this issue.
+ *
+ * basically this is ordered layout which has Sizeable interface 100 % height &
+ * width by default
+ *
+ * all contained components may also have Sizeable interfaces sizes
+ *
+ * can be used to build flexible layout where some component gets all the space
+ * other components don't use. Or just provide expanded container.
+ *
+ */
+public class ExpandLayout extends OrderedLayout implements Sizeable {
+
+ private int height = 100;
+
+ private int width = 100;
+
+ private int widthUnit = UNITS_PERCENTAGE;
+
+ private int heightUnit = UNITS_PERCENTAGE;
+
+ private Component expanded;
+
+ public ExpandLayout() {
+
+ }
+
+ /**
+ * @param c
+ * Component which container will be maximized
+ */
+ public void expand(Component c) {
+ this.expanded = c;
+ requestRepaint();
+ }
+
+ public String getTag() {
+ return "expandlayout";
+ }
+
+ public void paintContent(PaintTarget target) throws PaintException {
+ // Size
+ if (getHeight() >= 0)
+ target.addAttribute("height", "" + getHeight()
+ + Sizeable.UNIT_SYMBOLS[getHeightUnits()]);
+ if (getWidth() >= 0)
+ target.addAttribute("width", "" + getWidth()
+ + Sizeable.UNIT_SYMBOLS[getWidthUnits()]);
+
+ // Adds the attributes: orientation
+ // note that the default values (b/vertival) are omitted
+ if (getOrientation() == ORIENTATION_HORIZONTAL)
+ target.addAttribute("orientation", "horizontal");
+
+ // Adds all items in all the locations
+ for (Iterator i = getComponentIterator(); i.hasNext();) {
+ Component c = (Component) i.next();
+ if (c != null) {
+ target.startTag("cc");
+ if (c == expanded)
+ target.addAttribute("expanded", true);
+ c.paint(target);
+ target.endTag("cc");
+ }
+ }
+ }
+
+ public void addComponent(Component c, int index) {
+ if (expanded == null) {
+ expanded = c;
+ }
+ super.addComponent(c, index);
+ }
+
+ public void addComponent(Component c) {
+ if (expanded == null) {
+ expanded = c;
+ }
+ super.addComponent(c);
+ }
+
+ public void addComponentAsFirst(Component c) {
+ if (expanded == null) {
+ expanded = c;
+ }
+ super.addComponentAsFirst(c);
+ }
+
+ public void removeComponent(Component c) {
+ super.removeComponent(c);
+ if (c == expanded && this.getComponentIterator().hasNext())
+ expanded = (Component) this.getComponentIterator().next();
+ else
+ expanded = null;
+ }
+
+ public void replaceComponent(Component oldComponent, Component newComponent) {
+ super.replaceComponent(oldComponent, newComponent);
+ if(oldComponent == expanded)
+ expanded = newComponent;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public int getHeightUnits() {
+ return heightUnit;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getWidthUnits() {
+ return widthUnit;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+
+ }
+
+ public void setHeightUnits(int units) {
+ this.heightUnit = units;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ public void setWidthUnits(int units) {
+ this.widthUnit = units;
+ }
+}
}
/**
- * Sets the height units. Panel supports only Sizeable.UNITS_PIXELS and this
- * is ignored.
+ * Sets the height units.
*
* @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int)
*/
}
/**
- * Sets the width units. Panel supports only Sizeable.UNITS_PIXELS, and this
- * is ignored.
+ * Sets the width units.
*
* @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int)
*/
target.addAttribute("width", "100%");
}
if(height > 0) {
- target.addAttribute("height", height + UNIT_SYMBOLS[widthUnit]);
+ target.addAttribute("height", height + UNIT_SYMBOLS[heightUnit]);
} else {
target.addAttribute("height", "100%");
}
}
/**
- * Sets the height units. Table supports only Sizeable.UNITS_PIXELS. Setting
- * to any other throws IllegalArgumentException.
- *
+ * Sets the height units.
+ *
* @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int)
*/
public void setHeightUnits(int units) {
- if (units != Sizeable.UNITS_PIXELS)
- throw new IllegalArgumentException();
this.heightUnit = units;
}