diff options
author | Henri Sara <hesara@vaadin.com> | 2012-01-27 18:38:13 +0200 |
---|---|---|
committer | Henri Sara <hesara@vaadin.com> | 2012-01-27 18:38:13 +0200 |
commit | 91b3084e060f975ee35573972ace8bcf8fe3a5ed (patch) | |
tree | 154bb05f457b91388454fe42cd7652ca0d05c688 /src/com | |
parent | 06ef07c7fd6eab0b7446367fa5a43384ae469cef (diff) | |
download | vaadin-framework-91b3084e060f975ee35573972ace8bcf8fe3a5ed.tar.gz vaadin-framework-91b3084e060f975ee35573972ace8bcf8fe3a5ed.zip |
Merge changes from master to rpc branch.
Diffstat (limited to 'src/com')
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("Content-Type", "text/html"); + * response.getWriter().write( + * myLoginPageHtml + "<!-- Vaadin-Refresh: " + * + request.getContextPath() + " -->"); + * } + * </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 = "►"; - } - 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 = "►";
+ }
+ 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; } } |