svn changeset:5453/svn branch:trunktags/6.7.0.beta1
@@ -6,7 +6,9 @@ package com.itmill.toolkit.terminal.gwt.client; | |||
import java.util.Date; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.Set; | |||
import java.util.Vector; | |||
import com.google.gwt.core.client.GWT; | |||
@@ -503,6 +505,9 @@ public class ApplicationConnection { | |||
// Process changes | |||
final JSONArray changes = (JSONArray) ((JSONObject) json) | |||
.get("changes"); | |||
Set<Widget> sizeUpdatedWidgets = new HashSet<Widget>(); | |||
for (int i = 0; i < changes.size(); i++) { | |||
try { | |||
final UIDL change = new UIDL((JSONArray) changes.get(i)); | |||
@@ -517,7 +522,16 @@ public class ApplicationConnection { | |||
final UIDL uidl = change.getChildUIDL(0); | |||
final Paintable paintable = getPaintable(uidl.getId()); | |||
if (paintable != null) { | |||
Widget widget = (Widget) paintable; | |||
int w = widget.getOffsetWidth(); | |||
int h = widget.getOffsetHeight(); | |||
paintable.updateFromUIDL(uidl, this); | |||
if (w != widget.getOffsetWidth() | |||
|| h != widget.getOffsetHeight()) { | |||
sizeUpdatedWidgets.add((Widget) paintable); | |||
} | |||
} else { | |||
if (!uidl.getTag().equals("window")) { | |||
ClientExceptionHandler | |||
@@ -534,6 +548,8 @@ public class ApplicationConnection { | |||
} | |||
} | |||
Util.componentSizeUpdated(sizeUpdatedWidgets); | |||
if (meta != null) { | |||
if (meta.containsKey("focus")) { | |||
final String focusPid = meta.get("focus").isString() |
@@ -49,4 +49,12 @@ public interface Container extends Paintable { | |||
*/ | |||
void updateCaption(Paintable component, UIDL uidl); | |||
/** | |||
* Called when a child components size has been updated in the rendering | |||
* phase. | |||
* | |||
* @return true if the size of the Container remains the same, false if the | |||
* event need to be propagated to the Containers parent | |||
*/ | |||
boolean childComponentSizesUpdated(); | |||
} |
@@ -21,6 +21,12 @@ public interface ContainerResizedListener { | |||
* these numbers. If the parent container does not know (has not calculated) | |||
* or cannot produce (undefined dimensions) one of these numbers -1 is | |||
* passed. | |||
* | |||
* Note that these numbers should not be considered the maximum size for the | |||
* widget if the layout has undefined dimension. In that case the currently | |||
* allocated space is passed (eg. OrderedLayout with undefined width might | |||
* pass availableWidth 100 if the widest component in the layout is 100 but | |||
* it will still stretch if another 200 pixel wide component is rendered) | |||
*/ | |||
public void iLayout(int availableWidth, int availableHeight); | |||
} |
@@ -4,7 +4,9 @@ | |||
package com.itmill.toolkit.terminal.gwt.client; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.Set; | |||
import com.google.gwt.user.client.DOM; | |||
import com.google.gwt.user.client.Element; | |||
@@ -37,6 +39,43 @@ public class Util { | |||
el.oncontextmenu = null; | |||
}-*/; | |||
/** | |||
* Called when the size of one or more widgets have changed during | |||
* rendering. Finds parent container and notifies them of the size change. | |||
* | |||
* @param widgets | |||
*/ | |||
public static void componentSizeUpdated(Set<Widget> widgets) { | |||
if (widgets.isEmpty()) { | |||
return; | |||
} | |||
Set<Container> parents = new HashSet<Container>(); | |||
for (Widget widget : widgets) { | |||
/* ApplicationConnection.getConsole().log( | |||
"Size changed for widget: " | |||
+ widget.toString().split(">")[0]); | |||
*/ | |||
Widget parent = widget.getParent(); | |||
while (parent != null && !(parent instanceof Container)) { | |||
parent = parent.getParent(); | |||
} | |||
if (parent != null) { | |||
parents.add((Container) parent); | |||
} | |||
} | |||
Set<Widget> parentChanges = new HashSet<Widget>(); | |||
for (Container parent : parents) { | |||
if (!parent.childComponentSizesUpdated()) { | |||
parentChanges.add((Widget) parent); | |||
} | |||
} | |||
componentSizeUpdated(parentChanges); | |||
} | |||
/** | |||
* Traverses recursively ancestors until ContainerResizedListener child | |||
* widget is found. They will delegate it futher if needed. |
@@ -299,4 +299,9 @@ public class IAccordion extends ITabsheetBase implements | |||
} | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} |
@@ -61,4 +61,9 @@ public class ICustomComponent extends SimplePanel implements Container { | |||
// TODO custom component could handle its composition roots caption | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} |
@@ -476,4 +476,10 @@ public class ICustomLayout extends ComplexPanel implements Paintable, | |||
return false; | |||
} | |||
}-*/; | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} |
@@ -768,4 +768,10 @@ public class IExpandLayout extends ComplexPanel implements | |||
} | |||
rendering = false; | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} |
@@ -301,4 +301,10 @@ public class IFormLayout extends FlexTable implements Container { | |||
} | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} |
@@ -286,6 +286,11 @@ public class IGridLayout extends SimplePanel implements Paintable, Container, | |||
wrapper.updateCaption(uidl); | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} | |||
private void iLayout() { | |||
@@ -312,4 +317,9 @@ public class IGridLayout extends SimplePanel implements Paintable, Container, | |||
Util.runDescendentsLayout(this); | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} |
@@ -320,6 +320,10 @@ public class IOrderedLayout extends Panel implements Container, | |||
*/ | |||
private boolean childLayoutsHaveChanged = false; | |||
private int renderedHeight; | |||
private int renderedWidth; | |||
/** | |||
* Construct the DOM of the orderder layout. | |||
* | |||
@@ -535,7 +539,7 @@ public class IOrderedLayout extends Panel implements Container, | |||
handleAlignmentsSpacingAndMargins(uidl); | |||
// Reset sizes for the children | |||
updateChildSizes(); | |||
updateChildSizes(-1, -1); | |||
// Paint children | |||
for (int i = 0; i < childsToPaint.size(); i++) { | |||
@@ -550,6 +554,11 @@ public class IOrderedLayout extends Panel implements Container, | |||
Util.runDescendentsLayout(this); | |||
childLayoutsHaveChanged = false; | |||
} | |||
/* Store the rendered size so we later can see if it has changed */ | |||
renderedWidth = root.getOffsetWidth(); | |||
renderedHeight = root.getOffsetHeight(); | |||
} | |||
private void updateMarginAndSpacingSizesFromCSS(UIDL uidl) { | |||
@@ -657,7 +666,7 @@ public class IOrderedLayout extends Panel implements Container, | |||
} | |||
/** Recalculate and apply the space given for each child in this layout. */ | |||
private void updateChildSizes() { | |||
private void updateChildSizes(int renderedWidth, int renderedHeight) { | |||
int numChild = childWidgets.size(); | |||
int childHeightTotal = -1; | |||
@@ -672,7 +681,7 @@ public class IOrderedLayout extends Panel implements Container, | |||
if (tableMode) { | |||
// If we know explicitly set pixel-size, use that | |||
if (height != null && height.endsWith("px")) { | |||
if (height.endsWith("px")) { | |||
try { | |||
childHeightTotal = Integer.parseInt(height.substring(0, | |||
height.length() - 2)); | |||
@@ -686,9 +695,13 @@ public class IOrderedLayout extends Panel implements Container, | |||
// In case of invalid number, try to measure the size; | |||
childHeightTotal = rootOffsetMeasure("offsetHeight"); | |||
} | |||
} | |||
// If not, try to measure the size | |||
else { | |||
} else if (height.endsWith("%") && renderedHeight >= 0) { | |||
// If we have a relative height and know how large we are we | |||
// can | |||
// simply use that | |||
childWidthTotal = renderedHeight; | |||
} else { | |||
// If not pixels, nor percentage, try to measure the size | |||
childHeightTotal = rootOffsetMeasure("offsetHeight"); | |||
} | |||
@@ -718,7 +731,7 @@ public class IOrderedLayout extends Panel implements Container, | |||
// Calculate the space for fixed contents minus marginals | |||
// If we know explicitly set pixel-size, use that | |||
if (width != null && width.endsWith("px")) { | |||
if (width.endsWith("px")) { | |||
try { | |||
childWidthTotal = Integer.parseInt(width.substring(0, width | |||
.length() - 2)); | |||
@@ -733,9 +746,12 @@ public class IOrderedLayout extends Panel implements Container, | |||
// In case of invalid number, try to measure the size; | |||
childWidthTotal = rootOffsetMeasure("offsetWidth"); | |||
} | |||
} | |||
// If not, try to measure the size | |||
else { | |||
} else if (width.endsWith("%") && renderedWidth >= 0) { | |||
// If we have a relative width and know how large we are we can | |||
// simply use that | |||
childWidthTotal = renderedWidth; | |||
} else { | |||
// If not pixels, nor percentage, try to measure the size | |||
childWidthTotal = rootOffsetMeasure("offsetWidth"); | |||
} | |||
@@ -872,6 +888,8 @@ public class IOrderedLayout extends Panel implements Container, | |||
*/ | |||
int lastForcedPixelWidth = -1; | |||
int horizontalPadding = 0, verticalPadding = 0; | |||
/** Widget Wrapper root element */ | |||
Element wrapperElement; | |||
@@ -1252,31 +1270,72 @@ public class IOrderedLayout extends Panel implements Container, | |||
final Element e = getElementWrappingWidgetAndCaption(); | |||
int paddingLeft = 0, paddingRight = 0, paddingTop = 0, paddingBottom = 0; | |||
if (orientationMode == ORIENTATION_HORIZONTAL) { | |||
DOM.setStyleAttribute(e, "paddingLeft", first ? (margins | |||
.hasLeft() ? marginLeft + "px" : "0") | |||
: (hasComponentSpacing ? hSpacing + "px" : "0")); | |||
DOM.setStyleAttribute(e, "paddingRight", last ? (margins | |||
.hasRight() ? marginRight + "px" : "0") : ""); | |||
DOM.setStyleAttribute(e, "paddingTop", | |||
margins.hasTop() ? marginTop + "px" : ""); | |||
DOM.setStyleAttribute(e, "paddingBottom", | |||
margins.hasBottom() ? marginBottom + "px" : ""); | |||
if (first) { | |||
if (margins.hasLeft()) { | |||
paddingLeft = marginLeft; | |||
} | |||
} else if (hasComponentSpacing) { | |||
paddingLeft = hSpacing; | |||
} | |||
if (last) { | |||
if (margins.hasRight()) { | |||
paddingRight = marginRight; | |||
} | |||
} | |||
if (margins.hasTop()) { | |||
paddingTop = marginTop; | |||
} | |||
if (margins.hasBottom()) { | |||
paddingBottom = marginBottom; | |||
} | |||
} else { | |||
DOM.setStyleAttribute(e, "paddingLeft", | |||
margins.hasLeft() ? marginLeft + "px" : "0"); | |||
DOM.setStyleAttribute(e, "paddingRight", | |||
margins.hasRight() ? marginRight + "px" : "0"); | |||
DOM.setStyleAttribute(e, "paddingTop", first ? (margins | |||
.hasTop() ? marginTop + "px" : "") | |||
: (hasComponentSpacing ? vSpacing + "px" : "0")); | |||
DOM.setStyleAttribute(e, "paddingBottom", last | |||
&& margins.hasBottom() ? marginBottom + "px" : ""); | |||
if (margins.hasLeft()) { | |||
paddingLeft = marginLeft; | |||
} | |||
if (margins.hasRight()) { | |||
paddingRight = marginRight; | |||
} | |||
if (first) { | |||
if (margins.hasTop()) { | |||
paddingTop = marginTop; | |||
} | |||
} else if (hasComponentSpacing) { | |||
paddingTop = vSpacing; | |||
} | |||
if (last && margins.hasBottom()) { | |||
paddingBottom = marginBottom; | |||
} | |||
} | |||
horizontalPadding = paddingLeft + paddingRight; | |||
verticalPadding = paddingTop + paddingBottom; | |||
DOM.setStyleAttribute(e, "paddingLeft", paddingLeft + "px"); | |||
DOM.setStyleAttribute(e, "paddingRight", paddingRight + "px"); | |||
DOM.setStyleAttribute(e, "paddingTop", paddingTop + "px"); | |||
DOM.setStyleAttribute(e, "paddingBottom", paddingBottom + "px"); | |||
} | |||
public int getAllocatedHeight() { | |||
if (lastForcedPixelHeight == -1) { | |||
if (height == null) { | |||
/* | |||
* We have no height specified so return the space allocated | |||
* by components so far | |||
*/ | |||
return getElementWrappingClipperDiv().getOffsetHeight() | |||
- horizontalPadding; | |||
} | |||
return -1; | |||
} | |||
@@ -1289,6 +1348,15 @@ public class IOrderedLayout extends Panel implements Container, | |||
} | |||
public int getAllocatedWidth() { | |||
if (width == null) { | |||
/* | |||
* We have no width specified so return the space allocated by | |||
* components so far | |||
*/ | |||
return getElementWrappingClipperDiv().getOffsetWidth() | |||
- horizontalPadding; | |||
} | |||
return lastForcedPixelWidth; | |||
} | |||
} | |||
@@ -1451,7 +1519,7 @@ public class IOrderedLayout extends Panel implements Container, | |||
/* documented at super */ | |||
public void iLayout(int availableWidth, int availableHeight) { | |||
updateChildSizes(); | |||
updateChildSizes(availableWidth, availableHeight); | |||
Util.runDescendentsLayout(this); | |||
childLayoutsHaveChanged = false; | |||
} | |||
@@ -1475,4 +1543,35 @@ public class IOrderedLayout extends Panel implements Container, | |||
return -1; | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
if (height != null && width != null) { | |||
/* | |||
* If the height and width has been specified for this layout the | |||
* child components cannot make the size of the layout change | |||
*/ | |||
return true; | |||
} | |||
int currentHeight = getElement().getOffsetHeight(); | |||
int currentWidth = getElement().getOffsetWidth(); | |||
if (currentHeight != renderedHeight || currentWidth != renderedWidth) { | |||
/* | |||
* Size has changed so we let the child components know about the | |||
* new size. | |||
*/ | |||
iLayout(-1, -1); | |||
return false; | |||
} else { | |||
/* | |||
* Size has not changed so we do not need to propagate the event | |||
* further | |||
*/ | |||
return true; | |||
} | |||
} | |||
} |
@@ -171,10 +171,10 @@ public class IPopupView extends HTML implements Paintable { | |||
} | |||
public static native void nativeBlur(Element e) /*-{ | |||
if(e.focus) { | |||
e.blur(); | |||
} | |||
}-*/; | |||
if(e.focus) { | |||
e.blur(); | |||
} | |||
}-*/; | |||
private class CustomPopup extends IToolkitOverlay implements Container { | |||
@@ -228,7 +228,7 @@ public class IPopupView extends HTML implements Paintable { | |||
// Notify children that have used the keyboard | |||
for (Iterator<Element> iterator = activeChildren.iterator(); iterator | |||
.hasNext();) { | |||
nativeBlur((Element) iterator.next()); | |||
nativeBlur(iterator.next()); | |||
} | |||
activeChildren.clear(); | |||
remove(popupComponentWidget); | |||
@@ -312,6 +312,11 @@ public class IPopupView extends HTML implements Paintable { | |||
} | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
}// class CustomPopup | |||
}// class IPopupView |
@@ -478,4 +478,9 @@ public class ITabsheet extends ITabsheetBase implements | |||
ICaption c = (ICaption) captions.get("" + i); | |||
c.updateCaption(uidl); | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} |
@@ -249,6 +249,11 @@ public class ISizeableGridLayout extends IAbsoluteGrid implements Paintable, | |||
return marginPixels; | |||
} | |||
public boolean childComponentSizesUpdated() { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} | |||
class MarginPixels { |