Pārlūkot izejas kodu

ContainerResizedListener, ISplitPanel refactoring, ExpandLayout and test

svn changeset:2441/svn branch:trunk
tags/6.7.0.beta1
Matti Tahvonen pirms 16 gadiem
vecāks
revīzija
31d2e72389

+ 4
- 5
src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java Parādīt failu

@@ -5,7 +5,6 @@ import java.util.HashMap;
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;
@@ -20,7 +19,6 @@ import com.google.gwt.user.client.ui.FocusListener;
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;
@@ -46,7 +44,7 @@ public class ApplicationConnection implements FocusListener {

private ContextMenu contextMenu = null;

private IView view = new IView();
private IView view;

public ApplicationConnection(WidgetSet widgetSet) {
this.widgetSet = widgetSet;
@@ -59,9 +57,10 @@ public class ApplicationConnection implements FocusListener {
}

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() {

+ 16
- 0
src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java Parādīt failu

@@ -0,0 +1,16 @@
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();
}

+ 6
- 5
src/com/itmill/toolkit/terminal/gwt/client/DefaultWidgetSet.java Parādīt failu

@@ -8,6 +8,7 @@ import com.itmill.toolkit.terminal.gwt.client.ui.ICheckBox;
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;
@@ -35,7 +36,6 @@ import com.itmill.toolkit.terminal.gwt.client.ui.ITree;
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 {
@@ -58,10 +58,6 @@ 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();
@@ -155,6 +151,9 @@ public class DefaultWidgetSet implements WidgetSet {
} 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();
@@ -248,6 +247,8 @@ public class DefaultWidgetSet implements WidgetSet {
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";

+ 21
- 0
src/com/itmill/toolkit/terminal/gwt/client/Util.java Parādīt failu

@@ -1,6 +1,10 @@
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 {

@@ -40,4 +44,21 @@ 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);
}
}
}
}

+ 148
- 0
src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java Parādīt failu

@@ -0,0 +1,148 @@
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);
}
}

+ 7
- 7
src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java Parādīt failu

