aboutsummaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorHenri Sara <hesara@vaadin.com>2012-01-27 18:38:13 +0200
committerHenri Sara <hesara@vaadin.com>2012-01-27 18:38:13 +0200
commit91b3084e060f975ee35573972ace8bcf8fe3a5ed (patch)
tree154bb05f457b91388454fe42cd7652ca0d05c688 /src/com
parent06ef07c7fd6eab0b7446367fa5a43384ae469cef (diff)
downloadvaadin-framework-91b3084e060f975ee35573972ace8bcf8fe3a5ed.tar.gz
vaadin-framework-91b3084e060f975ee35573972ace8bcf8fe3a5ed.zip
Merge changes from master to rpc branch.
Diffstat (limited to 'src/com')
-rw-r--r--src/com/vaadin/data/validator/CompositeValidator.java2
-rw-r--r--src/com/vaadin/launcher/util/BrowserLauncher.java127
-rw-r--r--src/com/vaadin/terminal/Sizeable.java4
-rw-r--r--src/com/vaadin/terminal/UserError.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConnection.java190
-rw-r--r--src/com/vaadin/terminal/gwt/client/Container.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/Util.java20
-rw-r--r--src/com/vaadin/terminal/gwt/client/VDebugConsole.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/VPaintable.java57
-rw-r--r--src/com/vaadin/terminal/gwt/client/VPaintableMap.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/VPaintableWidget.java3
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java9
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java44
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VButton.java82
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VButtonPaintable.java87
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java200
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java34
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java149
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java161
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VNativeButton.java77
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VNativeButtonPaintable.java83
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java936
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java420
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java254
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VSlider.java1142
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTextArea.java7
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTextField.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java35
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java92
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java101
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VUpload.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VView.java8
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VWindow.java82
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java7
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java22
-rw-r--r--src/com/vaadin/ui/AbstractComponent.java10
-rw-r--r--src/com/vaadin/ui/AbstractSelect.java112
-rw-r--r--src/com/vaadin/ui/Button.java3
-rw-r--r--src/com/vaadin/ui/Component.java13
-rw-r--r--src/com/vaadin/ui/CssLayout.java26
-rw-r--r--src/com/vaadin/ui/MenuBar.java3
-rw-r--r--src/com/vaadin/ui/NativeButton.java4
-rw-r--r--src/com/vaadin/ui/Table.java354
-rw-r--r--src/com/vaadin/ui/TreeTable.java7
46 files changed, 2765 insertions, 2253 deletions
diff --git a/src/com/vaadin/data/validator/CompositeValidator.java b/src/com/vaadin/data/validator/CompositeValidator.java
index 083af70f30..956d773032 100644
--- a/src/com/vaadin/data/validator/CompositeValidator.java
+++ b/src/com/vaadin/data/validator/CompositeValidator.java
@@ -155,7 +155,7 @@ public class CompositeValidator implements Validator {
*/
public void setMode(CombinationMode mode) {
if (mode == null) {
- throw new IllegalStateException(
+ throw new IllegalArgumentException(
"The validator can't be set to null");
}
this.mode = mode;
diff --git a/src/com/vaadin/launcher/util/BrowserLauncher.java b/src/com/vaadin/launcher/util/BrowserLauncher.java
deleted file mode 100644
index 55692cb251..0000000000
--- a/src/com/vaadin/launcher/util/BrowserLauncher.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.launcher.util;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-/**
- * This class opens default browser for DemoLauncher class. Default browser is
- * detected by the operating system.
- *
- */
-public class BrowserLauncher {
-
- /**
- * Open browser on specified URL.
- *
- * @param url
- */
- public static void openBrowser(String url) {
-
- final Runtime runtime = Runtime.getRuntime();
- boolean started = false;
-
- final String os = System.getProperty("os.name", "windows")
- .toLowerCase();
-
- // Linux
- if (os.indexOf("linux") >= 0) {
- // See if the default browser is Konqueror by resolving the symlink.
- boolean isDefaultKonqueror = false;
- try {
- // Find out the location of the x-www-browser link from path.
- Process process = runtime.exec("which x-www-browser");
- BufferedInputStream ins = new BufferedInputStream(
- process.getInputStream());
- BufferedReader bufreader = new BufferedReader(
- new InputStreamReader(ins));
- String defaultLinkPath = bufreader.readLine();
- ins.close();
-
- // The path is null if the link did not exist.
- if (defaultLinkPath != null) {
- // See if the default browser is Konqueror.
- File file = new File(defaultLinkPath);
- String canonical = file.getCanonicalPath();
- if (canonical.indexOf("konqueror") != -1) {
- isDefaultKonqueror = true;
- }
- }
- } catch (IOException e1) {
- // The symlink was probably not found, so this is ok.
- }
-
- // Try x-www-browser, which is symlink to the default browser,
- // except if we found that it is Konqueror.
- if (!started && !isDefaultKonqueror) {
- try {
- runtime.exec("x-www-browser " + url);
- started = true;
- } catch (final IOException e) {
- }
- }
-
- // Try firefox
- if (!started) {
- try {
- runtime.exec("firefox " + url);
- started = true;
- } catch (final IOException e) {
- }
- }
-
- // Try mozilla
- if (!started) {
- try {
- runtime.exec("mozilla " + url);
- started = true;
- } catch (final IOException e) {
- }
- }
-
- // Try konqueror
- if (!started) {
- try {
- runtime.exec("konqueror " + url);
- started = true;
- } catch (final IOException e) {
- }
- }
- }
-
- // OS X
- if (os.indexOf("mac os x") >= 0) {
-
- // Try open
- if (!started) {
- try {
- runtime.exec("open " + url);
- started = true;
- } catch (final IOException e) {
- }
- }
- }
-
- // Try cmd /start command on windows
- if (os.indexOf("win") >= 0) {
- if (!started) {
- try {
- runtime.exec("cmd /c start " + url);
- started = true;
- } catch (final IOException e) {
- }
- }
- }
-
- if (!started) {
- System.out.println("Failed to open browser. Please go to " + url);
- }
- }
-
-}
diff --git a/src/com/vaadin/terminal/Sizeable.java b/src/com/vaadin/terminal/Sizeable.java
index 055c74f20f..e3c98e0fa9 100644
--- a/src/com/vaadin/terminal/Sizeable.java
+++ b/src/com/vaadin/terminal/Sizeable.java
@@ -129,14 +129,14 @@ public interface Sizeable extends Serializable {
public static Unit getUnitFromSymbol(String symbol) {
if (symbol == null) {
- return null;
+ return Unit.PIXELS; // Defaults to pixels
}
for (Unit unit : Unit.values()) {
if (symbol.equals(unit.getSymbol())) {
return unit;
}
}
- return null;
+ return Unit.PIXELS; // Defaults to pixels
}
}
diff --git a/src/com/vaadin/terminal/UserError.java b/src/com/vaadin/terminal/UserError.java
index 1cb79c146a..8ec45ac725 100644
--- a/src/com/vaadin/terminal/UserError.java
+++ b/src/com/vaadin/terminal/UserError.java
@@ -89,6 +89,12 @@ public class UserError implements ErrorMessage {
public UserError(String message, ContentMode contentMode,
ErrorLevel errorLevel) {
+ if (contentMode == null) {
+ contentMode = ContentMode.TEXT;
+ }
+ if (errorLevel == null) {
+ errorLevel = ErrorLevel.ERROR;
+ }
msg = message;
mode = contentMode;
level = errorLevel;
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
index 5e1bb89b0c..e790c1d3fc 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
@@ -25,6 +25,8 @@ import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONString;
+import com.google.gwt.regexp.shared.MatchResult;
+import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
@@ -41,6 +43,7 @@ import com.vaadin.terminal.gwt.client.RenderInformation.Size;
import com.vaadin.terminal.gwt.client.communication.JsonEncoder;
import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
import com.vaadin.terminal.gwt.client.ui.Field;
+import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget;
import com.vaadin.terminal.gwt.client.ui.VContextMenu;
import com.vaadin.terminal.gwt.client.ui.VNotification;
import com.vaadin.terminal.gwt.client.ui.VNotification.HideEvent;
@@ -102,6 +105,27 @@ public class ApplicationConnection {
public static final String ATTRIBUTE_DESCRIPTION = "description";
public static final String ATTRIBUTE_ERROR = "error";
+ /**
+ * A string that, if found in a non-JSON response to a UIDL request, will
+ * cause the browser to refresh the page. If followed by a colon, optional
+ * whitespace, and a URI, causes the browser to synchronously load the URI.
+ *
+ * <p>
+ * This allows, for instance, a servlet filter to redirect the application
+ * to a custom login page when the session expires. For example:
+ * </p>
+ *
+ * <pre>
+ * if (sessionExpired) {
+ * response.setHeader(&quot;Content-Type&quot;, &quot;text/html&quot;);
+ * response.getWriter().write(
+ * myLoginPageHtml + &quot;&lt;!-- Vaadin-Refresh: &quot;
+ * + request.getContextPath() + &quot; --&gt;&quot;);
+ * }
+ * </pre>
+ */
+ public static final String UIDL_REFRESH_TOKEN = "Vaadin-Refresh";
+
// will hold the UIDL security key (for XSS protection) once received
private String uidlSecurityKey = "init";
@@ -526,6 +550,25 @@ public class ApplicationConnection {
return;
}
+ String contentType = response.getHeader("Content-Type");
+ if (contentType == null
+ || !contentType.startsWith("application/json")) {
+ /*
+ * A servlet filter or equivalent may have intercepted
+ * the request and served non-UIDL content (for
+ * instance, a login page if the session has expired.)
+ * If the response contains a magic substring, do a
+ * synchronous refresh. See #8241.
+ */
+ MatchResult refreshToken = RegExp.compile(
+ UIDL_REFRESH_TOKEN + "(:\\s*(.*?))?(\\s|$)")
+ .exec(response.getText());
+ if (refreshToken != null) {
+ redirect(refreshToken.getGroup(2));
+ return;
+ }
+ }
+
// for(;;);[realjson]
final String jsonText = response.getText().substring(9,
response.getText().length() - 1);
@@ -1540,9 +1583,10 @@ public class ApplicationConnection {
*
* @return Returns true iff no further painting is needed by caller
*/
- public boolean updateComponent(Widget component, UIDL uidl,
+ @Deprecated
+ public boolean updateComponent(VPaintableWidget paintable, UIDL uidl,
boolean manageCaption) {
- VPaintableWidget paintable = paintableMap.getPaintable(component);
+ Widget component = paintable.getWidgetForPaintable();
String pid = paintableMap.getPid(paintable);
if (pid == null) {
@@ -1603,9 +1647,68 @@ public class ApplicationConnection {
fw.setEnabled(enabled);
}
+ // Style names
+ component.setStyleName(getStyleName(component.getStylePrimaryName(),
+ uidl, component instanceof Field));
+
+ TooltipInfo tooltipInfo = paintableMap.getTooltipInfo(paintable, null);
+ // Update tooltip
+ if (uidl.hasAttribute(ATTRIBUTE_DESCRIPTION)) {
+ tooltipInfo
+ .setTitle(uidl.getStringAttribute(ATTRIBUTE_DESCRIPTION));
+ } else {
+ tooltipInfo.setTitle(null);
+ }
+
+ // Set captions
+ if (manageCaption) {
+ final Container parent = Util.getLayout(component);
+ if (parent != null) {
+ parent.updateCaption(paintable, uidl);
+ }
+ }
+
+ // add error classname to components w/ error
+ if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
+ tooltipInfo.setErrorUidl(uidl.getErrors());
+ } else {
+ tooltipInfo.setErrorUidl(null);
+ }
+
+ // Set captions
+ if (manageCaption) {
+ final Container parent = Util.getLayout(component);
+ if (parent != null) {
+ parent.updateCaption(paintable, uidl);
+ }
+ }
+ /*
+ * updateComponentSize need to be after caption update so caption can be
+ * taken into account
+ */
+
+ updateComponentSize(paintable, uidl);
+
+ return false;
+ }
+
+ /**
+ * Generates the style name for the widget based on the given primary style
+ * name (typically returned by Widget.getPrimaryStyleName()) and the UIDL.
+ * An additional "modified" style name can be added if the field parameter
+ * is set to true.
+ *
+ * @param primaryStyleName
+ * @param uidl
+ * @param isField
+ * @return
+ */
+ public static String getStyleName(String primaryStyleName, UIDL uidl,
+ boolean field) {
+ boolean enabled = !uidl.getBooleanAttribute("disabled");
+
StringBuffer styleBuf = new StringBuffer();
- final String primaryName = component.getStylePrimaryName();
- styleBuf.append(primaryName);
+ styleBuf.append(primaryStyleName);
// first disabling and read-only status
if (!enabled) {
@@ -1623,7 +1726,7 @@ public class ApplicationConnection {
final String[] styles = uidl.getStringAttribute("style").split(" ");
for (int i = 0; i < styles.length; i++) {
styleBuf.append(" ");
- styleBuf.append(primaryName);
+ styleBuf.append(primaryStyleName);
styleBuf.append("-");
styleBuf.append(styles[i]);
styleBuf.append(" ");
@@ -1632,55 +1735,25 @@ public class ApplicationConnection {
}
// add modified classname to Fields
- if (uidl.hasAttribute("modified") && component instanceof Field) {
+ if (field && uidl.hasAttribute("modified")) {
styleBuf.append(" ");
styleBuf.append(MODIFIED_CLASSNAME);
}
- TooltipInfo tooltipInfo = paintableMap.getTooltipInfo(paintable, null);
- // Update tooltip
- if (uidl.hasAttribute(ATTRIBUTE_DESCRIPTION)) {
- tooltipInfo
- .setTitle(uidl.getStringAttribute(ATTRIBUTE_DESCRIPTION));
- } else {
- tooltipInfo.setTitle(null);
- }
-
// add error classname to components w/ error
if (uidl.hasAttribute(ATTRIBUTE_ERROR)) {
- tooltipInfo.setErrorUidl(uidl.getErrors());
styleBuf.append(" ");
- styleBuf.append(primaryName);
+ styleBuf.append(primaryStyleName);
styleBuf.append(ERROR_CLASSNAME_EXT);
- } else {
- tooltipInfo.setErrorUidl(null);
}
-
// add required style to required components
if (uidl.hasAttribute("required")) {
styleBuf.append(" ");
- styleBuf.append(primaryName);
+ styleBuf.append(primaryStyleName);
styleBuf.append(REQUIRED_CLASSNAME_EXT);
}
- // Styles + disabled & readonly
- component.setStyleName(styleBuf.toString());
-
- // Set captions
- if (manageCaption) {
- final Container parent = Util.getLayout(component);
- if (parent != null) {
- parent.updateCaption(paintable, uidl);
- }
- }
- /*
- * updateComponentSize need to be after caption update so caption can be
- * taken into account
- */
-
- updateComponentSize(paintable, uidl);
-
- return false;
+ return styleBuf.toString();
}
private void updateComponentSize(VPaintableWidget paintable, UIDL uidl) {
@@ -1773,7 +1846,7 @@ public class ApplicationConnection {
while (childWidgets.hasNext()) {
final Widget child = childWidgets.next();
- if (child instanceof VPaintableWidget) {
+ if (getPaintableMap().isPaintable(child)) {
if (handleComponentRelativeSize(child)) {
/*
@@ -1808,7 +1881,7 @@ public class ApplicationConnection {
if (paintable == null) {
return false;
}
- boolean debugSizes = false;
+ boolean debugSizes = true;
FloatSize relativeSize = paintableMap.getRelativeSize(paintable);
if (relativeSize == null) {
@@ -1983,6 +2056,10 @@ public class ApplicationConnection {
if (!paintableMap.hasPaintable(pid)) {
// Create and register a new paintable if no old was found
VPaintableWidget p = widgetSet.createWidget(uidl, configuration);
+ if (p instanceof VAbstractPaintableWidget) {
+ ((VAbstractPaintableWidget) p).setConnection(this);
+ ((VAbstractPaintableWidget) p).init();
+ }
paintableMap.registerPaintable(pid, p);
}
return (VPaintableWidget) paintableMap.getPaintable(pid);
@@ -2146,7 +2223,7 @@ public class ApplicationConnection {
}
};
- private VPaintableMap paintableMap = new VPaintableMap();
+ private VPaintableMap paintableMap = GWT.create(VPaintableMap.class);
/**
* Components can call this function to run all layout functions. This is
@@ -2229,7 +2306,7 @@ public class ApplicationConnection {
* @return true if at least one listener has been registered on server side
* for the event identified by eventIdentifier.
*/
- public boolean hasEventListeners(VPaintable paintable,
+ public boolean hasEventListeners(VPaintableWidget paintable,
String eventIdentifier) {
return paintableMap.hasEventListeners(paintable, eventIdentifier);
}
@@ -2284,4 +2361,31 @@ public class ApplicationConnection {
paintableMap.unregisterPaintable(p);
}
+ public VTooltip getVTooltip() {
+ return tooltip;
+ }
+
+ @Deprecated
+ public void handleWidgetTooltipEvent(Event event, Widget owner, Object key) {
+ handleTooltipEvent(event, getPaintableMap().getPaintable(owner), key);
+
+ }
+
+ @Deprecated
+ public void handleWidgetTooltipEvent(Event event, Widget owner) {
+ handleTooltipEvent(event, getPaintableMap().getPaintable(owner));
+
+ }
+
+ @Deprecated
+ public void registerWidgetTooltip(Widget owner, Object key, TooltipInfo info) {
+ registerTooltip(getPaintableMap().getPaintable(owner), key, info);
+ }
+
+ @Deprecated
+ public boolean hasWidgetEventListeners(Widget widget, String eventIdentifier) {
+ return hasEventListeners(getPaintableMap().getPaintable(widget),
+ eventIdentifier);
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/Container.java b/src/com/vaadin/terminal/gwt/client/Container.java
index 7c92bc261b..db6bbf0ee4 100644
--- a/src/com/vaadin/terminal/gwt/client/Container.java
+++ b/src/com/vaadin/terminal/gwt/client/Container.java
@@ -42,12 +42,12 @@ public interface Container extends VPaintableWidget {
* must provide service for it's childen to show those elements for them.
* </p>
*
- * @param component
+ * @param paintable
* Child component for which service is requested.
* @param uidl
* UIDL of the child component.
*/
- void updateCaption(VPaintableWidget component, UIDL uidl);
+ void updateCaption(VPaintableWidget paintable, UIDL uidl);
/**
* Called when a child components size has been updated in the rendering
diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java
index b411d9a89e..4487341bd7 100644
--- a/src/com/vaadin/terminal/gwt/client/Util.java
+++ b/src/com/vaadin/terminal/gwt/client/Util.java
@@ -832,6 +832,24 @@ public class Util {
}-*/;
/**
+ * Helper method to find the nearest parent paintable instance by traversing
+ * the DOM upwards from given element.
+ *
+ * @param element
+ * the element to start from
+ */
+ public static VPaintableWidget findPaintable(ApplicationConnection client,
+ Element element) {
+ Widget widget = Util.findWidget(element, null);
+ VPaintableMap vPaintableMap = VPaintableMap.get(client);
+ while (widget != null && !vPaintableMap.isPaintable(widget)) {
+ widget = widget.getParent();
+ }
+ return vPaintableMap.getPaintable(widget);
+
+ }
+
+ /**
* Helper method to find first instance of given Widget type found by
* traversing DOM upwards from given element.
*
@@ -968,6 +986,8 @@ public class Util {
+ invocation.getMethodName() + "(" + formattedParams
+ ")");
}
+ } else {
+ VConsole.log("\t" + id + ": Warning: no corresponding paintable!");
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/VDebugConsole.java b/src/com/vaadin/terminal/gwt/client/VDebugConsole.java
index 892260e6ca..fdaf944b9f 100644
--- a/src/com/vaadin/terminal/gwt/client/VDebugConsole.java
+++ b/src/com/vaadin/terminal/gwt/client/VDebugConsole.java
@@ -734,8 +734,10 @@ public class VDebugConsole extends VOverlay implements Console {
forceLayout.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
- // TODO for each client in appconf force layout
- // VDebugConsole.this.client.forceLayout();
+ for (ApplicationConnection applicationConnection : ApplicationConfiguration
+ .getRunningApplications()) {
+ applicationConnection.forceLayout();
+ }
}
});
diff --git a/src/com/vaadin/terminal/gwt/client/VPaintable.java b/src/com/vaadin/terminal/gwt/client/VPaintable.java
index 02b529b428..d85c6d33e2 100644
--- a/src/com/vaadin/terminal/gwt/client/VPaintable.java
+++ b/src/com/vaadin/terminal/gwt/client/VPaintable.java
@@ -4,8 +4,13 @@
package com.vaadin.terminal.gwt.client;
/**
- * TODO
+ * Interface implemented by all client side classes that can be communicate with
+ * the server. Classes implementing this interface are initialized by the
+ * framework when needed and have the ability to communicate with the server.
*
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
*/
public interface VPaintable {
/**
@@ -16,4 +21,54 @@ public interface VPaintable {
*/
public void updateFromUIDL(UIDL uidl, ApplicationConnection client);
+ // /**
+ // * Returns the id for this VPaintable. This must always be what has been
+ // set
+ // * using {@link #setId(String)}.
+ // *
+ // * @return The id for the VPaintable.
+ // */
+ // public String getId();
+ //
+ // /**
+ // * Sets the id for the VPaintable. This method is called once by the
+ // * framework when the VPaintable is initialized and should never be called
+ // * otherwise.
+ // * <p>
+ // * The VPaintable id is used to map the server and the client paintables
+ // * together. It is unique in this root and assigned by the framework.
+ // * </p>
+ // *
+ // * @param id
+ // * The id of the paintable.
+ // */
+ // public void setId(String id);
+
+ /**
+ * Gets ApplicationConnection instance that created this VPaintable.
+ *
+ * @return The ApplicationConnection as set by
+ * {@link #setConnection(ApplicationConnection)}
+ */
+ // public ApplicationConnection getConnection();
+
+ /**
+ * Sets the reference to ApplicationConnection. This method is called by the
+ * framework when the VPaintable is created and should never be called
+ * otherwise.
+ *
+ * @param connection
+ * The ApplicationConnection that created this VPaintable
+ */
+ // public void setConnection(ApplicationConnection connection);
+
+ /**
+ * Tests whether the component is enabled or not. A user can not interact
+ * with disabled components. Disabled components are rendered in a style
+ * that indicates the status, usually in gray color. Children of a disabled
+ * component are also disabled.
+ *
+ * @return true if the component is enabled, false otherwise
+ */
+ // public boolean isEnabled();
}
diff --git a/src/com/vaadin/terminal/gwt/client/VPaintableMap.java b/src/com/vaadin/terminal/gwt/client/VPaintableMap.java
index ef355d3cad..f21d85558c 100644
--- a/src/com/vaadin/terminal/gwt/client/VPaintableMap.java
+++ b/src/com/vaadin/terminal/gwt/client/VPaintableMap.java
@@ -335,7 +335,7 @@ public class VPaintableMap {
}
- private ComponentDetail getComponentDetail(VPaintable paintable) {
+ private ComponentDetail getComponentDetail(VPaintableWidget paintable) {
return idToComponentDetail.get(getPid(paintable));
}
@@ -344,7 +344,7 @@ public class VPaintableMap {
}
/**
- * FIXME: Should not be here
+ * FIXME: Should be moved to VAbstractPaintableWidget
*
* @param paintable
* @return
@@ -354,6 +354,11 @@ public class VPaintableMap {
return getComponentDetail(paintable).getTooltipInfo(key);
}
+ @Deprecated
+ public TooltipInfo getWidgetTooltipInfo(Widget widget, Object key) {
+ return getTooltipInfo(getPaintable(widget), key);
+ }
+
public Collection<? extends VPaintable> getPaintables() {
return Collections.unmodifiableCollection(paintableToId.keySet());
}
@@ -378,7 +383,7 @@ public class VPaintableMap {
* @return
*/
@Deprecated
- public boolean hasEventListeners(VPaintable paintable,
+ public boolean hasEventListeners(VPaintableWidget paintable,
String eventIdentifier) {
return getComponentDetail(paintable).hasEventListeners(eventIdentifier);
}
diff --git a/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java b/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java
index 9171fdceda..2f0cae1cc1 100644
--- a/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java
+++ b/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java
@@ -17,7 +17,8 @@ import com.google.gwt.user.client.ui.Widget;
public interface VPaintableWidget extends VPaintable {
/**
- * TODO: Renamed to getWidget
+ * TODO: Rename to getWidget
*/
public Widget getWidgetForPaintable();
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java b/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java
index 38f7878ba4..2bd578a45d 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java
@@ -15,13 +15,11 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.KeyboardListenerCollection;
-import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.Container;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VPaintableMap;
import com.vaadin.terminal.gwt.client.VPaintableWidget;
import com.vaadin.terminal.gwt.client.ui.richtextarea.VRichTextArea;
@@ -137,12 +135,7 @@ public class ShortcutActionHandler {
VPaintableWidget target) {
final Element et = DOM.eventGetTarget(event);
if (target == null) {
- Widget w = Util.findWidget(et, null);
- VPaintableMap paintableMap = VPaintableMap.get(client);
- while (w != null && !paintableMap.isPaintable(w)) {
- w = w.getParent();
- }
- target = paintableMap.getPaintable(w);
+ target = Util.findPaintable(client, et);
}
final VPaintableWidget finalTarget = target;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java
index dff5a286ba..9a2e728454 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java
@@ -1,12 +1,19 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
package com.vaadin.terminal.gwt.client.ui;
-import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.VPaintableWidget;
public abstract class VAbstractPaintableWidget implements VPaintableWidget {
private Widget widget;
+ private ApplicationConnection connection;
+
+ /* State variables */
+ // private boolean enabled = true;
/**
* Default constructor
@@ -15,14 +22,18 @@ public abstract class VAbstractPaintableWidget implements VPaintableWidget {
}
/**
+ * Called after the application connection reference has been set up
+ */
+ public void init() {
+ }
+
+ /**
* Creates and returns the widget for this VPaintableWidget. This method
* should only be called once when initializing the paintable.
*
* @return
*/
- protected Widget createWidget() {
- return GWT.create(getWidgetClass());
- }
+ protected abstract Widget createWidget();
/**
* Returns the widget associated with this paintable. The widget returned by
@@ -38,12 +49,27 @@ public abstract class VAbstractPaintableWidget implements VPaintableWidget {
return widget;
}
- /**
- * Returns the class of the widget for this paintable. Used to instansiate
- * the widget.
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.terminal.gwt.client.VPaintable#getConnection()
+ */
+ public final ApplicationConnection getConnection() {
+ return connection;
+ }
+
+ /*
+ * (non-Javadoc)
*
- * @return The widget class.
+ * @see
+ * com.vaadin.terminal.gwt.client.VPaintable#setConnection(com.vaadin.terminal
+ * .gwt.client.ApplicationConnection)
*/
- protected abstract Class<? extends Widget> getWidgetClass();
+ public final void setConnection(ApplicationConnection connection) {
+ this.connection = connection;
+ }
+ // public boolean isEnabled() {
+ // return enabled;
+ // }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/VButton.java
index b638304657..6872d5f640 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VButton.java
@@ -23,18 +23,15 @@ import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.EventHelper;
import com.vaadin.terminal.gwt.client.EventId;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.communication.ClientToServerRpc;
import com.vaadin.terminal.gwt.client.communication.ClientToServerRpc.InitializableClientToServerRpc;
-public class VButton extends FocusWidget implements VPaintableWidget,
- ClickHandler, FocusHandler, BlurHandler {
+public class VButton extends FocusWidget implements ClickHandler, FocusHandler,
+ BlurHandler {
public static final String CLASSNAME = "v-button";
private static final String CLASSNAME_PRESSED = "v-pressed";
@@ -67,7 +64,7 @@ public class VButton extends FocusWidget implements VPaintableWidget,
protected int mousedownX = 0;
protected int mousedownY = 0;
- protected String id;
+ protected String paintableId;
protected ApplicationConnection client;
@@ -90,7 +87,7 @@ public class VButton extends FocusWidget implements VPaintableWidget,
private int tabIndex = 0;
- private boolean disableOnClick = false;
+ protected boolean disableOnClick = false;
/*
* BELOW PRIVATE MEMBERS COPY-PASTED FROM GWT CustomButton
@@ -113,10 +110,10 @@ public class VButton extends FocusWidget implements VPaintableWidget,
private boolean disallowNextClick = false;
private boolean isHovering;
- private HandlerRegistration focusHandlerRegistration;
- private HandlerRegistration blurHandlerRegistration;
+ protected HandlerRegistration focusHandlerRegistration;
+ protected HandlerRegistration blurHandlerRegistration;
- private int clickShortcut = 0;
+ protected int clickShortcut = 0;
private ButtonClientToServerRpc buttonRpcProxy;
public VButton() {
@@ -139,59 +136,6 @@ public class VButton extends FocusWidget implements VPaintableWidget,
addClickHandler(this);
}
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
-
- // Ensure correct implementation,
- // but don't let container manage caption etc.
- if (client.updateComponent(this, uidl, false)) {
- return;
- }
-
- focusHandlerRegistration = EventHelper.updateFocusHandler(this, client,
- focusHandlerRegistration);
- blurHandlerRegistration = EventHelper.updateBlurHandler(this, client,
- blurHandlerRegistration);
-
- // Save details
- this.client = client;
- id = uidl.getId();
-
- // Set text
- setText(uidl.getStringAttribute("caption"));
-
- disableOnClick = uidl.hasAttribute(ATTR_DISABLE_ON_CLICK);
-
- // handle error
- if (uidl.hasAttribute("error")) {
- if (errorIndicatorElement == null) {
- errorIndicatorElement = DOM.createSpan();
- errorIndicatorElement.setClassName("v-errorindicator");
- }
- wrapper.insertBefore(errorIndicatorElement, captionElement);
-
- } else if (errorIndicatorElement != null) {
- wrapper.removeChild(errorIndicatorElement);
- errorIndicatorElement = null;
- }
-
- if (uidl.hasAttribute("icon")) {
- if (icon == null) {
- icon = new Icon(client);
- wrapper.insertBefore(icon.getElement(), captionElement);
- }
- icon.setUri(uidl.getStringAttribute("icon"));
- } else {
- if (icon != null) {
- wrapper.removeChild(icon.getElement());
- icon = null;
- }
- }
-
- if (uidl.hasAttribute("keycode")) {
- clickShortcut = uidl.getIntAttribute("keycode");
- }
- }
-
public void setText(String text) {
captionElement.setInnerText(text);
}
@@ -212,7 +156,7 @@ public class VButton extends FocusWidget implements VPaintableWidget,
*/
public void onBrowserEvent(Event event) {
if (client != null) {
- client.handleTooltipEvent(event, this);
+ client.handleWidgetTooltipEvent(event, this);
}
if (DOM.eventGetType(event) == Event.ONLOAD) {
Util.notifyParentOfSizeChange(this, true);
@@ -374,7 +318,7 @@ public class VButton extends FocusWidget implements VPaintableWidget,
* .dom.client.ClickEvent)
*/
public void onClick(ClickEvent event) {
- if (id == null || client == null) {
+ if (paintableId == null || client == null) {
return;
}
if (BrowserInfo.get().isSafari()) {
@@ -396,8 +340,8 @@ public class VButton extends FocusWidget implements VPaintableWidget,
protected ButtonClientToServerRpc getButtonRpcProxy() {
if (null == buttonRpcProxy) {
buttonRpcProxy = GWT.create(ButtonClientToServerRpc.class);
- ((InitializableClientToServerRpc) buttonRpcProxy).initRpc(id,
- client);
+ ((InitializableClientToServerRpc) buttonRpcProxy).initRpc(
+ paintableId, client);
}
return buttonRpcProxy;
}
@@ -531,11 +475,11 @@ public class VButton extends FocusWidget implements VPaintableWidget,
}-*/;
public void onFocus(FocusEvent arg0) {
- client.updateVariable(id, EventId.FOCUS, "", true);
+ client.updateVariable(paintableId, EventId.FOCUS, "", true);
}
public void onBlur(BlurEvent arg0) {
- client.updateVariable(id, EventId.BLUR, "", true);
+ client.updateVariable(paintableId, EventId.BLUR, "", true);
}
public Widget getWidgetForPaintable() {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VButtonPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VButtonPaintable.java
new file mode 100644
index 0000000000..1367d412a8
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/VButtonPaintable.java
@@ -0,0 +1,87 @@
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.EventHelper;
+import com.vaadin.terminal.gwt.client.UIDL;
+
+public class VButtonPaintable extends VAbstractPaintableWidget {
+
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+
+ // Ensure correct implementation,
+ // but don't let container manage caption etc.
+ if (client.updateComponent(this, uidl, false)) {
+ return;
+ }
+
+ getWidgetForPaintable().focusHandlerRegistration = EventHelper
+ .updateFocusHandler(this, client,
+ getWidgetForPaintable().focusHandlerRegistration);
+ getWidgetForPaintable().blurHandlerRegistration = EventHelper
+ .updateBlurHandler(this, client,
+ getWidgetForPaintable().blurHandlerRegistration);
+
+ // Save details
+ getWidgetForPaintable().client = client;
+ getWidgetForPaintable().paintableId = uidl.getId();
+
+ // Set text
+ getWidgetForPaintable().setText(uidl.getStringAttribute("caption"));
+
+ getWidgetForPaintable().disableOnClick = uidl
+ .hasAttribute(VButton.ATTR_DISABLE_ON_CLICK);
+
+ // handle error
+ if (uidl.hasAttribute("error")) {
+ if (getWidgetForPaintable().errorIndicatorElement == null) {
+ getWidgetForPaintable().errorIndicatorElement = DOM
+ .createSpan();
+ getWidgetForPaintable().errorIndicatorElement
+ .setClassName("v-errorindicator");
+ }
+ getWidgetForPaintable().wrapper.insertBefore(
+ getWidgetForPaintable().errorIndicatorElement,
+ getWidgetForPaintable().captionElement);
+
+ } else if (getWidgetForPaintable().errorIndicatorElement != null) {
+ getWidgetForPaintable().wrapper
+ .removeChild(getWidgetForPaintable().errorIndicatorElement);
+ getWidgetForPaintable().errorIndicatorElement = null;
+ }
+
+ if (uidl.hasAttribute("icon")) {
+ if (getWidgetForPaintable().icon == null) {
+ getWidgetForPaintable().icon = new Icon(client);
+ getWidgetForPaintable().wrapper.insertBefore(
+ getWidgetForPaintable().icon.getElement(),
+ getWidgetForPaintable().captionElement);
+ }
+ getWidgetForPaintable().icon
+ .setUri(uidl.getStringAttribute("icon"));
+ } else {
+ if (getWidgetForPaintable().icon != null) {
+ getWidgetForPaintable().wrapper
+ .removeChild(getWidgetForPaintable().icon.getElement());
+ getWidgetForPaintable().icon = null;
+ }
+ }
+
+ if (uidl.hasAttribute("keycode")) {
+ getWidgetForPaintable().clickShortcut = uidl
+ .getIntAttribute("keycode");
+ }
+ }
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VButton.class);
+ }
+
+ @Override
+ public VButton getWidgetForPaintable() {
+ return (VButton) super.getWidgetForPaintable();
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java
index ed05a3e67d..b318fe0af3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java
@@ -104,6 +104,8 @@ public class VCalendarPanel extends FocusableFlexTable implements
private static final String CN_SELECTED = "selected";
+ private static final String CN_OFFMONTH = "offmonth";
+
/**
* Represents a click handler for when a user selects a value by using the
* mouse
@@ -118,7 +120,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
*/
public void onClick(ClickEvent event) {
Day day = (Day) event.getSource();
- focusDay(day.getDay());
+ focusDay(day.getDate());
selectFocused();
onSubmit();
}
@@ -152,6 +154,8 @@ public class VCalendarPanel extends FocusableFlexTable implements
private boolean showISOWeekNumbers;
+ private Date displayedMonth;
+
private Date focusedDate;
private Day selectedDay;
@@ -191,18 +195,18 @@ public class VCalendarPanel extends FocusableFlexTable implements
* Sets the focus to given day of current time. Used when moving in the
* calender with the keyboard.
*
- * @param day
+ * @param date
* The day number from by Date.getDate()
*/
- private void focusDay(int day) {
+ private void focusDay(Date day) {
// Only used when calender body is present
if (resolution > VDateField.RESOLUTION_MONTH) {
if (focusedDay != null) {
focusedDay.removeStyleDependentName(CN_FOCUSED);
}
- if (day > 0 && focusedDate != null) {
- focusedDate.setDate(day);
+ if (day != null && focusedDate != null) {
+ focusedDate.setTime(day.getTime());
int rowCount = days.getRowCount();
for (int i = 0; i < rowCount; i++) {
int cellCount = days.getCellCount(i);
@@ -210,7 +214,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
Widget widget = days.getWidget(i, j);
if (widget != null && widget instanceof Day) {
Day curday = (Day) widget;
- if (curday.getDay() == day) {
+ if (curday.getDate().equals(day)) {
curday.addStyleDependentName(CN_FOCUSED);
focusedDay = curday;
focusedRow = i;
@@ -226,9 +230,9 @@ public class VCalendarPanel extends FocusableFlexTable implements
/**
* Sets the selection hightlight to a given date of current time
*
- * @param day
+ * @param date
*/
- private void selectDate(int day) {
+ private void selectDate(Date date) {
if (selectedDay != null) {
selectedDay.removeStyleDependentName(CN_SELECTED);
}
@@ -240,7 +244,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
Widget widget = days.getWidget(i, j);
if (widget != null && widget instanceof Day) {
Day curday = (Day) widget;
- if (curday.getDay() == day) {
+ if (curday.getDate().equals(date)) {
curday.addStyleDependentName(CN_SELECTED);
selectedDay = curday;
return;
@@ -279,7 +283,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
// it was forced to 1 above.
value.setDate(focusedDate.getDate());
- selectDate(focusedDate.getDate());
+ selectDate(focusedDate);
} else {
VConsole.log("Trying to select a the focused date which is NULL!");
}
@@ -468,97 +472,62 @@ public class VCalendarPanel extends FocusableFlexTable implements
}
}
- // The day of month that is selected, -1 if no day of this month is
- // selected (i.e, showing another month/year than selected or nothing is
- // selected)
- int dayOfMonthSelected = -1;
- // The day of month that is today, -1 if no day of this month is today
- // (i.e., showing another month/year than current)
- int dayOfMonthToday = -1;
-
- boolean initiallyNull = value == null;
-
- if (!initiallyNull && value.getMonth() == focusedDate.getMonth()
- && value.getYear() == focusedDate.getYear()) {
- dayOfMonthSelected = value.getDate();
- }
- final Date today = new Date();
- if (today.getMonth() == focusedDate.getMonth()
- && today.getYear() == focusedDate.getYear()) {
- dayOfMonthToday = today.getDate();
- }
+ // today must have zeroed hours, minutes, seconds, and milliseconds
+ final Date tmp = new Date();
+ final Date today = new Date(tmp.getYear(), tmp.getMonth(),
+ tmp.getDate());
final int startWeekDay = getDateTimeService().getStartWeekDay(
focusedDate);
- final int daysInMonth = DateTimeService
- .getNumberOfDaysInMonth(focusedDate);
-
- int dayCount = 0;
- final Date curr = new Date(focusedDate.getTime());
+ final Date curr = (Date) focusedDate.clone();
+ // Start from the first day of the week that at least partially belongs
+ // to the current month
+ curr.setDate(-startWeekDay);
// No month has more than 6 weeks so 6 is a safe maximum for rows.
for (int weekOfMonth = 1; weekOfMonth < 7; weekOfMonth++) {
- boolean weekNumberProcessed[] = new boolean[] { false, false,
- false, false, false, false, false };
-
for (int dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) {
- if (!(weekOfMonth == 1 && dayOfWeek < startWeekDay)) {
-
- if (dayCount >= daysInMonth) {
- // All days printed and we are done
- break;
- }
-
- final int dayOfMonth = ++dayCount;
-
- curr.setDate(dayCount);
- // Actually write the day of month
- Day day = new Day(dayOfMonth);
+ // Actually write the day of month
+ Day day = new Day((Date) curr.clone());
- if (dayOfMonthSelected == dayOfMonth) {
- day.addStyleDependentName(CN_SELECTED);
- selectedDay = day;
+ if (curr.equals(value)) {
+ day.addStyleDependentName(CN_SELECTED);
+ selectedDay = day;
+ }
+ if (curr.equals(today)) {
+ day.addStyleDependentName(CN_TODAY);
+ }
+ if (curr.equals(focusedDate)) {
+ focusedDay = day;
+ focusedRow = weekOfMonth;
+ if (hasFocus) {
+ day.addStyleDependentName(CN_FOCUSED);
}
+ }
+ if (curr.getMonth() != focusedDate.getMonth()) {
+ day.addStyleDependentName(CN_OFFMONTH);
+ }
- if (dayOfMonthToday == dayOfMonth) {
- day.addStyleDependentName(CN_TODAY);
- }
+ days.setWidget(weekOfMonth, firstWeekdayColumn + dayOfWeek, day);
- if (dayOfMonth == focusedDate.getDate()) {
- focusedDay = day;
- focusedRow = weekOfMonth;
- if (hasFocus) {
- day.addStyleDependentName(CN_FOCUSED);
- }
- }
+ // ISO week numbers if requested
+ days.getCellFormatter().setVisible(weekOfMonth, weekColumn,
+ isShowISOWeekNumbers());
+ if (isShowISOWeekNumbers()) {
+ final String baseCssClass = VDateField.CLASSNAME
+ + "-calendarpanel-weeknumber";
+ String weekCssClass = baseCssClass;
- days.setWidget(weekOfMonth, firstWeekdayColumn + dayOfWeek,
- day);
-
- // ISO week numbers if requested
- if (!weekNumberProcessed[weekOfMonth]) {
- days.getCellFormatter().setVisible(weekOfMonth,
- weekColumn, isShowISOWeekNumbers());
- if (isShowISOWeekNumbers()) {
- final String baseCssClass = VDateField.CLASSNAME
- + "-calendarpanel-weeknumber";
- String weekCssClass = baseCssClass;
-
- int weekNumber = DateTimeService
- .getISOWeekNumber(curr);
-
- days.setHTML(weekOfMonth, 0, "<span class=\""
- + weekCssClass + "\"" + ">" + weekNumber
- + "</span>");
- weekNumberProcessed[weekOfMonth] = true;
- }
+ int weekNumber = DateTimeService.getISOWeekNumber(curr);
- }
+ days.setHTML(weekOfMonth, 0, "<span class=\""
+ + weekCssClass + "\"" + ">" + weekNumber
+ + "</span>");
}
+ curr.setDate(curr.getDate() + 1);
}
}
-
}
/**
@@ -622,6 +591,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
while (focusedDate.getMonth() != requestedMonth) {
focusedDate.setDate(focusedDate.getDate() - 1);
}
+ displayedMonth.setMonth(displayedMonth.getMonth() + 1);
renderCalendar();
}
@@ -641,6 +611,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
while (focusedDate.getMonth() == currentMonth) {
focusedDate.setDate(focusedDate.getDate() - 1);
}
+ displayedMonth.setMonth(displayedMonth.getMonth() - 1);
renderCalendar();
}
@@ -650,6 +621,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
*/
private void focusPreviousYear(int years) {
focusedDate.setYear(focusedDate.getYear() - years);
+ displayedMonth.setYear(displayedMonth.getYear() - years);
renderCalendar();
}
@@ -658,6 +630,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
*/
private void focusNextYear(int years) {
focusedDate.setYear(focusedDate.getYear() + years);
+ displayedMonth.setYear(displayedMonth.getYear() + years);
renderCalendar();
}
@@ -906,7 +879,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
if (newCurrentDate.getMonth() == focusedDate.getMonth()) {
// Month did not change, only move the selection
- focusDay(focusedDate.getDate() + 1);
+ focusDay(newCurrentDate);
} else {
// If the month changed we need to re-render the calendar
focusedDate.setDate(focusedDate.getDate() + 1);
@@ -925,7 +898,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
if (newCurrentDate.getMonth() == focusedDate.getMonth()) {
// Month did not change, only move the selection
- focusDay(focusedDate.getDate() - 1);
+ focusDay(newCurrentDate);
} else {
// If the month changed we need to re-render the calendar
focusedDate.setDate(focusedDate.getDate() - 1);
@@ -945,10 +918,10 @@ public class VCalendarPanel extends FocusableFlexTable implements
if (newCurrentDate.getMonth() == focusedDate.getMonth()
&& focusedRow > 1) {
// Month did not change, only move the selection
- focusDay(focusedDate.getDate() - 7);
+ focusDay(newCurrentDate);
} else {
// If the month changed we need to re-render the calendar
- focusedDate.setDate(focusedDate.getDate() - 7);
+ focusedDate = newCurrentDate;
renderCalendar();
}
@@ -964,10 +937,10 @@ public class VCalendarPanel extends FocusableFlexTable implements
if (newCurrentDate.getMonth() == focusedDate.getMonth()) {
// Month did not change, only move the selection
- focusDay(focusedDate.getDate() + 7);
+ focusDay(newCurrentDate);
} else {
// If the month changed we need to re-render the calendar
- focusedDate.setDate(focusedDate.getDate() + 7);
+ focusedDate = newCurrentDate;
renderCalendar();
}
@@ -1211,27 +1184,28 @@ public class VCalendarPanel extends FocusableFlexTable implements
return;
}
- Date oldFocusedValue = focusedDate;
+ Date oldDisplayedMonth = displayedMonth;
value = currentDate;
if (value == null) {
- focusedDate = null;
+ focusedDate = displayedMonth = null;
} else {
focusedDate = (Date) value.clone();
+ displayedMonth = (Date) value.clone();
}
// Re-render calendar if month or year of focused date has changed
- if (oldFocusedValue == null || value == null
- || oldFocusedValue.getYear() != value.getYear()
- || oldFocusedValue.getMonth() != value.getMonth()) {
+ if (oldDisplayedMonth == null || value == null
+ || oldDisplayedMonth.getYear() != value.getYear()
+ || oldDisplayedMonth.getMonth() != value.getMonth()) {
renderCalendar();
} else {
- focusDay(currentDate.getDate());
+ focusDay(currentDate);
selectFocused();
}
if (!hasFocus) {
- focusDay(-1);
+ focusDay((Date) null);
}
}
@@ -1512,17 +1486,17 @@ public class VCalendarPanel extends FocusableFlexTable implements
private class Day extends InlineHTML {
private static final String BASECLASS = VDateField.CLASSNAME
+ "-calendarpanel-day";
- private final int day;
+ private final Date date;
- Day(int dayOfMonth) {
- super("" + dayOfMonth);
+ Day(Date date) {
+ super("" + date.getDate());
setStyleName(BASECLASS);
- day = dayOfMonth;
+ this.date = date;
addClickHandler(dayClickHandler);
}
- public int getDay() {
- return day;
+ public Date getDate() {
+ return date;
}
}
@@ -1605,7 +1579,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
public void onBlur(final BlurEvent event) {
if (event.getSource() instanceof VCalendarPanel) {
hasFocus = false;
- focusDay(-1);
+ focusDay(null);
}
}
@@ -1622,7 +1596,7 @@ public class VCalendarPanel extends FocusableFlexTable implements
// Focuses the current day if the calendar shows the days
if (focusedDay != null) {
- focusDay(focusedDay.getDay());
+ focusDay(focusedDate);
}
}
}
@@ -1653,7 +1627,15 @@ public class VCalendarPanel extends FocusableFlexTable implements
// Day, find out which dayOfMonth and use that as the identifier
Day day = Util.findWidget(subElement, Day.class);
if (day != null) {
- return SUBPART_DAY + day.getDay();
+ Date date = day.getDate();
+ int id = date.getDate();
+ if (date.getMonth() < displayedMonth.getMonth()) {
+ id -= DateTimeService.getNumberOfDaysInMonth(date);
+ } else if (date.getMonth() > displayedMonth.getMonth()) {
+ id += DateTimeService
+ .getNumberOfDaysInMonth(displayedMonth);
+ }
+ return SUBPART_DAY + id;
}
} else if (time != null) {
if (contains(time.hours, subElement)) {
@@ -1714,14 +1696,18 @@ public class VCalendarPanel extends FocusableFlexTable implements
return time.ampm.getElement();
}
if (subPart.startsWith(SUBPART_DAY)) {
+ // can be less than 1 or greater than the number of days in the current month
+ // these map to the "off-month" days
int dayOfMonth = Integer.parseInt(subPart.substring(SUBPART_DAY
.length()));
+ Date date = new Date(displayedMonth.getYear(),
+ displayedMonth.getMonth(), dayOfMonth);
Iterator<Widget> iter = days.iterator();
while (iter.hasNext()) {
Widget w = iter.next();
if (w instanceof Day) {
Day day = (Day) w;
- if (day.getDay() == dayOfMonth) {
+ if (day.getDate().equals(date)) {
return day.getElement();
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java
index da916f262e..3251a03d6a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java
@@ -113,14 +113,9 @@ public class VDragAndDropWrapper extends VCustomComponent implements
VTransferable transferable = new VTransferable();
transferable.setDragSource(VDragAndDropWrapper.this);
- Widget widget = Util.findWidget((Element) event.getEventTarget()
- .cast(), null);
- VPaintableMap vPaintableMap = VPaintableMap.get(client);
- while (widget != null && !vPaintableMap.isPaintable(widget)) {
- widget = widget.getParent();
- }
- VPaintableWidget paintable = vPaintableMap.getPaintable(widget);
-
+ VPaintableWidget paintable = Util.findPaintable(client,
+ (Element) event.getEventTarget().cast());
+ Widget widget = paintable.getWidgetForPaintable();
transferable.setData("component", paintable);
VDragEvent dragEvent = VDragAndDropManager.get().startDrag(
transferable, event, true);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java
index 6d068dd11a..e6305b3c42 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java
@@ -117,8 +117,7 @@ public class VFormLayout extends SimplePanel implements Container {
Widget childWidget = childPaintable.getWidgetForPaintable();
Caption caption = widgetToCaption.get(childWidget);
if (caption == null) {
- caption = new Caption(childPaintable, client,
- getStylesFromUIDL(childUidl));
+ caption = new Caption(childPaintable, client);
caption.addClickHandler(this);
widgetToCaption.put(childWidget, caption);
}
@@ -208,8 +207,7 @@ public class VFormLayout extends SimplePanel implements Container {
VPaintableWidget newPaintable = paintableMap
.getPaintable(newComponent);
Caption oldCap = widgetToCaption.get(oldComponent);
- final Caption newCap = new Caption(newPaintable, client,
- null);
+ final Caption newCap = new Caption(newPaintable, client);
newCap.addClickHandler(this);
newCap.setStyleName(oldCap.getStyleName());
widgetToCaption.put(newComponent, newCap);
@@ -333,29 +331,37 @@ public class VFormLayout extends SimplePanel implements Container {
* return null
* @param client
*/
- public Caption(VPaintableWidget component,
- ApplicationConnection client, String[] styles) {
+ public Caption(VPaintableWidget component, ApplicationConnection client) {
super();
this.client = client;
owner = component;
- String style = CLASSNAME;
+ sinkEvents(VTooltip.TOOLTIP_EVENTS);
+ }
+
+ private void setStyles(String[] styles) {
+ String styleName = CLASSNAME;
+
if (styles != null) {
- for (int i = 0; i < styles.length; i++) {
- style += " " + CLASSNAME + "-" + styles[i];
+ for (String style : styles) {
+ if (ApplicationConnection.DISABLED_CLASSNAME.equals(style)) {
+ // Add v-disabled also without classname prefix so
+ // generic v-disabled CSS rules work
+ styleName += " " + style;
+ }
+
+ styleName += " " + CLASSNAME + "-" + style;
}
}
- setStyleName(style);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
+ setStyleName(styleName);
}
public void updateCaption(UIDL uidl) {
setVisible(!uidl.getBooleanAttribute("invisible"));
- setStyleName(getElement(),
- ApplicationConnection.DISABLED_CLASSNAME,
- uidl.hasAttribute("disabled"));
+ // Update styles as they might have changed when the caption changed
+ setStyles(getStylesFromUIDL(uidl));
boolean isEmpty = true;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java
index 306086e357..c39155d032 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java
@@ -4,9 +4,7 @@
package com.vaadin.terminal.gwt.client.ui;
import java.util.ArrayList;
-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;
@@ -35,14 +33,12 @@ import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.ContainerResizedListener;
-import com.vaadin.terminal.gwt.client.VPaintableMap;
import com.vaadin.terminal.gwt.client.TooltipInfo;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
import com.vaadin.terminal.gwt.client.VTooltip;
-public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget,
+public class VMenuBar extends SimpleFocusablePanel implements
CloseHandler<PopupPanel>, ContainerResizedListener, KeyPressHandler,
KeyDownHandler, FocusHandler, SubPartAware {
@@ -82,7 +78,7 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget,
protected VMenuBar parentMenu;
protected CustomMenuItem selected;
- private boolean enabled = true;
+ boolean enabled = true;
private String width = "notinited";
@@ -94,9 +90,9 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget,
}
});
- private boolean openRootOnHover;
+ boolean openRootOnHover;
- private boolean htmlContentAllowed;
+ boolean htmlContentAllowed;
public VMenuBar() {
// Create an empty horizontal menubar
@@ -168,133 +164,6 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget,
}
/**
- * This method must be implemented to update the client-side component from
- * UIDL data received from server.
- *
- * This method is called when the page is loaded for the first time, and
- * every time UI changes in the component are received from the server.
- */
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- // This call should be made first. Ensure correct implementation,
- // and let the containing layout manage caption, etc.
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- htmlContentAllowed = uidl.hasAttribute(HTML_CONTENT_ALLOWED);
-
- openRootOnHover = uidl.getBooleanAttribute(OPEN_ROOT_MENU_ON_HOWER);
-
- enabled = !uidl.getBooleanAttribute("disabled");
-
- // For future connections
- this.client = client;
- uidlId = uidl.getId();
-
- // Empty the menu every time it receives new information
- if (!getItems().isEmpty()) {
- clearItems();
- }
-
- UIDL options = uidl.getChildUIDL(0);
-
- if (uidl.hasAttribute("width")) {
- UIDL moreItemUIDL = options.getChildUIDL(0);
- StringBuffer itemHTML = new StringBuffer();
-
- if (moreItemUIDL.hasAttribute("icon")) {
- itemHTML.append("<img src=\""
- + Util.escapeAttribute(client
- .translateVaadinUri(moreItemUIDL
- .getStringAttribute("icon")))
- + "\" class=\"" + Icon.CLASSNAME + "\" alt=\"\" />");
- }
-
- String moreItemText = moreItemUIDL.getStringAttribute("text");
- if ("".equals(moreItemText)) {
- moreItemText = "&#x25BA;";
- }
- itemHTML.append(moreItemText);
-
- moreItem = GWT.create(CustomMenuItem.class);
- moreItem.setHTML(itemHTML.toString());
- moreItem.setCommand(emptyCommand);
-
- collapsedRootItems = new VMenuBar(true, (VMenuBar) VPaintableMap
- .get(client).getPaintable(uidlId));
- moreItem.setSubMenu(collapsedRootItems);
- moreItem.addStyleName(CLASSNAME + "-more-menuitem");
- }
-
- UIDL uidlItems = uidl.getChildUIDL(1);
- Iterator<Object> itr = uidlItems.getChildIterator();
- Stack<Iterator<Object>> iteratorStack = new Stack<Iterator<Object>>();
- Stack<VMenuBar> menuStack = new Stack<VMenuBar>();
- VMenuBar currentMenu = this;
-
- while (itr.hasNext()) {
- UIDL item = (UIDL) itr.next();
- CustomMenuItem currentItem = null;
-
- final int itemId = item.getIntAttribute("id");
-
- boolean itemHasCommand = item.hasAttribute("command");
- boolean itemIsCheckable = item.hasAttribute(ATTRIBUTE_CHECKED);
-
- String itemHTML = buildItemHTML(item);
-
- 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() {
- public void execute() {
- hostReference.onMenuClick(itemId);
- }
- };
- }
- }
-
- currentItem = currentMenu.addItem(itemHTML.toString(), cmd);
- currentItem.updateFromUIDL(item, client);
-
- if (item.getChildCount() > 0) {
- menuStack.push(currentMenu);
- iteratorStack.push(itr);
- itr = item.getChildIterator();
- currentMenu = new VMenuBar(true, currentMenu);
- if (uidl.hasAttribute("style")) {
- for (String style : uidl.getStringAttribute("style").split(
- " ")) {
- currentMenu.addStyleDependentName(style);
- }
- }
- currentItem.setSubMenu(currentMenu);
- }
-
- 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();
- }
- }// while
-
- iLayout(false);
-
- }// updateFromUIDL
-
- /**
* Build the HTML content for a menu item.
*
* @param item
@@ -473,7 +342,7 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget,
// Handle tooltips
if (targetItem == null && client != null) {
// Handle root menubar tooltips
- client.handleTooltipEvent(e, this);
+ client.handleWidgetTooltipEvent(e, this);
} else if (targetItem != null) {
// Handle item tooltips
targetItem.onBrowserEvent(e);
@@ -1051,7 +920,7 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget,
TooltipInfo info = new TooltipInfo(description);
VMenuBar root = findRootMenu();
- client.registerTooltip(root, this, info);
+ client.registerWidgetTooltip(root, this, info);
}
}
@@ -1059,7 +928,7 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget,
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (client != null) {
- client.handleTooltipEvent(event, findRootMenu(), this);
+ client.handleWidgetTooltipEvent(event, findRootMenu(), this);
}
}
@@ -1551,8 +1420,4 @@ public class VMenuBar extends SimpleFocusablePanel implements VPaintableWidget,
return null;
}
- public Widget getWidgetForPaintable() {
- return this;
- }
-
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java
new file mode 100644
index 0000000000..fabc77bced
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java
@@ -0,0 +1,161 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Iterator;
+import java.util.Stack;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.ui.VMenuBar.CustomMenuItem;
+
+public class VMenuBarPaintable extends VAbstractPaintableWidget {
+ /**
+ * This method must be implemented to update the client-side component from
+ * UIDL data received from server.
+ *
+ * This method is called when the page is loaded for the first time, and
+ * every time UI changes in the component are received from the server.
+ */
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ // This call should be made first. Ensure correct implementation,
+ // and let the containing layout manage caption, etc.
+ if (client.updateComponent(this, uidl, true)) {
+ return;
+ }
+
+ getWidgetForPaintable().htmlContentAllowed = uidl
+ .hasAttribute(VMenuBar.HTML_CONTENT_ALLOWED);
+
+ getWidgetForPaintable().openRootOnHover = uidl
+ .getBooleanAttribute(VMenuBar.OPEN_ROOT_MENU_ON_HOWER);
+
+ getWidgetForPaintable().enabled = !uidl.getBooleanAttribute("disabled");
+
+ // For future connections
+ getWidgetForPaintable().client = client;
+ getWidgetForPaintable().uidlId = uidl.getId();
+
+ // Empty the menu every time it receives new information
+ if (!getWidgetForPaintable().getItems().isEmpty()) {
+ getWidgetForPaintable().clearItems();
+ }
+
+ UIDL options = uidl.getChildUIDL(0);
+
+ if (uidl.hasAttribute("width")) {
+ UIDL moreItemUIDL = options.getChildUIDL(0);
+ StringBuffer itemHTML = new StringBuffer();
+
+ if (moreItemUIDL.hasAttribute("icon")) {
+ itemHTML.append("<img src=\""
+ + Util.escapeAttribute(client
+ .translateVaadinUri(moreItemUIDL
+ .getStringAttribute("icon")))
+ + "\" class=\"" + Icon.CLASSNAME + "\" alt=\"\" />");
+ }
+
+ String moreItemText = moreItemUIDL.getStringAttribute("text");
+ if ("".equals(moreItemText)) {
+ moreItemText = "&#x25BA;";
+ }
+ itemHTML.append(moreItemText);
+
+ getWidgetForPaintable().moreItem = GWT.create(CustomMenuItem.class);
+ getWidgetForPaintable().moreItem.setHTML(itemHTML.toString());
+ getWidgetForPaintable().moreItem.setCommand(VMenuBar.emptyCommand);
+
+ getWidgetForPaintable().collapsedRootItems = new VMenuBar(true,
+ getWidgetForPaintable());
+ getWidgetForPaintable().moreItem
+ .setSubMenu(getWidgetForPaintable().collapsedRootItems);
+ getWidgetForPaintable().moreItem.addStyleName(VMenuBar.CLASSNAME
+ + "-more-menuitem");
+ }
+
+ UIDL uidlItems = uidl.getChildUIDL(1);
+ Iterator<Object> itr = uidlItems.getChildIterator();
+ Stack<Iterator<Object>> iteratorStack = new Stack<Iterator<Object>>();
+ Stack<VMenuBar> menuStack = new Stack<VMenuBar>();
+ VMenuBar currentMenu = getWidgetForPaintable();
+
+ while (itr.hasNext()) {
+ UIDL item = (UIDL) itr.next();
+ CustomMenuItem currentItem = null;
+
+ final int itemId = item.getIntAttribute("id");
+
+ boolean itemHasCommand = item.hasAttribute("command");
+ boolean itemIsCheckable = item
+ .hasAttribute(VMenuBar.ATTRIBUTE_CHECKED);
+
+ String itemHTML = getWidgetForPaintable().buildItemHTML(item);
+
+ 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() {
+ public void execute() {
+ getWidgetForPaintable().hostReference
+ .onMenuClick(itemId);
+ }
+ };
+ }
+ }
+
+ currentItem = currentMenu.addItem(itemHTML.toString(), cmd);
+ currentItem.updateFromUIDL(item, client);
+
+ if (item.getChildCount() > 0) {
+ menuStack.push(currentMenu);
+ iteratorStack.push(itr);
+ itr = item.getChildIterator();
+ currentMenu = new VMenuBar(true, currentMenu);
+ if (uidl.hasAttribute("style")) {
+ for (String style : uidl.getStringAttribute("style").split(
+ " ")) {
+ currentMenu.addStyleDependentName(style);
+ }
+ }
+ currentItem.setSubMenu(currentMenu);
+ }
+
+ 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();
+ }
+ }// while
+
+ getWidgetForPaintable().iLayout(false);
+
+ }// updateFromUIDL
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VMenuBar.class);
+ }
+
+ @Override
+ public VMenuBar getWidgetForPaintable() {
+ return (VMenuBar) super.getWidgetForPaintable();
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VNativeButton.java b/src/com/vaadin/terminal/gwt/client/ui/VNativeButton.java
index 8385130a42..a0b374c97e 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VNativeButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VNativeButton.java
@@ -19,24 +19,21 @@ import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.EventHelper;
import com.vaadin.terminal.gwt.client.EventId;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.communication.ClientToServerRpc.InitializableClientToServerRpc;
import com.vaadin.terminal.gwt.client.ui.VButton.ButtonClientToServerRpc;
-public class VNativeButton extends Button implements VPaintableWidget,
- ClickHandler, FocusHandler, BlurHandler {
+public class VNativeButton extends Button implements ClickHandler,
+ FocusHandler, BlurHandler {
public static final String CLASSNAME = "v-nativebutton";
protected String width = null;
- protected String id;
+ protected String paintableId;
protected ApplicationConnection client;
@@ -55,10 +52,10 @@ public class VNativeButton extends Button implements VPaintableWidget,
*/
private boolean clickPending;
- private HandlerRegistration focusHandlerRegistration;
- private HandlerRegistration blurHandlerRegistration;
+ protected HandlerRegistration focusHandlerRegistration;
+ protected HandlerRegistration blurHandlerRegistration;
- private boolean disableOnClick = false;
+ protected boolean disableOnClick = false;
public VNativeButton() {
setStyleName(CLASSNAME);
@@ -73,56 +70,6 @@ public class VNativeButton extends Button implements VPaintableWidget,
sinkEvents(Event.ONMOUSEUP);
}
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
-
- // Ensure correct implementation,
- // but don't let container manage caption etc.
- if (client.updateComponent(this, uidl, false)) {
- return;
- }
-
- disableOnClick = uidl.hasAttribute(VButton.ATTR_DISABLE_ON_CLICK);
-
- focusHandlerRegistration = EventHelper.updateFocusHandler(this, client,
- focusHandlerRegistration);
- blurHandlerRegistration = EventHelper.updateBlurHandler(this, client,
- blurHandlerRegistration);
-
- // Save details
- this.client = client;
- id = uidl.getId();
-
- // Set text
- setText(uidl.getStringAttribute("caption"));
-
- // handle error
- if (uidl.hasAttribute("error")) {
- if (errorIndicatorElement == null) {
- errorIndicatorElement = DOM.createSpan();
- errorIndicatorElement.setClassName("v-errorindicator");
- }
- getElement().insertBefore(errorIndicatorElement, captionElement);
-
- } else if (errorIndicatorElement != null) {
- getElement().removeChild(errorIndicatorElement);
- errorIndicatorElement = null;
- }
-
- if (uidl.hasAttribute("icon")) {
- if (icon == null) {
- icon = new Icon(client);
- getElement().insertBefore(icon.getElement(), captionElement);
- }
- icon.setUri(uidl.getStringAttribute("icon"));
- } else {
- if (icon != null) {
- getElement().removeChild(icon.getElement());
- icon = null;
- }
- }
-
- }
-
@Override
public void setText(String text) {
captionElement.setInnerText(text);
@@ -148,7 +95,7 @@ public class VNativeButton extends Button implements VPaintableWidget,
}
if (client != null) {
- client.handleTooltipEvent(event, this);
+ client.handleWidgetTooltipEvent(event, this);
}
}
@@ -166,7 +113,7 @@ public class VNativeButton extends Button implements VPaintableWidget,
* .dom.client.ClickEvent)
*/
public void onClick(ClickEvent event) {
- if (id == null || client == null) {
+ if (paintableId == null || client == null) {
return;
}
@@ -189,18 +136,18 @@ public class VNativeButton extends Button implements VPaintableWidget,
protected ButtonClientToServerRpc getButtonRpcProxy() {
if (null == buttonRpcProxy) {
buttonRpcProxy = GWT.create(ButtonClientToServerRpc.class);
- ((InitializableClientToServerRpc) buttonRpcProxy).initRpc(id,
- client);
+ ((InitializableClientToServerRpc) buttonRpcProxy).initRpc(
+ paintableId, client);
}
return buttonRpcProxy;
}
public void onFocus(FocusEvent arg0) {
- client.updateVariable(id, EventId.FOCUS, "", true);
+ client.updateVariable(paintableId, EventId.FOCUS, "", true);
}
public void onBlur(BlurEvent arg0) {
- client.updateVariable(id, EventId.BLUR, "", true);
+ client.updateVariable(paintableId, EventId.BLUR, "", true);
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VNativeButtonPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VNativeButtonPaintable.java
new file mode 100644
index 0000000000..5e0dceea75
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/VNativeButtonPaintable.java
@@ -0,0 +1,83 @@
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.EventHelper;
+import com.vaadin.terminal.gwt.client.UIDL;
+
+public class VNativeButtonPaintable extends VAbstractPaintableWidget {
+
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+
+ // Ensure correct implementation,
+ // but don't let container manage caption etc.
+ if (client.updateComponent(this, uidl, false)) {
+ return;
+ }
+
+ getWidgetForPaintable().disableOnClick = uidl
+ .hasAttribute(VButton.ATTR_DISABLE_ON_CLICK);
+
+ getWidgetForPaintable().focusHandlerRegistration = EventHelper
+ .updateFocusHandler(this, client,
+ getWidgetForPaintable().focusHandlerRegistration);
+ getWidgetForPaintable().blurHandlerRegistration = EventHelper
+ .updateBlurHandler(this, client,
+ getWidgetForPaintable().blurHandlerRegistration);
+
+ // Save details
+ getWidgetForPaintable().client = client;
+ getWidgetForPaintable().paintableId = uidl.getId();
+
+ // Set text
+ getWidgetForPaintable().setText(uidl.getStringAttribute("caption"));
+
+ // handle error
+ if (uidl.hasAttribute("error")) {
+ if (getWidgetForPaintable().errorIndicatorElement == null) {
+ getWidgetForPaintable().errorIndicatorElement = DOM
+ .createSpan();
+ getWidgetForPaintable().errorIndicatorElement
+ .setClassName("v-errorindicator");
+ }
+ getWidgetForPaintable().getElement().insertBefore(
+ getWidgetForPaintable().errorIndicatorElement,
+ getWidgetForPaintable().captionElement);
+
+ } else if (getWidgetForPaintable().errorIndicatorElement != null) {
+ getWidgetForPaintable().getElement().removeChild(
+ getWidgetForPaintable().errorIndicatorElement);
+ getWidgetForPaintable().errorIndicatorElement = null;
+ }
+
+ if (uidl.hasAttribute("icon")) {
+ if (getWidgetForPaintable().icon == null) {
+ getWidgetForPaintable().icon = new Icon(client);
+ getWidgetForPaintable().getElement().insertBefore(
+ getWidgetForPaintable().icon.getElement(),
+ getWidgetForPaintable().captionElement);
+ }
+ getWidgetForPaintable().icon
+ .setUri(uidl.getStringAttribute("icon"));
+ } else {
+ if (getWidgetForPaintable().icon != null) {
+ getWidgetForPaintable().getElement().removeChild(
+ getWidgetForPaintable().icon.getElement());
+ getWidgetForPaintable().icon = null;
+ }
+ }
+
+ }
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VNativeButton.class);
+ }
+
+ @Override
+ public VNativeButton getWidgetForPaintable() {
+ return (VNativeButton) super.getWidgetForPaintable();
+ }
+} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java
index 7de1658c5d..44fb9ac69c 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java
@@ -1,462 +1,474 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Date;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.DomEvent;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.DateTimeService;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusChangeListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusOutListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.SubmitListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.TimeChangeListener;
-
-/**
- * Represents a date selection component with a text field and a popup date
- * selector.
- *
- * <b>Note:</b> To change the keyboard assignments used in the popup dialog you
- * should extend <code>com.vaadin.terminal.gwt.client.ui.VCalendarPanel</code>
- * and then pass set it by calling the
- * <code>setCalendarPanel(VCalendarPanel panel)</code> method.
- *
- */
-public class VPopupCalendar extends VTextualDate implements VPaintableWidget,
- Field, ClickHandler, CloseHandler<PopupPanel>, SubPartAware {
-
- private final Button calendarToggle;
-
- private VCalendarPanel calendar;
-
- private final VOverlay popup;
- private boolean open = false;
- private boolean parsable = true;
-
- public VPopupCalendar() {
- super();
-
- calendarToggle = new Button();
- calendarToggle.setStyleName(CLASSNAME + "-button");
- calendarToggle.setText("");
- calendarToggle.addClickHandler(this);
- // -2 instead of -1 to avoid FocusWidget.onAttach to reset it
- calendarToggle.getElement().setTabIndex(-2);
- add(calendarToggle);
-
- calendar = GWT.create(VCalendarPanel.class);
- calendar.setFocusOutListener(new FocusOutListener() {
- public boolean onFocusOut(DomEvent<?> event) {
- event.preventDefault();
- closeCalendarPanel();
- return true;
- }
- });
-
- calendar.setSubmitListener(new SubmitListener() {
- public void onSubmit() {
- // Update internal value and send valuechange event if immediate
- updateValue(calendar.getDate());
-
- // Update text field (a must when not immediate).
- buildDate(true);
-
- closeCalendarPanel();
- }
-
- public void onCancel() {
- closeCalendarPanel();
- }
- });
-
- popup = new VOverlay(true, true, true);
- popup.setStyleName(VDateField.CLASSNAME + "-popup");
- popup.setWidget(calendar);
- popup.addCloseHandler(this);
-
- DOM.setElementProperty(calendar.getElement(), "id",
- "PID_VAADIN_POPUPCAL");
-
- sinkEvents(Event.ONKEYDOWN);
-
- }
-
- @SuppressWarnings("deprecation")
- private void updateValue(Date newDate) {
- Date currentDate = getCurrentDate();
- if (currentDate == null || newDate.getTime() != currentDate.getTime()) {
- setCurrentDate((Date) newDate.clone());
- getClient().updateVariable(getId(), "year",
- newDate.getYear() + 1900, false);
- if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) {
- getClient().updateVariable(getId(), "month",
- newDate.getMonth() + 1, false);
- if (getCurrentResolution() > RESOLUTION_MONTH) {
- getClient().updateVariable(getId(), "day",
- newDate.getDate(), false);
- if (getCurrentResolution() > RESOLUTION_DAY) {
- getClient().updateVariable(getId(), "hour",
- newDate.getHours(), false);
- if (getCurrentResolution() > RESOLUTION_HOUR) {
- getClient().updateVariable(getId(), "min",
- newDate.getMinutes(), false);
- if (getCurrentResolution() > RESOLUTION_MIN) {
- getClient().updateVariable(getId(), "sec",
- newDate.getSeconds(), false);
- }
- }
- }
- }
- }
- if (isImmediate()) {
- getClient().sendPendingVariableChanges();
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.ui.VTextualDate#updateFromUIDL(com.vaadin
- * .terminal.gwt.client.UIDL,
- * com.vaadin.terminal.gwt.client.ApplicationConnection)
- */
- @Override
- @SuppressWarnings("deprecation")
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- boolean lastReadOnlyState = readonly;
- parsable = uidl.getBooleanAttribute("parsable");
-
- super.updateFromUIDL(uidl, client);
-
- popup.setStyleName(VDateField.CLASSNAME + "-popup "
- + VDateField.CLASSNAME + "-"
- + resolutionToString(currentResolution));
- calendar.setDateTimeService(getDateTimeService());
- calendar.setShowISOWeekNumbers(isShowISOWeekNumbers());
- if (calendar.getResolution() != currentResolution) {
- calendar.setResolution(currentResolution);
- if (calendar.getDate() != null) {
- calendar.setDate((Date) getCurrentDate().clone());
- // force re-render when changing resolution only
- calendar.renderCalendar();
- }
- }
- calendarToggle.setEnabled(enabled);
-
- if (currentResolution <= RESOLUTION_MONTH) {
- calendar.setFocusChangeListener(new FocusChangeListener() {
- public void focusChanged(Date date) {
- updateValue(date);
- buildDate();
- Date date2 = calendar.getDate();
- date2.setYear(date.getYear());
- date2.setMonth(date.getMonth());
- }
- });
- } else {
- calendar.setFocusChangeListener(null);
- }
-
- if (currentResolution > RESOLUTION_DAY) {
- calendar.setTimeChangeListener(new TimeChangeListener() {
- public void changed(int hour, int min, int sec, int msec) {
- Date d = getDate();
- if (d == null) {
- // date currently null, use the value from calendarPanel
- // (~ client time at the init of the widget)
- d = (Date) calendar.getDate().clone();
- }
- d.setHours(hour);
- d.setMinutes(min);
- d.setSeconds(sec);
- DateTimeService.setMilliseconds(d, msec);
-
- // Always update time changes to the server
- updateValue(d);
-
- // Update text field
- buildDate();
- }
- });
- }
-
- if (readonly) {
- calendarToggle.addStyleName(CLASSNAME + "-button-readonly");
- } else {
- calendarToggle.removeStyleName(CLASSNAME + "-button-readonly");
- }
-
- if (lastReadOnlyState != readonly) {
- updateWidth();
- }
-
- calendarToggle.setEnabled(true);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.user.client.ui.UIObject#setStyleName(java.lang.String)
- */
- @Override
- public void setStyleName(String style) {
- // make sure the style is there before size calculation
- super.setStyleName(style + " " + CLASSNAME + "-popupcalendar");
- }
-
- /**
- * Opens the calendar panel popup
- */
- public void openCalendarPanel() {
-
- if (!open && !readonly) {
- open = true;
-
- if (getCurrentDate() != null) {
- calendar.setDate((Date) getCurrentDate().clone());
- } else {
- calendar.setDate(new Date());
- }
-
- // clear previous values
- popup.setWidth("");
- popup.setHeight("");
- popup.setPopupPositionAndShow(new PositionCallback() {
- public void setPosition(int offsetWidth, int offsetHeight) {
- final int w = offsetWidth;
- final int h = offsetHeight;
- final int browserWindowWidth = Window.getClientWidth()
- + Window.getScrollLeft();
- final int browserWindowHeight = Window.getClientHeight()
- + Window.getScrollTop();
- int t = calendarToggle.getAbsoluteTop();
- int l = calendarToggle.getAbsoluteLeft();
-
- // Add a little extra space to the right to avoid
- // problems with IE7 scrollbars and to make it look
- // nicer.
- int extraSpace = 30;
-
- boolean overflowRight = false;
- if (l + +w + extraSpace > browserWindowWidth) {
- overflowRight = true;
- // Part of the popup is outside the browser window
- // (to the right)
- l = browserWindowWidth - w - extraSpace;
- }
-
- if (t + h + calendarToggle.getOffsetHeight() + 30 > browserWindowHeight) {
- // Part of the popup is outside the browser window
- // (below)
- t = browserWindowHeight - h
- - calendarToggle.getOffsetHeight() - 30;
- if (!overflowRight) {
- // Show to the right of the popup button unless we
- // are in the lower right corner of the screen
- l += calendarToggle.getOffsetWidth();
- }
- }
-
- // fix size
- popup.setWidth(w + "px");
- popup.setHeight(h + "px");
-
- popup.setPopupPosition(l,
- t + calendarToggle.getOffsetHeight() + 2);
-
- /*
- * We have to wait a while before focusing since the popup
- * needs to be opened before we can focus
- */
- Timer focusTimer = new Timer() {
- @Override
- public void run() {
- setFocus(true);
- }
- };
-
- focusTimer.schedule(100);
- }
- });
- } else {
- VConsole.error("Cannot reopen popup, it is already open!");
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event
- * .dom.client.ClickEvent)
- */
- public void onClick(ClickEvent event) {
- if (event.getSource() == calendarToggle && isEnabled()) {
- openCalendarPanel();
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt
- * .event.logical.shared.CloseEvent)
- */
- public void onClose(CloseEvent<PopupPanel> event) {
- if (event.getSource() == popup) {
- buildDate();
- if (!BrowserInfo.get().isTouchDevice()) {
- /*
- * Move focus to textbox, unless on touch device (avoids opening
- * virtual keyboard).
- */
- focus();
- }
-
- // TODO resolve what the "Sigh." is all about and document it here
- // Sigh.
- Timer t = new Timer() {
- @Override
- public void run() {
- open = false;
- }
- };
- t.schedule(100);
- }
- }
-
- /**
- * Sets focus to Calendar panel.
- *
- * @param focus
- */
- public void setFocus(boolean focus) {
- calendar.setFocus(focus);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#getFieldExtraWidth()
- */
- @Override
- protected int getFieldExtraWidth() {
- if (fieldExtraWidth < 0) {
- fieldExtraWidth = super.getFieldExtraWidth();
- fieldExtraWidth += calendarToggle.getOffsetWidth();
- }
- return fieldExtraWidth;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#buildDate()
- */
- @Override
- protected void buildDate() {
- // Save previous value
- String previousValue = getText();
- super.buildDate();
-
- // Restore previous value if the input could not be parsed
- if (!parsable) {
- setText(previousValue);
- }
- }
-
- /**
- * Update the text field contents from the date. See {@link #buildDate()}.
- *
- * @param forceValid
- * true to force the text field to be updated, false to only
- * update if the parsable flag is true.
- */
- protected void buildDate(boolean forceValid) {
- if (forceValid) {
- parsable = true;
- }
- buildDate();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.ui.VDateField#onBrowserEvent(com.google
- * .gwt.user.client.Event)
- */
- @Override
- public void onBrowserEvent(com.google.gwt.user.client.Event event) {
- super.onBrowserEvent(event);
- if (DOM.eventGetType(event) == Event.ONKEYDOWN
- && event.getKeyCode() == getOpenCalenderPanelKey()) {
- openCalendarPanel();
- event.preventDefault();
- }
- }
-
- /**
- * Get the key code that opens the calendar panel. By default it is the down
- * key but you can override this to be whatever you like
- *
- * @return
- */
- protected int getOpenCalenderPanelKey() {
- return KeyCodes.KEY_DOWN;
- }
-
- /**
- * Closes the open popup panel
- */
- public void closeCalendarPanel() {
- if (open) {
- popup.hide(true);
- }
- }
-
- private final String CALENDAR_TOGGLE_ID = "popupButton";
-
- @Override
- public Element getSubPartElement(String subPart) {
- if (subPart.equals(CALENDAR_TOGGLE_ID)) {
- return calendarToggle.getElement();
- }
-
- return super.getSubPartElement(subPart);
- }
-
- @Override
- public String getSubPartName(Element subElement) {
- if (calendarToggle.getElement().isOrHasChild(subElement)) {
- return CALENDAR_TOGGLE_ID;
- }
-
- return super.getSubPartName(subElement);
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Date;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.DomEvent;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.DateTimeService;
+import com.vaadin.terminal.gwt.client.VPaintableWidget;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusChangeListener;
+import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusOutListener;
+import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.SubmitListener;
+import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.TimeChangeListener;
+
+/**
+ * Represents a date selection component with a text field and a popup date
+ * selector.
+ *
+ * <b>Note:</b> To change the keyboard assignments used in the popup dialog you
+ * should extend <code>com.vaadin.terminal.gwt.client.ui.VCalendarPanel</code>
+ * and then pass set it by calling the
+ * <code>setCalendarPanel(VCalendarPanel panel)</code> method.
+ *
+ */
+public class VPopupCalendar extends VTextualDate implements VPaintableWidget,
+ Field, ClickHandler, CloseHandler<PopupPanel>, SubPartAware {
+
+ private static final String POPUP_PRIMARY_STYLE_NAME = VDateField.CLASSNAME
+ + "-popup";
+
+ private final Button calendarToggle;
+
+ private VCalendarPanel calendar;
+
+ private final VOverlay popup;
+ private boolean open = false;
+ private boolean parsable = true;
+
+ public VPopupCalendar() {
+ super();
+
+ calendarToggle = new Button();
+ calendarToggle.setStyleName(CLASSNAME + "-button");
+ calendarToggle.setText("");
+ calendarToggle.addClickHandler(this);
+ // -2 instead of -1 to avoid FocusWidget.onAttach to reset it
+ calendarToggle.getElement().setTabIndex(-2);
+ add(calendarToggle);
+
+ calendar = GWT.create(VCalendarPanel.class);
+ calendar.setFocusOutListener(new FocusOutListener() {
+ public boolean onFocusOut(DomEvent<?> event) {
+ event.preventDefault();
+ closeCalendarPanel();
+ return true;
+ }
+ });
+
+ calendar.setSubmitListener(new SubmitListener() {
+ public void onSubmit() {
+ // Update internal value and send valuechange event if immediate
+ updateValue(calendar.getDate());
+
+ // Update text field (a must when not immediate).
+ buildDate(true);
+
+ closeCalendarPanel();
+ }
+
+ public void onCancel() {
+ closeCalendarPanel();
+ }
+ });
+
+ popup = new VOverlay(true, true, true);
+ popup.setStyleName(POPUP_PRIMARY_STYLE_NAME);
+ popup.setWidget(calendar);
+ popup.addCloseHandler(this);
+
+ DOM.setElementProperty(calendar.getElement(), "id",
+ "PID_VAADIN_POPUPCAL");
+
+ sinkEvents(Event.ONKEYDOWN);
+
+ }
+
+ @SuppressWarnings("deprecation")
+ private void updateValue(Date newDate) {
+ Date currentDate = getCurrentDate();
+ if (currentDate == null || newDate.getTime() != currentDate.getTime()) {
+ setCurrentDate((Date) newDate.clone());
+ getClient().updateVariable(getId(), "year",
+ newDate.getYear() + 1900, false);
+ if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) {
+ getClient().updateVariable(getId(), "month",
+ newDate.getMonth() + 1, false);
+ if (getCurrentResolution() > RESOLUTION_MONTH) {
+ getClient().updateVariable(getId(), "day",
+ newDate.getDate(), false);
+ if (getCurrentResolution() > RESOLUTION_DAY) {
+ getClient().updateVariable(getId(), "hour",
+ newDate.getHours(), false);
+ if (getCurrentResolution() > RESOLUTION_HOUR) {
+ getClient().updateVariable(getId(), "min",
+ newDate.getMinutes(), false);
+ if (getCurrentResolution() > RESOLUTION_MIN) {
+ getClient().updateVariable(getId(), "sec",
+ newDate.getSeconds(), false);
+ }
+ }
+ }
+ }
+ }
+ if (isImmediate()) {
+ getClient().sendPendingVariableChanges();
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.terminal.gwt.client.ui.VTextualDate#updateFromUIDL(com.vaadin
+ * .terminal.gwt.client.UIDL,
+ * com.vaadin.terminal.gwt.client.ApplicationConnection)
+ */
+ @Override
+ @SuppressWarnings("deprecation")
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ boolean lastReadOnlyState = readonly;
+ boolean lastEnabledState = isEnabled();
+
+ parsable = uidl.getBooleanAttribute("parsable");
+
+ super.updateFromUIDL(uidl, client);
+
+ String popupStyleNames = ApplicationConnection.getStyleName(
+ POPUP_PRIMARY_STYLE_NAME, uidl, false);
+ popupStyleNames += " " + VDateField.CLASSNAME + "-"
+ + resolutionToString(currentResolution);
+ popup.setStyleName(popupStyleNames);
+
+ calendar.setDateTimeService(getDateTimeService());
+ calendar.setShowISOWeekNumbers(isShowISOWeekNumbers());
+ if (calendar.getResolution() != currentResolution) {
+ calendar.setResolution(currentResolution);
+ if (calendar.getDate() != null) {
+ calendar.setDate((Date) getCurrentDate().clone());
+ // force re-render when changing resolution only
+ calendar.renderCalendar();
+ }
+ }
+ calendarToggle.setEnabled(enabled);
+
+ if (currentResolution <= RESOLUTION_MONTH) {
+ calendar.setFocusChangeListener(new FocusChangeListener() {
+ public void focusChanged(Date date) {
+ updateValue(date);
+ buildDate();
+ Date date2 = calendar.getDate();
+ date2.setYear(date.getYear());
+ date2.setMonth(date.getMonth());
+ }
+ });
+ } else {
+ calendar.setFocusChangeListener(null);
+ }
+
+ if (currentResolution > RESOLUTION_DAY) {
+ calendar.setTimeChangeListener(new TimeChangeListener() {
+ public void changed(int hour, int min, int sec, int msec) {
+ Date d = getDate();
+ if (d == null) {
+ // date currently null, use the value from calendarPanel
+ // (~ client time at the init of the widget)
+ d = (Date) calendar.getDate().clone();
+ }
+ d.setHours(hour);
+ d.setMinutes(min);
+ d.setSeconds(sec);
+ DateTimeService.setMilliseconds(d, msec);
+
+ // Always update time changes to the server
+ updateValue(d);
+
+ // Update text field
+ buildDate();
+ }
+ });
+ }
+
+ if (readonly) {
+ calendarToggle.addStyleName(CLASSNAME + "-button-readonly");
+ } else {
+ calendarToggle.removeStyleName(CLASSNAME + "-button-readonly");
+ }
+
+ if (lastReadOnlyState != readonly || lastEnabledState != isEnabled()) {
+ // Enabled or readonly state changed. Differences in theming might
+ // affect the width (for instance if the popup button is hidden) so
+ // we have to recalculate the width (IF the width of the field is
+ // fixed)
+ updateWidth();
+ }
+
+ calendarToggle.setEnabled(true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.user.client.ui.UIObject#setStyleName(java.lang.String)
+ */
+ @Override
+ public void setStyleName(String style) {
+ // make sure the style is there before size calculation
+ super.setStyleName(style + " " + CLASSNAME + "-popupcalendar");
+ }
+
+ /**
+ * Opens the calendar panel popup
+ */
+ public void openCalendarPanel() {
+
+ if (!open && !readonly) {
+ open = true;
+
+ if (getCurrentDate() != null) {
+ calendar.setDate((Date) getCurrentDate().clone());
+ } else {
+ calendar.setDate(new Date());
+ }
+
+ // clear previous values
+ popup.setWidth("");
+ popup.setHeight("");
+ popup.setPopupPositionAndShow(new PositionCallback() {
+ public void setPosition(int offsetWidth, int offsetHeight) {
+ final int w = offsetWidth;
+ final int h = offsetHeight;
+ final int browserWindowWidth = Window.getClientWidth()
+ + Window.getScrollLeft();
+ final int browserWindowHeight = Window.getClientHeight()
+ + Window.getScrollTop();
+ int t = calendarToggle.getAbsoluteTop();
+ int l = calendarToggle.getAbsoluteLeft();
+
+ // Add a little extra space to the right to avoid
+ // problems with IE7 scrollbars and to make it look
+ // nicer.
+ int extraSpace = 30;
+
+ boolean overflowRight = false;
+ if (l + +w + extraSpace > browserWindowWidth) {
+ overflowRight = true;
+ // Part of the popup is outside the browser window
+ // (to the right)
+ l = browserWindowWidth - w - extraSpace;
+ }
+
+ if (t + h + calendarToggle.getOffsetHeight() + 30 > browserWindowHeight) {
+ // Part of the popup is outside the browser window
+ // (below)
+ t = browserWindowHeight - h
+ - calendarToggle.getOffsetHeight() - 30;
+ if (!overflowRight) {
+ // Show to the right of the popup button unless we
+ // are in the lower right corner of the screen
+ l += calendarToggle.getOffsetWidth();
+ }
+ }
+
+ // fix size
+ popup.setWidth(w + "px");
+ popup.setHeight(h + "px");
+
+ popup.setPopupPosition(l,
+ t + calendarToggle.getOffsetHeight() + 2);
+
+ /*
+ * We have to wait a while before focusing since the popup
+ * needs to be opened before we can focus
+ */
+ Timer focusTimer = new Timer() {
+ @Override
+ public void run() {
+ setFocus(true);
+ }
+ };
+
+ focusTimer.schedule(100);
+ }
+ });
+ } else {
+ VConsole.error("Cannot reopen popup, it is already open!");
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event
+ * .dom.client.ClickEvent)
+ */
+ public void onClick(ClickEvent event) {
+ if (event.getSource() == calendarToggle && isEnabled()) {
+ openCalendarPanel();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt
+ * .event.logical.shared.CloseEvent)
+ */
+ public void onClose(CloseEvent<PopupPanel> event) {
+ if (event.getSource() == popup) {
+ buildDate();
+ if (!BrowserInfo.get().isTouchDevice()) {
+ /*
+ * Move focus to textbox, unless on touch device (avoids opening
+ * virtual keyboard).
+ */
+ focus();
+ }
+
+ // TODO resolve what the "Sigh." is all about and document it here
+ // Sigh.
+ Timer t = new Timer() {
+ @Override
+ public void run() {
+ open = false;
+ }
+ };
+ t.schedule(100);
+ }
+ }
+
+ /**
+ * Sets focus to Calendar panel.
+ *
+ * @param focus
+ */
+ public void setFocus(boolean focus) {
+ calendar.setFocus(focus);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#getFieldExtraWidth()
+ */
+ @Override
+ protected int getFieldExtraWidth() {
+ if (fieldExtraWidth < 0) {
+ fieldExtraWidth = super.getFieldExtraWidth();
+ fieldExtraWidth += calendarToggle.getOffsetWidth();
+ }
+ return fieldExtraWidth;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#buildDate()
+ */
+ @Override
+ protected void buildDate() {
+ // Save previous value
+ String previousValue = getText();
+ super.buildDate();
+
+ // Restore previous value if the input could not be parsed
+ if (!parsable) {
+ setText(previousValue);
+ }
+ }
+
+ /**
+ * Update the text field contents from the date. See {@link #buildDate()}.
+ *
+ * @param forceValid
+ * true to force the text field to be updated, false to only
+ * update if the parsable flag is true.
+ */
+ protected void buildDate(boolean forceValid) {
+ if (forceValid) {
+ parsable = true;
+ }
+ buildDate();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.terminal.gwt.client.ui.VDateField#onBrowserEvent(com.google
+ * .gwt.user.client.Event)
+ */
+ @Override
+ public void onBrowserEvent(com.google.gwt.user.client.Event event) {
+ super.onBrowserEvent(event);
+ if (DOM.eventGetType(event) == Event.ONKEYDOWN
+ && event.getKeyCode() == getOpenCalenderPanelKey()) {
+ openCalendarPanel();
+ event.preventDefault();
+ }
+ }
+
+ /**
+ * Get the key code that opens the calendar panel. By default it is the down
+ * key but you can override this to be whatever you like
+ *
+ * @return
+ */
+ protected int getOpenCalenderPanelKey() {
+ return KeyCodes.KEY_DOWN;
+ }
+
+ /**
+ * Closes the open popup panel
+ */
+ public void closeCalendarPanel() {
+ if (open) {
+ popup.hide(true);
+ }
+ }
+
+ private final String CALENDAR_TOGGLE_ID = "popupButton";
+
+ @Override
+ public Element getSubPartElement(String subPart) {
+ if (subPart.equals(CALENDAR_TOGGLE_ID)) {
+ return calendarToggle.getElement();
+ }
+
+ return super.getSubPartElement(subPart);
+ }
+
+ @Override
+ public String getSubPartName(Element subElement) {
+ if (calendarToggle.getElement().isOrHasChild(subElement)) {
+ return CALENDAR_TOGGLE_ID;
+ }
+
+ return super.getSubPartName(subElement);
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
index 736635ecd0..de68ae96a4 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
@@ -52,6 +52,7 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.UIObject;
@@ -103,17 +104,31 @@ import com.vaadin.terminal.gwt.client.ui.label.VLabel;
*
* TODO implement unregistering for child components in Cells
*/
-public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
- VHasDropHandler, FocusHandler, BlurHandler, Focusable, ActionOwner {
+public class VScrollTable extends FlowPanel implements HasWidgets,
+ ScrollHandler, VHasDropHandler, FocusHandler, BlurHandler, Focusable,
+ ActionOwner {
- public static final String ATTRIBUTE_PAGEBUFFER_FIRST = "pb-ft";
- public static final String ATTRIBUTE_PAGEBUFFER_LAST = "pb-l";
+ public enum SelectMode {
+ NONE(0), SINGLE(1), MULTI(2);
+ private int id;
+
+ private SelectMode(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+ }
private static final String ROW_HEADER_COLUMN_KEY = "0";
public static final String CLASSNAME = "v-table";
public static final String CLASSNAME_SELECTION_FOCUS = CLASSNAME + "-focus";
+ public static final String ATTRIBUTE_PAGEBUFFER_FIRST = "pb-ft";
+ public static final String ATTRIBUTE_PAGEBUFFER_LAST = "pb-l";
+
public static final String ITEM_CLICK_EVENT_ID = "itemClick";
public static final String HEADER_CLICK_EVENT_ID = "handleHeaderClick";
public static final String FOOTER_CLICK_EVENT_ID = "handleFooterClick";
@@ -162,10 +177,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
protected ApplicationConnection client;
protected String paintableId;
- private boolean immediate;
+ boolean immediate;
private boolean nullSelectionAllowed = true;
- private int selectMode = Table.SELECT_MODE_NONE;
+ private SelectMode selectMode = SelectMode.NONE;
private final HashSet<String> selectedRowKeys = new HashSet<String>();
@@ -178,15 +193,15 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
/*
* These are used when jumping between pages when pressing Home and End
*/
- private boolean selectLastItemInNextRender = false;
- private boolean selectFirstItemInNextRender = false;
- private boolean focusFirstItemInNextRender = false;
- private boolean focusLastItemInNextRender = false;
+ boolean selectLastItemInNextRender = false;
+ boolean selectFirstItemInNextRender = false;
+ boolean focusFirstItemInNextRender = false;
+ boolean focusLastItemInNextRender = false;
/*
* The currently focused row
*/
- private VScrollTableRow focusedRow;
+ VScrollTableRow focusedRow;
/*
* Helper to store selection range start in when using the keyboard
@@ -197,7 +212,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* Flag for notifying when the selection has changed and should be sent to
* the server
*/
- private boolean selectionChanged = false;
+ boolean selectionChanged = false;
/*
* The speed (in pixels) which the scrolling scrolls vertically/horizontally
@@ -206,7 +221,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
private Timer scrollingVelocityTimer = null;
- private String[] bodyActionKeys;
+ String[] bodyActionKeys;
private boolean enableDebug = false;
@@ -282,19 +297,18 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
private final HashSet<SelectionRange> selectedRowRanges = new HashSet<SelectionRange>();
- private boolean initializedAndAttached = false;
+ boolean initializedAndAttached = false;
/**
* Flag to indicate if a column width recalculation is needed due update.
*/
- private boolean headerChangedDuringUpdate = false;
+ boolean headerChangedDuringUpdate = false;
protected final TableHead tHead = new TableHead();
- private final TableFooter tFoot = new TableFooter();
+ final TableFooter tFoot = new TableFooter();
- private final FocusableScrollPanel scrollBodyPanel = new FocusableScrollPanel(
- true);
+ final FocusableScrollPanel scrollBodyPanel = new FocusableScrollPanel(true);
private KeyPressHandler navKeyPressHandler = new KeyPressHandler() {
public void onKeyPress(KeyPressEvent keyPressEvent) {
@@ -383,12 +397,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
}
};
- private int totalRows;
+ int totalRows;
private Set<String> collapsedColumns;
- private final RowRequestHandler rowRequestHandler;
- private VScrollTableBody scrollBody;
+ final RowRequestHandler rowRequestHandler;
+ VScrollTableBody scrollBody;
private int firstvisible = 0;
private boolean sortAscending;
private String sortColumn;
@@ -403,9 +417,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
private String[] visibleColOrder;
private boolean initialContentReceived = false;
private Element scrollPositionElement;
- private boolean enabled;
- private boolean showColHeaders;
- private boolean showColFooters;
+ boolean enabled;
+ boolean showColHeaders;
+ boolean showColFooters;
/** flag to indicate that table body has changed */
private boolean isNewBody = true;
@@ -420,15 +434,15 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
private final ArrayList<Panel> lazyUnregistryBag = new ArrayList<Panel>();
private String height;
private String width = "";
- private boolean rendering = false;
+ boolean rendering = false;
private boolean hasFocus = false;
private int dragmode;
private int multiselectmode;
- private int tabIndex;
+ int tabIndex;
private TouchScrollDelegate touchScrollDelegate;
- private int lastRenderedHeight;
+ int lastRenderedHeight;
/**
* Values (serverCacheFirst+serverCacheLast) sent by server that tells which
@@ -442,8 +456,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* scrolling in the client will cause empty buttons to be rendered
* (cached=true request for non-existing components)
*/
- private int serverCacheFirst = -1;
- private int serverCacheLast = -1;
+ int serverCacheFirst = -1;
+ int serverCacheLast = -1;
public VScrollTable() {
setMultiSelectMode(MULTISELECT_MODE_DEFAULT);
@@ -810,211 +824,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
return KeyCodes.KEY_END;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
- * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
- */
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- rendering = true;
-
- if (uidl.hasAttribute(ATTRIBUTE_PAGEBUFFER_FIRST)) {
- serverCacheFirst = uidl.getIntAttribute(ATTRIBUTE_PAGEBUFFER_FIRST);
- serverCacheLast = uidl.getIntAttribute(ATTRIBUTE_PAGEBUFFER_LAST);
- } else {
- serverCacheFirst = -1;
- serverCacheLast = -1;
- }
- /*
- * We need to do this before updateComponent since updateComponent calls
- * this.setHeight() which will calculate a new body height depending on
- * the space available.
- */
- if (uidl.hasAttribute("colfooters")) {
- showColFooters = uidl.getBooleanAttribute("colfooters");
- }
-
- tFoot.setVisible(showColFooters);
-
- if (client.updateComponent(this, uidl, true)) {
- rendering = false;
- return;
- }
-
- enabled = !uidl.hasAttribute("disabled");
-
- if (BrowserInfo.get().isIE8() && !enabled) {
- /*
- * The disabled shim will not cover the table body if it is relative
- * in IE8. See #7324
- */
- scrollBodyPanel.getElement().getStyle()
- .setPosition(Position.STATIC);
- } else if (BrowserInfo.get().isIE8()) {
- scrollBodyPanel.getElement().getStyle()
- .setPosition(Position.RELATIVE);
- }
-
- this.client = client;
- paintableId = uidl.getStringAttribute("id");
- immediate = uidl.getBooleanAttribute("immediate");
-
- int previousTotalRows = totalRows;
- updateTotalRows(uidl);
- boolean totalRowsChanged = (totalRows != previousTotalRows);
-
- updateDragMode(uidl);
-
- updateSelectionProperties(uidl);
-
- if (uidl.hasAttribute("alb")) {
- bodyActionKeys = uidl.getStringArrayAttribute("alb");
- } else {
- // Need to clear the actions if the action handlers have been
- // removed
- bodyActionKeys = null;
- }
-
- setCacheRateFromUIDL(uidl);
-
- recalcWidths = uidl.hasAttribute("recalcWidths");
- if (recalcWidths) {
- tHead.clear();
- tFoot.clear();
- }
-
- updatePageLength(uidl);
-
- updateFirstVisibleAndScrollIfNeeded(uidl);
-
- showRowHeaders = uidl.getBooleanAttribute("rowheaders");
- showColHeaders = uidl.getBooleanAttribute("colheaders");
-
- updateSortingProperties(uidl);
-
- boolean keyboardSelectionOverRowFetchInProgress = selectSelectedRows(uidl);
-
- updateActionMap(uidl);
-
- updateColumnProperties(uidl);
-
- UIDL ac = uidl.getChildByTagName("-ac");
- if (ac == null) {
- if (dropHandler != null) {
- // remove dropHandler if not present anymore
- dropHandler = null;
- }
- } else {
- if (dropHandler == null) {
- dropHandler = new VScrollTableDropHandler();
- }
- dropHandler.updateAcceptRules(ac);
- }
-
- UIDL partialRowAdditions = uidl.getChildByTagName("prows");
- UIDL partialRowUpdates = uidl.getChildByTagName("urows");
- if (partialRowUpdates != null || partialRowAdditions != null) {
- // we may have pending cache row fetch, cancel it. See #2136
- rowRequestHandler.cancel();
-
- updateRowsInBody(partialRowUpdates);
- addAndRemoveRows(partialRowAdditions);
- } else {
- UIDL rowData = uidl.getChildByTagName("rows");
- if (rowData != null) {
- // we may have pending cache row fetch, cancel it. See #2136
- rowRequestHandler.cancel();
-
- if (!recalcWidths && initializedAndAttached) {
- updateBody(rowData, uidl.getIntAttribute("firstrow"),
- uidl.getIntAttribute("rows"));
- if (headerChangedDuringUpdate) {
- triggerLazyColumnAdjustment(true);
- } else if (!isScrollPositionVisible()
- || totalRowsChanged
- || lastRenderedHeight != scrollBody
- .getOffsetHeight()) {
- // webkits may still bug with their disturbing scrollbar
- // bug, see #3457
- // Run overflow fix for the scrollable area
- // #6698 - If there's a scroll going on, don't abort it
- // by changing overflows as the length of the contents
- // *shouldn't* have changed (unless the number of rows
- // or the height of the widget has also changed)
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- Util.runWebkitOverflowAutoFix(scrollBodyPanel
- .getElement());
- }
- });
- }
- } else {
- initializeRows(uidl, rowData);
- }
- }
- }
-
- if (!isSelectable()) {
- scrollBody.addStyleName(CLASSNAME + "-body-noselection");
- } else {
- scrollBody.removeStyleName(CLASSNAME + "-body-noselection");
- }
-
- hideScrollPositionAnnotation();
- purgeUnregistryBag();
-
- // selection is no in sync with server, avoid excessive server visits by
- // clearing to flag used during the normal operation
- if (!keyboardSelectionOverRowFetchInProgress) {
- selectionChanged = false;
- }
-
- /*
- * This is called when the Home or page up button has been pressed in
- * selectable mode and the next selected row was not yet rendered in the
- * client
- */
- if (selectFirstItemInNextRender || focusFirstItemInNextRender) {
- selectFirstRenderedRowInViewPort(focusFirstItemInNextRender);
- selectFirstItemInNextRender = focusFirstItemInNextRender = false;
- }
-
- /*
- * This is called when the page down or end button has been pressed in
- * selectable mode and the next selected row was not yet rendered in the
- * client
- */
- if (selectLastItemInNextRender || focusLastItemInNextRender) {
- selectLastRenderedRowInViewPort(focusLastItemInNextRender);
- selectLastItemInNextRender = focusLastItemInNextRender = false;
- }
- multiselectPending = false;
-
- if (focusedRow != null) {
- if (!focusedRow.isAttached() && !rowRequestHandler.isRunning()) {
- // focused row has been orphaned, can't focus
- focusRowFromBody();
- }
- }
-
- tabIndex = uidl.hasAttribute("tabindex") ? uidl
- .getIntAttribute("tabindex") : 0;
- setProperTabIndex();
-
- resizeSortedColumnForSortIndicator();
-
- // Remember this to detect situations where overflow hack might be
- // needed during scrolling
- lastRenderedHeight = scrollBody.getOffsetHeight();
-
- rendering = false;
- headerChangedDuringUpdate = false;
-
- }
-
- private void initializeRows(UIDL uidl, UIDL rowData) {
+ void initializeRows(UIDL uidl, UIDL rowData) {
if (scrollBody != null) {
scrollBody.removeFromParent();
lazyUnregistryBag.add(scrollBody);
@@ -1037,7 +847,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
scrollBody.restoreRowVisibility();
}
- private void updateColumnProperties(UIDL uidl) {
+ void updateColumnProperties(UIDL uidl) {
updateColumnOrder(uidl);
updateCollapsedColumns(uidl);
@@ -1072,7 +882,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
}
- private boolean selectSelectedRows(UIDL uidl) {
+ boolean selectSelectedRows(UIDL uidl) {
boolean keyboardSelectionOverRowFetchInProgress = false;
if (uidl.hasVariable("selected")) {
@@ -1109,7 +919,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
return keyboardSelectionOverRowFetchInProgress;
}
- private void updateSortingProperties(UIDL uidl) {
+ void updateSortingProperties(UIDL uidl) {
oldSortColumn = sortColumn;
if (uidl.hasVariable("sortascending")) {
sortAscending = uidl.getBooleanVariable("sortascending");
@@ -1117,7 +927,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
}
- private void resizeSortedColumnForSortIndicator() {
+ void resizeSortedColumnForSortIndicator() {
// Force recalculation of the captionContainer element inside the header
// cell to accomodate for the size of the sort arrow.
HeaderCell sortedHeader = tHead.getHeaderCell(sortColumn);
@@ -1132,7 +942,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
}
- private void updateFirstVisibleAndScrollIfNeeded(UIDL uidl) {
+ void updateFirstVisibleAndScrollIfNeeded(UIDL uidl) {
firstvisible = uidl.hasVariable("firstvisible") ? uidl
.getIntVariable("firstvisible") : 0;
if (firstvisible != lastRequestedFirstvisible && scrollBody != null) {
@@ -1147,7 +957,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
return (int) (rowIx * scrollBody.getRowHeight());
}
- private void updatePageLength(UIDL uidl) {
+ void updatePageLength(UIDL uidl) {
int oldPageLength = pageLength;
if (uidl.hasAttribute("pagelength")) {
pageLength = uidl.getIntAttribute("pagelength");
@@ -1162,7 +972,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
}
- private void updateSelectionProperties(UIDL uidl) {
+ void updateSelectionProperties(UIDL uidl) {
setMultiSelectMode(uidl.hasAttribute("multiselectmode") ? uidl
.getIntAttribute("multiselectmode") : MULTISELECT_MODE_DEFAULT);
@@ -1171,18 +981,18 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
if (uidl.hasAttribute("selectmode")) {
if (uidl.getBooleanAttribute("readonly")) {
- selectMode = Table.SELECT_MODE_NONE;
+ selectMode = SelectMode.NONE;
} else if (uidl.getStringAttribute("selectmode").equals("multi")) {
- selectMode = Table.SELECT_MODE_MULTI;
+ selectMode = SelectMode.MULTI;
} else if (uidl.getStringAttribute("selectmode").equals("single")) {
- selectMode = Table.SELECT_MODE_SINGLE;
+ selectMode = SelectMode.SINGLE;
} else {
- selectMode = Table.SELECT_MODE_NONE;
+ selectMode = SelectMode.NONE;
}
}
}
- private void updateDragMode(UIDL uidl) {
+ void updateDragMode(UIDL uidl) {
dragmode = uidl.hasAttribute("dragmode") ? uidl
.getIntAttribute("dragmode") : 0;
if (BrowserInfo.get().isIE()) {
@@ -1219,7 +1029,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
return totalRows;
}
- private void focusRowFromBody() {
+ void focusRowFromBody() {
if (selectedRowKeys.size() == 1) {
// try to focus a row currently selected and in viewport
String selectedRowKey = selectedRowKeys.iterator().next();
@@ -1247,7 +1057,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* @param focusOnly
* Should the focus only be moved to the last row
*/
- private void selectLastRenderedRowInViewPort(boolean focusOnly) {
+ void selectLastRenderedRowInViewPort(boolean focusOnly) {
int index = firstRowInViewPort + getFullyVisibleRowCount();
VScrollTableRow lastRowInViewport = scrollBody.getRowByRowIndex(index);
if (lastRowInViewport == null) {
@@ -1272,7 +1082,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* @param focusOnly
* Should the focus only be moved to the first row
*/
- private void selectFirstRenderedRowInViewPort(boolean focusOnly) {
+ void selectFirstRenderedRowInViewPort(boolean focusOnly) {
int index = firstRowInViewPort;
VScrollTableRow firstInViewport = scrollBody.getRowByRowIndex(index);
if (firstInViewport == null) {
@@ -1286,7 +1096,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
}
- private void setCacheRateFromUIDL(UIDL uidl) {
+ void setCacheRateFromUIDL(UIDL uidl) {
setCacheRate(uidl.hasAttribute("cr") ? uidl.getDoubleAttribute("cr")
: CACHE_RATE_DEFAULT);
}
@@ -1303,7 +1113,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* IScrollTableRows). This is done lazily as Table must survive from
* "subtreecaching" logic.
*/
- private void purgeUnregistryBag() {
+ void purgeUnregistryBag() {
for (Iterator<Panel> iterator = lazyUnregistryBag.iterator(); iterator
.hasNext();) {
VPaintableMap.get(client)
@@ -1312,7 +1122,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
lazyUnregistryBag.clear();
}
- private void updateActionMap(UIDL mainUidl) {
+ void updateActionMap(UIDL mainUidl) {
UIDL actionsUidl = mainUidl.getChildByTagName("actions");
if (actionsUidl == null) {
return;
@@ -1414,7 +1224,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* @param reqRows
* amount of rows in data set
*/
- private void updateBody(UIDL uidl, int firstRow, int reqRows) {
+ void updateBody(UIDL uidl, int firstRow, int reqRows) {
if (uidl == null || reqRows < 1) {
// container is empty, remove possibly existing rows
if (firstRow <= 0) {
@@ -1431,7 +1241,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
discardRowsOutsideCacheWindow();
}
- private void updateRowsInBody(UIDL partialRowUpdates) {
+ void updateRowsInBody(UIDL partialRowUpdates) {
if (partialRowUpdates == null) {
return;
}
@@ -1564,20 +1374,20 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
private boolean isMultiSelectModeSimple() {
- return selectMode == Table.SELECT_MODE_MULTI
+ return selectMode == SelectMode.MULTI
&& multiselectmode == MULTISELECT_MODE_SIMPLE;
}
private boolean isSingleSelectMode() {
- return selectMode == Table.SELECT_MODE_SINGLE;
+ return selectMode == SelectMode.SINGLE;
}
private boolean isMultiSelectModeAny() {
- return selectMode == Table.SELECT_MODE_MULTI;
+ return selectMode == SelectMode.MULTI;
}
private boolean isMultiSelectModeDefault() {
- return selectMode == Table.SELECT_MODE_MULTI
+ return selectMode == SelectMode.MULTI
&& multiselectmode == MULTISELECT_MODE_DEFAULT;
}
@@ -1593,7 +1403,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
protected boolean isSelectable() {
- return selectMode > Table.SELECT_MODE_NONE;
+ return selectMode.getId() > SelectMode.NONE.getId();
}
private boolean isCollapsedColumn(String colKey) {
@@ -1769,7 +1579,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
}
client.updateVariable(paintableId, "columnorder", columnOrder, false);
- if (client.hasEventListeners(this, COLUMN_REORDER_EVENT_ID)) {
+ if (client.hasWidgetEventListeners(this, COLUMN_REORDER_EVENT_ID)) {
client.sendPendingVariableChanges();
}
}
@@ -2108,19 +1918,19 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
style.setDisplay(Display.BLOCK);
}
- private void hideScrollPositionAnnotation() {
+ void hideScrollPositionAnnotation() {
if (scrollPositionElement != null) {
DOM.setStyleAttribute(scrollPositionElement, "display", "none");
}
}
- private boolean isScrollPositionVisible() {
+ boolean isScrollPositionVisible() {
return scrollPositionElement != null
&& !scrollPositionElement.getStyle().getDisplay()
.equals(Display.NONE.toString());
}
- private class RowRequestHandler extends Timer {
+ class RowRequestHandler extends Timer {
private int reqFirstRow = 0;
private int reqRows = 0;
@@ -2295,26 +2105,16 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* of the caption container element by the correct amount
*/
public void resizeCaptionContainer(int rightSpacing) {
+ int captionContainerWidth = width
+ - colResizeWidget.getOffsetWidth() - rightSpacing;
+
if (td.getClassName().contains("-asc")
|| td.getClassName().contains("-desc")) {
- /*
- * Room for the sort indicator is made by subtracting the styled
- * margin and width of the resizer from the width of the caption
- * container.
- */
- int captionContainerWidth = width
- - sortIndicator.getOffsetWidth()
- - colResizeWidget.getOffsetWidth() - rightSpacing;
- captionContainer.getStyle().setPropertyPx("width",
- captionContainerWidth);
- } else {
- /*
- * Set the caption container element as wide as possible when
- * the sorting indicator is not visible.
- */
- captionContainer.getStyle().setPropertyPx("width",
- width - rightSpacing);
+ // Leave room for the sort indicator
+ captionContainerWidth -= sortIndicator.getOffsetWidth();
}
+ captionContainer.getStyle().setPropertyPx("width",
+ captionContainerWidth);
// Apply/Remove spacing if defined
if (rightSpacing > 0) {
@@ -2512,7 +2312,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* The click event
*/
private void fireHeaderClickedEvent(Event event) {
- if (client.hasEventListeners(VScrollTable.this,
+ if (client.hasWidgetEventListeners(VScrollTable.this,
HEADER_CLICK_EVENT_ID)) {
MouseEventDetails details = new MouseEventDetails(event);
client.updateVariable(paintableId, "headerClickEvent",
@@ -3543,7 +3343,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* The click event
*/
private void fireFooterClickedEvent(Event event) {
- if (client.hasEventListeners(VScrollTable.this,
+ if (client.hasWidgetEventListeners(VScrollTable.this,
FOOTER_CLICK_EVENT_ID)) {
MouseEventDetails details = new MouseEventDetails(event);
client.updateVariable(paintableId, "footerClickEvent",
@@ -4295,12 +4095,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
final VScrollTableRow toBeRemoved = (VScrollTableRow) renderedRows
.get(index);
// Unregister row tooltip
- client.registerTooltip(VScrollTable.this, toBeRemoved.getElement(),
- null);
+ client.registerWidgetTooltip(VScrollTable.this,
+ toBeRemoved.getElement(), null);
for (int i = 0; i < toBeRemoved.getElement().getChildCount(); i++) {
// Unregister cell tooltips
Element td = toBeRemoved.getElement().getChild(i).cast();
- client.registerTooltip(VScrollTable.this, td, null);
+ client.registerWidgetTooltip(VScrollTable.this, td, null);
}
lazyUnregistryBag.add(toBeRemoved);
tBodyElement.removeChild(toBeRemoved.getElement());
@@ -4559,10 +4359,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
String rowDescription = uidl.getStringAttribute("rowdescr");
if (rowDescription != null && !rowDescription.equals("")) {
TooltipInfo info = new TooltipInfo(rowDescription);
- client.registerTooltip(VScrollTable.this, rowElement, info);
+ client.registerWidgetTooltip(VScrollTable.this, rowElement,
+ info);
} else {
// Remove possibly previously set tooltip
- client.registerTooltip(VScrollTable.this, rowElement, null);
+ client.registerWidgetTooltip(VScrollTable.this, rowElement,
+ null);
}
tHead.getColumnAlignments();
@@ -4797,10 +4599,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
if (description != null && !description.equals("")) {
TooltipInfo info = new TooltipInfo(description);
- client.registerTooltip(VScrollTable.this, td, info);
+ client.registerWidgetTooltip(VScrollTable.this, td, info);
} else {
// Remove possibly previously set tooltip
- client.registerTooltip(VScrollTable.this, td, null);
+ client.registerWidgetTooltip(VScrollTable.this, td, null);
}
td.appendChild(container);
@@ -4879,7 +4681,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
*/
private boolean handleClickEvent(Event event, Element targetTdOrTr,
boolean immediate) {
- if (!client.hasEventListeners(VScrollTable.this,
+ if (!client.hasWidgetEventListeners(VScrollTable.this,
ITEM_CLICK_EVENT_ID)) {
// Don't send an event if nobody is listening
return false;
@@ -4923,22 +4725,24 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
if (!containsWidget) {
// Only text nodes has tooltips
- if (client.getTooltipTitleInfo(VScrollTable.this,
- target) != null) {
+ if (VPaintableMap.get(client).getWidgetTooltipInfo(
+ VScrollTable.this, target) != null) {
// Cell has description, use it
- client.handleTooltipEvent(event, VScrollTable.this,
- target);
+ client.handleWidgetTooltipEvent(event,
+ VScrollTable.this, target);
} else {
// Cell might have row description, use row
// description
- client.handleTooltipEvent(event, VScrollTable.this,
+ client.handleWidgetTooltipEvent(event,
+ VScrollTable.this,
target.getParentElement());
}
}
} else {
// Table row (tr)
- client.handleTooltipEvent(event, VScrollTable.this, target);
+ client.handleWidgetTooltipEvent(event, VScrollTable.this,
+ target);
}
}
@@ -4954,7 +4758,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
showContextMenu(event);
if (enabled
&& (actionKeys != null || client
- .hasEventListeners(VScrollTable.this,
+ .hasWidgetEventListeners(
+ VScrollTable.this,
ITEM_CLICK_EVENT_ID))) {
/*
* Prevent browser context menu only if there are
@@ -5243,7 +5048,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
Element targetTdOrTr) {
mDown = true;
VTransferable transferable = new VTransferable();
- transferable.setDragSource(VScrollTable.this);
+ transferable.setDragSource(VPaintableMap.get(client)
+ .getPaintable(VScrollTable.this));
transferable.setData("itemId", "" + rowKey);
NodeList<TableCellElement> cells = rowElement.getCells();
for (int i = 0; i < cells.getLength(); i++) {
@@ -5972,9 +5778,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
private int contentAreaBorderHeight = -1;
private int scrollLeft;
private int scrollTop;
- private VScrollTableDropHandler dropHandler;
+ VScrollTableDropHandler dropHandler;
private boolean navKeyDown;
- private boolean multiselectPending;
+ boolean multiselectPending;
/**
* @return border top + border bottom of the scrollable area of table
@@ -6066,7 +5872,15 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
public void onScroll(ScrollEvent event) {
scrollLeft = scrollBodyPanel.getElement().getScrollLeft();
scrollTop = scrollBodyPanel.getScrollPosition();
- if (!initializedAndAttached) {
+ /*
+ * #6970 - IE sometimes fires scroll events for a detached table.
+ *
+ * FIXME initializedAndAttached should probably be renamed - its name
+ * doesn't seem to reflect its semantics. onDetach() doesn't set it to
+ * false, and changing that might break something else, so we need to
+ * check isAttached() separately.
+ */
+ if (!initializedAndAttached || !isAttached()) {
return;
}
if (!enabled) {
@@ -6315,7 +6129,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
@Override
public VPaintableWidget getPaintable() {
- return VScrollTable.this;
+ return VPaintableMap.get(client).getPaintable(VScrollTable.this);
}
public ApplicationConnection getApplicationConnection() {
@@ -6752,7 +6566,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
* actions may need focus.
*
*/
- private void setProperTabIndex() {
+ void setProperTabIndex() {
int storedScrollTop = 0;
int storedScrollLeft = 0;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java
new file mode 100644
index 0000000000..fa7cc3d4ec
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java
@@ -0,0 +1,254 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
+
+public class VScrollTablePaintable extends VAbstractPaintableWidget {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
+ * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
+ */
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ getWidgetForPaintable().rendering = true;
+
+ if (uidl.hasAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST)) {
+ getWidgetForPaintable().serverCacheFirst = uidl
+ .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST);
+ getWidgetForPaintable().serverCacheLast = uidl
+ .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_LAST);
+ } else {
+ getWidgetForPaintable().serverCacheFirst = -1;
+ getWidgetForPaintable().serverCacheLast = -1;
+ }
+ /*
+ * We need to do this before updateComponent since updateComponent calls
+ * this.setHeight() which will calculate a new body height depending on
+ * the space available.
+ */
+ if (uidl.hasAttribute("colfooters")) {
+ getWidgetForPaintable().showColFooters = uidl
+ .getBooleanAttribute("colfooters");
+ }
+
+ getWidgetForPaintable().tFoot
+ .setVisible(getWidgetForPaintable().showColFooters);
+
+ if (client.updateComponent(this, uidl, true)) {
+ getWidgetForPaintable().rendering = false;
+ return;
+ }
+
+ getWidgetForPaintable().enabled = !uidl.hasAttribute("disabled");
+
+ if (BrowserInfo.get().isIE8() && !getWidgetForPaintable().enabled) {
+ /*
+ * The disabled shim will not cover the table body if it is relative
+ * in IE8. See #7324
+ */
+ getWidgetForPaintable().scrollBodyPanel.getElement().getStyle()
+ .setPosition(Position.STATIC);
+ } else if (BrowserInfo.get().isIE8()) {
+ getWidgetForPaintable().scrollBodyPanel.getElement().getStyle()
+ .setPosition(Position.RELATIVE);
+ }
+
+ getWidgetForPaintable().client = client;
+ getWidgetForPaintable().paintableId = uidl.getStringAttribute("id");
+ getWidgetForPaintable().immediate = uidl
+ .getBooleanAttribute("immediate");
+
+ int previousTotalRows = getWidgetForPaintable().totalRows;
+ getWidgetForPaintable().updateTotalRows(uidl);
+ boolean totalRowsChanged = (getWidgetForPaintable().totalRows != previousTotalRows);
+
+ getWidgetForPaintable().updateDragMode(uidl);
+
+ getWidgetForPaintable().updateSelectionProperties(uidl);
+
+ if (uidl.hasAttribute("alb")) {
+ getWidgetForPaintable().bodyActionKeys = uidl
+ .getStringArrayAttribute("alb");
+ } else {
+ // Need to clear the actions if the action handlers have been
+ // removed
+ getWidgetForPaintable().bodyActionKeys = null;
+ }
+
+ getWidgetForPaintable().setCacheRateFromUIDL(uidl);
+
+ getWidgetForPaintable().recalcWidths = uidl
+ .hasAttribute("recalcWidths");
+ if (getWidgetForPaintable().recalcWidths) {
+ getWidgetForPaintable().tHead.clear();
+ getWidgetForPaintable().tFoot.clear();
+ }
+
+ getWidgetForPaintable().updatePageLength(uidl);
+
+ getWidgetForPaintable().updateFirstVisibleAndScrollIfNeeded(uidl);
+
+ getWidgetForPaintable().showRowHeaders = uidl
+ .getBooleanAttribute("rowheaders");
+ getWidgetForPaintable().showColHeaders = uidl
+ .getBooleanAttribute("colheaders");
+
+ getWidgetForPaintable().updateSortingProperties(uidl);
+
+ boolean keyboardSelectionOverRowFetchInProgress = getWidgetForPaintable()
+ .selectSelectedRows(uidl);
+
+ getWidgetForPaintable().updateActionMap(uidl);
+
+ getWidgetForPaintable().updateColumnProperties(uidl);
+
+ UIDL ac = uidl.getChildByTagName("-ac");
+ if (ac == null) {
+ if (getWidgetForPaintable().dropHandler != null) {
+ // remove dropHandler if not present anymore
+ getWidgetForPaintable().dropHandler = null;
+ }
+ } else {
+ if (getWidgetForPaintable().dropHandler == null) {
+ getWidgetForPaintable().dropHandler = getWidgetForPaintable().new VScrollTableDropHandler();
+ }
+ getWidgetForPaintable().dropHandler.updateAcceptRules(ac);
+ }
+
+ UIDL partialRowAdditions = uidl.getChildByTagName("prows");
+ UIDL partialRowUpdates = uidl.getChildByTagName("urows");
+ if (partialRowUpdates != null || partialRowAdditions != null) {
+ // we may have pending cache row fetch, cancel it. See #2136
+ getWidgetForPaintable().rowRequestHandler.cancel();
+
+ getWidgetForPaintable().updateRowsInBody(partialRowUpdates);
+ getWidgetForPaintable().addAndRemoveRows(partialRowAdditions);
+ } else {
+ UIDL rowData = uidl.getChildByTagName("rows");
+ if (rowData != null) {
+ // we may have pending cache row fetch, cancel it. See #2136
+ getWidgetForPaintable().rowRequestHandler.cancel();
+
+ if (!getWidgetForPaintable().recalcWidths
+ && getWidgetForPaintable().initializedAndAttached) {
+ getWidgetForPaintable().updateBody(rowData,
+ uidl.getIntAttribute("firstrow"),
+ uidl.getIntAttribute("rows"));
+ if (getWidgetForPaintable().headerChangedDuringUpdate) {
+ getWidgetForPaintable().triggerLazyColumnAdjustment(
+ true);
+ } else if (!getWidgetForPaintable()
+ .isScrollPositionVisible()
+ || totalRowsChanged
+ || getWidgetForPaintable().lastRenderedHeight != getWidgetForPaintable().scrollBody
+ .getOffsetHeight()) {
+ // webkits may still bug with their disturbing scrollbar
+ // bug, see #3457
+ // Run overflow fix for the scrollable area
+ // #6698 - If there's a scroll going on, don't abort it
+ // by changing overflows as the length of the contents
+ // *shouldn't* have changed (unless the number of rows
+ // or the height of the widget has also changed)
+ Scheduler.get().scheduleDeferred(new Command() {
+ public void execute() {
+ Util.runWebkitOverflowAutoFix(getWidgetForPaintable().scrollBodyPanel
+ .getElement());
+ }
+ });
+ }
+ } else {
+ getWidgetForPaintable().initializeRows(uidl, rowData);
+ }
+ }
+ }
+
+ if (!getWidgetForPaintable().isSelectable()) {
+ getWidgetForPaintable().scrollBody
+ .addStyleName(VScrollTable.CLASSNAME + "-body-noselection");
+ } else {
+ getWidgetForPaintable().scrollBody
+ .removeStyleName(VScrollTable.CLASSNAME
+ + "-body-noselection");
+ }
+
+ getWidgetForPaintable().hideScrollPositionAnnotation();
+ getWidgetForPaintable().purgeUnregistryBag();
+
+ // selection is no in sync with server, avoid excessive server visits by
+ // clearing to flag used during the normal operation
+ if (!keyboardSelectionOverRowFetchInProgress) {
+ getWidgetForPaintable().selectionChanged = false;
+ }
+
+ /*
+ * This is called when the Home or page up button has been pressed in
+ * selectable mode and the next selected row was not yet rendered in the
+ * client
+ */
+ if (getWidgetForPaintable().selectFirstItemInNextRender
+ || getWidgetForPaintable().focusFirstItemInNextRender) {
+ getWidgetForPaintable().selectFirstRenderedRowInViewPort(
+ getWidgetForPaintable().focusFirstItemInNextRender);
+ getWidgetForPaintable().selectFirstItemInNextRender = getWidgetForPaintable().focusFirstItemInNextRender = false;
+ }
+
+ /*
+ * This is called when the page down or end button has been pressed in
+ * selectable mode and the next selected row was not yet rendered in the
+ * client
+ */
+ if (getWidgetForPaintable().selectLastItemInNextRender
+ || getWidgetForPaintable().focusLastItemInNextRender) {
+ getWidgetForPaintable().selectLastRenderedRowInViewPort(
+ getWidgetForPaintable().focusLastItemInNextRender);
+ getWidgetForPaintable().selectLastItemInNextRender = getWidgetForPaintable().focusLastItemInNextRender = false;
+ }
+ getWidgetForPaintable().multiselectPending = false;
+
+ if (getWidgetForPaintable().focusedRow != null) {
+ if (!getWidgetForPaintable().focusedRow.isAttached()
+ && !getWidgetForPaintable().rowRequestHandler.isRunning()) {
+ // focused row has been orphaned, can't focus
+ getWidgetForPaintable().focusRowFromBody();
+ }
+ }
+
+ getWidgetForPaintable().tabIndex = uidl.hasAttribute("tabindex") ? uidl
+ .getIntAttribute("tabindex") : 0;
+ getWidgetForPaintable().setProperTabIndex();
+
+ getWidgetForPaintable().resizeSortedColumnForSortIndicator();
+
+ // Remember this to detect situations where overflow hack might be
+ // needed during scrolling
+ getWidgetForPaintable().lastRenderedHeight = getWidgetForPaintable().scrollBody
+ .getOffsetHeight();
+
+ getWidgetForPaintable().rendering = false;
+ getWidgetForPaintable().headerChangedDuringUpdate = false;
+
+ }
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VScrollTable.class);
+ }
+
+ @Override
+ public VScrollTable getWidgetForPaintable() {
+ return (VScrollTable) super.getWidgetForPaintable();
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java
index 6b55fa0802..3632e90956 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java
@@ -1,573 +1,569 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-//
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.ContainerResizedListener;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VConsole;
-
-public class VSlider extends SimpleFocusablePanel implements VPaintableWidget,
- Field, ContainerResizedListener {
-
- public static final String CLASSNAME = "v-slider";
-
- /**
- * Minimum size (width or height, depending on orientation) of the slider
- * base.
- */
- private static final int MIN_SIZE = 50;
-
- ApplicationConnection client;
-
- String id;
-
- private boolean immediate;
- private boolean disabled;
- private boolean readonly;
-
- private int acceleration = 1;
- private double min;
- private double max;
- private int resolution;
- private Double value;
- private boolean vertical;
-
- private final HTML feedback = new HTML("", false);
- private final VOverlay feedbackPopup = new VOverlay(true, false, true) {
- @Override
- public void show() {
- super.show();
- updateFeedbackPosition();
- }
- };
-
- /* DOM element for slider's base */
- private final Element base;
- private final int BASE_BORDER_WIDTH = 1;
-
- /* DOM element for slider's handle */
- private final Element handle;
-
- /* DOM element for decrement arrow */
- private final Element smaller;
-
- /* DOM element for increment arrow */
- private final Element bigger;
-
- /* Temporary dragging/animation variables */
- private boolean dragging = false;
-
- private VLazyExecutor delayedValueUpdater = new VLazyExecutor(100,
- new ScheduledCommand() {
-
- public void execute() {
- updateValueToServer();
- acceleration = 1;
- }
- });
-
- public VSlider() {
- super();
-
- base = DOM.createDiv();
- handle = DOM.createDiv();
- smaller = DOM.createDiv();
- bigger = DOM.createDiv();
-
- setStyleName(CLASSNAME);
- DOM.setElementProperty(base, "className", CLASSNAME + "-base");
- DOM.setElementProperty(handle, "className", CLASSNAME + "-handle");
- DOM.setElementProperty(smaller, "className", CLASSNAME + "-smaller");
- DOM.setElementProperty(bigger, "className", CLASSNAME + "-bigger");
-
- DOM.appendChild(getElement(), bigger);
- DOM.appendChild(getElement(), smaller);
- DOM.appendChild(getElement(), base);
- DOM.appendChild(base, handle);
-
- // Hide initially
- DOM.setStyleAttribute(smaller, "display", "none");
- DOM.setStyleAttribute(bigger, "display", "none");
- DOM.setStyleAttribute(handle, "visibility", "hidden");
-
- sinkEvents(Event.MOUSEEVENTS | Event.ONMOUSEWHEEL | Event.KEYEVENTS
- | Event.FOCUSEVENTS | Event.TOUCHEVENTS);
-
- feedbackPopup.addStyleName(CLASSNAME + "-feedback");
- feedbackPopup.setWidget(feedback);
- }
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
-
- this.client = client;
- id = uidl.getId();
-
- // Ensure correct implementation
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- immediate = uidl.getBooleanAttribute("immediate");
- disabled = uidl.getBooleanAttribute("disabled");
- readonly = uidl.getBooleanAttribute("readonly");
-
- vertical = uidl.hasAttribute("vertical");
-
- String style = "";
- if (uidl.hasAttribute("style")) {
- style = uidl.getStringAttribute("style");
- }
-
- if (vertical) {
- addStyleName(CLASSNAME + "-vertical");
- } else {
- removeStyleName(CLASSNAME + "-vertical");
- }
-
- min = uidl.getDoubleAttribute("min");
- max = uidl.getDoubleAttribute("max");
- resolution = uidl.getIntAttribute("resolution");
- value = new Double(uidl.getDoubleVariable("value"));
-
- setFeedbackValue(value);
-
- buildBase();
-
- if (!vertical) {
- // Draw handle with a delay to allow base to gain maximum width
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- buildHandle();
- setValue(value, false);
- }
- });
- } else {
- buildHandle();
- setValue(value, false);
- }
- }
-
- private void setFeedbackValue(double value) {
- String currentValue = "" + value;
- if (resolution == 0) {
- currentValue = "" + new Double(value).intValue();
- }
- feedback.setText(currentValue);
- }
-
- private void updateFeedbackPosition() {
- if (vertical) {
- feedbackPopup.setPopupPosition(
- DOM.getAbsoluteLeft(handle) + handle.getOffsetWidth(),
- DOM.getAbsoluteTop(handle) + handle.getOffsetHeight() / 2
- - feedbackPopup.getOffsetHeight() / 2);
- } else {
- feedbackPopup.setPopupPosition(
- DOM.getAbsoluteLeft(handle) + handle.getOffsetWidth() / 2
- - feedbackPopup.getOffsetWidth() / 2,
- DOM.getAbsoluteTop(handle)
- - feedbackPopup.getOffsetHeight());
- }
- }
-
- private void buildBase() {
- final String styleAttribute = vertical ? "height" : "width";
- final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
-
- final Element p = DOM.getParent(getElement());
- if (DOM.getElementPropertyInt(p, domProperty) > 50) {
- if (vertical) {
- setHeight();
- } else {
- DOM.setStyleAttribute(base, styleAttribute, "");
- }
- } else {
- // Set minimum size and adjust after all components have
- // (supposedly) been drawn completely.
- DOM.setStyleAttribute(base, styleAttribute, MIN_SIZE + "px");
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- final Element p = DOM.getParent(getElement());
- if (DOM.getElementPropertyInt(p, domProperty) > (MIN_SIZE + 5)) {
- if (vertical) {
- setHeight();
- } else {
- DOM.setStyleAttribute(base, styleAttribute, "");
- }
- // Ensure correct position
- setValue(value, false);
- }
- }
- });
- }
-
- // TODO attach listeners for focusing and arrow keys
- }
-
- private void buildHandle() {
- final String handleAttribute = vertical ? "marginTop" : "marginLeft";
-
- DOM.setStyleAttribute(handle, handleAttribute, "0");
-
- // Restore visibility
- DOM.setStyleAttribute(handle, "visibility", "visible");
-
- }
-
- private void setValue(Double value, boolean updateToServer) {
- if (value == null) {
- return;
- }
-
- if (value < min) {
- value = min;
- } else if (value > max) {
- value = max;
- }
-
- // Update handle position
- final String styleAttribute = vertical ? "marginTop" : "marginLeft";
- final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
- final int handleSize = Integer.parseInt(DOM.getElementProperty(handle,
- domProperty));
- final int baseSize = Integer.parseInt(DOM.getElementProperty(base,
- domProperty)) - (2 * BASE_BORDER_WIDTH);
-
- final int range = baseSize - handleSize;
- double v = value.doubleValue();
-
- // Round value to resolution
- if (resolution > 0) {
- v = Math.round(v * Math.pow(10, resolution));
- v = v / Math.pow(10, resolution);
- } else {
- v = Math.round(v);
- }
- final double valueRange = max - min;
- double p = 0;
- if (valueRange > 0) {
- p = range * ((v - min) / valueRange);
- }
- if (p < 0) {
- p = 0;
- }
- if (vertical) {
- p = range - p;
- }
- final double pos = p;
-
- DOM.setStyleAttribute(handle, styleAttribute, (Math.round(pos)) + "px");
-
- // Update value
- this.value = new Double(v);
- setFeedbackValue(v);
-
- if (updateToServer) {
- updateValueToServer();
- }
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- if (disabled || readonly) {
- return;
- }
- final Element targ = DOM.eventGetTarget(event);
-
- if (DOM.eventGetType(event) == Event.ONMOUSEWHEEL) {
- processMouseWheelEvent(event);
- } else if (dragging || targ == handle) {
- processHandleEvent(event);
- } else if (targ == smaller) {
- decreaseValue(true);
- } else if (targ == bigger) {
- increaseValue(true);
- } else if (DOM.eventGetType(event) == Event.MOUSEEVENTS) {
- processBaseEvent(event);
- } else if ((BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYPRESS)
- || (!BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYDOWN)) {
-
- if (handleNavigation(event.getKeyCode(), event.getCtrlKey(),
- event.getShiftKey())) {
-
- feedbackPopup.show();
-
- delayedValueUpdater.trigger();
-
- DOM.eventPreventDefault(event);
- DOM.eventCancelBubble(event, true);
- }
- } else if (targ.equals(getElement())
- && DOM.eventGetType(event) == Event.ONFOCUS) {
- feedbackPopup.show();
- } else if (targ.equals(getElement())
- && DOM.eventGetType(event) == Event.ONBLUR) {
- feedbackPopup.hide();
- } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
- feedbackPopup.show();
- }
- if (Util.isTouchEvent(event)) {
- event.preventDefault(); // avoid simulated events
- event.stopPropagation();
- }
- }
-
- private void processMouseWheelEvent(final Event event) {
- final int dir = DOM.eventGetMouseWheelVelocityY(event);
-
- if (dir < 0) {
- increaseValue(false);
- } else {
- decreaseValue(false);
- }
-
- delayedValueUpdater.trigger();
-
- DOM.eventPreventDefault(event);
- DOM.eventCancelBubble(event, true);
- }
-
- private void processHandleEvent(Event event) {
- switch (DOM.eventGetType(event)) {
- case Event.ONMOUSEDOWN:
- case Event.ONTOUCHSTART:
- if (!disabled && !readonly) {
- focus();
- feedbackPopup.show();
- dragging = true;
- DOM.setElementProperty(handle, "className", CLASSNAME
- + "-handle " + CLASSNAME + "-handle-active");
- DOM.setCapture(getElement());
- DOM.eventPreventDefault(event); // prevent selecting text
- DOM.eventCancelBubble(event, true);
- event.stopPropagation();
- VConsole.log("Slider move start");
- }
- break;
- case Event.ONMOUSEMOVE:
- case Event.ONTOUCHMOVE:
- if (dragging) {
- VConsole.log("Slider move");
- setValueByEvent(event, false);
- updateFeedbackPosition();
- event.stopPropagation();
- }
- break;
- case Event.ONTOUCHEND:
- feedbackPopup.hide();
- case Event.ONMOUSEUP:
- // feedbackPopup.hide();
- VConsole.log("Slider move end");
- dragging = false;
- DOM.setElementProperty(handle, "className", CLASSNAME + "-handle");
- DOM.releaseCapture(getElement());
- setValueByEvent(event, true);
- event.stopPropagation();
- break;
- default:
- break;
- }
- }
-
- private void processBaseEvent(Event event) {
- if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
- if (!disabled && !readonly && !dragging) {
- setValueByEvent(event, true);
- DOM.eventCancelBubble(event, true);
- }
- } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && dragging) {
- dragging = false;
- DOM.releaseCapture(getElement());
- setValueByEvent(event, true);
- }
- }
-
- private void decreaseValue(boolean updateToServer) {
- setValue(new Double(value.doubleValue() - Math.pow(10, -resolution)),
- updateToServer);
- }
-
- private void increaseValue(boolean updateToServer) {
- setValue(new Double(value.doubleValue() + Math.pow(10, -resolution)),
- updateToServer);
- }
-
- private void setValueByEvent(Event event, boolean updateToServer) {
- double v = min; // Fallback to min
-
- final int coord = getEventPosition(event);
-
- final int handleSize, baseSize, baseOffset;
- if (vertical) {
- handleSize = handle.getOffsetHeight();
- baseSize = base.getOffsetHeight();
- baseOffset = base.getAbsoluteTop() - Window.getScrollTop()
- - handleSize / 2;
- } else {
- handleSize = handle.getOffsetWidth();
- baseSize = base.getOffsetWidth();
- baseOffset = base.getAbsoluteLeft() - Window.getScrollLeft()
- + handleSize / 2;
- }
-
- if (vertical) {
- v = ((baseSize - (coord - baseOffset)) / (double) (baseSize - handleSize))
- * (max - min) + min;
- } else {
- v = ((coord - baseOffset) / (double) (baseSize - handleSize))
- * (max - min) + min;
- }
-
- if (v < min) {
- v = min;
- } else if (v > max) {
- v = max;
- }
-
- setValue(v, updateToServer);
- }
-
- /**
- * TODO consider extracting touches support to an impl class specific for
- * webkit (only browser that really supports touches).
- *
- * @param event
- * @return
- */
- protected int getEventPosition(Event event) {
- if (vertical) {
- return Util.getTouchOrMouseClientY(event);
- } else {
- return Util.getTouchOrMouseClientX(event);
- }
- }
-
- public void iLayout() {
- if (vertical) {
- setHeight();
- }
- // Update handle position
- setValue(value, false);
- }
-
- private void setHeight() {
- // Calculate decoration size
- DOM.setStyleAttribute(base, "height", "0");
- DOM.setStyleAttribute(base, "overflow", "hidden");
- int h = DOM.getElementPropertyInt(getElement(), "offsetHeight");
- if (h < MIN_SIZE) {
- h = MIN_SIZE;
- }
- DOM.setStyleAttribute(base, "height", h + "px");
- DOM.setStyleAttribute(base, "overflow", "");
- }
-
- private void updateValueToServer() {
- client.updateVariable(id, "value", value.doubleValue(), immediate);
- }
-
- /**
- * Handles the keyboard events handled by the Slider
- *
- * @param event
- * The keyboard event received
- * @return true iff the navigation event was handled
- */
- public boolean handleNavigation(int keycode, boolean ctrl, boolean shift) {
-
- // No support for ctrl moving
- if (ctrl) {
- return false;
- }
-
- if ((keycode == getNavigationUpKey() && vertical)
- || (keycode == getNavigationRightKey() && !vertical)) {
- if (shift) {
- for (int a = 0; a < acceleration; a++) {
- increaseValue(false);
- }
- acceleration++;
- } else {
- increaseValue(false);
- }
- return true;
- } else if (keycode == getNavigationDownKey() && vertical
- || (keycode == getNavigationLeftKey() && !vertical)) {
- if (shift) {
- for (int a = 0; a < acceleration; a++) {
- decreaseValue(false);
- }
- acceleration++;
- } else {
- decreaseValue(false);
- }
- return true;
- }
-
- return false;
- }
-
- /**
- * Get the key that increases the vertical slider. By default it is the up
- * arrow key but by overriding this you can change the key to whatever you
- * want.
- *
- * @return The keycode of the key
- */
- protected int getNavigationUpKey() {
- return KeyCodes.KEY_UP;
- }
-
- /**
- * Get the key that decreases the vertical slider. By default it is the down
- * arrow key but by overriding this you can change the key to whatever you
- * want.
- *
- * @return The keycode of the key
- */
- protected int getNavigationDownKey() {
- return KeyCodes.KEY_DOWN;
- }
-
- /**
- * Get the key that decreases the horizontal slider. By default it is the
- * left arrow key but by overriding this you can change the key to whatever
- * you want.
- *
- * @return The keycode of the key
- */
- protected int getNavigationLeftKey() {
- return KeyCodes.KEY_LEFT;
- }
-
- /**
- * Get the key that increases the horizontal slider. By default it is the
- * right arrow key but by overriding this you can change the key to whatever
- * you want.
- *
- * @return The keycode of the key
- */
- protected int getNavigationRightKey() {
- return KeyCodes.KEY_RIGHT;
- }
-
- public Widget getWidgetForPaintable() {
- return this;
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+//
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.ContainerResizedListener;
+import com.vaadin.terminal.gwt.client.VPaintableWidget;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.VConsole;
+
+public class VSlider extends SimpleFocusablePanel implements VPaintableWidget,
+ Field, ContainerResizedListener {
+
+ public static final String CLASSNAME = "v-slider";
+
+ /**
+ * Minimum size (width or height, depending on orientation) of the slider
+ * base.
+ */
+ private static final int MIN_SIZE = 50;
+
+ ApplicationConnection client;
+
+ String id;
+
+ private boolean immediate;
+ private boolean disabled;
+ private boolean readonly;
+
+ private int acceleration = 1;
+ private double min;
+ private double max;
+ private int resolution;
+ private Double value;
+ private boolean vertical;
+
+ private final HTML feedback = new HTML("", false);
+ private final VOverlay feedbackPopup = new VOverlay(true, false, true) {
+ @Override
+ public void show() {
+ super.show();
+ updateFeedbackPosition();
+ }
+ };
+
+ /* DOM element for slider's base */
+ private final Element base;
+ private final int BASE_BORDER_WIDTH = 1;
+
+ /* DOM element for slider's handle */
+ private final Element handle;
+
+ /* DOM element for decrement arrow */
+ private final Element smaller;
+
+ /* DOM element for increment arrow */
+ private final Element bigger;
+
+ /* Temporary dragging/animation variables */
+ private boolean dragging = false;
+
+ private VLazyExecutor delayedValueUpdater = new VLazyExecutor(100,
+ new ScheduledCommand() {
+
+ public void execute() {
+ updateValueToServer();
+ acceleration = 1;
+ }
+ });
+
+ public VSlider() {
+ super();
+
+ base = DOM.createDiv();
+ handle = DOM.createDiv();
+ smaller = DOM.createDiv();
+ bigger = DOM.createDiv();
+
+ setStyleName(CLASSNAME);
+ DOM.setElementProperty(base, "className", CLASSNAME + "-base");
+ DOM.setElementProperty(handle, "className", CLASSNAME + "-handle");
+ DOM.setElementProperty(smaller, "className", CLASSNAME + "-smaller");
+ DOM.setElementProperty(bigger, "className", CLASSNAME + "-bigger");
+
+ DOM.appendChild(getElement(), bigger);
+ DOM.appendChild(getElement(), smaller);
+ DOM.appendChild(getElement(), base);
+ DOM.appendChild(base, handle);
+
+ // Hide initially
+ DOM.setStyleAttribute(smaller, "display", "none");
+ DOM.setStyleAttribute(bigger, "display", "none");
+ DOM.setStyleAttribute(handle, "visibility", "hidden");
+
+ sinkEvents(Event.MOUSEEVENTS | Event.ONMOUSEWHEEL | Event.KEYEVENTS
+ | Event.FOCUSEVENTS | Event.TOUCHEVENTS);
+
+ feedbackPopup.addStyleName(CLASSNAME + "-feedback");
+ feedbackPopup.setWidget(feedback);
+ }
+
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+
+ this.client = client;
+ id = uidl.getId();
+
+ // Ensure correct implementation
+ if (client.updateComponent(this, uidl, true)) {
+ return;
+ }
+
+ immediate = uidl.getBooleanAttribute("immediate");
+ disabled = uidl.getBooleanAttribute("disabled");
+ readonly = uidl.getBooleanAttribute("readonly");
+
+ vertical = uidl.hasAttribute("vertical");
+
+ String style = "";
+ if (uidl.hasAttribute("style")) {
+ style = uidl.getStringAttribute("style");
+ }
+
+ if (vertical) {
+ addStyleName(CLASSNAME + "-vertical");
+ } else {
+ removeStyleName(CLASSNAME + "-vertical");
+ }
+
+ min = uidl.getDoubleAttribute("min");
+ max = uidl.getDoubleAttribute("max");
+ resolution = uidl.getIntAttribute("resolution");
+ value = new Double(uidl.getDoubleVariable("value"));
+
+ setFeedbackValue(value);
+
+ buildBase();
+
+ if (!vertical) {
+ // Draw handle with a delay to allow base to gain maximum width
+ Scheduler.get().scheduleDeferred(new Command() {
+ public void execute() {
+ buildHandle();
+ setValue(value, false);
+ }
+ });
+ } else {
+ buildHandle();
+ setValue(value, false);
+ }
+ }
+
+ private void setFeedbackValue(double value) {
+ String currentValue = "" + value;
+ if (resolution == 0) {
+ currentValue = "" + new Double(value).intValue();
+ }
+ feedback.setText(currentValue);
+ }
+
+ private void updateFeedbackPosition() {
+ if (vertical) {
+ feedbackPopup.setPopupPosition(
+ DOM.getAbsoluteLeft(handle) + handle.getOffsetWidth(),
+ DOM.getAbsoluteTop(handle) + handle.getOffsetHeight() / 2
+ - feedbackPopup.getOffsetHeight() / 2);
+ } else {
+ feedbackPopup.setPopupPosition(
+ DOM.getAbsoluteLeft(handle) + handle.getOffsetWidth() / 2
+ - feedbackPopup.getOffsetWidth() / 2,
+ DOM.getAbsoluteTop(handle)
+ - feedbackPopup.getOffsetHeight());
+ }
+ }
+
+ private void buildBase() {
+ final String styleAttribute = vertical ? "height" : "width";
+ final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
+
+ final Element p = DOM.getParent(getElement());
+ if (DOM.getElementPropertyInt(p, domProperty) > 50) {
+ if (vertical) {
+ setHeight();
+ } else {
+ DOM.setStyleAttribute(base, styleAttribute, "");
+ }
+ } else {
+ // Set minimum size and adjust after all components have
+ // (supposedly) been drawn completely.
+ DOM.setStyleAttribute(base, styleAttribute, MIN_SIZE + "px");
+ Scheduler.get().scheduleDeferred(new Command() {
+ public void execute() {
+ final Element p = DOM.getParent(getElement());
+ if (DOM.getElementPropertyInt(p, domProperty) > (MIN_SIZE + 5)) {
+ if (vertical) {
+ setHeight();
+ } else {
+ DOM.setStyleAttribute(base, styleAttribute, "");
+ }
+ // Ensure correct position
+ setValue(value, false);
+ }
+ }
+ });
+ }
+
+ // TODO attach listeners for focusing and arrow keys
+ }
+
+ private void buildHandle() {
+ final String handleAttribute = vertical ? "marginTop" : "marginLeft";
+
+ DOM.setStyleAttribute(handle, handleAttribute, "0");
+
+ // Restore visibility
+ DOM.setStyleAttribute(handle, "visibility", "visible");
+
+ }
+
+ private void setValue(Double value, boolean updateToServer) {
+ if (value == null) {
+ return;
+ }
+
+ if (value < min) {
+ value = min;
+ } else if (value > max) {
+ value = max;
+ }
+
+ // Update handle position
+ final String styleAttribute = vertical ? "marginTop" : "marginLeft";
+ final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
+ final int handleSize = Integer.parseInt(DOM.getElementProperty(handle,
+ domProperty));
+ final int baseSize = Integer.parseInt(DOM.getElementProperty(base,
+ domProperty)) - (2 * BASE_BORDER_WIDTH);
+
+ final int range = baseSize - handleSize;
+ double v = value.doubleValue();
+
+ // Round value to resolution
+ if (resolution > 0) {
+ v = Math.round(v * Math.pow(10, resolution));
+ v = v / Math.pow(10, resolution);
+ } else {
+ v = Math.round(v);
+ }
+ final double valueRange = max - min;
+ double p = 0;
+ if (valueRange > 0) {
+ p = range * ((v - min) / valueRange);
+ }
+ if (p < 0) {
+ p = 0;
+ }
+ if (vertical) {
+ p = range - p;
+ }
+ final double pos = p;
+
+ DOM.setStyleAttribute(handle, styleAttribute, (Math.round(pos)) + "px");
+
+ // Update value
+ this.value = new Double(v);
+ setFeedbackValue(v);
+
+ if (updateToServer) {
+ updateValueToServer();
+ }
+ }
+
+ @Override
+ public void onBrowserEvent(Event event) {
+ if (disabled || readonly) {
+ return;
+ }
+ final Element targ = DOM.eventGetTarget(event);
+
+ if (DOM.eventGetType(event) == Event.ONMOUSEWHEEL) {
+ processMouseWheelEvent(event);
+ } else if (dragging || targ == handle) {
+ processHandleEvent(event);
+ } else if (targ == smaller) {
+ decreaseValue(true);
+ } else if (targ == bigger) {
+ increaseValue(true);
+ } else if (DOM.eventGetType(event) == Event.MOUSEEVENTS) {
+ processBaseEvent(event);
+ } else if ((BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYPRESS)
+ || (!BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYDOWN)) {
+
+ if (handleNavigation(event.getKeyCode(), event.getCtrlKey(),
+ event.getShiftKey())) {
+
+ feedbackPopup.show();
+
+ delayedValueUpdater.trigger();
+
+ DOM.eventPreventDefault(event);
+ DOM.eventCancelBubble(event, true);
+ }
+ } else if (targ.equals(getElement())
+ && DOM.eventGetType(event) == Event.ONFOCUS) {
+ feedbackPopup.show();
+ } else if (targ.equals(getElement())
+ && DOM.eventGetType(event) == Event.ONBLUR) {
+ feedbackPopup.hide();
+ } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
+ feedbackPopup.show();
+ }
+ if (Util.isTouchEvent(event)) {
+ event.preventDefault(); // avoid simulated events
+ event.stopPropagation();
+ }
+ }
+
+ private void processMouseWheelEvent(final Event event) {
+ final int dir = DOM.eventGetMouseWheelVelocityY(event);
+
+ if (dir < 0) {
+ increaseValue(false);
+ } else {
+ decreaseValue(false);
+ }
+
+ delayedValueUpdater.trigger();
+
+ DOM.eventPreventDefault(event);
+ DOM.eventCancelBubble(event, true);
+ }
+
+ private void processHandleEvent(Event event) {
+ switch (DOM.eventGetType(event)) {
+ case Event.ONMOUSEDOWN:
+ case Event.ONTOUCHSTART:
+ if (!disabled && !readonly) {
+ focus();
+ feedbackPopup.show();
+ dragging = true;
+ DOM.setElementProperty(handle, "className", CLASSNAME
+ + "-handle " + CLASSNAME + "-handle-active");
+ DOM.setCapture(getElement());
+ DOM.eventPreventDefault(event); // prevent selecting text
+ DOM.eventCancelBubble(event, true);
+ event.stopPropagation();
+ VConsole.log("Slider move start");
+ }
+ break;
+ case Event.ONMOUSEMOVE:
+ case Event.ONTOUCHMOVE:
+ if (dragging) {
+ VConsole.log("Slider move");
+ setValueByEvent(event, false);
+ updateFeedbackPosition();
+ event.stopPropagation();
+ }
+ break;
+ case Event.ONTOUCHEND:
+ feedbackPopup.hide();
+ case Event.ONMOUSEUP:
+ // feedbackPopup.hide();
+ VConsole.log("Slider move end");
+ dragging = false;
+ DOM.setElementProperty(handle, "className", CLASSNAME + "-handle");
+ DOM.releaseCapture(getElement());
+ setValueByEvent(event, true);
+ event.stopPropagation();
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void processBaseEvent(Event event) {
+ if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
+ if (!disabled && !readonly && !dragging) {
+ setValueByEvent(event, true);
+ DOM.eventCancelBubble(event, true);
+ }
+ }
+ }
+
+ private void decreaseValue(boolean updateToServer) {
+ setValue(new Double(value.doubleValue() - Math.pow(10, -resolution)),
+ updateToServer);
+ }
+
+ private void increaseValue(boolean updateToServer) {
+ setValue(new Double(value.doubleValue() + Math.pow(10, -resolution)),
+ updateToServer);
+ }
+
+ private void setValueByEvent(Event event, boolean updateToServer) {
+ double v = min; // Fallback to min
+
+ final int coord = getEventPosition(event);
+
+ final int handleSize, baseSize, baseOffset;
+ if (vertical) {
+ handleSize = handle.getOffsetHeight();
+ baseSize = base.getOffsetHeight();
+ baseOffset = base.getAbsoluteTop() - Window.getScrollTop()
+ - handleSize / 2;
+ } else {
+ handleSize = handle.getOffsetWidth();
+ baseSize = base.getOffsetWidth();
+ baseOffset = base.getAbsoluteLeft() - Window.getScrollLeft()
+ + handleSize / 2;
+ }
+
+ if (vertical) {
+ v = ((baseSize - (coord - baseOffset)) / (double) (baseSize - handleSize))
+ * (max - min) + min;
+ } else {
+ v = ((coord - baseOffset) / (double) (baseSize - handleSize))
+ * (max - min) + min;
+ }
+
+ if (v < min) {
+ v = min;
+ } else if (v > max) {
+ v = max;
+ }
+
+ setValue(v, updateToServer);
+ }
+
+ /**
+ * TODO consider extracting touches support to an impl class specific for
+ * webkit (only browser that really supports touches).
+ *
+ * @param event
+ * @return
+ */
+ protected int getEventPosition(Event event) {
+ if (vertical) {
+ return Util.getTouchOrMouseClientY(event);
+ } else {
+ return Util.getTouchOrMouseClientX(event);
+ }
+ }
+
+ public void iLayout() {
+ if (vertical) {
+ setHeight();
+ }
+ // Update handle position
+ setValue(value, false);
+ }
+
+ private void setHeight() {
+ // Calculate decoration size
+ DOM.setStyleAttribute(base, "height", "0");
+ DOM.setStyleAttribute(base, "overflow", "hidden");
+ int h = DOM.getElementPropertyInt(getElement(), "offsetHeight");
+ if (h < MIN_SIZE) {
+ h = MIN_SIZE;
+ }
+ DOM.setStyleAttribute(base, "height", h + "px");
+ DOM.setStyleAttribute(base, "overflow", "");
+ }
+
+ private void updateValueToServer() {
+ client.updateVariable(id, "value", value.doubleValue(), immediate);
+ }
+
+ /**
+ * Handles the keyboard events handled by the Slider
+ *
+ * @param event
+ * The keyboard event received
+ * @return true iff the navigation event was handled
+ */
+ public boolean handleNavigation(int keycode, boolean ctrl, boolean shift) {
+
+ // No support for ctrl moving
+ if (ctrl) {
+ return false;
+ }
+
+ if ((keycode == getNavigationUpKey() && vertical)
+ || (keycode == getNavigationRightKey() && !vertical)) {
+ if (shift) {
+ for (int a = 0; a < acceleration; a++) {
+ increaseValue(false);
+ }
+ acceleration++;
+ } else {
+ increaseValue(false);
+ }
+ return true;
+ } else if (keycode == getNavigationDownKey() && vertical
+ || (keycode == getNavigationLeftKey() && !vertical)) {
+ if (shift) {
+ for (int a = 0; a < acceleration; a++) {
+ decreaseValue(false);
+ }
+ acceleration++;
+ } else {
+ decreaseValue(false);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the key that increases the vertical slider. By default it is the up
+ * arrow key but by overriding this you can change the key to whatever you
+ * want.
+ *
+ * @return The keycode of the key
+ */
+ protected int getNavigationUpKey() {
+ return KeyCodes.KEY_UP;
+ }
+
+ /**
+ * Get the key that decreases the vertical slider. By default it is the down
+ * arrow key but by overriding this you can change the key to whatever you
+ * want.
+ *
+ * @return The keycode of the key
+ */
+ protected int getNavigationDownKey() {
+ return KeyCodes.KEY_DOWN;
+ }
+
+ /**
+ * Get the key that decreases the horizontal slider. By default it is the
+ * left arrow key but by overriding this you can change the key to whatever
+ * you want.
+ *
+ * @return The keycode of the key
+ */
+ protected int getNavigationLeftKey() {
+ return KeyCodes.KEY_LEFT;
+ }
+
+ /**
+ * Get the key that increases the horizontal slider. By default it is the
+ * right arrow key but by overriding this you can change the key to whatever
+ * you want.
+ *
+ * @return The keycode of the key
+ */
+ protected int getNavigationRightKey() {
+ return KeyCodes.KEY_RIGHT;
+ }
+
+ public Widget getWidgetForPaintable() {
+ return this;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java
index 32a9cf3e11..74ff328710 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java
@@ -54,7 +54,7 @@ public class VTabsheet extends VTabsheetBase {
/**
* Representation of a single "tab" shown in the TabBar
- *
+ *
*/
private static class Tab extends SimplePanel {
private static final String TD_CLASSNAME = CLASSNAME + "-tabitemcell";
@@ -64,6 +64,8 @@ public class VTabsheet extends VTabsheetBase {
+ "-selected";
private static final String TD_SELECTED_FIRST_CLASSNAME = TD_SELECTED_CLASSNAME
+ "-first";
+ private static final String TD_DISABLED_CLASSNAME = TD_CLASSNAME
+ + "-disabled";
private static final String DIV_CLASSNAME = CLASSNAME + "-tabitem";
private static final String DIV_SELECTED_CLASSNAME = DIV_CLASSNAME
@@ -116,6 +118,7 @@ public class VTabsheet extends VTabsheetBase {
public void setEnabledOnServer(boolean enabled) {
enabledOnServer = enabled;
+ setStyleName(td, TD_DISABLED_CLASSNAME, !enabled);
}
public void addClickHandler(ClickHandler handler) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java b/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java
index a74fd9f5dc..cd09e24d67 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java
@@ -69,4 +69,11 @@ public class VTextArea extends VTextField {
super.onBrowserEvent(event);
}
+ @Override
+ public int getCursorPos() {
+ // This is needed so that TextBoxImplIE6 is used to return the correct
+ // position for old Internet Explorer versions where it has to be
+ // detected in a different way.
+ return getImpl().getTextAreaCursorPos(getElement());
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
index 26c7430e74..80dad78e58 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
@@ -90,12 +90,6 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field,
protected VTextField(Element node) {
super(node);
- if (BrowserInfo.get().getIEVersion() > 0
- && BrowserInfo.get().getIEVersion() < 8) {
- // Fixes IE margin problem (#2058)
- DOM.setStyleAttribute(node, "marginTop", "-1px");
- DOM.setStyleAttribute(node, "marginBottom", "-1px");
- }
setStyleName(CLASSNAME);
addChangeHandler(this);
if (BrowserInfo.get().isIE()) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java b/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java
index ed4953d463..a522c79736 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java
@@ -20,12 +20,12 @@ import com.vaadin.terminal.gwt.client.EventId;
import com.vaadin.terminal.gwt.client.Focusable;
import com.vaadin.terminal.gwt.client.LocaleNotLoadedException;
import com.vaadin.terminal.gwt.client.LocaleService;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.VPaintableWidget;
-public class VTextualDate extends VDateField implements VPaintableWidget, Field,
- ChangeHandler, ContainerResizedListener, Focusable, SubPartAware {
+public class VTextualDate extends VDateField implements VPaintableWidget,
+ Field, ChangeHandler, ContainerResizedListener, Focusable, SubPartAware {
private static final String PARSE_ERROR_CLASSNAME = CLASSNAME
+ "-parseerror";
@@ -331,7 +331,8 @@ public class VTextualDate extends VDateField implements VPaintableWidget, Field,
@Override
public void setWidth(String newWidth) {
- if (!"".equals(newWidth) && (width == null || !newWidth.equals(width))) {
+ if (!"".equals(newWidth)
+ && (isUndefinedWidth() || !newWidth.equals(width))) {
needLayout = true;
width = newWidth;
super.setWidth(width);
@@ -340,16 +341,18 @@ public class VTextualDate extends VDateField implements VPaintableWidget, Field,
needLayout = false;
}
} else {
- if ("".equals(newWidth) && width != null && !"".equals(width)) {
+ if ("".equals(newWidth) && !isUndefinedWidth()) {
super.setWidth("");
- needLayout = true;
- iLayout();
- needLayout = false;
+ iLayout(true);
width = null;
}
}
}
+ protected boolean isUndefinedWidth() {
+ return width == null || "".equals(width);
+ }
+
/**
* Returns pixels in x-axis reserved for other than textfield content.
*
@@ -363,14 +366,26 @@ public class VTextualDate extends VDateField implements VPaintableWidget, Field,
return fieldExtraWidth;
}
+ /**
+ * Force an recalculation of the width of the component IF the width has
+ * been defined. Does nothing if width is undefined as the width will be
+ * automatically adjusted by the browser.
+ */
public void updateWidth() {
+ if (isUndefinedWidth()) {
+ return;
+ }
needLayout = true;
fieldExtraWidth = -1;
- iLayout();
+ iLayout(true);
}
public void iLayout() {
- if (needLayout) {
+ iLayout(false);
+ }
+
+ public void iLayout(boolean force) {
+ if (needLayout || force) {
int textFieldWidth = getOffsetWidth() - getFieldExtraWidth();
if (textFieldWidth < 0) {
// Field can never be smaller than 0 (causes exception in IE)
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java
index 77dd1cc39e..0eddca0ed3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java
@@ -24,21 +24,19 @@ import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.ComputedStyle;
import com.vaadin.terminal.gwt.client.RenderSpace;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.ui.VScrollTable.VScrollTableBody.VScrollTableRow;
import com.vaadin.terminal.gwt.client.ui.VTreeTable.VTreeTableScrollBody.VTreeTableRow;
public class VTreeTable extends VScrollTable {
- private static class PendingNavigationEvent {
- private final int keycode;
- private final boolean ctrl;
- private final boolean shift;
+ static class PendingNavigationEvent {
+ final int keycode;
+ final boolean ctrl;
+ final boolean shift;
public PendingNavigationEvent(int keycode, boolean ctrl, boolean shift) {
this.keycode = keycode;
@@ -59,82 +57,14 @@ public class VTreeTable extends VScrollTable {
}
}
- public static final String ATTRIBUTE_HIERARCHY_COLUMN_INDEX = "hci";
- private boolean collapseRequest;
+ boolean collapseRequest;
private boolean selectionPending;
- private int colIndexOfHierarchy;
- private String collapsedRowKey;
- private VTreeTableScrollBody scrollBody;
- private boolean animationsEnabled;
- private LinkedList<PendingNavigationEvent> pendingNavigationEvents = new LinkedList<VTreeTable.PendingNavigationEvent>();
- private boolean focusParentResponsePending;
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- FocusableScrollPanel widget = null;
- int scrollPosition = 0;
- if (collapseRequest) {
- widget = (FocusableScrollPanel) getWidget(1);
- scrollPosition = widget.getScrollPosition();
- }
- animationsEnabled = uidl.getBooleanAttribute("animate");
- colIndexOfHierarchy = uidl
- .hasAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) ? uidl
- .getIntAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) : 0;
- int oldTotalRows = getTotalRows();
- super.updateFromUIDL(uidl, client);
- if (collapseRequest) {
- if (collapsedRowKey != null && scrollBody != null) {
- VScrollTableRow row = getRenderedRowByKey(collapsedRowKey);
- if (row != null) {
- setRowFocus(row);
- focus();
- }
- }
-
- int scrollPosition2 = widget.getScrollPosition();
- if (scrollPosition != scrollPosition2) {
- widget.setScrollPosition(scrollPosition);
- }
-
- // check which rows are needed from the server and initiate a
- // deferred fetch
- onScroll(null);
- }
- // Recalculate table size if collapse request, or if page length is zero
- // (not sent by server) and row count changes (#7908).
- if (collapseRequest
- || (!uidl.hasAttribute("pagelength") && getTotalRows() != oldTotalRows)) {
- /*
- * Ensure that possibly removed/added scrollbars are considered.
- * Triggers row calculations, removes cached rows etc. Basically
- * cleans up state. Be careful if touching this, you will break
- * pageLength=0 if you remove this.
- */
- triggerLazyColumnAdjustment(true);
-
- collapseRequest = false;
- }
- if (uidl.hasAttribute("focusedRow")) {
- String key = uidl.getStringAttribute("focusedRow");
- setRowFocus(getRenderedRowByKey(key));
- focusParentResponsePending = false;
- } else if (uidl.hasAttribute("clearFocusPending")) {
- // Special case to detect a response to a focusParent request that
- // does not return any focusedRow because the selected node has no
- // parent
- focusParentResponsePending = false;
- }
-
- while (!collapseRequest && !focusParentResponsePending
- && !pendingNavigationEvents.isEmpty()) {
- // Keep replaying any queued events as long as we don't have any
- // potential content changes pending
- PendingNavigationEvent event = pendingNavigationEvents
- .removeFirst();
- handleNavigation(event.keycode, event.ctrl, event.shift);
- }
- }
+ int colIndexOfHierarchy;
+ String collapsedRowKey;
+ VTreeTableScrollBody scrollBody;
+ boolean animationsEnabled;
+ LinkedList<PendingNavigationEvent> pendingNavigationEvents = new LinkedList<VTreeTable.PendingNavigationEvent>();
+ boolean focusParentResponsePending;
@Override
protected VScrollTableBody createScrollBody() {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java
new file mode 100644
index 0000000000..9b6f03f612
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java
@@ -0,0 +1,101 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.ui.VScrollTable.VScrollTableBody.VScrollTableRow;
+import com.vaadin.terminal.gwt.client.ui.VTreeTable.PendingNavigationEvent;
+
+public class VTreeTablePaintable extends VScrollTablePaintable {
+ public static final String ATTRIBUTE_HIERARCHY_COLUMN_INDEX = "hci";
+
+ @Override
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ FocusableScrollPanel widget = null;
+ int scrollPosition = 0;
+ if (getWidgetForPaintable().collapseRequest) {
+ widget = (FocusableScrollPanel) getWidgetForPaintable()
+ .getWidget(1);
+ scrollPosition = widget.getScrollPosition();
+ }
+ getWidgetForPaintable().animationsEnabled = uidl
+ .getBooleanAttribute("animate");
+ getWidgetForPaintable().colIndexOfHierarchy = uidl
+ .hasAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) ? uidl
+ .getIntAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) : 0;
+ int oldTotalRows = getWidgetForPaintable().getTotalRows();
+ super.updateFromUIDL(uidl, client);
+ if (getWidgetForPaintable().collapseRequest) {
+ if (getWidgetForPaintable().collapsedRowKey != null
+ && getWidgetForPaintable().scrollBody != null) {
+ VScrollTableRow row = getWidgetForPaintable()
+ .getRenderedRowByKey(
+ getWidgetForPaintable().collapsedRowKey);
+ if (row != null) {
+ getWidgetForPaintable().setRowFocus(row);
+ getWidgetForPaintable().focus();
+ }
+ }
+
+ int scrollPosition2 = widget.getScrollPosition();
+ if (scrollPosition != scrollPosition2) {
+ widget.setScrollPosition(scrollPosition);
+ }
+
+ // check which rows are needed from the server and initiate a
+ // deferred fetch
+ getWidgetForPaintable().onScroll(null);
+ }
+ // Recalculate table size if collapse request, or if page length is zero
+ // (not sent by server) and row count changes (#7908).
+ if (getWidgetForPaintable().collapseRequest
+ || (!uidl.hasAttribute("pagelength") && getWidgetForPaintable()
+ .getTotalRows() != oldTotalRows)) {
+ /*
+ * Ensure that possibly removed/added scrollbars are considered.
+ * Triggers row calculations, removes cached rows etc. Basically
+ * cleans up state. Be careful if touching this, you will break
+ * pageLength=0 if you remove this.
+ */
+ getWidgetForPaintable().triggerLazyColumnAdjustment(true);
+
+ getWidgetForPaintable().collapseRequest = false;
+ }
+ if (uidl.hasAttribute("focusedRow")) {
+ String key = uidl.getStringAttribute("focusedRow");
+ getWidgetForPaintable().setRowFocus(
+ getWidgetForPaintable().getRenderedRowByKey(key));
+ getWidgetForPaintable().focusParentResponsePending = false;
+ } else if (uidl.hasAttribute("clearFocusPending")) {
+ // Special case to detect a response to a focusParent request that
+ // does not return any focusedRow because the selected node has no
+ // parent
+ getWidgetForPaintable().focusParentResponsePending = false;
+ }
+
+ while (!getWidgetForPaintable().collapseRequest
+ && !getWidgetForPaintable().focusParentResponsePending
+ && !getWidgetForPaintable().pendingNavigationEvents.isEmpty()) {
+ // Keep replaying any queued events as long as we don't have any
+ // potential content changes pending
+ PendingNavigationEvent event = getWidgetForPaintable().pendingNavigationEvents
+ .removeFirst();
+ getWidgetForPaintable().handleNavigation(event.keycode, event.ctrl,
+ event.shift);
+ }
+ }
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VTreeTable.class);
+ }
+
+ @Override
+ public VTreeTable getWidgetForPaintable() {
+ return (VTreeTable) super.getWidgetForPaintable();
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VUpload.java b/src/com/vaadin/terminal/gwt/client/ui/VUpload.java
index 3d49b8d9d1..66894417f3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VUpload.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VUpload.java
@@ -24,9 +24,9 @@ import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.VPaintableWidget;
import com.vaadin.terminal.gwt.client.VTooltip;
/**
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java
index 8eabf6c625..e3aba21096 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VView.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java
@@ -640,6 +640,11 @@ public class VView extends SimplePanel implements Container, ResizeHandler,
String ownAppId = connection.getConfiguration().getRootPanelId();
+ // Hiding elements causes browser to forget scroll position -> must
+ // save values and restore when the elements are visible again #7976
+ int originalScrollTop = Window.getScrollTop();
+ int originalScrollLeft = Window.getScrollLeft();
+
// Set display: none for all Vaadin apps
for (int i = 0; i < vaadinApps.size(); i++) {
String appId = vaadinApps.get(i);
@@ -678,6 +683,9 @@ public class VView extends SimplePanel implements Container, ResizeHandler,
}
}
+ // Scroll back to original location
+ Window.scrollTo(originalScrollLeft, originalScrollTop);
+
return w;
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java
index c1ef2bbac4..95ab0dc773 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java
@@ -140,6 +140,7 @@ public class VWindow extends VOverlay implements Container,
private Element modalityCurtain;
private Element draggingCurtain;
+ private Element resizingCurtain;
private Element headerText;
@@ -568,12 +569,17 @@ public class VWindow extends VOverlay implements Container,
this.draggable = draggable;
+ setCursorProperties();
+ }
+
+ private void setCursorProperties() {
if (!this.draggable) {
header.getStyle().setProperty("cursor", "default");
+ footer.getStyle().setProperty("cursor", "default");
} else {
header.getStyle().setProperty("cursor", "");
+ footer.getStyle().setProperty("cursor", "");
}
-
}
private void setNaturalWidth() {
@@ -703,28 +709,62 @@ public class VWindow extends VOverlay implements Container,
}
/*
- * Shows (or hides) an empty div on top of all other content; used when
- * resizing or moving, so that iframes (etc) do not steal event.
+ * Shows an empty div on top of all other content; used when moving, so that
+ * iframes (etc) do not steal event.
*/
- private void showDraggingCurtain(boolean show) {
- if (show && draggingCurtain == null) {
+ private void showDraggingCurtain() {
+ DOM.appendChild(RootPanel.getBodyElement(), getDraggingCurtain());
+ }
- draggingCurtain = DOM.createDiv();
- DOM.setStyleAttribute(draggingCurtain, "position", "absolute");
- DOM.setStyleAttribute(draggingCurtain, "top", "0px");
- DOM.setStyleAttribute(draggingCurtain, "left", "0px");
- DOM.setStyleAttribute(draggingCurtain, "width", "100%");
- DOM.setStyleAttribute(draggingCurtain, "height", "100%");
- DOM.setStyleAttribute(draggingCurtain, "zIndex", ""
- + VOverlay.Z_INDEX);
+ private void hideDraggingCurtain() {
+ if (draggingCurtain != null) {
+ DOM.removeChild(RootPanel.getBodyElement(), draggingCurtain);
+ }
+ }
- DOM.appendChild(RootPanel.getBodyElement(), draggingCurtain);
- } else if (!show && draggingCurtain != null) {
+ /*
+ * Shows an empty div on top of all other content; used when resizing, so
+ * that iframes (etc) do not steal event.
+ */
+ private void showResizingCurtain() {
+ DOM.appendChild(RootPanel.getBodyElement(), getResizingCurtain());
+ }
- DOM.removeChild(RootPanel.getBodyElement(), draggingCurtain);
- draggingCurtain = null;
+ private void hideResizingCurtain() {
+ if (resizingCurtain != null) {
+ DOM.removeChild(RootPanel.getBodyElement(), resizingCurtain);
}
+ }
+
+ private Element getDraggingCurtain() {
+ if (draggingCurtain == null) {
+ draggingCurtain = createCurtain();
+ draggingCurtain.setClassName(CLASSNAME + "-draggingCurtain");
+ }
+
+ return draggingCurtain;
+ }
+
+ private Element getResizingCurtain() {
+ if (resizingCurtain == null) {
+ resizingCurtain = createCurtain();
+ resizingCurtain.setClassName(CLASSNAME + "-resizingCurtain");
+ }
+
+ return resizingCurtain;
+ }
+
+ private Element createCurtain() {
+ Element curtain = DOM.createDiv();
+
+ DOM.setStyleAttribute(curtain, "position", "absolute");
+ DOM.setStyleAttribute(curtain, "top", "0px");
+ DOM.setStyleAttribute(curtain, "left", "0px");
+ DOM.setStyleAttribute(curtain, "width", "100%");
+ DOM.setStyleAttribute(curtain, "height", "100%");
+ DOM.setStyleAttribute(curtain, "zIndex", "" + VOverlay.Z_INDEX);
+ return curtain;
}
private void setResizable(boolean resizability) {
@@ -844,7 +884,7 @@ public class VWindow extends VOverlay implements Container,
if (!isActive()) {
bringToFront();
}
- showDraggingCurtain(true);
+ showResizingCurtain();
if (BrowserInfo.get().isIE()) {
DOM.setStyleAttribute(resizeBox, "visibility", "hidden");
}
@@ -862,7 +902,7 @@ public class VWindow extends VOverlay implements Container,
case Event.ONTOUCHCANCEL:
DOM.releaseCapture(getElement());
case Event.ONLOSECAPTURE:
- showDraggingCurtain(false);
+ hideResizingCurtain();
if (BrowserInfo.get().isIE()) {
DOM.setStyleAttribute(resizeBox, "visibility", "");
}
@@ -1097,7 +1137,7 @@ public class VWindow extends VOverlay implements Container,
private void beginMovingWindow(Event event) {
if (draggable) {
- showDraggingCurtain(true);
+ showDraggingCurtain();
dragging = true;
startX = Util.getTouchOrMouseClientX(event);
startY = Util.getTouchOrMouseClientY(event);
@@ -1110,7 +1150,7 @@ public class VWindow extends VOverlay implements Container,
private void stopMovingWindow() {
dragging = false;
- showDraggingCurtain(false);
+ hideDraggingCurtain();
DOM.releaseCapture(getElement());
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java b/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java
index 09f435227d..8828582b57 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java
@@ -34,15 +34,10 @@ public class VLabel extends HTML {
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (event.getTypeInt() == Event.ONLOAD) {
- // FIXME: Should not be here but in paintable
Util.notifyParentOfSizeChange(this, true);
- event.cancelBubble(true);
+ event.stopPropagation();
return;
}
- // FIXME: Move to paintable
- // if (client != null) {
- // client.handleTooltipEvent(event, this);
- // }
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java
index 796bce265e..269afde25d 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java
@@ -6,27 +6,21 @@ package com.vaadin.terminal.gwt.client.ui.label;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.PreElement;
+import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VLabelPaintable implements VPaintableWidget {
-
- private VLabel widget = GWT.create(VLabel.class);
- private ApplicationConnection client;
+import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget;
+public class VLabelPaintable extends VAbstractPaintableWidget {
public VLabelPaintable() {
}
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
-
- if (client.updateComponent(getWidgetForPaintable(), uidl, true)) {
+ if (client.updateComponent(this, uidl, true)) {
return;
}
- this.client = client;
-
boolean sinkOnloads = false;
final String mode = uidl.getStringAttribute("mode");
@@ -64,8 +58,14 @@ public class VLabelPaintable implements VPaintableWidget {
}
}
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VLabel.class);
+ }
+
+ @Override
public VLabel getWidgetForPaintable() {
- return widget;
+ return (VLabel) super.getWidgetForPaintable();
}
}
diff --git a/src/com/vaadin/ui/AbstractComponent.java b/src/com/vaadin/ui/AbstractComponent.java
index de114e996e..318bcd7ea2 100644
--- a/src/com/vaadin/ui/AbstractComponent.java
+++ b/src/com/vaadin/ui/AbstractComponent.java
@@ -1334,9 +1334,12 @@ public abstract class AbstractComponent implements Component, MethodEventSource
/*
* (non-Javadoc)
*
- * @see com.vaadin.terminal.Sizeable#setHeight(float, int)
+ * @see com.vaadin.terminal.Sizeable#setHeight(float, Unit)
*/
public void setHeight(float height, Unit unit) {
+ if (unit == null) {
+ throw new IllegalArgumentException("Unit can not be null");
+ }
this.height = height;
heightUnit = unit;
requestRepaint();
@@ -1366,9 +1369,12 @@ public abstract class AbstractComponent implements Component, MethodEventSource
/*
* (non-Javadoc)
*
- * @see com.vaadin.terminal.Sizeable#setWidth(float, int)
+ * @see com.vaadin.terminal.Sizeable#setWidth(float, Unit)
*/
public void setWidth(float width, Unit unit) {
+ if (unit == null) {
+ throw new IllegalArgumentException("Unit can not be null");
+ }
this.width = width;
widthUnit = unit;
requestRepaint();
diff --git a/src/com/vaadin/ui/AbstractSelect.java b/src/com/vaadin/ui/AbstractSelect.java
index b65cb61450..5e086f0b8d 100644
--- a/src/com/vaadin/ui/AbstractSelect.java
+++ b/src/com/vaadin/ui/AbstractSelect.java
@@ -61,41 +61,85 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
Container.PropertySetChangeNotifier, Container.ItemSetChangeNotifier,
Container.ItemSetChangeListener {
+ public enum ItemCaptionMode {
+ /**
+ * Item caption mode: Item's ID's <code>String</code> representation is
+ * used as caption.
+ */
+ ID,
+ /**
+ * Item caption mode: Item's <code>String</code> representation is used
+ * as caption.
+ */
+ ITEM,
+ /**
+ * Item caption mode: Index of the item is used as caption. The index
+ * mode can only be used with the containers implementing the
+ * {@link com.vaadin.data.Container.Indexed} interface.
+ */
+ INDEX,
+ /**
+ * Item caption mode: If an Item has a caption it's used, if not, Item's
+ * ID's <code>String</code> representation is used as caption. <b>This
+ * is the default</b>.
+ */
+ EXPLICIT_DEFAULTS_ID,
+ /**
+ * Item caption mode: Captions must be explicitly specified.
+ */
+ EXPLICIT,
+ /**
+ * Item caption mode: Only icons are shown, captions are hidden.
+ */
+ ICON_ONLY,
+ /**
+ * Item caption mode: Item captions are read from property specified
+ * with <code>setItemCaptionPropertyId</code>.
+ */
+ PROPERTY;
+ }
+
/**
- * Item caption mode: Item's ID's <code>String</code> representation is used
- * as caption.
+ * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead
*/
- public static final int ITEM_CAPTION_MODE_ID = 0;
+ @Deprecated
+ public static final ItemCaptionMode ITEM_CAPTION_MODE_ID = ItemCaptionMode.ID;
+
/**
- * Item caption mode: Item's <code>String</code> representation is used as
- * caption.
+ * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead
*/
- public static final int ITEM_CAPTION_MODE_ITEM = 1;
+ @Deprecated
+ public static final ItemCaptionMode ITEM_CAPTION_MODE_ITEM = ItemCaptionMode.ITEM;
+
/**
- * Item caption mode: Index of the item is used as caption. The index mode
- * can only be used with the containers implementing the
- * {@link com.vaadin.data.Container.Indexed} interface.
+ * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead
*/
- public static final int ITEM_CAPTION_MODE_INDEX = 2;
+ @Deprecated
+ public static final ItemCaptionMode ITEM_CAPTION_MODE_INDEX = ItemCaptionMode.INDEX;
+
/**
- * Item caption mode: If an Item has a caption it's used, if not, Item's
- * ID's <code>String</code> representation is used as caption. <b>This is
- * the default</b>.
+ * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead
*/
- public static final int ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID = 3;
+ @Deprecated
+ public static final ItemCaptionMode ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID = ItemCaptionMode.EXPLICIT_DEFAULTS_ID;
+
/**
- * Item caption mode: Captions must be explicitly specified.
+ * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead
*/
- public static final int ITEM_CAPTION_MODE_EXPLICIT = 4;
+ @Deprecated
+ public static final ItemCaptionMode ITEM_CAPTION_MODE_EXPLICIT = ItemCaptionMode.EXPLICIT;
+
/**
- * Item caption mode: Only icons are shown, captions are hidden.
+ * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead
*/
- public static final int ITEM_CAPTION_MODE_ICON_ONLY = 5;
+ @Deprecated
+ public static final ItemCaptionMode ITEM_CAPTION_MODE_ICON_ONLY = ItemCaptionMode.ICON_ONLY;
+
/**
- * Item caption mode: Item captions are read from property specified with
- * <code>setItemCaptionPropertyId</code>.
+ * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead
*/
- public static final int ITEM_CAPTION_MODE_PROPERTY = 6;
+ @Deprecated
+ public static final ItemCaptionMode ITEM_CAPTION_MODE_PROPERTY = ItemCaptionMode.PROPERTY;
/**
* Interface for option filtering, used to filter options based on user
@@ -175,7 +219,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
/**
* Item caption mode.
*/
- private int itemCaptionMode = ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID;
+ private ItemCaptionMode itemCaptionMode = ItemCaptionMode.EXPLICIT_DEFAULTS_ID;
/**
* Item caption source property id.
@@ -1038,11 +1082,11 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
switch (getItemCaptionMode()) {
- case ITEM_CAPTION_MODE_ID:
+ case ID:
caption = itemId.toString();
break;
- case ITEM_CAPTION_MODE_INDEX:
+ case INDEX:
if (items instanceof Container.Indexed) {
caption = String.valueOf(((Container.Indexed) items)
.indexOfId(itemId));
@@ -1051,25 +1095,25 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
}
break;
- case ITEM_CAPTION_MODE_ITEM:
+ case ITEM:
final Item i = getItem(itemId);
if (i != null) {
caption = i.toString();
}
break;
- case ITEM_CAPTION_MODE_EXPLICIT:
+ case EXPLICIT:
caption = itemCaptions.get(itemId);
break;
- case ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID:
+ case EXPLICIT_DEFAULTS_ID:
caption = itemCaptions.get(itemId);
if (caption == null) {
caption = itemId.toString();
}
break;
- case ITEM_CAPTION_MODE_PROPERTY:
+ case PROPERTY:
final Property<?> p = getContainerProperty(itemId,
getItemCaptionPropertyId());
if (p != null) {
@@ -1086,7 +1130,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
}
/**
- * Sets the icon for an item.
+ * Sets tqhe icon for an item.
*
* @param itemId
* the id of the item to be assigned an icon.
@@ -1163,8 +1207,8 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
* @param mode
* the One of the modes listed above.
*/
- public void setItemCaptionMode(int mode) {
- if (ITEM_CAPTION_MODE_ID <= mode && mode <= ITEM_CAPTION_MODE_PROPERTY) {
+ public void setItemCaptionMode(ItemCaptionMode mode) {
+ if (mode != null) {
itemCaptionMode = mode;
requestRepaint();
}
@@ -1198,7 +1242,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
*
* @return the One of the modes listed above.
*/
- public int getItemCaptionMode() {
+ public ItemCaptionMode getItemCaptionMode() {
return itemCaptionMode;
}
@@ -1689,7 +1733,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
public void addNotifierForItem(Object itemId) {
switch (getItemCaptionMode()) {
- case ITEM_CAPTION_MODE_ITEM:
+ case ITEM:
final Item i = getItem(itemId);
if (i == null) {
return;
@@ -1713,7 +1757,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
}
break;
- case ITEM_CAPTION_MODE_PROPERTY:
+ case PROPERTY:
final Property<?> p = getContainerProperty(itemId,
getItemCaptionPropertyId());
if (p != null && p instanceof Property.ValueChangeNotifier) {
diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java
index 7c0811008a..9910f3a4c4 100644
--- a/src/com/vaadin/ui/Button.java
+++ b/src/com/vaadin/ui/Button.java
@@ -24,6 +24,7 @@ import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.ui.VButton;
import com.vaadin.terminal.gwt.client.ui.VButton.ButtonClientToServerRpc;
+import com.vaadin.terminal.gwt.client.ui.VButtonPaintable;
import com.vaadin.terminal.gwt.server.RpcTarget;
import com.vaadin.tools.ReflectTools;
import com.vaadin.ui.ClientWidget.LoadStyle;
@@ -38,7 +39,7 @@ import com.vaadin.ui.Component.Focusable;
* @since 3.0
*/
@SuppressWarnings("serial")
-@ClientWidget(value = VButton.class, loadStyle = LoadStyle.EAGER)
+@ClientWidget(value = VButtonPaintable.class, loadStyle = LoadStyle.EAGER)
public class Button extends AbstractComponent implements
FieldEvents.BlurNotifier, FieldEvents.FocusNotifier, Focusable,
Action.ShortcutNotifier, RpcTarget {
diff --git a/src/com/vaadin/ui/Component.java b/src/com/vaadin/ui/Component.java
index 53fdfdb4ff..1289b57bd9 100644
--- a/src/com/vaadin/ui/Component.java
+++ b/src/com/vaadin/ui/Component.java
@@ -11,7 +11,6 @@ import java.util.EventObject;
import java.util.Locale;
import com.vaadin.Application;
-import com.vaadin.data.Property;
import com.vaadin.event.FieldEvents;
import com.vaadin.terminal.ErrorMessage;
import com.vaadin.terminal.Paintable;
@@ -363,12 +362,6 @@ public interface Component extends Paintable, VariableOwner, Sizeable,
* </p>
*
* <p>
- * The read-only status affects only the user; the value can still be
- * changed programmatically, for example, with
- * {@link Property#setValue(Object)}.
- * </p>
- *
- * <p>
* The method will return {@code true} if the component or any of its
* parents is in the read-only mode.
* </p>
@@ -396,12 +389,6 @@ public interface Component extends Paintable, VariableOwner, Sizeable,
* </p>
*
* <p>
- * The read-only status affects only the user; the value can still be
- * changed programmatically, for example, with
- * {@link Property#setValue(Object)}.
- * </p>
- *
- * <p>
* This method will trigger a
* {@link com.vaadin.terminal.Paintable.RepaintRequestEvent
* RepaintRequestEvent}.
diff --git a/src/com/vaadin/ui/CssLayout.java b/src/com/vaadin/ui/CssLayout.java
index b952609b20..b9432df6b6 100644
--- a/src/com/vaadin/ui/CssLayout.java
+++ b/src/com/vaadin/ui/CssLayout.java
@@ -125,7 +125,7 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier {
// see ticket #7668
if (c.getParent() == this) {
// When c is removed, all components after it are shifted down
- if (index > components.indexOf(c)) {
+ if (index > getComponentIndex(c)) {
index--;
}
removeComponent(c);
@@ -275,4 +275,28 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier {
removeListener(CLICK_EVENT, LayoutClickEvent.class, listener);
}
+ /**
+ * Returns the index of the given component.
+ *
+ * @param component
+ * The component to look up.
+ * @return The index of the component or -1 if the component is not a child.
+ */
+ public int getComponentIndex(Component component) {
+ return components.indexOf(component);
+ }
+
+ /**
+ * Returns the component at the given position.
+ *
+ * @param index
+ * The position of the component.
+ * @return The component at the given index.
+ * @throws IndexOutOfBoundsException
+ * If the index is out of range.
+ */
+ public Component getComponent(int index) throws IndexOutOfBoundsException {
+ return components.get(index);
+ }
+
}
diff --git a/src/com/vaadin/ui/MenuBar.java b/src/com/vaadin/ui/MenuBar.java
index 7ed432a12b..54a094a4e7 100644
--- a/src/com/vaadin/ui/MenuBar.java
+++ b/src/com/vaadin/ui/MenuBar.java
@@ -14,6 +14,7 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.ui.VMenuBar;
+import com.vaadin.terminal.gwt.client.ui.VMenuBarPaintable;
import com.vaadin.ui.ClientWidget.LoadStyle;
/**
@@ -24,7 +25,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle;
* </p>
*/
@SuppressWarnings("serial")
-@ClientWidget(value = VMenuBar.class, loadStyle = LoadStyle.LAZY)
+@ClientWidget(value = VMenuBarPaintable.class, loadStyle = LoadStyle.LAZY)
public class MenuBar extends AbstractComponent {
// Items of the top-level menu
diff --git a/src/com/vaadin/ui/NativeButton.java b/src/com/vaadin/ui/NativeButton.java
index 46d13c4150..b7b7fcb38c 100644
--- a/src/com/vaadin/ui/NativeButton.java
+++ b/src/com/vaadin/ui/NativeButton.java
@@ -3,10 +3,10 @@
*/
package com.vaadin.ui;
-import com.vaadin.terminal.gwt.client.ui.VNativeButton;
+import com.vaadin.terminal.gwt.client.ui.VNativeButtonPaintable;
@SuppressWarnings("serial")
-@ClientWidget(VNativeButton.class)
+@ClientWidget(VNativeButtonPaintable.class)
public class NativeButton extends Button {
public NativeButton() {
diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java
index 8b9dc3ef81..003ef6978c 100644
--- a/src/com/vaadin/ui/Table.java
+++ b/src/com/vaadin/ui/Table.java
@@ -47,6 +47,7 @@ import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.ui.VScrollTable;
+import com.vaadin.terminal.gwt.client.ui.VScrollTablePaintable;
import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;
/**
@@ -73,7 +74,7 @@ import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;
* @since 3.0
*/
@SuppressWarnings({ "deprecation" })
-@ClientWidget(VScrollTable.class)
+@ClientWidget(VScrollTablePaintable.class)
public class Table extends AbstractSelect implements Action.Container,
Container.Ordered, Container.Sortable, ItemClickSource,
ItemClickNotifier, DragSource, DropTarget {
@@ -115,91 +116,215 @@ public class Table extends AbstractSelect implements Action.Container,
protected static final int CELL_FIRSTCOL = 5;
+ public enum Align {
+ /**
+ * Left column alignment. <b>This is the default behaviour. </b>
+ */
+ LEFT("b"),
+
+ /**
+ * Center column alignment.
+ */
+ CENTER("c"),
+
+ /**
+ * Right column alignment.
+ */
+ RIGHT("e");
+
+ private String alignment;
+
+ private Align(String alignment) {
+ this.alignment = alignment;
+ }
+
+ @Override
+ public String toString() {
+ return alignment;
+ }
+
+ public Align convertStringToAlign(String string) {
+ if (string == null) {
+ return null;
+ }
+ if (string.equals("b")) {
+ return Align.LEFT;
+ } else if (string.equals("c")) {
+ return Align.CENTER;
+ } else if (string.equals("e")) {
+ return Align.RIGHT;
+ } else {
+ return null;
+ }
+ }
+ }
+
/**
- * Left column alignment. <b>This is the default behaviour. </b>
+ * @deprecated from 7.0, use {@link Align#LEFT} instead
*/
- public static final String ALIGN_LEFT = "b";
+ @Deprecated
+ public static final Align ALIGN_LEFT = Align.LEFT;
/**
- * Center column alignment.
+ * @deprecated from 7.0, use {@link Align#CENTER} instead
*/
- public static final String ALIGN_CENTER = "c";
+ @Deprecated
+ public static final Align ALIGN_CENTER = Align.CENTER;
/**
- * Right column alignment.
+ * @deprecated from 7.0, use {@link Align#RIGHT} instead
*/
- public static final String ALIGN_RIGHT = "e";
+ @Deprecated
+ public static final Align ALIGN_RIGHT = Align.RIGHT;
+
+ public enum ColumnHeaderMode {
+ /**
+ * Column headers are hidden.
+ */
+ HIDDEN,
+ /**
+ * Property ID:s are used as column headers.
+ */
+ ID,
+ /**
+ * Column headers are explicitly specified with
+ * {@link #setColumnHeaders(String[])}.
+ */
+ EXPLICIT,
+ /**
+ * Column headers are explicitly specified with
+ * {@link #setColumnHeaders(String[])}. If a header is not specified for
+ * a given property, its property id is used instead.
+ * <p>
+ * <b>This is the default behavior. </b>
+ */
+ EXPLICIT_DEFAULTS_ID
+ }
/**
- * Column header mode: Column headers are hidden.
+ * @deprecated from 7.0, use {@link ColumnHeaderMode#HIDDEN} instead
*/
- public static final int COLUMN_HEADER_MODE_HIDDEN = -1;
+ @Deprecated
+ public static final ColumnHeaderMode COLUMN_HEADER_MODE_HIDDEN = ColumnHeaderMode.HIDDEN;
/**
- * Column header mode: Property ID:s are used as column headers.
+ * @deprecated from 7.0, use {@link ColumnHeaderMode#ID} instead
*/
- public static final int COLUMN_HEADER_MODE_ID = 0;
+ @Deprecated
+ public static final ColumnHeaderMode COLUMN_HEADER_MODE_ID = ColumnHeaderMode.ID;
/**
- * Column header mode: Column headers are explicitly specified with
- * {@link #setColumnHeaders(String[])}.
+ * @deprecated from 7.0, use {@link ColumnHeaderMode#EXPLICIT} instead
*/
- public static final int COLUMN_HEADER_MODE_EXPLICIT = 1;
+ @Deprecated
+ public static final ColumnHeaderMode COLUMN_HEADER_MODE_EXPLICIT = ColumnHeaderMode.EXPLICIT;
/**
- * Column header mode: Column headers are explicitly specified with
- * {@link #setColumnHeaders(String[])}. If a header is not specified for a
- * given property, its property id is used instead.
- * <p>
- * <b>This is the default behavior. </b>
+ * @deprecated from 7.0, use {@link ColumnHeaderMode#EXPLICIT_DEFAULTS_ID}
+ * instead
*/
- public static final int COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID = 2;
+ @Deprecated
+ public static final ColumnHeaderMode COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID = ColumnHeaderMode.EXPLICIT_DEFAULTS_ID;
+
+ public enum RowHeaderMode {
+ /**
+ * Row caption mode: The row headers are hidden. <b>This is the default
+ * mode. </b>
+ */
+ HIDDEN(null),
+ /**
+ * Row caption mode: Items Id-objects toString is used as row caption.
+ */
+ ID(ItemCaptionMode.ID),
+ /**
+ * Row caption mode: Item-objects toString is used as row caption.
+ */
+ ITEM(ItemCaptionMode.ITEM),
+ /**
+ * Row caption mode: Index of the item is used as item caption. The
+ * index mode can only be used with the containers implementing the
+ * {@link com.vaadin.data.Container.Indexed} interface.
+ */
+ INDEX(ItemCaptionMode.INDEX),
+ /**
+ * Row caption mode: Item captions are explicitly specified, but if the
+ * caption is missing, the item id objects <code>toString()</code> is
+ * used instead.
+ */
+ EXPLICIT_DEFAULTS_ID(ItemCaptionMode.EXPLICIT_DEFAULTS_ID),
+ /**
+ * Row caption mode: Item captions are explicitly specified.
+ */
+ EXPLICIT(ItemCaptionMode.EXPLICIT),
+ /**
+ * Row caption mode: Only icons are shown, the captions are hidden.
+ */
+ ICON_ONLY(ItemCaptionMode.ICON_ONLY),
+ /**
+ * Row caption mode: Item captions are read from property specified with
+ * {@link #setItemCaptionPropertyId(Object)}.
+ */
+ PROPERTY(ItemCaptionMode.PROPERTY);
+
+ ItemCaptionMode mode;
+
+ private RowHeaderMode(ItemCaptionMode mode) {
+ this.mode = mode;
+ }
+
+ public ItemCaptionMode getItemCaptionMode() {
+ return mode;
+ }
+ }
/**
- * Row caption mode: The row headers are hidden. <b>This is the default
- * mode. </b>
+ * @deprecated from 7.0, use {@link RowHeaderMode#HIDDEN} instead
*/
- public static final int ROW_HEADER_MODE_HIDDEN = -1;
+ @Deprecated
+ public static final RowHeaderMode ROW_HEADER_MODE_HIDDEN = RowHeaderMode.HIDDEN;
/**
- * Row caption mode: Items Id-objects toString is used as row caption.
+ * @deprecated from 7.0, use {@link RowHeaderMode#ID} instead
*/
- public static final int ROW_HEADER_MODE_ID = AbstractSelect.ITEM_CAPTION_MODE_ID;
+ @Deprecated
+ public static final RowHeaderMode ROW_HEADER_MODE_ID = RowHeaderMode.ID;
/**
- * Row caption mode: Item-objects toString is used as row caption.
+ * @deprecated from 7.0, use {@link RowHeaderMode#ITEM} instead
*/
- public static final int ROW_HEADER_MODE_ITEM = AbstractSelect.ITEM_CAPTION_MODE_ITEM;
+ @Deprecated
+ public static final RowHeaderMode ROW_HEADER_MODE_ITEM = RowHeaderMode.ITEM;
/**
- * Row caption mode: Index of the item is used as item caption. The index
- * mode can only be used with the containers implementing Container.Indexed
- * interface.
+ * @deprecated from 7.0, use {@link RowHeaderMode#INDEX} instead
*/
- public static final int ROW_HEADER_MODE_INDEX = AbstractSelect.ITEM_CAPTION_MODE_INDEX;
+ @Deprecated
+ public static final RowHeaderMode ROW_HEADER_MODE_INDEX = RowHeaderMode.INDEX;
/**
- * Row caption mode: Item captions are explicitly specified.
+ * @deprecated from 7.0, use {@link RowHeaderMode#EXPLICIT_DEFAULTS_ID}
+ * instead
*/
- public static final int ROW_HEADER_MODE_EXPLICIT = AbstractSelect.ITEM_CAPTION_MODE_EXPLICIT;
+ @Deprecated
+ public static final RowHeaderMode ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID = RowHeaderMode.EXPLICIT_DEFAULTS_ID;
/**
- * Row caption mode: Item captions are read from property specified with
- * {@link #setItemCaptionPropertyId(Object)}.
+ * @deprecated from 7.0, use {@link RowHeaderMode#EXPLICIT} instead
*/
- public static final int ROW_HEADER_MODE_PROPERTY = AbstractSelect.ITEM_CAPTION_MODE_PROPERTY;
+ @Deprecated
+ public static final RowHeaderMode ROW_HEADER_MODE_EXPLICIT = RowHeaderMode.EXPLICIT;
/**
- * Row caption mode: Only icons are shown, the captions are hidden.
+ * @deprecated from 7.0, use {@link RowHeaderMode#ICON_ONLY} instead
*/
- public static final int ROW_HEADER_MODE_ICON_ONLY = AbstractSelect.ITEM_CAPTION_MODE_ICON_ONLY;
+ @Deprecated
+ public static final RowHeaderMode ROW_HEADER_MODE_ICON_ONLY = RowHeaderMode.ICON_ONLY;
/**
- * Row caption mode: Item captions are explicitly specified, but if the
- * caption is missing, the item id objects <code>toString()</code> is used
- * instead.
+ * @deprecated from 7.0, use {@link RowHeaderMode#PROPERTY} instead
*/
- public static final int ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID = AbstractSelect.ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID;
+ @Deprecated
+ public static final RowHeaderMode ROW_HEADER_MODE_PROPERTY = RowHeaderMode.PROPERTY;
/**
* The default rate that table caches rows for smooth scrolling.
@@ -254,7 +379,7 @@ public class Table extends AbstractSelect implements Action.Container,
/**
* Holds alignments for visible columns (by propertyId).
*/
- private HashMap<Object, String> columnAlignments = new HashMap<Object, String>();
+ private HashMap<Object, Align> columnAlignments = new HashMap<Object, Align>();
/**
* Holds column widths in pixels (Integer) or expand ratios (Float) for
@@ -290,17 +415,17 @@ public class Table extends AbstractSelect implements Action.Container,
/**
* Holds value of property columnHeaderMode.
*/
- private int columnHeaderMode = COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID;
+ private ColumnHeaderMode columnHeaderMode = ColumnHeaderMode.EXPLICIT_DEFAULTS_ID;
/**
- * Should the Table footer be visible?
+ * Holds value of property rowHeaderMode.
*/
- private boolean columnFootersVisible = false;
+ private RowHeaderMode rowHeaderMode = RowHeaderMode.EXPLICIT_DEFAULTS_ID;
/**
- * True iff the row captions are hidden.
+ * Should the Table footer be visible?
*/
- private boolean rowCaptionsAreHidden = true;
+ private boolean columnFootersVisible = false;
/**
* Page contents buffer used in buffered mode.
@@ -512,7 +637,7 @@ public class Table extends AbstractSelect implements Action.Container,
final Object col = i.next();
if (!newVC.contains(col)) {
setColumnHeader(col, null);
- setColumnAlignment(col, null);
+ setColumnAlignment(col, (Align) null);
setColumnIcon(col, null);
}
}
@@ -656,21 +781,21 @@ public class Table extends AbstractSelect implements Action.Container,
* {@link #getVisibleColumns()}. The possible values for the alignments
* include:
* <ul>
- * <li>{@link #ALIGN_LEFT}: Left alignment</li>
- * <li>{@link #ALIGN_CENTER}: Centered</li>
- * <li>{@link #ALIGN_RIGHT}: Right alignment</li>
+ * <li>{@link Align#LEFT}: Left alignment</li>
+ * <li>{@link Align#CENTER}: Centered</li>
+ * <li>{@link Align#RIGHT}: Right alignment</li>
* </ul>
- * The alignments default to {@link #ALIGN_LEFT}: any null values are
+ * The alignments default to {@link Align#LEFT}: any null values are
* rendered as align lefts.
* </p>
*
* @return the Column alignments array.
*/
- public String[] getColumnAlignments() {
+ public Align[] getColumnAlignments() {
if (columnAlignments == null) {
return null;
}
- final String[] alignments = new String[visibleColumns.size()];
+ final Align[] alignments = new Align[visibleColumns.size()];
int i = 0;
for (final Iterator<Object> it = visibleColumns.iterator(); it
.hasNext(); i++) {
@@ -684,39 +809,29 @@ public class Table extends AbstractSelect implements Action.Container,
* Sets the column alignments.
*
* <p>
- * The items in the array must match the properties identified by
- * {@link #getVisibleColumns()}. The possible values for the alignments
- * include:
+ * The amount of items in the array must match the amount of properties
+ * identified by {@link #getVisibleColumns()}. The possible values for the
+ * alignments include:
* <ul>
- * <li>{@link #ALIGN_LEFT}: Left alignment</li>
- * <li>{@link #ALIGN_CENTER}: Centered</li>
- * <li>{@link #ALIGN_RIGHT}: Right alignment</li>
+ * <li>{@link Align#LEFT}: Left alignment</li>
+ * <li>{@link Align#CENTER}: Centered</li>
+ * <li>{@link Align#RIGHT}: Right alignment</li>
* </ul>
- * The alignments default to {@link #ALIGN_LEFT}
+ * The alignments default to {@link Align#LEFT}
* </p>
*
* @param columnAlignments
* the Column alignments array.
*/
- public void setColumnAlignments(String[] columnAlignments) {
+ public void setColumnAlignments(Align... columnAlignments) {
if (columnAlignments.length != visibleColumns.size()) {
throw new IllegalArgumentException(
"The length of the alignments array must match the number of visible columns");
}
- // Checks all alignments
- for (int i = 0; i < columnAlignments.length; i++) {
- final String a = columnAlignments[i];
- if (a != null && !a.equals(ALIGN_LEFT) && !a.equals(ALIGN_CENTER)
- && !a.equals(ALIGN_RIGHT)) {
- throw new IllegalArgumentException("Column " + i
- + " aligment '" + a + "' is invalid");
- }
- }
-
// Resets the alignments
- final HashMap<Object, String> newCA = new HashMap<Object, String>();
+ final HashMap<Object, Align> newCA = new HashMap<Object, Align>();
int i = 0;
for (final Iterator<Object> it = visibleColumns.iterator(); it
.hasNext() && i < columnAlignments.length; i++) {
@@ -1034,13 +1149,13 @@ public class Table extends AbstractSelect implements Action.Container,
* @return the header for the specified column if it has one.
*/
public String getColumnHeader(Object propertyId) {
- if (getColumnHeaderMode() == COLUMN_HEADER_MODE_HIDDEN) {
+ if (getColumnHeaderMode() == ColumnHeaderMode.HIDDEN) {
return null;
}
String header = columnHeaders.get(propertyId);
- if ((header == null && getColumnHeaderMode() == COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID)
- || getColumnHeaderMode() == COLUMN_HEADER_MODE_ID) {
+ if ((header == null && getColumnHeaderMode() == ColumnHeaderMode.EXPLICIT_DEFAULTS_ID)
+ || getColumnHeaderMode() == ColumnHeaderMode.ID) {
header = propertyId.toString();
}
@@ -1073,9 +1188,9 @@ public class Table extends AbstractSelect implements Action.Container,
* the propertyID identifying the column.
* @return the specified column's alignment if it as one; null otherwise.
*/
- public String getColumnAlignment(Object propertyId) {
- final String a = columnAlignments.get(propertyId);
- return a == null ? ALIGN_LEFT : a;
+ public Align getColumnAlignment(Object propertyId) {
+ final Align a = columnAlignments.get(propertyId);
+ return a == null ? Align.LEFT : a;
}
/**
@@ -1083,8 +1198,8 @@ public class Table extends AbstractSelect implements Action.Container,
*
* <p>
* Throws IllegalArgumentException if the alignment is not one of the
- * following: {@link #ALIGN_LEFT}, {@link #ALIGN_CENTER} or
- * {@link #ALIGN_RIGHT}
+ * following: {@link Align#LEFT}, {@link Align#CENTER} or
+ * {@link Align#RIGHT}
* </p>
*
* @param propertyId
@@ -1092,17 +1207,8 @@ public class Table extends AbstractSelect implements Action.Container,
* @param alignment
* the desired alignment.
*/
- public void setColumnAlignment(Object propertyId, String alignment) {
-
- // Checks for valid alignments
- if (alignment != null && !alignment.equals(ALIGN_LEFT)
- && !alignment.equals(ALIGN_CENTER)
- && !alignment.equals(ALIGN_RIGHT)) {
- throw new IllegalArgumentException("Column alignment '" + alignment
- + "' is not supported.");
- }
-
- if (alignment == null || alignment.equals(ALIGN_LEFT)) {
+ public void setColumnAlignment(Object propertyId, Align alignment) {
+ if (alignment == null || alignment == Align.LEFT) {
columnAlignments.remove(propertyId);
} else {
columnAlignments.put(propertyId, alignment);
@@ -1397,7 +1503,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @return the Value of property columnHeaderMode.
*/
- public int getColumnHeaderMode() {
+ public ColumnHeaderMode getColumnHeaderMode() {
return columnHeaderMode;
}
@@ -1407,10 +1513,12 @@ public class Table extends AbstractSelect implements Action.Container,
* @param columnHeaderMode
* the New value of property columnHeaderMode.
*/
- public void setColumnHeaderMode(int columnHeaderMode) {
- if (columnHeaderMode != this.columnHeaderMode
- && columnHeaderMode >= COLUMN_HEADER_MODE_HIDDEN
- && columnHeaderMode <= COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID) {
+ public void setColumnHeaderMode(ColumnHeaderMode columnHeaderMode) {
+ if (columnHeaderMode == null) {
+ throw new IllegalArgumentException(
+ "Column header mode can not be null");
+ }
+ if (columnHeaderMode != this.columnHeaderMode) {
this.columnHeaderMode = columnHeaderMode;
requestRepaint();
}
@@ -1750,7 +1858,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
}
- final int headmode = getRowHeaderMode();
+ final RowHeaderMode headmode = getRowHeaderMode();
final boolean[] iscomponent = new boolean[cols];
for (int i = 0; i < cols; i++) {
iscomponent[i] = columnGenerators.containsKey(colids[i])
@@ -1771,7 +1879,7 @@ public class Table extends AbstractSelect implements Action.Container,
cells[CELL_KEY][i] = itemIdMapper.key(id);
if (headmode != ROW_HEADER_MODE_HIDDEN) {
switch (headmode) {
- case ROW_HEADER_MODE_INDEX:
+ case INDEX:
cells[CELL_HEADER][i] = String.valueOf(i + firstIndex + 1);
break;
default:
@@ -2070,17 +2178,17 @@ public class Table extends AbstractSelect implements Action.Container,
* @param mode
* the One of the modes listed above.
*/
- public void setRowHeaderMode(int mode) {
- if (ROW_HEADER_MODE_HIDDEN == mode) {
- rowCaptionsAreHidden = true;
- } else {
- rowCaptionsAreHidden = false;
- setItemCaptionMode(mode);
+ public void setRowHeaderMode(RowHeaderMode mode) {
+ if (mode != null) {
+ rowHeaderMode = mode;
+ if (mode != RowHeaderMode.HIDDEN) {
+ setItemCaptionMode(mode.getItemCaptionMode());
+ }
+ // Assures the visual refresh. No need to reset the page buffer
+ // before
+ // as the content has not changed, only the alignments.
+ refreshRenderedCells();
}
-
- // Assures the visual refresh. No need to reset the page buffer before
- // as the content has not changed, only the alignments.
- refreshRenderedCells();
}
/**
@@ -2089,9 +2197,8 @@ public class Table extends AbstractSelect implements Action.Container,
* @return the Row header mode.
* @see #setRowHeaderMode(int)
*/
- public int getRowHeaderMode() {
- return rowCaptionsAreHidden ? ROW_HEADER_MODE_HIDDEN
- : getItemCaptionMode();
+ public RowHeaderMode getRowHeaderMode() {
+ return rowHeaderMode;
}
/**
@@ -2928,7 +3035,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
private boolean areColumnHeadersEnabled() {
- return getColumnHeaderMode() != COLUMN_HEADER_MODE_HIDDEN;
+ return getColumnHeaderMode() != ColumnHeaderMode.HIDDEN;
}
private void paintVisibleColumns(PaintTarget target) throws PaintException {
@@ -2959,8 +3066,9 @@ public class Table extends AbstractSelect implements Action.Container,
target.addAttribute("sortable", true);
}
}
- if (!ALIGN_LEFT.equals(getColumnAlignment(colId))) {
- target.addAttribute("align", getColumnAlignment(colId));
+ if (!Align.LEFT.equals(getColumnAlignment(colId))) {
+ target.addAttribute("align", getColumnAlignment(colId)
+ .toString());
}
paintColumnWidth(target, colId);
target.endTag("column");
@@ -3051,6 +3159,9 @@ public class Table extends AbstractSelect implements Action.Container,
if (start > cells[CELL_ITEMID].length || start < 0) {
start = 0;
}
+ if (end > cells[CELL_ITEMID].length) {
+ end = cells[CELL_ITEMID].length;
+ }
for (int indexInRowbuffer = start; indexInRowbuffer < end; indexInRowbuffer++) {
final Object itemId = cells[CELL_ITEMID][indexInRowbuffer];
@@ -3721,7 +3832,7 @@ public class Table extends AbstractSelect implements Action.Container,
*/
public boolean addContainerProperty(Object propertyId, Class<?> type,
Object defaultValue, String columnHeader, Resource columnIcon,
- String columnAlignment) throws UnsupportedOperationException {
+ Align columnAlignment) throws UnsupportedOperationException {
if (!this.addContainerProperty(propertyId, type, defaultValue)) {
return false;
}
@@ -5187,4 +5298,13 @@ public class Table extends AbstractSelect implements Action.Container,
return propertyValueConverters.get(propertyId);
}
+ @Override
+ public void setVisible(boolean visible) {
+ if (!isVisible() && visible) {
+ // We need to ensure that the rows are sent to the client when the
+ // Table is made visible if it has been rendered as invisible.
+ setRowCacheInvalidated(true);
+ }
+ super.setVisible(visible);
+ }
}
diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java
index 43bc7a80fe..09417e1e16 100644
--- a/src/com/vaadin/ui/TreeTable.java
+++ b/src/com/vaadin/ui/TreeTable.java
@@ -22,7 +22,7 @@ import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
-import com.vaadin.terminal.gwt.client.ui.VTreeTable;
+import com.vaadin.terminal.gwt.client.ui.VTreeTablePaintable;
import com.vaadin.ui.Tree.CollapseEvent;
import com.vaadin.ui.Tree.CollapseListener;
import com.vaadin.ui.Tree.ExpandEvent;
@@ -48,7 +48,7 @@ import com.vaadin.ui.treetable.HierarchicalContainerOrderedWrapper;
* share UI state in the container.
*/
@SuppressWarnings({ "serial" })
-@ClientWidget(VTreeTable.class)
+@ClientWidget(VTreeTablePaintable.class)
public class TreeTable extends Table implements Hierarchical {
private static final Logger logger = Logger.getLogger(TreeTable.class
@@ -454,7 +454,8 @@ public class TreeTable extends Table implements Hierarchical {
Object object = visibleColumns2[i];
if (hierarchyColumnId.equals(object)) {
target.addAttribute(
- VTreeTable.ATTRIBUTE_HIERARCHY_COLUMN_INDEX, i);
+ VTreeTablePaintable.ATTRIBUTE_HIERARCHY_COLUMN_INDEX,
+ i);
break;
}
}