svn changeset:2441/svn branch:trunktags/6.7.0.beta1
@@ -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() { |
@@ -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(); | |||
} |
@@ -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"; |
@@ -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); | |||
} | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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(); |
@@ -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()); | |||
} | |||
} |
@@ -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; | |||
}; | |||
}-*/; | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
@@ -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 { |
@@ -13,4 +13,4 @@ | |||
@import "splitpanel/splitpanel.css"; | |||
@import "select/filterselect.css"; | |||
@import "progressindicator/progressindicator.css"; | |||
@import "expandlayout/expandlayout.css"; |
@@ -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")); | |||
} | |||
} |
@@ -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++) { |
@@ -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; | |||
} | |||
} |
@@ -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) | |||
*/ |
@@ -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%"); | |||
} |
@@ -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; | |||
} | |||