@@ -29,15 +29,15 @@ public abstract class IOrderedLayout extends ComplexPanel implements Container {
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;
@@ -45,7 +45,7 @@ public abstract class IOrderedLayout extends ComplexPanel implements Container {
setStyleName(CLASSNAME);
}
private void constructDOM() {
protected void constructDOM() {
switch (orientationMode) {
case ORIENTATION_HORIZONTAL:
Element table = DOM.createTable();
@@ -139,7 +139,7 @@ public abstract class IOrderedLayout extends ComplexPanel implements Container {
*
* @return list of Paintable objects
*/
private ArrayList getPaintables() {
protected ArrayList getPaintables() {
ArrayList al = new ArrayList();
Iterator it = iterator();
while (it.hasNext()) {
@@ -184,7 +184,7 @@ public abstract class IOrderedLayout extends ComplexPanel implements Container {
}
}

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
@@ -203,7 +203,7 @@ public abstract class IOrderedLayout extends ComplexPanel implements Container {
/**
* creates an Element which will contain child widget
*/
private Element createWidgetWrappper() {
protected Element createWidgetWrappper() {
switch (orientationMode) {
case ORIENTATION_HORIZONTAL:
return DOM.createTD();

+ 203
- 71
src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanel.java Parādīt failu

@@ -1,132 +1,264 @@
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());
}

}

+ 74
- 72
src/com/itmill/toolkit/terminal/gwt/client/ui/ITree.java Parādīt failu

@@ -18,14 +18,14 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL;
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();
@@ -33,69 +33,65 @@ public class ITree extends Tree implements Paintable {
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;
}
@@ -106,29 +102,31 @@ public class ITree extends Tree implements Paintable {
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 {
@@ -138,46 +136,48 @@ public class ITree extends Tree implements Paintable {
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);
@@ -186,15 +186,15 @@ public class ITree extends Tree implements Paintable {
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;
@@ -205,20 +205,20 @@ public class ITree extends Tree implements Paintable {
} 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;
}
@@ -228,18 +228,19 @@ public class ITree extends Tree implements Paintable {
}
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;
@@ -254,19 +255,19 @@ public class ITree extends Tree implements Paintable {
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();
@@ -275,8 +276,9 @@ public class ITree extends Tree implements Paintable {
}
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)
@@ -285,6 +287,6 @@ public class ITree extends Tree implements Paintable {
return false;
};
}-*/;
}
}

+ 15
- 2
src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java Parādīt failu

@@ -6,6 +6,7 @@ import java.util.Iterator;
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;
@@ -13,12 +14,15 @@ import com.google.gwt.user.client.ui.Widget;
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;
@@ -29,9 +33,14 @@ public class IView extends SimplePanel implements Paintable {

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() {
@@ -118,5 +127,9 @@ public class IView extends SimplePanel implements Paintable {
}
}

public void onWindowResized(int width, int height) {
Util.runAnchestorsLayout(this);
}

}


+ 11
- 0
src/com/itmill/toolkit/terminal/gwt/public/default/common/common.css Parādīt failu

@@ -1,9 +1,20 @@
html, body {
margin:0;
padding:0;
height:100%;
}

#itmtk-ajax-window {
background: #e9eced;
font-family: "Trebuchet MS", geneva, helvetica, arial, tahoma, verdana, sans-serif;
color: #464f52;
font-size: 12px;
line-height: 18px;
height:100%;
}

.i-view {
height:100%;
}
input, select, textarea, button {

+ 0
- 0
src/com/itmill/toolkit/terminal/gwt/public/default/expandlayout/expandlayout.css Parādīt failu


+ 1
- 1
src/com/itmill/toolkit/terminal/gwt/public/default/styles.css Parādīt failu

@@ -13,4 +13,4 @@
@import "splitpanel/splitpanel.css";
@import "select/filterselect.css";
@import "progressindicator/progressindicator.css";
@import "expandlayout/expandlayout.css";

+ 58
- 0
src/com/itmill/toolkit/tests/TestForApplicationLayoutThatUsesWholeBrosersSpace.java Parādīt failu

@@ -0,0 +1,58 @@
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šš"));

firstLevelSplit.setFirstComponent(secondSplitPanel);
firstLevelSplit.setSecondComponent(el);

rootLayout.addComponent(firstLevelSplit);
rootLayout.expand(firstLevelSplit);

rootLayout.addComponent(new Label("footer"));

}

}

+ 1
- 1
src/com/itmill/toolkit/tests/TestForTablesInitialColumnWidthLogicRendering.java Parādīt failu

@@ -83,7 +83,7 @@ public class TestForTablesInitialColumnWidthLogicRendering extends CustomCompone

}
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++) {

+ 147
- 0
src/com/itmill/toolkit/ui/ExpandLayout.java Parādīt failu

@@ -0,0 +1,147 @@
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;
}
}

+ 2
- 4
src/com/itmill/toolkit/ui/Panel.java Parādīt failu

@@ -401,8 +401,7 @@ public class Panel extends AbstractComponentContainer implements Sizeable,
}

/**
* 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)
*/
@@ -411,8 +410,7 @@ public class Panel extends AbstractComponentContainer implements Sizeable,
}

/**
* 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)
*/

+ 1
- 1
src/com/itmill/toolkit/ui/SplitPanel.java Parādīt failu

@@ -214,7 +214,7 @@ public class SplitPanel extends AbstractComponentContainer implements Layout, Si
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%");
}

+ 2
- 5
src/com/itmill/toolkit/ui/Table.java Parādīt failu

@@ -2372,14 +2372,11 @@ public class Table extends Select implements Action.Container,
}

/**
* 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;
}


Notiek ielāde…
Atcelt
Saglabāt