aboutsummaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorHenri Sara <henri.sara@itmill.com>2011-06-16 07:19:43 +0000
committerHenri Sara <henri.sara@itmill.com>2011-06-16 07:19:43 +0000
commit79c52ac3d4756a6f8cbb94b9e7dc264ba61c5430 (patch)
treed2ede4345c21d3caffe5dd2873f10ccb4aabbfff /src/com
parent3239587ad38fb20df82a235d732c10d88aebe5b8 (diff)
parent3547a37b82a25f2f8a7ecf4ca012094d62159ab3 (diff)
downloadvaadin-framework-79c52ac3d4756a6f8cbb94b9e7dc264ba61c5430.tar.gz
vaadin-framework-79c52ac3d4756a6f8cbb94b9e7dc264ba61c5430.zip
Merge from 6.6
svn changeset:19412/svn branch:6.7
Diffstat (limited to 'src/com')
-rw-r--r--src/com/vaadin/data/util/HierarchicalContainer.java18
-rwxr-xr-xsrc/com/vaadin/terminal/gwt/client/ApplicationConnection.java3
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java223
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VOverlay.java113
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTextField.java18
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VWindow.java48
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java22
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java16
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java4
-rw-r--r--src/com/vaadin/terminal/gwt/server/WebBrowser.java200
-rw-r--r--src/com/vaadin/ui/AbstractOrderedLayout.java2
-rw-r--r--src/com/vaadin/ui/Button.java100
-rw-r--r--src/com/vaadin/ui/MenuBar.java122
-rw-r--r--src/com/vaadin/ui/themes/BaseTheme.java8
15 files changed, 640 insertions, 261 deletions
diff --git a/src/com/vaadin/data/util/HierarchicalContainer.java b/src/com/vaadin/data/util/HierarchicalContainer.java
index d671dbc833..99de7a1352 100644
--- a/src/com/vaadin/data/util/HierarchicalContainer.java
+++ b/src/com/vaadin/data/util/HierarchicalContainer.java
@@ -471,6 +471,9 @@ public class HierarchicalContainer extends IndexedContainer implements
if (filteredChildren != null) {
filteredChildren = null;
}
+ if (filteredParent != null) {
+ filteredParent = null;
+ }
}
enableAndFireContentsChangeEvents();
return success;
@@ -516,18 +519,30 @@ public class HierarchicalContainer extends IndexedContainer implements
if (c != null) {
c.remove(itemId);
+ if (c.isEmpty()) {
+ children.remove(parentItemId);
+ }
+
// Found in the children list so might also be in the
// filteredChildren list
if (filteredChildren != null) {
LinkedList<Object> f = filteredChildren
.get(parentItemId);
if (f != null) {
- f.remove(parentItemId);
+ f.remove(itemId);
+ if (f.isEmpty()) {
+ filteredChildren.remove(parentItemId);
+ }
}
}
}
}
parent.remove(itemId);
+ if (filteredParent != null) {
+ // Item id no longer has a parent as the item id is not in the
+ // container.
+ filteredParent.remove(itemId);
+ }
noChildrenAllowed.remove(itemId);
}
@@ -642,6 +657,7 @@ public class HierarchicalContainer extends IndexedContainer implements
// All filters removed
filteredRoots = null;
filteredChildren = null;
+ filteredParent = null;
return super.doFilterContainer(hasFilters);
}
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
index 5f808ea8cd..056428881f 100755
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
@@ -367,7 +367,8 @@ public class ApplicationConnection {
+ "&vw=" + offsetWidth + "&vh=" + offsetHeight + "&fr=" + token
+ "&tzo=" + tzOffset + "&rtzo=" + rtzOffset + "&dstd="
+ dstDiff + "&dston=" + dstInEffect + "&curdate=" + curDate
- + "&wsver=" + widgetsetVersion;
+ + "&wsver=" + widgetsetVersion
+ + (BrowserInfo.get().isTouchDevice() ? "&td=1" : "");
return parameters;
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java
index 996b719e33..4d43b7c346 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java
@@ -8,6 +8,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Stack;
+import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.NodeList;
@@ -66,6 +67,8 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
public static final String OPEN_ROOT_MENU_ON_HOWER = "ormoh";
+ public static final String ATTRIBUTE_CHECKED = "checked";
+
/** Widget fields **/
protected boolean subMenu;
protected ArrayList<CustomMenuItem> items;
@@ -154,8 +157,8 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
// special case that uses another method. Really should fix the
// Util.setWidthExcludingPaddingAndBorder method but that will
// probably break additional cases
- int requestedPixelWidth = Integer.parseInt(width.substring(0, width
- .length() - 2));
+ int requestedPixelWidth = Integer.parseInt(width.substring(0,
+ width.length() - 2));
int paddingBorder = Util.measureHorizontalPaddingAndBorder(
getElement(), 0);
int w = requestedPixelWidth - paddingBorder;
@@ -228,9 +231,12 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
}
itemHTML.append(moreItemText);
- moreItem = new CustomMenuItem(itemHTML.toString(), emptyCommand);
- collapsedRootItems = new VMenuBar(true, (VMenuBar) client
- .getPaintable(uidlId));
+ moreItem = GWT.create(CustomMenuItem.class);
+ moreItem.setHTML(itemHTML.toString());
+ moreItem.setCommand(emptyCommand);
+
+ collapsedRootItems = new VMenuBar(true,
+ (VMenuBar) client.getPaintable(uidlId));
moreItem.setSubMenu(collapsedRootItems);
moreItem.addStyleName(CLASSNAME + "-more-menuitem");
}
@@ -245,45 +251,16 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
UIDL item = (UIDL) itr.next();
CustomMenuItem currentItem = null;
- String itemText = item.getStringAttribute("text");
final int itemId = item.getIntAttribute("id");
boolean itemHasCommand = item.hasAttribute("command");
+ boolean itemIsCheckable = item.hasAttribute(ATTRIBUTE_CHECKED);
- // Construct html from the text and the optional icon
- StringBuffer itemHTML = new StringBuffer();
- Command cmd = null;
-
- if (item.hasAttribute("separator")) {
- itemHTML.append("<span>---</span>");
- } else {
- // Add submenu indicator
- if (item.getChildCount() > 0) {
- // FIXME For compatibility reasons: remove in version 7
- String bgStyle = "";
- if (submenuIcon != null) {
- bgStyle = " style=\"background-image: url("
- + submenuIcon
- + "); text-indent: -999px; width: 1em;\"";
- }
- itemHTML.append("<span class=\"" + CLASSNAME
- + "-submenu-indicator\"" + bgStyle
- + ">&#x25BA;</span>");
- }
-
- itemHTML.append("<span class=\"" + CLASSNAME
- + "-menuitem-caption\">");
- if (item.hasAttribute("icon")) {
- itemHTML
- .append("<img src=\""
- + client.translateVaadinUri(item
- .getStringAttribute("icon"))
- + "\" class=\"" + Icon.CLASSNAME
- + "\" alt=\"\" />");
- }
- itemHTML.append(Util.escapeHTML(itemText) + "</span>");
+ String itemHTML = buildItemHTML(item);
- if (itemHasCommand) {
+ Command cmd = null;
+ if (!item.hasAttribute("separator")) {
+ if (itemHasCommand || itemIsCheckable) {
// Construct a command that fires onMenuClick(int) with the
// item's id-number
cmd = new Command() {
@@ -312,6 +289,17 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
}
while (!itr.hasNext() && !iteratorStack.empty()) {
+ boolean hasCheckableItem = false;
+ for (CustomMenuItem menuItem : currentMenu.getItems()) {
+ hasCheckableItem = hasCheckableItem
+ || menuItem.isCheckable();
+ }
+ if (hasCheckableItem) {
+ currentMenu.addStyleDependentName("check-column");
+ } else {
+ currentMenu.removeStyleDependentName("check-column");
+ }
+
itr = iteratorStack.pop();
currentMenu = menuStack.pop();
}
@@ -322,6 +310,45 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
}// updateFromUIDL
/**
+ * Build the HTML content for a menu item.
+ *
+ * @param item
+ * @return
+ */
+ protected String buildItemHTML(UIDL item) {
+ // Construct html from the text and the optional icon
+ StringBuffer itemHTML = new StringBuffer();
+ if (item.hasAttribute("separator")) {
+ itemHTML.append("<span>---</span>");
+ } else {
+ // Add submenu indicator
+ if (item.getChildCount() > 0) {
+ // FIXME For compatibility reasons: remove in version 7
+ String bgStyle = "";
+ if (submenuIcon != null) {
+ bgStyle = " style=\"background-image: url(" + submenuIcon
+ + "); text-indent: -999px; width: 1em;\"";
+ }
+ itemHTML.append("<span class=\"" + CLASSNAME
+ + "-submenu-indicator\"" + bgStyle + ">&#x25BA;</span>");
+ }
+
+ itemHTML.append("<span class=\"" + CLASSNAME
+ + "-menuitem-caption\">");
+ if (item.hasAttribute("icon")) {
+ itemHTML.append("<img src=\""
+ + client.translateVaadinUri(item
+ .getStringAttribute("icon")) + "\" class=\""
+ + Icon.CLASSNAME + "\" alt=\"\" />");
+ }
+ String itemText = item.getStringAttribute("text");
+ itemHTML.append(Util.escapeHTML(itemText));
+ itemHTML.append("</span>");
+ }
+ return itemHTML.toString();
+ }
+
+ /**
* This is called by the items in the menu and it communicates the
* information to the server
*
@@ -379,7 +406,10 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
* @return the item created
*/
public CustomMenuItem addItem(String html, Command cmd) {
- CustomMenuItem item = new CustomMenuItem(html, cmd);
+ CustomMenuItem item = GWT.create(CustomMenuItem.class);
+ item.setHTML(html);
+ item.setCommand(cmd);
+
addItem(item);
return item;
}
@@ -418,8 +448,8 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
if (items.contains(item)) {
int index = items.indexOf(item);
- DOM.removeChild(getContainerElement(), DOM.getChild(
- getContainerElement(), index));
+ DOM.removeChild(getContainerElement(),
+ DOM.getChild(getContainerElement(), index));
items.remove(index);
}
}
@@ -672,8 +702,7 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
popup.show();
if (left + popup.getOffsetWidth() >= RootPanel.getBodyElement()
- .getOffsetWidth()
- - shadowSpace) {
+ .getOffsetWidth() - shadowSpace) {
if (subMenu) {
left = item.getParentMenu().getAbsoluteLeft()
- popup.getOffsetWidth() - shadowSpace;
@@ -701,8 +730,8 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
}
if (popup.getElement().getStyle().getProperty("width") == null
- || popup.getElement().getStyle().getProperty(
- "width") == "") {
+ || popup.getElement().getStyle()
+ .getProperty("width") == "") {
popup.setWidth(popup.getOffsetWidth() + "px");
}
popup.getElement().getStyle().setProperty("zoom", "1");
@@ -835,7 +864,28 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
protected VMenuBar parentMenu = null;
protected boolean enabled = true;
protected boolean isSeparator = false;
+ protected boolean checkable = false;
+ protected boolean checked = false;
+
+ /**
+ * Default menu item {@link Widget} constructor for GWT.create().
+ *
+ * Use {@link #setHTML(String)} and {@link #setCommand(Command)} after
+ * constructing a menu item.
+ */
+ public CustomMenuItem() {
+ this("", null);
+ }
+ /**
+ * Creates a menu item {@link Widget}.
+ *
+ * @param html
+ * @param cmd
+ * @deprecated use the default constructor and {@link #setHTML(String)}
+ * and {@link #setCommand(Command)} instead
+ */
+ @Deprecated
public CustomMenuItem(String html, Command cmd) {
// We need spans to allow inline-block in IE
setElement(DOM.createSpan());
@@ -846,20 +896,64 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
setStyleName(CLASSNAME + "-menuitem");
sinkEvents(VTooltip.TOOLTIP_EVENTS);
-
- // Sink the onload event for any icons. The onload
- // events are handled by the parent VMenuBar.
- Util.sinkOnloadForImages(getElement());
}
public void setSelected(boolean selected) {
if (selected && !isSeparator) {
addStyleDependentName("selected");
+ // needed for IE6 to have a single style name to match for an
+ // element
+ if (checkable) {
+ if (checked) {
+ removeStyleDependentName("selected-unchecked");
+ addStyleDependentName("selected-checked");
+ } else {
+ removeStyleDependentName("selected-checked");
+ addStyleDependentName("selected-unchecked");
+ }
+ }
} else {
removeStyleDependentName("selected");
+ // needed for IE6 to have a single style name to match for an
+ // element
+ removeStyleDependentName("selected-checked");
+ removeStyleDependentName("selected-unchecked");
}
}
+ public void setChecked(boolean checked) {
+ if (checkable && !isSeparator) {
+ this.checked = checked;
+
+ if (checked) {
+ addStyleDependentName("checked");
+ removeStyleDependentName("unchecked");
+ } else {
+ addStyleDependentName("unchecked");
+ removeStyleDependentName("checked");
+ }
+ } else {
+ this.checked = false;
+ }
+ }
+
+ public boolean isChecked() {
+ return checked;
+ }
+
+ public void setCheckable(boolean checkable) {
+ if (checkable && !isSeparator) {
+ this.checkable = true;
+ } else {
+ setChecked(false);
+ this.checkable = false;
+ }
+ }
+
+ public boolean isCheckable() {
+ return checkable;
+ }
+
/*
* setters and getters for the fields
*/
@@ -895,6 +989,10 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
public void setHTML(String html) {
this.html = html;
DOM.setInnerHTML(getElement(), html);
+
+ // Sink the onload event for any icons. The onload
+ // events are handled by the parent VMenuBar.
+ Util.sinkOnloadForImages(getElement());
}
public String getText() {
@@ -937,6 +1035,15 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
setSeparator(uidl.hasAttribute("separator"));
setEnabled(!uidl.hasAttribute("disabled"));
+ if (!isSeparator() && uidl.hasAttribute(ATTRIBUTE_CHECKED)) {
+ // if the selected attribute is present (either true or false),
+ // the item is selectable
+ setCheckable(true);
+ setChecked(uidl.getBooleanAttribute(ATTRIBUTE_CHECKED));
+ } else {
+ setCheckable(false);
+ }
+
if (uidl.hasAttribute("style")) {
String itemStyle = uidl.getStringAttribute("style");
addStyleDependentName(itemStyle);
@@ -1111,9 +1218,9 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
* .gwt.event.dom.client.KeyPressEvent)
*/
public void onKeyPress(KeyPressEvent event) {
- if (handleNavigation(event.getNativeEvent().getKeyCode(), event
- .isControlKeyDown()
- || event.isMetaKeyDown(), event.isShiftKeyDown())) {
+ if (handleNavigation(event.getNativeEvent().getKeyCode(),
+ event.isControlKeyDown() || event.isMetaKeyDown(),
+ event.isShiftKeyDown())) {
event.preventDefault();
}
}
@@ -1126,9 +1233,9 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
* .event.dom.client.KeyDownEvent)
*/
public void onKeyDown(KeyDownEvent event) {
- if (handleNavigation(event.getNativeEvent().getKeyCode(), event
- .isControlKeyDown()
- || event.isMetaKeyDown(), event.isShiftKeyDown())) {
+ if (handleNavigation(event.getNativeEvent().getKeyCode(),
+ event.isControlKeyDown() || event.isMetaKeyDown(),
+ event.isShiftKeyDown())) {
event.preventDefault();
}
}
@@ -1435,9 +1542,7 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
* .dom.client.FocusEvent)
*/
public void onFocus(FocusEvent event) {
- // Focus the first element directly, so the keyboard focus becomes
- // visible
- setSelected(items.get(0));
+
}
private final String SUBPART_PREFIX = "item";
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java b/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java
index aba7ccf217..a277b4c42d 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java
@@ -22,7 +22,7 @@ import com.vaadin.terminal.gwt.client.Util;
* temporary float over other components like context menus etc. This is to deal
* stacking order correctly with VWindow objects.
*/
-public class VOverlay extends PopupPanel {
+public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
/*
* The z-index value from where all overlays live. This can be overridden in
@@ -84,23 +84,43 @@ public class VOverlay extends PopupPanel {
public VOverlay(boolean autoHide, boolean modal, boolean showShadow) {
super(autoHide, modal);
- if (showShadow) {
- shadow = DOM.createDiv();
- shadow.setClassName(CLASSNAME_SHADOW);
- shadow.setInnerHTML(SHADOW_HTML);
- DOM.setStyleAttribute(shadow, "position", "absolute");
-
- addCloseHandler(new CloseHandler<PopupPanel>() {
- public void onClose(CloseEvent<PopupPanel> event) {
- if (shadow.getParentElement() != null) {
- shadow.getParentElement().removeChild(shadow);
- }
- }
- });
- }
+ setShadowEnabled(showShadow);
adjustZIndex();
}
+ /**
+ * Method to controle whether DOM elements for shadow are added. With this
+ * method subclasses can control displaying of shadow also after the
+ * constructor.
+ *
+ * @param enabled
+ * true if shadow should be displayed
+ */
+ protected void setShadowEnabled(boolean enabled) {
+ if (enabled != isShadowEnabled()) {
+ if (enabled) {
+ shadow = DOM.createDiv();
+ shadow.setClassName(CLASSNAME_SHADOW);
+ shadow.setInnerHTML(SHADOW_HTML);
+ DOM.setStyleAttribute(shadow, "position", "absolute");
+ addCloseHandler(this);
+ } else {
+ removeShadowIfPresent();
+ shadow = null;
+ }
+ }
+ }
+
+ protected boolean isShadowEnabled() {
+ return shadow != null;
+ }
+
+ private void removeShadowIfPresent() {
+ if (isShadowEnabled() && shadow.getParentElement() != null) {
+ shadow.getParentElement().removeChild(shadow);
+ }
+ }
+
private void adjustZIndex() {
setZIndex(Z_INDEX);
}
@@ -113,7 +133,7 @@ public class VOverlay extends PopupPanel {
*/
protected void setZIndex(int zIndex) {
DOM.setStyleAttribute(getElement(), "zIndex", "" + zIndex);
- if (shadow != null) {
+ if (isShadowEnabled()) {
DOM.setStyleAttribute(shadow, "zIndex", "" + zIndex);
}
}
@@ -128,25 +148,37 @@ public class VOverlay extends PopupPanel {
style.setMarginLeft(-adjustByRelativeLeftBodyMargin(), Unit.PX);
style.setMarginTop(-adjustByRelativeTopBodyMargin(), Unit.PX);
super.setPopupPosition(left, top);
- if (shadow != null) {
- updateShadowSizeAndPosition(isAnimationEnabled() ? 0 : 1);
- }
+ updateShadowSizeAndPosition(isAnimationEnabled() ? 0 : 1);
}
private static int adjustByRelativeTopBodyMargin() {
if (topFix == -1) {
- topFix = detectRelativeBodyFixes("top");
+ boolean ie6OrIe7 = BrowserInfo.get().isIE()
+ && BrowserInfo.get().getIEVersion() <= 7;
+ topFix = detectRelativeBodyFixes("top", ie6OrIe7);
}
return topFix;
}
- private native static int detectRelativeBodyFixes(String axis)
+ private native static int detectRelativeBodyFixes(String axis,
+ boolean removeClientLeftOrTop)
/*-{
try {
var b = $wnd.document.body;
var cstyle = b.currentStyle ? b.currentStyle : getComputedStyle(b);
if(cstyle && cstyle.position == 'relative') {
- return b.getBoundingClientRect()[axis];
+ var offset = b.getBoundingClientRect()[axis];
+ if (removeClientLeftOrTop) {
+ // IE6 and IE7 include the top left border of the client area into the boundingClientRect
+ var clientTopOrLeft = 0;
+ if (axis == "top")
+ clientTopOrLeft = $wnd.document.documentElement.clientTop;
+ else
+ clientTopOrLeft = $wnd.document.documentElement.clientLeft;
+
+ offset -= clientTopOrLeft;
+ }
+ return offset;
}
} catch(e){}
return 0;
@@ -154,7 +186,10 @@ public class VOverlay extends PopupPanel {
private static int adjustByRelativeLeftBodyMargin() {
if (leftFix == -1) {
- leftFix = detectRelativeBodyFixes("left");
+ boolean ie6OrIe7 = BrowserInfo.get().isIE()
+ && BrowserInfo.get().getIEVersion() <= 7;
+ leftFix = detectRelativeBodyFixes("left", ie6OrIe7);
+
}
return leftFix;
}
@@ -162,7 +197,7 @@ public class VOverlay extends PopupPanel {
@Override
public void show() {
super.show();
- if (shadow != null) {
+ if (isShadowEnabled()) {
if (isAnimationEnabled()) {
ShadowAnimation sa = new ShadowAnimation();
sa.run(200);
@@ -180,9 +215,17 @@ public class VOverlay extends PopupPanel {
}
@Override
+ protected void onDetach() {
+ super.onDetach();
+
+ // Always ensure shadow is removed when the overlay is removed.
+ removeShadowIfPresent();
+ }
+
+ @Override
public void setVisible(boolean visible) {
super.setVisible(visible);
- if (shadow != null) {
+ if (isShadowEnabled()) {
shadow.getStyle().setProperty("visibility",
visible ? "visible" : "hidden");
}
@@ -191,17 +234,13 @@ public class VOverlay extends PopupPanel {
@Override
public void setWidth(String width) {
super.setWidth(width);
- if (shadow != null) {
- updateShadowSizeAndPosition(1.0);
- }
+ updateShadowSizeAndPosition(1.0);
}
@Override
public void setHeight(String height) {
super.setHeight(height);
- if (shadow != null) {
- updateShadowSizeAndPosition(1.0);
- }
+ updateShadowSizeAndPosition(1.0);
}
/**
@@ -215,7 +254,7 @@ public class VOverlay extends PopupPanel {
* name=='v-shadow-foobar'.
*/
protected void setShadowStyle(String style) {
- if (shadow != null) {
+ if (isShadowEnabled()) {
shadow.setClassName(CLASSNAME_SHADOW + "-" + style);
}
}
@@ -241,7 +280,7 @@ public class VOverlay extends PopupPanel {
*/
private void updateShadowSizeAndPosition(final double progress) {
// Don't do anything if overlay element is not attached
- if (!isAttached()) {
+ if (!isAttached() || shadow == null) {
return;
}
// Calculate proper z-index
@@ -336,9 +375,11 @@ public class VOverlay extends PopupPanel {
protected class ShadowAnimation extends Animation {
@Override
protected void onUpdate(double progress) {
- if (shadow != null) {
- updateShadowSizeAndPosition(progress);
- }
+ updateShadowSizeAndPosition(progress);
}
}
+
+ public void onClose(CloseEvent<PopupPanel> event) {
+ removeShadowIfPresent();
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
index c1d674a367..d36c2137d8 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
@@ -843,6 +843,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
if (uidl.hasAttribute("alb")) {
bodyActionKeys = uidl.getStringArrayAttribute("alb");
+ } else {
+ // Need to clear the actions if the action handlers have been
+ // removed
+ bodyActionKeys = null;
}
setCacheRate(uidl.hasAttribute("cr") ? uidl.getDoubleAttribute("cr")
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
index 3df2e356d1..a05cef3984 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
@@ -12,6 +12,9 @@ import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
@@ -24,7 +27,6 @@ import com.vaadin.terminal.gwt.client.EventId;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener;
@@ -35,7 +37,8 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutAct
*
*/
public class VTextField extends TextBoxBase implements Paintable, Field,
- ChangeHandler, FocusHandler, BlurHandler, BeforeShortcutActionListener {
+ ChangeHandler, FocusHandler, BlurHandler, BeforeShortcutActionListener,
+ KeyDownHandler {
public static final String VAR_CUR_TEXT = "curText";
/**
@@ -85,6 +88,11 @@ public class VTextField extends TextBoxBase implements Paintable, Field,
}
setStyleName(CLASSNAME);
addChangeHandler(this);
+ if (BrowserInfo.get().isIE()) {
+ // IE does not send change events when pressing enter in a text
+ // input so we handle it using a key listener instead
+ addKeyDownHandler(this);
+ }
addFocusHandler(this);
addBlurHandler(this);
sinkEvents(VTooltip.TOOLTIP_EVENTS);
@@ -590,4 +598,10 @@ public class VTextField extends TextBoxBase implements Paintable, Field,
}
wordwrap = enabled;
}
+
+ public void onKeyDown(KeyDownEvent event) {
+ if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
+ valueChange(false);
+ }
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java
index 98ebf73b77..e2fe47cc2c 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java
@@ -14,13 +14,13 @@ import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.DomEvent.Type;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
-import com.google.gwt.event.dom.client.DomEvent.Type;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Command;
@@ -258,9 +258,7 @@ public class VWindow extends VOverlay implements Container,
footer = DOM.createDiv();
DOM.setElementProperty(footer, "className", CLASSNAME + "-footer");
resizeBox = DOM.createDiv();
- DOM
- .setElementProperty(resizeBox, "className", CLASSNAME
- + "-resizebox");
+ DOM.setElementProperty(resizeBox, "className", CLASSNAME + "-resizebox");
closeBox = DOM.createDiv();
DOM.setElementProperty(closeBox, "className", CLASSNAME + "-closebox");
DOM.appendChild(footer, resizeBox);
@@ -313,11 +311,11 @@ public class VWindow extends VOverlay implements Container,
resizeLazy = uidl.hasAttribute(VView.RESIZE_LAZY);
setDraggable(!uidl.hasAttribute("fixedposition"));
- }
- if (uidl.hasAttribute("caption")) {
- setCaption(uidl.getStringAttribute("caption"), uidl
- .getStringAttribute("icon"));
+ // Caption must be set before required header size is measured. If
+ // the caption attribute is missing the caption should be cleared.
+ setCaption(uidl.getStringAttribute("caption"),
+ uidl.getStringAttribute("icon"));
}
visibilityChangesDisabled = true;
@@ -458,8 +456,7 @@ public class VWindow extends VOverlay implements Container,
}
final String style = notification.hasAttribute("style") ? notification
- .getStringAttribute("style")
- : null;
+ .getStringAttribute("style") : null;
final int position = notification
.getIntAttribute("position");
final int delay = notification.getIntAttribute("delay");
@@ -679,7 +676,8 @@ public class VWindow extends VOverlay implements Container,
* Sets the closable state of the window. Additionally hides/shows the close
* button according to the new state.
*
- * @param closable true if the window can be closed by the user
+ * @param closable
+ * true if the window can be closed by the user
*/
protected void setClosable(boolean closable) {
if (this.closable == closable) {
@@ -777,14 +775,15 @@ public class VWindow extends VOverlay implements Container,
private void showModalityCurtain() {
if (BrowserInfo.get().isFF2()) {
- DOM.setStyleAttribute(getModalityCurtain(), "height", DOM
- .getElementPropertyInt(RootPanel.getBodyElement(),
- "offsetHeight")
- + "px");
+ DOM.setStyleAttribute(
+ getModalityCurtain(),
+ "height",
+ DOM.getElementPropertyInt(RootPanel.getBodyElement(),
+ "offsetHeight") + "px");
DOM.setStyleAttribute(getModalityCurtain(), "position", "absolute");
}
- DOM.setStyleAttribute(getModalityCurtain(), "zIndex", ""
- + (windowOrder.indexOf(this) + Z_INDEX));
+ DOM.setStyleAttribute(getModalityCurtain(), "zIndex",
+ "" + (windowOrder.indexOf(this) + Z_INDEX));
if (isShowing()) {
RootPanel.getBodyElement().insertBefore(getModalityCurtain(),
getElement());
@@ -987,7 +986,8 @@ public class VWindow extends VOverlay implements Container,
* Checks if the cursor was inside the browser content area when the event
* happened.
*
- * @param event The event to be checked
+ * @param event
+ * The event to be checked
* @return true, if the cursor is inside the browser content area
*
* false, otherwise
@@ -1075,8 +1075,8 @@ public class VWindow extends VOverlay implements Container,
rootPixelWidth = getElement().getOffsetWidth();
width = rootPixelWidth + "px";
} else {
- rootPixelWidth = Integer.parseInt(width.substring(0, width
- .indexOf("px")));
+ rootPixelWidth = Integer.parseInt(width.substring(0,
+ width.indexOf("px")));
}
// "width" now contains the new width in pixels
@@ -1305,15 +1305,15 @@ public class VWindow extends VOverlay implements Container,
public void onScroll(ScrollEvent event) {
client.updateVariable(id, "scrollTop",
contentPanel.getScrollPosition(), false);
- client.updateVariable(id, "scrollLeft", contentPanel
- .getHorizontalScrollPosition(), false);
+ client.updateVariable(id, "scrollLeft",
+ contentPanel.getHorizontalScrollPosition(), false);
}
public void onKeyDown(KeyDownEvent event) {
if (shortcutHandler != null) {
- shortcutHandler.handleKeyboardEvent(Event
- .as(event.getNativeEvent()));
+ shortcutHandler
+ .handleKeyboardEvent(Event.as(event.getNativeEvent()));
return;
}
}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
index cb4ba16f65..b4f194c7f7 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
@@ -561,15 +561,19 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
private void updateBrowserProperties(WebBrowser browser,
PortletRequest request) {
String userAgent = getHTTPHeader(request, "user-agent");
- browser.updateBrowserProperties(request.getLocale(), null,
- request.isSecure(), userAgent,
- getHTTPRequestParameter(request, "sw"),
- getHTTPRequestParameter(request, "sh"),
- getHTTPRequestParameter(request, "tzo"),
- getHTTPRequestParameter(request, "rtzo"),
- getHTTPRequestParameter(request, "dstd"),
- getHTTPRequestParameter(request, "dstActive"),
- getHTTPRequestParameter(request, "curdate"));
+ browser.updateRequestDetails(request.getLocale(), null,
+ request.isSecure(), userAgent);
+ if (getHTTPRequestParameter(request, "repaintAll") != null) {
+ browser.updateClientSideDetails(
+ getHTTPRequestParameter(request, "sw"),
+ getHTTPRequestParameter(request, "sh"),
+ getHTTPRequestParameter(request, "tzo"),
+ getHTTPRequestParameter(request, "rtzo"),
+ getHTTPRequestParameter(request, "dstd"),
+ getHTTPRequestParameter(request, "dstActive"),
+ getHTTPRequestParameter(request, "curdate"),
+ getHTTPRequestParameter(request, "td") != null);
+ }
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
index f274a474dd..c394e8ae6a 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
@@ -589,12 +589,18 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
private void updateBrowserProperties(WebBrowser browser,
HttpServletRequest request) {
- browser.updateBrowserProperties(request.getLocale(),
+ // request based details updated always
+ browser.updateRequestDetails(request.getLocale(),
request.getRemoteAddr(), request.isSecure(),
- request.getHeader("user-agent"), request.getParameter("sw"),
- request.getParameter("sh"), request.getParameter("tzo"),
- request.getParameter("rtzo"), request.getParameter("dstd"),
- request.getParameter("dston"), request.getParameter("curdate"));
+ request.getHeader("user-agent"));
+ if (request.getParameter("repaintAll") != null) {
+ browser.updateClientSideDetails(request.getParameter("sw"),
+ request.getParameter("sh"), request.getParameter("tzo"),
+ request.getParameter("rtzo"), request.getParameter("dstd"),
+ request.getParameter("dston"),
+ request.getParameter("curdate"),
+ request.getParameter("td") != null);
+ }
}
protected ClassLoader getClassLoader() throws ServletException {
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
index 152fa81bb5..74b7a27a96 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
@@ -392,6 +392,7 @@ public abstract class AbstractCommunicationManager implements
int contentLength = request.getContentLength();
boolean atStart = false;
+ boolean firstFileFieldFound = false;
String rawfilename = "unknown";
String rawMimeType = "application/octet-stream";
@@ -410,7 +411,8 @@ public abstract class AbstractCommunicationManager implements
rawfilename = rawfilename.substring(1);
rawfilename = rawfilename.substring(0,
rawfilename.indexOf(parenthesis));
- } else if (readLine.equals("")) {
+ firstFileFieldFound = true;
+ } else if (firstFileFieldFound && readLine.equals("")) {
atStart = true;
} else if (readLine.startsWith("Content-Type")) {
rawMimeType = readLine.split(": ")[1];
diff --git a/src/com/vaadin/terminal/gwt/server/WebBrowser.java b/src/com/vaadin/terminal/gwt/server/WebBrowser.java
index 1b0d7fe986..4835b3c55b 100644
--- a/src/com/vaadin/terminal/gwt/server/WebBrowser.java
+++ b/src/com/vaadin/terminal/gwt/server/WebBrowser.java
@@ -30,9 +30,10 @@ public class WebBrowser implements Terminal {
private int rawTimezoneOffset = 0;
private int dstSavings;
private boolean dstInEffect;
- private Date currentDate;
+ private boolean touchDevice;
private VBrowserDetails browserDetails;
+ private long clientServerTimeDelta;
/**
* There is no default-theme for this terminal type.
@@ -71,91 +72,6 @@ public class WebBrowser implements Terminal {
}
/**
- * For internal use by AbstractApplicationServlet/AbstractApplicationPortlet
- * only. Updates all properties in the class according to the given
- * information.
- *
- * @param locale
- * The browser primary locale
- * @param address
- * The browser ip address
- * @param secureConnection
- * true if using an https connection
- * @param agent
- * Raw userAgent string from the browser
- * @param sw
- * Screen width
- * @param sh
- * Screen height
- * @param tzo
- * TimeZone offset in minutes from GMT
- * @param rtzo
- * raw TimeZone offset in minutes from GMT (w/o DST adjustment)
- * @param dstSavings
- * the difference between the raw TimeZone and DST in minutes
- * @param dstInEffect
- * is DST currently active in the region or not?
- * @param curDate
- * the current date in milliseconds since the epoch
- */
- void updateBrowserProperties(Locale locale, String address,
- boolean secureConnection, String agent, String sw, String sh,
- String tzo, String rtzo, String dstSavings, String dstInEffect,
- String curDate) {
- this.locale = locale;
- this.address = address;
- this.secureConnection = secureConnection;
- if (agent != null) {
- browserApplication = agent;
- browserDetails = new VBrowserDetails(agent);
- }
-
- if (sw != null) {
- try {
- screenHeight = Integer.parseInt(sh);
- screenWidth = Integer.parseInt(sw);
- } catch (final NumberFormatException e) {
- screenHeight = screenWidth = 0;
- }
- }
- if (tzo != null) {
- try {
- // browser->java conversion: min->ms, reverse sign
- timezoneOffset = -Integer.parseInt(tzo) * 60 * 1000;
- } catch (final NumberFormatException e) {
- timezoneOffset = 0; // default gmt+0
- }
- }
- if (rtzo != null) {
- try {
- // browser->java conversion: min->ms, reverse sign
- rawTimezoneOffset = -Integer.parseInt(rtzo) * 60 * 1000;
- } catch (final NumberFormatException e) {
- rawTimezoneOffset = 0; // default gmt+0
- }
- }
- if (dstSavings != null) {
- try {
- // browser->java conversion: min->ms
- this.dstSavings = Integer.parseInt(dstSavings) * 60 * 1000;
- } catch (final NumberFormatException e) {
- this.dstSavings = 0; // default no savings
- }
- }
- if (dstInEffect != null) {
- this.dstInEffect = Boolean.parseBoolean(dstInEffect);
- }
- if (curDate != null) {
- try {
- long curTime = Long.parseLong(curDate);
- currentDate = new Date(curTime);
- } catch (final NumberFormatException e) {
- currentDate = new Date();
- }
- }
- }
-
- /**
* Gets the IP-address of the web browser. If the application is running
* inside a portlet, this method will return null.
*
@@ -368,12 +284,120 @@ public class WebBrowser implements Terminal {
/**
* Returns the current date and time of the browser. This will not be
* entirely accurate due to varying network latencies, but should provide a
- * close-enough value for most cases.
+ * close-enough value for most cases. Also note that the returned Date
+ * object uses servers default time zone, not the clients.
*
* @return the current date and time of the browser.
+ * @see #isDSTInEffect()
+ * @see #getDSTSavings()
+ * @see #getTimezoneOffset()
*/
public Date getCurrentDate() {
- return currentDate;
+ return new Date(new Date().getTime() + clientServerTimeDelta);
+ }
+
+ /**
+ * @return true if the browser is detected to support touch events
+ */
+ public boolean isTouchDevice() {
+ return touchDevice;
+ }
+
+ /**
+ * For internal use by AbstractApplicationServlet/AbstractApplicationPortlet
+ * only. Updates all properties in the class according to the given
+ * information.
+ *
+ * @param sw
+ * Screen width
+ * @param sh
+ * Screen height
+ * @param tzo
+ * TimeZone offset in minutes from GMT
+ * @param rtzo
+ * raw TimeZone offset in minutes from GMT (w/o DST adjustment)
+ * @param dstSavings
+ * the difference between the raw TimeZone and DST in minutes
+ * @param dstInEffect
+ * is DST currently active in the region or not?
+ * @param curDate
+ * the current date in milliseconds since the epoch
+ * @param touchDevice
+ */
+ void updateClientSideDetails(String sw, String sh, String tzo, String rtzo,
+ String dstSavings, String dstInEffect, String curDate,
+ boolean touchDevice) {
+ if (sw != null) {
+ try {
+ screenHeight = Integer.parseInt(sh);
+ screenWidth = Integer.parseInt(sw);
+ } catch (final NumberFormatException e) {
+ screenHeight = screenWidth = 0;
+ }
+ }
+ if (tzo != null) {
+ try {
+ // browser->java conversion: min->ms, reverse sign
+ timezoneOffset = -Integer.parseInt(tzo) * 60 * 1000;
+ } catch (final NumberFormatException e) {
+ timezoneOffset = 0; // default gmt+0
+ }
+ }
+ if (rtzo != null) {
+ try {
+ // browser->java conversion: min->ms, reverse sign
+ rawTimezoneOffset = -Integer.parseInt(rtzo) * 60 * 1000;
+ } catch (final NumberFormatException e) {
+ rawTimezoneOffset = 0; // default gmt+0
+ }
+ }
+ if (dstSavings != null) {
+ try {
+ // browser->java conversion: min->ms
+ this.dstSavings = Integer.parseInt(dstSavings) * 60 * 1000;
+ } catch (final NumberFormatException e) {
+ this.dstSavings = 0; // default no savings
+ }
+ }
+ if (dstInEffect != null) {
+ this.dstInEffect = Boolean.parseBoolean(dstInEffect);
+ }
+ if (curDate != null) {
+ try {
+ long curTime = Long.parseLong(curDate);
+ clientServerTimeDelta = curTime - new Date().getTime();
+ } catch (final NumberFormatException e) {
+ clientServerTimeDelta = 0;
+ }
+ }
+ this.touchDevice = touchDevice;
+
+ }
+
+ /**
+ * For internal use by AbstractApplicationServlet/AbstractApplicationPortlet
+ * only. Updates all properties in the class according to the given
+ * information.
+ *
+ * @param locale
+ * The browser primary locale
+ * @param address
+ * The browser ip address
+ * @param secureConnection
+ * true if using an https connection
+ * @param agent
+ * Raw userAgent string from the browser
+ */
+ void updateRequestDetails(Locale locale, String address,
+ boolean secureConnection, String agent) {
+ this.locale = locale;
+ this.address = address;
+ this.secureConnection = secureConnection;
+ if (agent != null) {
+ browserApplication = agent;
+ browserDetails = new VBrowserDetails(agent);
+ }
+
}
}
diff --git a/src/com/vaadin/ui/AbstractOrderedLayout.java b/src/com/vaadin/ui/AbstractOrderedLayout.java
index 8dfbe07b18..0b0fff2a34 100644
--- a/src/com/vaadin/ui/AbstractOrderedLayout.java
+++ b/src/com/vaadin/ui/AbstractOrderedLayout.java
@@ -23,7 +23,7 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
private static final String CLICK_EVENT = EventId.LAYOUT_CLICK;
- private static final Alignment ALIGNMENT_DEFAULT = Alignment.TOP_LEFT;
+ public static final Alignment ALIGNMENT_DEFAULT = Alignment.TOP_LEFT;
/**
* Custom layout slots containing the components.
diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java
index c64cd386ce..122d155e0f 100644
--- a/src/com/vaadin/ui/Button.java
+++ b/src/com/vaadin/ui/Button.java
@@ -176,15 +176,29 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
if (newValue != null && !newValue.equals(oldValue)
&& !isReadOnly()) {
setValue(newValue);
- fireClick(MouseEventDetails.deSerialize((String) variables
- .get("mousedetails")));
+ if (variables.containsKey("mousedetails")) {
+ fireClick(MouseEventDetails
+ .deSerialize((String) variables
+ .get("mousedetails")));
+ } else {
+ // for compatibility with custom implementations which
+ // don't send mouse details
+ fireClick();
+ }
}
} else {
// Only send click event if the button is pushed
if (newValue.booleanValue()) {
- fireClick(MouseEventDetails.deSerialize((String) variables
- .get("mousedetails")));
+ if (variables.containsKey("mousedetails")) {
+ fireClick(MouseEventDetails
+ .deSerialize((String) variables
+ .get("mousedetails")));
+ } else {
+ // for compatibility with custom implementations which
+ // don't send mouse details
+ fireClick();
+ }
}
// If the button is true for some reason, release it
@@ -298,7 +312,7 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
*/
public class ClickEvent extends Component.Event {
- private MouseEventDetails details;
+ private final MouseEventDetails details;
/**
* New instance of text change event.
@@ -308,6 +322,7 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
*/
public ClickEvent(Component source) {
super(source);
+ details = null;
}
/**
@@ -336,20 +351,28 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
* Returns the mouse position (x coordinate) when the click took place.
* The position is relative to the browser client area.
*
- * @return The mouse cursor x position
+ * @return The mouse cursor x position or -1 if unknown
*/
public int getClientX() {
- return details.getClientX();
+ if (null != details) {
+ return details.getClientX();
+ } else {
+ return -1;
+ }
}
/**
* Returns the mouse position (y coordinate) when the click took place.
* The position is relative to the browser client area.
*
- * @return The mouse cursor y position
+ * @return The mouse cursor y position or -1 if unknown
*/
public int getClientY() {
- return details.getClientY();
+ if (null != details) {
+ return details.getClientY();
+ } else {
+ return -1;
+ }
}
/**
@@ -360,7 +383,11 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
* component or -1 if no x coordinate available
*/
public int getRelativeX() {
- return details.getRelativeX();
+ if (null != details) {
+ return details.getRelativeX();
+ } else {
+ return -1;
+ }
}
/**
@@ -371,46 +398,67 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
* component or -1 if no y coordinate available
*/
public int getRelativeY() {
- return details.getRelativeY();
+ if (null != details) {
+ return details.getRelativeY();
+ } else {
+ return -1;
+ }
}
/**
* Checks if the Alt key was down when the mouse event took place.
*
* @return true if Alt was down when the event occured, false otherwise
+ * or if unknown
*/
public boolean isAltKey() {
- return details.isAltKey();
+ if (null != details) {
+ return details.isAltKey();
+ } else {
+ return false;
+ }
}
/**
* Checks if the Ctrl key was down when the mouse event took place.
*
* @return true if Ctrl was pressed when the event occured, false
- * otherwise
+ * otherwise or if unknown
*/
public boolean isCtrlKey() {
- return details.isCtrlKey();
+ if (null != details) {
+ return details.isCtrlKey();
+ } else {
+ return false;
+ }
}
/**
* Checks if the Meta key was down when the mouse event took place.
*
* @return true if Meta was pressed when the event occured, false
- * otherwise
+ * otherwise or if unknown
*/
public boolean isMetaKey() {
- return details.isMetaKey();
+ if (null != details) {
+ return details.isMetaKey();
+ } else {
+ return false;
+ }
}
/**
* Checks if the Shift key was down when the mouse event took place.
*
* @return true if Shift was pressed when the event occured, false
- * otherwise
+ * otherwise or if unknown
*/
public boolean isShiftKey() {
- return details.isShiftKey();
+ if (null != details) {
+ return details.isShiftKey();
+ } else {
+ return false;
+ }
}
}
@@ -457,13 +505,25 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
}
/**
- * Emits the options change event.
+ * Fires a click event to all listeners without any event details.
+ *
+ * In subclasses, override {@link #fireClick(MouseEventDetails)} instead of
+ * this method.
*/
protected void fireClick() {
fireEvent(new Button.ClickEvent(this));
}
- private void fireClick(MouseEventDetails details) {
+ /**
+ * Fires a click event to all listeners.
+ *
+ * @param details
+ * MouseEventDetails from which keyboard modifiers and other
+ * information about the mouse click can be obtained. If the
+ * button was clicked by a keyboard event, some of the fields may
+ * be empty/undefined.
+ */
+ protected void fireClick(MouseEventDetails details) {
fireEvent(new Button.ClickEvent(this, details));
}
diff --git a/src/com/vaadin/ui/MenuBar.java b/src/com/vaadin/ui/MenuBar.java
index d79e070fca..f8fbf91712 100644
--- a/src/com/vaadin/ui/MenuBar.java
+++ b/src/com/vaadin/ui/MenuBar.java
@@ -123,7 +123,12 @@ public class MenuBar extends AbstractComponent {
if (description != null && description.length() > 0) {
target.addAttribute("description", description);
}
-
+ if (item.isCheckable()) {
+ // if the "checked" attribute is present (either true or false),
+ // the item is checkable
+ target.addAttribute(VMenuBar.ATTRIBUTE_CHECKED,
+ item.isChecked());
+ }
if (item.hasChildren()) {
for (MenuItem child : item.getChildren()) {
paintItem(target, child);
@@ -167,7 +172,12 @@ public class MenuBar extends AbstractComponent {
// If we got the clicked item, launch the command.
if (found && tmpItem.isEnabled()) {
- tmpItem.getCommand().menuSelected(tmpItem);
+ if (tmpItem.isCheckable()) {
+ tmpItem.setChecked(!tmpItem.isChecked());
+ }
+ if (null != tmpItem.getCommand()) {
+ tmpItem.getCommand().menuSelected(tmpItem);
+ }
}
}// if
}// changeVariables
@@ -431,6 +441,8 @@ public class MenuBar extends AbstractComponent {
private boolean isSeparator = false;
private String styleName;
private String description;
+ private boolean checkable = false;
+ private boolean checked = false;
/**
* Constructs a new menu item that can optionally have an icon and a
@@ -505,13 +517,19 @@ public class MenuBar extends AbstractComponent {
* the icon for the menu item
* @param command
* the command for the menu item
+ * @throws IllegalStateException
+ * If the item is checkable and thus cannot have children.
*/
public MenuBar.MenuItem addItem(String caption, Resource icon,
- MenuBar.Command command) {
+ MenuBar.Command command) throws IllegalStateException {
if (isSeparator()) {
throw new UnsupportedOperationException(
"Cannot add items to a separator");
}
+ if (isCheckable()) {
+ throw new IllegalStateException(
+ "A checkable item cannot have children");
+ }
if (caption == null) {
throw new IllegalArgumentException("Caption cannot be null");
}
@@ -544,11 +562,16 @@ public class MenuBar extends AbstractComponent {
* the command for the menu item
* @param itemToAddBefore
* the item that will be after the new item
- *
+ * @throws IllegalStateException
+ * If the item is checkable and thus cannot have children.
*/
public MenuBar.MenuItem addItemBefore(String caption, Resource icon,
- MenuBar.Command command, MenuBar.MenuItem itemToAddBefore) {
-
+ MenuBar.Command command, MenuBar.MenuItem itemToAddBefore)
+ throws IllegalStateException {
+ if (isCheckable()) {
+ throw new IllegalStateException(
+ "A checkable item cannot have children");
+ }
MenuItem newItem = null;
if (hasChildren() && itsChildren.contains(itemToAddBefore)) {
@@ -814,6 +837,93 @@ public class MenuBar extends AbstractComponent {
return description;
}
+ /**
+ * Gets the checkable state of the item - whether the item has checked
+ * and unchecked states. If an item is checkable its checked state (as
+ * returned by {@link #isChecked()}) is indicated in the UI.
+ *
+ * <p>
+ * An item is not checkable by default.
+ * </p>
+ *
+ * @return true if the item is checkable, false otherwise
+ * @since 6.6.2
+ */
+ public boolean isCheckable() {
+ return checkable;
+ }
+
+ /**
+ * Sets the checkable state of the item. If an item is checkable its
+ * checked state (as returned by {@link #isChecked()}) is indicated in
+ * the UI.
+ *
+ * <p>
+ * An item is not checkable by default.
+ * </p>
+ *
+ * <p>
+ * Items with sub items cannot be checkable.
+ * </p>
+ *
+ * @param checkable
+ * true if the item should be checkable, false otherwise
+ * @throws IllegalStateException
+ * If the item has children
+ * @since 6.6.2
+ */
+ public void setCheckable(boolean checkable)
+ throws IllegalStateException {
+ if (hasChildren()) {
+ throw new IllegalStateException(
+ "A menu item with children cannot be checkable");
+ }
+ this.checkable = checkable;
+ requestRepaint();
+ }
+
+ /**
+ * Gets the checked state of the item (checked or unchecked). Only used
+ * if the item is checkable (as indicated by {@link #isCheckable()}).
+ * The checked state is indicated in the UI with the item, if the item
+ * is checkable.
+ *
+ * <p>
+ * An item is not checked by default.
+ * </p>
+ *
+ * <p>
+ * The CSS style corresponding to the checked state is "-checked".
+ * </p>
+ *
+ * @return true if the item is checked, false otherwise
+ * @since 6.6.2
+ */
+ public boolean isChecked() {
+ return checked;
+ }
+
+ /**
+ * Sets the checked state of the item. Only used if the item is
+ * checkable (indicated by {@link #isCheckable()}). The checked state is
+ * indicated in the UI with the item, if the item is checkable.
+ *
+ * <p>
+ * An item is not checked by default.
+ * </p>
+ *
+ * <p>
+ * The CSS style corresponding to the checked state is "-checked".
+ * </p>
+ *
+ * @return true if the item is checked, false otherwise
+ * @since 6.6.2
+ */
+ public void setChecked(boolean checked) {
+ this.checked = checked;
+ requestRepaint();
+ }
+
}// class MenuItem
}// class MenuBar
diff --git a/src/com/vaadin/ui/themes/BaseTheme.java b/src/com/vaadin/ui/themes/BaseTheme.java
index babdb1f1d5..c8ba08d30d 100644
--- a/src/com/vaadin/ui/themes/BaseTheme.java
+++ b/src/com/vaadin/ui/themes/BaseTheme.java
@@ -44,12 +44,4 @@ public class BaseTheme {
@Deprecated
public static final String PANEL_LIGHT = "light";
- /**
- * Adds connector lines between the tree nodes to better visualize the
- * hierarchy.
- *
- * @since 6.6.1
- */
- public static final String TREE_CONNECTORS = "connectors";
-
} \ No newline at end of file