import com.google.gwt.user.client.Element; | import com.google.gwt.user.client.Element; | ||||
import com.google.gwt.user.client.Event; | import com.google.gwt.user.client.Event; | ||||
import com.google.gwt.user.client.Timer; | import com.google.gwt.user.client.Timer; | ||||
import com.google.gwt.user.client.Window; | |||||
import com.google.gwt.user.client.ui.FocusWidget; | import com.google.gwt.user.client.ui.FocusWidget; | ||||
import com.google.gwt.user.client.ui.Focusable; | import com.google.gwt.user.client.ui.Focusable; | ||||
import com.google.gwt.user.client.ui.HasWidgets; | import com.google.gwt.user.client.ui.HasWidgets; | ||||
import com.google.gwt.user.client.ui.Widget; | import com.google.gwt.user.client.ui.Widget; | ||||
import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage; | import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage; | ||||
import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; | |||||
import com.vaadin.terminal.gwt.client.RenderInformation.Size; | import com.vaadin.terminal.gwt.client.RenderInformation.Size; | ||||
import com.vaadin.terminal.gwt.client.ui.Field; | import com.vaadin.terminal.gwt.client.ui.Field; | ||||
import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget; | import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget; | ||||
/** redirectTimer scheduling interval in seconds */ | /** redirectTimer scheduling interval in seconds */ | ||||
private int sessionExpirationInterval; | private int sessionExpirationInterval; | ||||
private ArrayList<VPaintableWidget> relativeSizeChanges = new ArrayList<VPaintableWidget>(); | |||||
private ArrayList<Widget> componentCaptionSizeChanges = new ArrayList<Widget>(); | private ArrayList<Widget> componentCaptionSizeChanges = new ArrayList<Widget>(); | ||||
private Date requestStartTime; | private Date requestStartTime; | ||||
JsArray<ValueMap> changes = json.getJSValueMapArray("changes"); | JsArray<ValueMap> changes = json.getJSValueMapArray("changes"); | ||||
ArrayList<VPaintableWidget> updatedVPaintableWidgets = new ArrayList<VPaintableWidget>(); | ArrayList<VPaintableWidget> updatedVPaintableWidgets = new ArrayList<VPaintableWidget>(); | ||||
relativeSizeChanges.clear(); | |||||
componentCaptionSizeChanges.clear(); | componentCaptionSizeChanges.clear(); | ||||
int length = changes.length(); | int length = changes.length(); | ||||
// Check which widgets' size has been updated | // Check which widgets' size has been updated | ||||
Set<Widget> sizeUpdatedWidgets = new HashSet<Widget>(); | Set<Widget> sizeUpdatedWidgets = new HashSet<Widget>(); | ||||
updatedVPaintableWidgets.addAll(relativeSizeChanges); | |||||
sizeUpdatedWidgets.addAll(componentCaptionSizeChanges); | sizeUpdatedWidgets.addAll(componentCaptionSizeChanges); | ||||
for (VPaintableWidget paintable : updatedVPaintableWidgets) { | for (VPaintableWidget paintable : updatedVPaintableWidgets) { | ||||
String h = uidl.hasAttribute("height") ? uidl | String h = uidl.hasAttribute("height") ? uidl | ||||
.getStringAttribute("height") : ""; | .getStringAttribute("height") : ""; | ||||
float relativeWidth = Util.parseRelativeSize(w); | |||||
float relativeHeight = Util.parseRelativeSize(h); | |||||
// First update maps so they are correct in the setHeight/setWidth calls | |||||
if (relativeHeight >= 0.0 || relativeWidth >= 0.0) { | |||||
// One or both is relative | |||||
FloatSize relativeSize = new FloatSize(relativeWidth, | |||||
relativeHeight); | |||||
if (paintableMap.getRelativeSize(paintable) == null | |||||
&& paintableMap.getOffsetSize(paintable) != null) { | |||||
// The component has changed from absolute size to relative size | |||||
relativeSizeChanges.add(paintable); | |||||
} | |||||
paintableMap.setRelativeSize(paintable, relativeSize); | |||||
} else if (relativeHeight < 0.0 && relativeWidth < 0.0) { | |||||
if (paintableMap.getRelativeSize(paintable) != null) { | |||||
// The component has changed from relative size to absolute size | |||||
relativeSizeChanges.add(paintable); | |||||
} | |||||
paintableMap.setRelativeSize(paintable, null); | |||||
} | |||||
Widget component = paintableMap.getWidget(paintable); | Widget component = paintableMap.getWidget(paintable); | ||||
// Set absolute sizes | |||||
if (relativeHeight < 0.0) { | |||||
component.setHeight(h); | |||||
} | |||||
if (relativeWidth < 0.0) { | |||||
component.setWidth(w); | |||||
} | |||||
// Set relative sizes | |||||
if (relativeHeight >= 0.0 || relativeWidth >= 0.0) { | |||||
// One or both is relative | |||||
handleComponentRelativeSize(paintable); | |||||
} | |||||
// Set defined sizes | |||||
component.setHeight(h); | |||||
component.setWidth(w); | |||||
} | } | ||||
/** | /** | ||||
* @return true if the child has a relative size | * @return true if the child has a relative size | ||||
*/ | */ | ||||
private boolean handleComponentRelativeSize(VPaintableWidget paintable) { | private boolean handleComponentRelativeSize(VPaintableWidget paintable) { | ||||
if (paintable == null) { | |||||
return false; | |||||
} | |||||
boolean debugSizes = true; | |||||
FloatSize relativeSize = paintableMap.getRelativeSize(paintable); | |||||
if (relativeSize == null) { | |||||
return false; | |||||
} | |||||
Widget widget = paintableMap.getWidget(paintable); | |||||
boolean horizontalScrollBar = false; | |||||
boolean verticalScrollBar = false; | |||||
Container parentPaintable = Util.getLayout(widget); | |||||
RenderSpace renderSpace; | |||||
// Parent-less components (like sub-windows) are relative to browser | |||||
// window. | |||||
if (parentPaintable == null) { | |||||
renderSpace = new RenderSpace(Window.getClientWidth(), | |||||
Window.getClientHeight()); | |||||
} else { | |||||
renderSpace = parentPaintable.getAllocatedSpace(widget); | |||||
} | |||||
if (relativeSize.getHeight() >= 0) { | |||||
if (renderSpace != null) { | |||||
if (renderSpace.getScrollbarSize() > 0) { | |||||
if (relativeSize.getWidth() > 100) { | |||||
horizontalScrollBar = true; | |||||
} else if (relativeSize.getWidth() < 0 | |||||
&& renderSpace.getWidth() > 0) { | |||||
int offsetWidth = widget.getOffsetWidth(); | |||||
int width = renderSpace.getWidth(); | |||||
if (offsetWidth > width) { | |||||
horizontalScrollBar = true; | |||||
} | |||||
} | |||||
} | |||||
int height = renderSpace.getHeight(); | |||||
if (horizontalScrollBar) { | |||||
height -= renderSpace.getScrollbarSize(); | |||||
} | |||||
if (validatingLayouts && height <= 0) { | |||||
zeroHeightComponents.add(paintable); | |||||
} | |||||
height = (int) (height * relativeSize.getHeight() / 100.0); | |||||
if (height < 0) { | |||||
height = 0; | |||||
} | |||||
if (debugSizes) { | |||||
VConsole.log("Widget " | |||||
+ Util.getSimpleName(widget) | |||||
+ "/" | |||||
+ paintableMap.getPid(paintable) | |||||
+ " relative height " | |||||
+ relativeSize.getHeight() | |||||
+ "% of " | |||||
+ renderSpace.getHeight() | |||||
+ "px (reported by " | |||||
+ Util.getSimpleName(parentPaintable) | |||||
+ "/" | |||||
+ (parentPaintable == null ? "?" : parentPaintable | |||||
.hashCode()) + ") : " + height + "px"); | |||||
} | |||||
widget.setHeight(height + "px"); | |||||
} else { | |||||
widget.setHeight(relativeSize.getHeight() + "%"); | |||||
VConsole.error(Util.getLayout(widget).getClass().getName() | |||||
+ " did not produce allocatedSpace for " | |||||
+ widget.getClass().getName()); | |||||
} | |||||
} | |||||
if (relativeSize.getWidth() >= 0) { | |||||
if (renderSpace != null) { | |||||
int width = renderSpace.getWidth(); | |||||
if (renderSpace.getScrollbarSize() > 0) { | |||||
if (relativeSize.getHeight() > 100) { | |||||
verticalScrollBar = true; | |||||
} else if (relativeSize.getHeight() < 0 | |||||
&& renderSpace.getHeight() > 0 | |||||
&& widget.getOffsetHeight() > renderSpace | |||||
.getHeight()) { | |||||
verticalScrollBar = true; | |||||
} | |||||
} | |||||
if (verticalScrollBar) { | |||||
width -= renderSpace.getScrollbarSize(); | |||||
} | |||||
if (validatingLayouts && width <= 0) { | |||||
zeroWidthComponents.add(paintable); | |||||
} | |||||
width = (int) (width * relativeSize.getWidth() / 100.0); | |||||
if (width < 0) { | |||||
width = 0; | |||||
} | |||||
if (debugSizes) { | |||||
VConsole.log("Widget " | |||||
+ Util.getSimpleName(widget) | |||||
+ "/" | |||||
+ paintableMap.getPid(paintable) | |||||
+ " relative width " | |||||
+ relativeSize.getWidth() | |||||
+ "% of " | |||||
+ renderSpace.getWidth() | |||||
+ "px (reported by " | |||||
+ Util.getSimpleName(parentPaintable) | |||||
+ "/" | |||||
+ (parentPaintable == null ? "?" : paintableMap | |||||
.getPid(parentPaintable)) + ") : " + width | |||||
+ "px"); | |||||
} | |||||
widget.setWidth(width + "px"); | |||||
} else { | |||||
widget.setWidth(relativeSize.getWidth() + "%"); | |||||
VConsole.error(Util.getLayout(widget).getClass().getName() | |||||
+ " did not produce allocatedSpace for " | |||||
+ widget.getClass().getName()); | |||||
} | |||||
} | |||||
return true; | |||||
return false; | |||||
} | } | ||||
/** | /** | ||||
} | } | ||||
/** | |||||
* Gets the specified Paintables relative size (percent). | |||||
* | |||||
* @param widget | |||||
* the paintable whose size is needed | |||||
* @return the the size if the paintable is relatively sized, -1 otherwise | |||||
*/ | |||||
public FloatSize getRelativeSize(Widget widget) { | |||||
return paintableMap.getRelativeSize(paintableMap.getPaintable(widget)); | |||||
} | |||||
/** | /** | ||||
* Get either existing or new Paintable for given UIDL. | * Get either existing or new Paintable for given UIDL. | ||||
* | * |
import java.util.HashMap; | import java.util.HashMap; | ||||
import com.google.gwt.core.client.JsArrayString; | import com.google.gwt.core.client.JsArrayString; | ||||
import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; | |||||
import com.vaadin.terminal.gwt.client.RenderInformation.Size; | import com.vaadin.terminal.gwt.client.RenderInformation.Size; | ||||
class ComponentDetail { | class ComponentDetail { | ||||
this.tooltipInfo = tooltipInfo; | this.tooltipInfo = tooltipInfo; | ||||
} | } | ||||
private FloatSize relativeSize; | |||||
private Size offsetSize; | private Size offsetSize; | ||||
private HashMap<Object, TooltipInfo> additionalTooltips; | private HashMap<Object, TooltipInfo> additionalTooltips; | ||||
/** | /** | ||||
* @return the relativeSize | |||||
*/ | |||||
FloatSize getRelativeSize() { | |||||
return relativeSize; | |||||
} | |||||
/** | |||||
* @param relativeSize | |||||
* the relativeSize to set | |||||
*/ | |||||
void setRelativeSize(FloatSize relativeSize) { | |||||
this.relativeSize = relativeSize; | |||||
} | |||||
/** | /** | ||||
* @return the offsetSize | * @return the offsetSize |
import com.google.gwt.user.client.ui.HasWidgets; | import com.google.gwt.user.client.ui.HasWidgets; | ||||
import com.google.gwt.user.client.ui.Widget; | import com.google.gwt.user.client.ui.Widget; | ||||
import com.vaadin.terminal.Paintable; | import com.vaadin.terminal.Paintable; | ||||
import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; | |||||
import com.vaadin.terminal.gwt.client.RenderInformation.Size; | import com.vaadin.terminal.gwt.client.RenderInformation.Size; | ||||
public class VPaintableMap { | public class VPaintableMap { | ||||
return getComponentDetail(paintable).getOffsetSize(); | return getComponentDetail(paintable).getOffsetSize(); | ||||
} | } | ||||
/** | |||||
* FIXME: Should not be here | |||||
* | |||||
* @param paintable | |||||
* @return | |||||
*/ | |||||
@Deprecated | |||||
public FloatSize getRelativeSize(VPaintableWidget paintable) { | |||||
return getComponentDetail(paintable).getRelativeSize(); | |||||
} | |||||
/** | /** | ||||
* FIXME: Should not be here | * FIXME: Should not be here | ||||
* | * | ||||
getComponentDetail(paintable).setOffsetSize(newSize); | getComponentDetail(paintable).setOffsetSize(newSize); | ||||
} | } | ||||
/** | |||||
* FIXME: Should not be here | |||||
* | |||||
* @param paintable | |||||
* @return | |||||
*/ | |||||
@Deprecated | |||||
public void setRelativeSize(VPaintableWidget paintable, | |||||
FloatSize relativeSize) { | |||||
getComponentDetail(paintable).setRelativeSize(relativeSize); | |||||
} | |||||
private ComponentDetail getComponentDetail(VPaintableWidget paintable) { | private ComponentDetail getComponentDetail(VPaintableWidget paintable) { | ||||
return idToComponentDetail.get(getPid(paintable)); | return idToComponentDetail.get(getPid(paintable)); | ||||
} | } |
}-*/; | }-*/; | ||||
public boolean requestLayout(Set<Widget> children) { | public boolean requestLayout(Set<Widget> children) { | ||||
updateRelativeSizedComponents(true, true); | |||||
if (width.equals("") || height.equals("")) { | if (width.equals("") || height.equals("")) { | ||||
/* Automatically propagated upwards if the size can change */ | /* Automatically propagated upwards if the size can change */ | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
@Override | |||||
public void setHeight(String height) { | |||||
if (this.height.equals(height)) { | |||||
return; | |||||
} | |||||
boolean shrinking = true; | |||||
if (isLarger(height, this.height)) { | |||||
shrinking = false; | |||||
} | |||||
this.height = height; | |||||
super.setHeight(height); | |||||
/* | |||||
* If the height shrinks we must remove all components with relative | |||||
* height from the DOM, update their height when they do not affect the | |||||
* available space and finally restore them to the original state | |||||
*/ | |||||
if (shrinking) { | |||||
updateRelativeSizedComponents(false, true); | |||||
} | |||||
} | |||||
@Override | |||||
public void setWidth(String width) { | |||||
if (this.width.equals(width)) { | |||||
return; | |||||
} | |||||
boolean shrinking = true; | |||||
if (isLarger(width, this.width)) { | |||||
shrinking = false; | |||||
} | |||||
super.setWidth(width); | |||||
this.width = width; | |||||
/* | |||||
* If the width shrinks we must remove all components with relative | |||||
* width from the DOM, update their width when they do not affect the | |||||
* available space and finally restore them to the original state | |||||
*/ | |||||
if (shrinking) { | |||||
updateRelativeSizedComponents(true, false); | |||||
} | |||||
} | |||||
private void updateRelativeSizedComponents(boolean relativeWidth, | |||||
boolean relativeHeight) { | |||||
Set<Widget> relativeSizeWidgets = new HashSet<Widget>(); | |||||
for (Widget widget : locationToWidget.values()) { | |||||
FloatSize relativeSize = client.getRelativeSize(widget); | |||||
if (relativeSize != null) { | |||||
if ((relativeWidth && (relativeSize.getWidth() >= 0.0f)) | |||||
|| (relativeHeight && (relativeSize.getHeight() >= 0.0f))) { | |||||
relativeSizeWidgets.add(widget); | |||||
widget.getElement().getStyle() | |||||
.setProperty("position", "absolute"); | |||||
} | |||||
} | |||||
} | |||||
for (Widget widget : relativeSizeWidgets) { | |||||
client.handleComponentRelativeSize(widget); | |||||
widget.getElement().getStyle().setProperty("position", ""); | |||||
} | |||||
} | |||||
/** | /** | ||||
* Compares newSize with currentSize and returns true if it is clear that | * Compares newSize with currentSize and returns true if it is clear that | ||||
* newSize is larger than currentSize. Returns false if newSize is smaller | * newSize is larger than currentSize. Returns false if newSize is smaller |
package com.vaadin.terminal.gwt.client.ui.label; | package com.vaadin.terminal.gwt.client.ui.label; | ||||
import com.google.gwt.dom.client.Style.Display; | |||||
import com.google.gwt.user.client.Event; | import com.google.gwt.user.client.Event; | ||||
import com.google.gwt.user.client.ui.HTML; | import com.google.gwt.user.client.ui.HTML; | ||||
import com.vaadin.terminal.gwt.client.BrowserInfo; | import com.vaadin.terminal.gwt.client.BrowserInfo; | ||||
public static final String CLASSNAME = "v-label"; | public static final String CLASSNAME = "v-label"; | ||||
private static final String CLASSNAME_UNDEFINED_WIDTH = "v-label-undef-w"; | private static final String CLASSNAME_UNDEFINED_WIDTH = "v-label-undef-w"; | ||||
private int verticalPaddingBorder = 0; | |||||
private int horizontalPaddingBorder = 0; | |||||
public VLabel() { | public VLabel() { | ||||
super(); | super(); | ||||
setStyleName(CLASSNAME); | setStyleName(CLASSNAME); | ||||
} | } | ||||
} | } | ||||
@Override | |||||
public void setHeight(String height) { | |||||
verticalPaddingBorder = Util.setHeightExcludingPaddingAndBorder(this, | |||||
height, verticalPaddingBorder); | |||||
} | |||||
@Override | @Override | ||||
public void setWidth(String width) { | public void setWidth(String width) { | ||||
horizontalPaddingBorder = Util.setWidthExcludingPaddingAndBorder(this, | |||||
width, horizontalPaddingBorder); | |||||
super.setWidth(width); | |||||
if (width == null || width.equals("")) { | if (width == null || width.equals("")) { | ||||
setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, true); | setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, true); | ||||
getElement().getStyle().setDisplay(Display.INLINE_BLOCK); | |||||
} else { | } else { | ||||
setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, false); | setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, false); | ||||
getElement().getStyle().clearDisplay(); | |||||
} | } | ||||
} | } | ||||
import com.google.gwt.dom.client.DivElement; | import com.google.gwt.dom.client.DivElement; | ||||
import com.google.gwt.dom.client.Document; | import com.google.gwt.dom.client.Document; | ||||
import com.google.gwt.dom.client.Element; | import com.google.gwt.dom.client.Element; | ||||
import com.google.gwt.dom.client.Style.Display; | |||||
import com.google.gwt.user.client.ui.Panel; | import com.google.gwt.user.client.ui.Panel; | ||||
import com.google.gwt.user.client.ui.Widget; | import com.google.gwt.user.client.ui.Widget; | ||||
import com.vaadin.terminal.gwt.client.ApplicationConnection; | import com.vaadin.terminal.gwt.client.ApplicationConnection; | ||||
widgetDIV = Document.get().createDivElement(); | widgetDIV = Document.get().createDivElement(); | ||||
setFloat(widgetDIV, "left"); | |||||
setElement(containerDIV); | setElement(containerDIV); | ||||
containerDIV.getStyle().setProperty("height", "0"); | containerDIV.getStyle().setProperty("height", "0"); | ||||
containerDIV.getStyle().setProperty("width", "0px"); | containerDIV.getStyle().setProperty("width", "0px"); | ||||
// Physical attach. | // Physical attach. | ||||
widgetDIV.appendChild(widget.getElement()); | widgetDIV.appendChild(widget.getElement()); | ||||
adopt(w); | adopt(w); | ||||
w.getElement().getStyle().setDisplay(Display.INLINE_BLOCK); | |||||
} | } | ||||
} | } | ||||