aboutsummaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorArtur Signell <artur.signell@itmill.com>2012-01-27 14:08:53 +0000
committerArtur Signell <artur.signell@itmill.com>2012-01-27 14:08:53 +0000
commitc2722bfeb2552158c9717110b35518a07e13ab85 (patch)
treeb32ead2ac3b8ab68027e12e9bf97394cbad906f1 /src/com
parentb1ae3cd70e2ca4656bb28f77ca79fe0efd29dd67 (diff)
downloadvaadin-framework-c2722bfeb2552158c9717110b35518a07e13ab85.tar.gz
vaadin-framework-c2722bfeb2552158c9717110b35518a07e13ab85.zip
#8311 Converted CRLF to LF in all source files
svn changeset:22797/svn branch:6.7
Diffstat (limited to 'src/com')
-rw-r--r--src/com/google/gwt/dom/client/VaadinDOMImplSafari.java52
-rw-r--r--src/com/vaadin/data/util/TextFileProperty.java282
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/CacheFlushNotifier.java184
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/CacheMap.java60
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/Reference.java112
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/RowId.java162
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPool.java330
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/query/FreeformStatementDelegate.java114
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/query/generator/StatementHelper.java270
-rw-r--r--src/com/vaadin/event/FieldEvents.java500
-rw-r--r--src/com/vaadin/terminal/gwt/client/DateTimeService.java878
-rw-r--r--src/com/vaadin/terminal/gwt/client/LocaleNotLoadedException.java26
-rw-r--r--src/com/vaadin/terminal/gwt/client/LocaleService.java296
-rw-r--r--src/com/vaadin/terminal/gwt/client/VBrowserDetails.java610
-rw-r--r--src/com/vaadin/terminal/gwt/client/VSchedulerImpl.java64
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/CalendarEntry.java254
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/FocusableFlowPanel.java198
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/TreeImages.java58
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java3579
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VDateField.java554
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java306
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VForm.java662
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VLazyExecutor.java104
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VNotification.java834
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VOptionGroup.java470
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java454
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VPasswordField.java42
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java964
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VSlider.java1202
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java428
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTextArea.java158
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java1290
-rw-r--r--src/com/vaadin/ui/ComboBox.java258
-rw-r--r--src/com/vaadin/ui/InlineDateField.java96
-rw-r--r--src/com/vaadin/ui/PopupDateField.java160
36 files changed, 8011 insertions, 8002 deletions
diff --git a/src/com/google/gwt/dom/client/VaadinDOMImplSafari.java b/src/com/google/gwt/dom/client/VaadinDOMImplSafari.java
index 3975bf73d8..6e9cc81f43 100644
--- a/src/com/google/gwt/dom/client/VaadinDOMImplSafari.java
+++ b/src/com/google/gwt/dom/client/VaadinDOMImplSafari.java
@@ -1,26 +1,26 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.google.gwt.dom.client;
-
-/**
- * Overridden to workaround GWT issue #6194. Remove this when updating to a
- * newer GWT that fixes the problem (2.3.0 possibly). Must be in this package as
- * the whole DOMImpl hierarchy is package private and I really did not want to
- * copy all the parent classes into this one...
- */
-class VaadinDOMImplSafari extends DOMImplSafari {
- @Override
- public int getAbsoluteLeft(Element elem) {
- // Chrome returns a float in certain cases (at least when zoom != 100%).
- // The |0 ensures it is converted to an int.
- return super.getAbsoluteLeft(elem) | 0;
- }
-
- @Override
- public int getAbsoluteTop(Element elem) {
- // Chrome returns a float in certain cases (at least when zoom != 100%).
- // The |0 ensures it is converted to an int.
- return super.getAbsoluteTop(elem) | 0;
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.google.gwt.dom.client;
+
+/**
+ * Overridden to workaround GWT issue #6194. Remove this when updating to a
+ * newer GWT that fixes the problem (2.3.0 possibly). Must be in this package as
+ * the whole DOMImpl hierarchy is package private and I really did not want to
+ * copy all the parent classes into this one...
+ */
+class VaadinDOMImplSafari extends DOMImplSafari {
+ @Override
+ public int getAbsoluteLeft(Element elem) {
+ // Chrome returns a float in certain cases (at least when zoom != 100%).
+ // The |0 ensures it is converted to an int.
+ return super.getAbsoluteLeft(elem) | 0;
+ }
+
+ @Override
+ public int getAbsoluteTop(Element elem) {
+ // Chrome returns a float in certain cases (at least when zoom != 100%).
+ // The |0 ensures it is converted to an int.
+ return super.getAbsoluteTop(elem) | 0;
+ }
+}
diff --git a/src/com/vaadin/data/util/TextFileProperty.java b/src/com/vaadin/data/util/TextFileProperty.java
index 2ad1f593af..cfa8d4fabf 100644
--- a/src/com/vaadin/data/util/TextFileProperty.java
+++ b/src/com/vaadin/data/util/TextFileProperty.java
@@ -1,141 +1,141 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.nio.charset.Charset;
-
-/**
- * Property implementation for wrapping a text file.
- *
- * Supports reading and writing of a File from/to String.
- *
- * {@link ValueChangeListener}s are supported, but only fire when
- * setValue(Object) is explicitly called. {@link ReadOnlyStatusChangeListener}s
- * are supported but only fire when setReadOnly(boolean) is explicitly called.
- *
- */
-@SuppressWarnings("serial")
-public class TextFileProperty extends AbstractProperty {
-
- private File file;
- private Charset charset = null;
-
- /**
- * Wrap given file with property interface.
- *
- * Setting the file to null works, but getValue() will return null.
- *
- * @param file
- * File to be wrapped.
- */
- public TextFileProperty(File file) {
- this.file = file;
- }
-
- /**
- * Wrap the given file with the property interface and specify character
- * set.
- *
- * Setting the file to null works, but getValue() will return null.
- *
- * @param file
- * File to be wrapped.
- * @param charset
- * Charset to be used for reading and writing the file.
- */
- public TextFileProperty(File file, Charset charset) {
- this.file = file;
- this.charset = charset;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Property#getType()
- */
- public Class<?> getType() {
- return String.class;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Property#getValue()
- */
- public Object getValue() {
- if (file == null) {
- return null;
- }
- try {
- FileInputStream fis = new FileInputStream(file);
- InputStreamReader isr = charset == null ? new InputStreamReader(fis)
- : new InputStreamReader(fis, charset);
- BufferedReader r = new BufferedReader(isr);
- StringBuilder b = new StringBuilder();
- char buf[] = new char[8 * 1024];
- int len;
- while ((len = r.read(buf)) != -1) {
- b.append(buf, 0, len);
- }
- r.close();
- isr.close();
- fis.close();
- return b.toString();
- } catch (FileNotFoundException e) {
- return null;
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Property#isReadOnly()
- */
- @Override
- public boolean isReadOnly() {
- return file == null || super.isReadOnly() || !file.canWrite();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Property#setValue(java.lang.Object)
- */
- public void setValue(Object newValue) throws ReadOnlyException {
- if (isReadOnly()) {
- throw new ReadOnlyException();
- }
- if (file == null) {
- return;
- }
-
- try {
- FileOutputStream fos = new FileOutputStream(file);
- OutputStreamWriter osw = charset == null ? new OutputStreamWriter(
- fos) : new OutputStreamWriter(fos, charset);
- BufferedWriter w = new BufferedWriter(osw);
- w.append(newValue.toString());
- w.flush();
- w.close();
- osw.close();
- fos.close();
- fireValueChange();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.data.util;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+
+/**
+ * Property implementation for wrapping a text file.
+ *
+ * Supports reading and writing of a File from/to String.
+ *
+ * {@link ValueChangeListener}s are supported, but only fire when
+ * setValue(Object) is explicitly called. {@link ReadOnlyStatusChangeListener}s
+ * are supported but only fire when setReadOnly(boolean) is explicitly called.
+ *
+ */
+@SuppressWarnings("serial")
+public class TextFileProperty extends AbstractProperty {
+
+ private File file;
+ private Charset charset = null;
+
+ /**
+ * Wrap given file with property interface.
+ *
+ * Setting the file to null works, but getValue() will return null.
+ *
+ * @param file
+ * File to be wrapped.
+ */
+ public TextFileProperty(File file) {
+ this.file = file;
+ }
+
+ /**
+ * Wrap the given file with the property interface and specify character
+ * set.
+ *
+ * Setting the file to null works, but getValue() will return null.
+ *
+ * @param file
+ * File to be wrapped.
+ * @param charset
+ * Charset to be used for reading and writing the file.
+ */
+ public TextFileProperty(File file, Charset charset) {
+ this.file = file;
+ this.charset = charset;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Property#getType()
+ */
+ public Class<?> getType() {
+ return String.class;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Property#getValue()
+ */
+ public Object getValue() {
+ if (file == null) {
+ return null;
+ }
+ try {
+ FileInputStream fis = new FileInputStream(file);
+ InputStreamReader isr = charset == null ? new InputStreamReader(fis)
+ : new InputStreamReader(fis, charset);
+ BufferedReader r = new BufferedReader(isr);
+ StringBuilder b = new StringBuilder();
+ char buf[] = new char[8 * 1024];
+ int len;
+ while ((len = r.read(buf)) != -1) {
+ b.append(buf, 0, len);
+ }
+ r.close();
+ isr.close();
+ fis.close();
+ return b.toString();
+ } catch (FileNotFoundException e) {
+ return null;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Property#isReadOnly()
+ */
+ @Override
+ public boolean isReadOnly() {
+ return file == null || super.isReadOnly() || !file.canWrite();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.data.Property#setValue(java.lang.Object)
+ */
+ public void setValue(Object newValue) throws ReadOnlyException {
+ if (isReadOnly()) {
+ throw new ReadOnlyException();
+ }
+ if (file == null) {
+ return;
+ }
+
+ try {
+ FileOutputStream fos = new FileOutputStream(file);
+ OutputStreamWriter osw = charset == null ? new OutputStreamWriter(
+ fos) : new OutputStreamWriter(fos, charset);
+ BufferedWriter w = new BufferedWriter(osw);
+ w.append(newValue.toString());
+ w.flush();
+ w.close();
+ osw.close();
+ fos.close();
+ fireValueChange();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/src/com/vaadin/data/util/sqlcontainer/CacheFlushNotifier.java b/src/com/vaadin/data/util/sqlcontainer/CacheFlushNotifier.java
index ac6efaa49b..788966048d 100644
--- a/src/com/vaadin/data/util/sqlcontainer/CacheFlushNotifier.java
+++ b/src/com/vaadin/data/util/sqlcontainer/CacheFlushNotifier.java
@@ -1,92 +1,92 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.util.sqlcontainer;
-
-import java.io.Serializable;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.vaadin.data.util.sqlcontainer.query.FreeformQuery;
-import com.vaadin.data.util.sqlcontainer.query.QueryDelegate;
-import com.vaadin.data.util.sqlcontainer.query.TableQuery;
-
-/**
- * CacheFlushNotifier is a simple static notification mechanism to inform other
- * SQLContainers that the contents of their caches may have become stale.
- */
-class CacheFlushNotifier implements Serializable {
- /*
- * SQLContainer instance reference list and dead reference queue. Used for
- * the cache flush notification feature.
- */
- private static List<WeakReference<SQLContainer>> allInstances = new ArrayList<WeakReference<SQLContainer>>();
- private static ReferenceQueue<SQLContainer> deadInstances = new ReferenceQueue<SQLContainer>();
-
- /**
- * Adds the given SQLContainer to the cache flush notification receiver list
- *
- * @param c
- * Container to add
- */
- public static void addInstance(SQLContainer c) {
- removeDeadReferences();
- if (c != null) {
- allInstances.add(new WeakReference<SQLContainer>(c, deadInstances));
- }
- }
-
- /**
- * Removes dead references from instance list
- */
- private static void removeDeadReferences() {
- java.lang.ref.Reference<? extends SQLContainer> dead = deadInstances
- .poll();
- while (dead != null) {
- allInstances.remove(dead);
- dead = deadInstances.poll();
- }
- }
-
- /**
- * Iterates through the instances and notifies containers which are
- * connected to the same table or are using the same query string.
- *
- * @param c
- * SQLContainer that issued the cache flush notification
- */
- public static void notifyOfCacheFlush(SQLContainer c) {
- removeDeadReferences();
- for (WeakReference<SQLContainer> wr : allInstances) {
- if (wr.get() != null) {
- SQLContainer wrc = wr.get();
- if (wrc == null) {
- continue;
- }
- /*
- * If the reference points to the container sending the
- * notification, do nothing.
- */
- if (wrc.equals(c)) {
- continue;
- }
- /* Compare QueryDelegate types and tableName/queryString */
- QueryDelegate wrQd = wrc.getQueryDelegate();
- QueryDelegate qd = c.getQueryDelegate();
- if (wrQd instanceof TableQuery
- && qd instanceof TableQuery
- && ((TableQuery) wrQd).getTableName().equals(
- ((TableQuery) qd).getTableName())) {
- wrc.refresh();
- } else if (wrQd instanceof FreeformQuery
- && qd instanceof FreeformQuery
- && ((FreeformQuery) wrQd).getQueryString().equals(
- ((FreeformQuery) qd).getQueryString())) {
- wrc.refresh();
- }
- }
- }
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.util.sqlcontainer;
+
+import java.io.Serializable;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.vaadin.data.util.sqlcontainer.query.FreeformQuery;
+import com.vaadin.data.util.sqlcontainer.query.QueryDelegate;
+import com.vaadin.data.util.sqlcontainer.query.TableQuery;
+
+/**
+ * CacheFlushNotifier is a simple static notification mechanism to inform other
+ * SQLContainers that the contents of their caches may have become stale.
+ */
+class CacheFlushNotifier implements Serializable {
+ /*
+ * SQLContainer instance reference list and dead reference queue. Used for
+ * the cache flush notification feature.
+ */
+ private static List<WeakReference<SQLContainer>> allInstances = new ArrayList<WeakReference<SQLContainer>>();
+ private static ReferenceQueue<SQLContainer> deadInstances = new ReferenceQueue<SQLContainer>();
+
+ /**
+ * Adds the given SQLContainer to the cache flush notification receiver list
+ *
+ * @param c
+ * Container to add
+ */
+ public static void addInstance(SQLContainer c) {
+ removeDeadReferences();
+ if (c != null) {
+ allInstances.add(new WeakReference<SQLContainer>(c, deadInstances));
+ }
+ }
+
+ /**
+ * Removes dead references from instance list
+ */
+ private static void removeDeadReferences() {
+ java.lang.ref.Reference<? extends SQLContainer> dead = deadInstances
+ .poll();
+ while (dead != null) {
+ allInstances.remove(dead);
+ dead = deadInstances.poll();
+ }
+ }
+
+ /**
+ * Iterates through the instances and notifies containers which are
+ * connected to the same table or are using the same query string.
+ *
+ * @param c
+ * SQLContainer that issued the cache flush notification
+ */
+ public static void notifyOfCacheFlush(SQLContainer c) {
+ removeDeadReferences();
+ for (WeakReference<SQLContainer> wr : allInstances) {
+ if (wr.get() != null) {
+ SQLContainer wrc = wr.get();
+ if (wrc == null) {
+ continue;
+ }
+ /*
+ * If the reference points to the container sending the
+ * notification, do nothing.
+ */
+ if (wrc.equals(c)) {
+ continue;
+ }
+ /* Compare QueryDelegate types and tableName/queryString */
+ QueryDelegate wrQd = wrc.getQueryDelegate();
+ QueryDelegate qd = c.getQueryDelegate();
+ if (wrQd instanceof TableQuery
+ && qd instanceof TableQuery
+ && ((TableQuery) wrQd).getTableName().equals(
+ ((TableQuery) qd).getTableName())) {
+ wrc.refresh();
+ } else if (wrQd instanceof FreeformQuery
+ && qd instanceof FreeformQuery
+ && ((FreeformQuery) wrQd).getQueryString().equals(
+ ((FreeformQuery) qd).getQueryString())) {
+ wrc.refresh();
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/vaadin/data/util/sqlcontainer/CacheMap.java b/src/com/vaadin/data/util/sqlcontainer/CacheMap.java
index 44921dd12d..839fceb3c2 100644
--- a/src/com/vaadin/data/util/sqlcontainer/CacheMap.java
+++ b/src/com/vaadin/data/util/sqlcontainer/CacheMap.java
@@ -1,31 +1,31 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.util.sqlcontainer;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * CacheMap extends LinkedHashMap, adding the possibility to adjust maximum
- * number of items. In SQLContainer this is used for RowItem -cache. Cache size
- * will be two times the page length parameter of the container.
- */
-class CacheMap<K, V> extends LinkedHashMap<K, V> {
- private static final long serialVersionUID = 679999766473555231L;
- private int cacheLimit = SQLContainer.CACHE_RATIO
- * SQLContainer.DEFAULT_PAGE_LENGTH;
-
- @Override
- protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
- return size() > cacheLimit;
- }
-
- void setCacheLimit(int limit) {
- cacheLimit = limit > 0 ? limit : SQLContainer.DEFAULT_PAGE_LENGTH;
- }
-
- int getCacheLimit() {
- return cacheLimit;
- }
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.util.sqlcontainer;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * CacheMap extends LinkedHashMap, adding the possibility to adjust maximum
+ * number of items. In SQLContainer this is used for RowItem -cache. Cache size
+ * will be two times the page length parameter of the container.
+ */
+class CacheMap<K, V> extends LinkedHashMap<K, V> {
+ private static final long serialVersionUID = 679999766473555231L;
+ private int cacheLimit = SQLContainer.CACHE_RATIO
+ * SQLContainer.DEFAULT_PAGE_LENGTH;
+
+ @Override
+ protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
+ return size() > cacheLimit;
+ }
+
+ void setCacheLimit(int limit) {
+ cacheLimit = limit > 0 ? limit : SQLContainer.DEFAULT_PAGE_LENGTH;
+ }
+
+ int getCacheLimit() {
+ return cacheLimit;
+ }
} \ No newline at end of file
diff --git a/src/com/vaadin/data/util/sqlcontainer/Reference.java b/src/com/vaadin/data/util/sqlcontainer/Reference.java
index 6e863fa040..dea1aa87c0 100644
--- a/src/com/vaadin/data/util/sqlcontainer/Reference.java
+++ b/src/com/vaadin/data/util/sqlcontainer/Reference.java
@@ -1,56 +1,56 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.util.sqlcontainer;
-
-import java.io.Serializable;
-
-/**
- * The reference class represents a simple [usually foreign key] reference to
- * another SQLContainer. Actual foreign key reference in the database is not
- * required, but it is recommended to make sure that certain constraints are
- * followed.
- */
-@SuppressWarnings("serial")
-class Reference implements Serializable {
-
- /**
- * The SQLContainer that this reference points to.
- */
- private SQLContainer referencedContainer;
-
- /**
- * The column ID/name in the referencing SQLContainer that contains the key
- * used for the reference.
- */
- private String referencingColumn;
-
- /**
- * The column ID/name in the referenced SQLContainer that contains the key
- * used for the reference.
- */
- private String referencedColumn;
-
- /**
- * Constructs a new reference to be used within the SQLContainer to
- * reference another SQLContainer.
- */
- Reference(SQLContainer referencedContainer, String referencingColumn,
- String referencedColumn) {
- this.referencedContainer = referencedContainer;
- this.referencingColumn = referencingColumn;
- this.referencedColumn = referencedColumn;
- }
-
- SQLContainer getReferencedContainer() {
- return referencedContainer;
- }
-
- String getReferencingColumn() {
- return referencingColumn;
- }
-
- String getReferencedColumn() {
- return referencedColumn;
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.util.sqlcontainer;
+
+import java.io.Serializable;
+
+/**
+ * The reference class represents a simple [usually foreign key] reference to
+ * another SQLContainer. Actual foreign key reference in the database is not
+ * required, but it is recommended to make sure that certain constraints are
+ * followed.
+ */
+@SuppressWarnings("serial")
+class Reference implements Serializable {
+
+ /**
+ * The SQLContainer that this reference points to.
+ */
+ private SQLContainer referencedContainer;
+
+ /**
+ * The column ID/name in the referencing SQLContainer that contains the key
+ * used for the reference.
+ */
+ private String referencingColumn;
+
+ /**
+ * The column ID/name in the referenced SQLContainer that contains the key
+ * used for the reference.
+ */
+ private String referencedColumn;
+
+ /**
+ * Constructs a new reference to be used within the SQLContainer to
+ * reference another SQLContainer.
+ */
+ Reference(SQLContainer referencedContainer, String referencingColumn,
+ String referencedColumn) {
+ this.referencedContainer = referencedContainer;
+ this.referencingColumn = referencingColumn;
+ this.referencedColumn = referencedColumn;
+ }
+
+ SQLContainer getReferencedContainer() {
+ return referencedContainer;
+ }
+
+ String getReferencingColumn() {
+ return referencingColumn;
+ }
+
+ String getReferencedColumn() {
+ return referencedColumn;
+ }
+}
diff --git a/src/com/vaadin/data/util/sqlcontainer/RowId.java b/src/com/vaadin/data/util/sqlcontainer/RowId.java
index ed01b72e06..925325134a 100644
--- a/src/com/vaadin/data/util/sqlcontainer/RowId.java
+++ b/src/com/vaadin/data/util/sqlcontainer/RowId.java
@@ -1,81 +1,81 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.util.sqlcontainer;
-
-import java.io.Serializable;
-
-/**
- * RowId represents identifiers of a single database result set row.
- *
- * The data structure of a RowId is an Object array which contains the values of
- * the primary key columns of the identified row. This allows easy equals()
- * -comparison of RowItems.
- */
-public class RowId implements Serializable {
- private static final long serialVersionUID = -3161778404698901258L;
- protected Object[] id;
-
- /**
- * Prevent instantiation without required parameters.
- */
- protected RowId() {
- }
-
- public RowId(Object[] id) {
- if (id == null) {
- throw new IllegalArgumentException("id parameter must not be null!");
- }
- this.id = id;
- }
-
- public Object[] getId() {
- return id;
- }
-
- @Override
- public int hashCode() {
- int result = 31;
- if (id != null) {
- for (Object o : id) {
- if (o != null) {
- result += o.hashCode();
- }
- }
- }
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null || !(obj instanceof RowId)) {
- return false;
- }
- Object[] compId = ((RowId) obj).getId();
- if (id == null && compId == null) {
- return true;
- }
- if (id.length != compId.length) {
- return false;
- }
- for (int i = 0; i < id.length; i++) {
- if ((id[i] == null && compId[i] != null)
- || (id[i] != null && !id[i].equals(compId[i]))) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public String toString() {
- StringBuffer s = new StringBuffer();
- for (int i = 0; i < id.length; i++) {
- s.append(id[i]);
- if (i < id.length - 1) {
- s.append("/");
- }
- }
- return s.toString();
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.util.sqlcontainer;
+
+import java.io.Serializable;
+
+/**
+ * RowId represents identifiers of a single database result set row.
+ *
+ * The data structure of a RowId is an Object array which contains the values of
+ * the primary key columns of the identified row. This allows easy equals()
+ * -comparison of RowItems.
+ */
+public class RowId implements Serializable {
+ private static final long serialVersionUID = -3161778404698901258L;
+ protected Object[] id;
+
+ /**
+ * Prevent instantiation without required parameters.
+ */
+ protected RowId() {
+ }
+
+ public RowId(Object[] id) {
+ if (id == null) {
+ throw new IllegalArgumentException("id parameter must not be null!");
+ }
+ this.id = id;
+ }
+
+ public Object[] getId() {
+ return id;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 31;
+ if (id != null) {
+ for (Object o : id) {
+ if (o != null) {
+ result += o.hashCode();
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof RowId)) {
+ return false;
+ }
+ Object[] compId = ((RowId) obj).getId();
+ if (id == null && compId == null) {
+ return true;
+ }
+ if (id.length != compId.length) {
+ return false;
+ }
+ for (int i = 0; i < id.length; i++) {
+ if ((id[i] == null && compId[i] != null)
+ || (id[i] != null && !id[i].equals(compId[i]))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer s = new StringBuffer();
+ for (int i = 0; i < id.length; i++) {
+ s.append(id[i]);
+ if (i < id.length - 1) {
+ s.append("/");
+ }
+ }
+ return s.toString();
+ }
+}
diff --git a/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPool.java b/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPool.java
index c1a7c61eab..2a1068e786 100644
--- a/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPool.java
+++ b/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPool.java
@@ -1,165 +1,165 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.util.sqlcontainer.connection;
-
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Simple implementation of the JDBCConnectionPool interface. Handles loading
- * the JDBC driver, setting up the connections and ensuring they are still
- * usable upon release.
- */
-@SuppressWarnings("serial")
-public class SimpleJDBCConnectionPool implements JDBCConnectionPool {
-
- private int initialConnections = 5;
- private int maxConnections = 20;
-
- private String driverName;
- private String connectionUri;
- private String userName;
- private String password;
-
- private transient Set<Connection> availableConnections;
- private transient Set<Connection> reservedConnections;
-
- private boolean initialized;
-
- public SimpleJDBCConnectionPool(String driverName, String connectionUri,
- String userName, String password) throws SQLException {
- if (driverName == null) {
- throw new IllegalArgumentException(
- "JDBC driver class name must be given.");
- }
- if (connectionUri == null) {
- throw new IllegalArgumentException(
- "Database connection URI must be given.");
- }
- if (userName == null) {
- throw new IllegalArgumentException(
- "Database username must be given.");
- }
- if (password == null) {
- throw new IllegalArgumentException(
- "Database password must be given.");
- }
- this.driverName = driverName;
- this.connectionUri = connectionUri;
- this.userName = userName;
- this.password = password;
-
- /* Initialize JDBC driver */
- try {
- Class.forName(driverName).newInstance();
- } catch (Exception ex) {
- throw new RuntimeException("Specified JDBC Driver: " + driverName
- + " - initialization failed.", ex);
- }
- }
-
- public SimpleJDBCConnectionPool(String driverName, String connectionUri,
- String userName, String password, int initialConnections,
- int maxConnections) throws SQLException {
- this(driverName, connectionUri, userName, password);
- this.initialConnections = initialConnections;
- this.maxConnections = maxConnections;
- }
-
- private void initializeConnections() throws SQLException {
- availableConnections = new HashSet<Connection>(initialConnections);
- reservedConnections = new HashSet<Connection>(initialConnections);
- for (int i = 0; i < initialConnections; i++) {
- availableConnections.add(createConnection());
- }
- initialized = true;
- }
-
- public synchronized Connection reserveConnection() throws SQLException {
- if (!initialized) {
- initializeConnections();
- }
- if (availableConnections.isEmpty()) {
- if (reservedConnections.size() < maxConnections) {
- availableConnections.add(createConnection());
- } else {
- throw new SQLException("Connection limit has been reached.");
- }
- }
-
- Connection c = availableConnections.iterator().next();
- availableConnections.remove(c);
- reservedConnections.add(c);
-
- return c;
- }
-
- public synchronized void releaseConnection(Connection conn) {
- if (conn == null || !initialized) {
- return;
- }
- /* Try to roll back if necessary */
- try {
- if (!conn.getAutoCommit()) {
- conn.rollback();
- }
- } catch (SQLException e) {
- /* Roll back failed, close and discard connection */
- try {
- conn.close();
- } catch (SQLException e1) {
- /* Nothing needs to be done */
- }
- reservedConnections.remove(conn);
- return;
- }
- reservedConnections.remove(conn);
- availableConnections.add(conn);
- }
-
- private Connection createConnection() throws SQLException {
- Connection c = DriverManager.getConnection(connectionUri, userName,
- password);
- c.setAutoCommit(false);
- if (driverName.toLowerCase().contains("mysql")) {
- try {
- Statement s = c.createStatement();
- s.execute("SET SESSION sql_mode = 'ANSI'");
- s.close();
- } catch (Exception e) {
- // Failed to set ansi mode; continue
- }
- }
- return c;
- }
-
- public void destroy() {
- for (Connection c : availableConnections) {
- try {
- c.close();
- } catch (SQLException e) {
- // No need to do anything
- }
- }
- for (Connection c : reservedConnections) {
- try {
- c.close();
- } catch (SQLException e) {
- // No need to do anything
- }
- }
-
- }
-
- private void writeObject(java.io.ObjectOutputStream out) throws IOException {
- initialized = false;
- out.defaultWriteObject();
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.util.sqlcontainer.connection;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Simple implementation of the JDBCConnectionPool interface. Handles loading
+ * the JDBC driver, setting up the connections and ensuring they are still
+ * usable upon release.
+ */
+@SuppressWarnings("serial")
+public class SimpleJDBCConnectionPool implements JDBCConnectionPool {
+
+ private int initialConnections = 5;
+ private int maxConnections = 20;
+
+ private String driverName;
+ private String connectionUri;
+ private String userName;
+ private String password;
+
+ private transient Set<Connection> availableConnections;
+ private transient Set<Connection> reservedConnections;
+
+ private boolean initialized;
+
+ public SimpleJDBCConnectionPool(String driverName, String connectionUri,
+ String userName, String password) throws SQLException {
+ if (driverName == null) {
+ throw new IllegalArgumentException(
+ "JDBC driver class name must be given.");
+ }
+ if (connectionUri == null) {
+ throw new IllegalArgumentException(
+ "Database connection URI must be given.");
+ }
+ if (userName == null) {
+ throw new IllegalArgumentException(
+ "Database username must be given.");
+ }
+ if (password == null) {
+ throw new IllegalArgumentException(
+ "Database password must be given.");
+ }
+ this.driverName = driverName;
+ this.connectionUri = connectionUri;
+ this.userName = userName;
+ this.password = password;
+
+ /* Initialize JDBC driver */
+ try {
+ Class.forName(driverName).newInstance();
+ } catch (Exception ex) {
+ throw new RuntimeException("Specified JDBC Driver: " + driverName
+ + " - initialization failed.", ex);
+ }
+ }
+
+ public SimpleJDBCConnectionPool(String driverName, String connectionUri,
+ String userName, String password, int initialConnections,
+ int maxConnections) throws SQLException {
+ this(driverName, connectionUri, userName, password);
+ this.initialConnections = initialConnections;
+ this.maxConnections = maxConnections;
+ }
+
+ private void initializeConnections() throws SQLException {
+ availableConnections = new HashSet<Connection>(initialConnections);
+ reservedConnections = new HashSet<Connection>(initialConnections);
+ for (int i = 0; i < initialConnections; i++) {
+ availableConnections.add(createConnection());
+ }
+ initialized = true;
+ }
+
+ public synchronized Connection reserveConnection() throws SQLException {
+ if (!initialized) {
+ initializeConnections();
+ }
+ if (availableConnections.isEmpty()) {
+ if (reservedConnections.size() < maxConnections) {
+ availableConnections.add(createConnection());
+ } else {
+ throw new SQLException("Connection limit has been reached.");
+ }
+ }
+
+ Connection c = availableConnections.iterator().next();
+ availableConnections.remove(c);
+ reservedConnections.add(c);
+
+ return c;
+ }
+
+ public synchronized void releaseConnection(Connection conn) {
+ if (conn == null || !initialized) {
+ return;
+ }
+ /* Try to roll back if necessary */
+ try {
+ if (!conn.getAutoCommit()) {
+ conn.rollback();
+ }
+ } catch (SQLException e) {
+ /* Roll back failed, close and discard connection */
+ try {
+ conn.close();
+ } catch (SQLException e1) {
+ /* Nothing needs to be done */
+ }
+ reservedConnections.remove(conn);
+ return;
+ }
+ reservedConnections.remove(conn);
+ availableConnections.add(conn);
+ }
+
+ private Connection createConnection() throws SQLException {
+ Connection c = DriverManager.getConnection(connectionUri, userName,
+ password);
+ c.setAutoCommit(false);
+ if (driverName.toLowerCase().contains("mysql")) {
+ try {
+ Statement s = c.createStatement();
+ s.execute("SET SESSION sql_mode = 'ANSI'");
+ s.close();
+ } catch (Exception e) {
+ // Failed to set ansi mode; continue
+ }
+ }
+ return c;
+ }
+
+ public void destroy() {
+ for (Connection c : availableConnections) {
+ try {
+ c.close();
+ } catch (SQLException e) {
+ // No need to do anything
+ }
+ }
+ for (Connection c : reservedConnections) {
+ try {
+ c.close();
+ } catch (SQLException e) {
+ // No need to do anything
+ }
+ }
+
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws IOException {
+ initialized = false;
+ out.defaultWriteObject();
+ }
+
+}
diff --git a/src/com/vaadin/data/util/sqlcontainer/query/FreeformStatementDelegate.java b/src/com/vaadin/data/util/sqlcontainer/query/FreeformStatementDelegate.java
index 2ea151c578..95521c5019 100644
--- a/src/com/vaadin/data/util/sqlcontainer/query/FreeformStatementDelegate.java
+++ b/src/com/vaadin/data/util/sqlcontainer/query/FreeformStatementDelegate.java
@@ -1,57 +1,57 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.util.sqlcontainer.query;
-
-import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper;
-
-/**
- * FreeformStatementDelegate is an extension to FreeformQueryDelegate that
- * provides definitions for methods that produce StatementHelper objects instead
- * of basic query strings. This allows the FreeformQuery query delegate to use
- * PreparedStatements instead of regular Statement when accessing the database.
- *
- * Due to the injection protection and other benefits of prepared statements, it
- * is advisable to implement this interface instead of the FreeformQueryDelegate
- * whenever possible.
- */
-public interface FreeformStatementDelegate extends FreeformQueryDelegate {
- /**
- * Should return a new instance of StatementHelper that contains the query
- * string and parameter values required to create a PreparedStatement. This
- * method is responsible for gluing together the select query from the
- * filters and the order by conditions if these are supported.
- *
- * @param offset
- * the first record (row) to fetch.
- * @param pagelength
- * the number of records (rows) to fetch. 0 means all records
- * starting from offset.
- */
- public StatementHelper getQueryStatement(int offset, int limit)
- throws UnsupportedOperationException;
-
- /**
- * Should return a new instance of StatementHelper that contains the query
- * string and parameter values required to create a PreparedStatement that
- * will fetch the row count from the DB. Row count should be fetched using
- * filters that are currently set to the QueryDelegate.
- */
- public StatementHelper getCountStatement()
- throws UnsupportedOperationException;
-
- /**
- * Should return a new instance of StatementHelper that contains the query
- * string and parameter values required to create a PreparedStatement used
- * by the FreeformQuery.containsRowWithKeys() method. This is useful for
- * cases when the default logic in said method is not enough to support more
- * complex free form queries.
- *
- * @param keys
- * the values of the primary keys
- * @throws UnsupportedOperationException
- * to use the default logic in FreeformQuery
- */
- public StatementHelper getContainsRowQueryStatement(Object... keys)
- throws UnsupportedOperationException;
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.util.sqlcontainer.query;
+
+import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper;
+
+/**
+ * FreeformStatementDelegate is an extension to FreeformQueryDelegate that
+ * provides definitions for methods that produce StatementHelper objects instead
+ * of basic query strings. This allows the FreeformQuery query delegate to use
+ * PreparedStatements instead of regular Statement when accessing the database.
+ *
+ * Due to the injection protection and other benefits of prepared statements, it
+ * is advisable to implement this interface instead of the FreeformQueryDelegate
+ * whenever possible.
+ */
+public interface FreeformStatementDelegate extends FreeformQueryDelegate {
+ /**
+ * Should return a new instance of StatementHelper that contains the query
+ * string and parameter values required to create a PreparedStatement. This
+ * method is responsible for gluing together the select query from the
+ * filters and the order by conditions if these are supported.
+ *
+ * @param offset
+ * the first record (row) to fetch.
+ * @param pagelength
+ * the number of records (rows) to fetch. 0 means all records
+ * starting from offset.
+ */
+ public StatementHelper getQueryStatement(int offset, int limit)
+ throws UnsupportedOperationException;
+
+ /**
+ * Should return a new instance of StatementHelper that contains the query
+ * string and parameter values required to create a PreparedStatement that
+ * will fetch the row count from the DB. Row count should be fetched using
+ * filters that are currently set to the QueryDelegate.
+ */
+ public StatementHelper getCountStatement()
+ throws UnsupportedOperationException;
+
+ /**
+ * Should return a new instance of StatementHelper that contains the query
+ * string and parameter values required to create a PreparedStatement used
+ * by the FreeformQuery.containsRowWithKeys() method. This is useful for
+ * cases when the default logic in said method is not enough to support more
+ * complex free form queries.
+ *
+ * @param keys
+ * the values of the primary keys
+ * @throws UnsupportedOperationException
+ * to use the default logic in FreeformQuery
+ */
+ public StatementHelper getContainsRowQueryStatement(Object... keys)
+ throws UnsupportedOperationException;
+}
diff --git a/src/com/vaadin/data/util/sqlcontainer/query/generator/StatementHelper.java b/src/com/vaadin/data/util/sqlcontainer/query/generator/StatementHelper.java
index 888f1ec501..3fd92e920d 100644
--- a/src/com/vaadin/data/util/sqlcontainer/query/generator/StatementHelper.java
+++ b/src/com/vaadin/data/util/sqlcontainer/query/generator/StatementHelper.java
@@ -1,135 +1,135 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.util.sqlcontainer.query.generator;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.sql.Date;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * StatementHelper is a simple helper class that assists TableQuery and the
- * query generators in filling a PreparedStatement. The actual statement is
- * generated by the query generator methods, but the resulting statement and all
- * the parameter values are stored in an instance of StatementHelper.
- *
- * This class will also fill the values with correct setters into the
- * PreparedStatement on request.
- */
-public class StatementHelper implements Serializable {
-
- private String queryString;
-
- private List<Object> parameters = new ArrayList<Object>();
- private Map<Integer, Class<?>> dataTypes = new HashMap<Integer, Class<?>>();
-
- public StatementHelper() {
- }
-
- public void setQueryString(String queryString) {
- this.queryString = queryString;
- }
-
- public String getQueryString() {
- return queryString;
- }
-
- public void addParameterValue(Object parameter) {
- if (parameter != null) {
- parameters.add(parameter);
- dataTypes.put(parameters.size() - 1, parameter.getClass());
- }
- }
-
- public void addParameterValue(Object parameter, Class<?> type) {
- parameters.add(parameter);
- dataTypes.put(parameters.size() - 1, type);
- }
-
- public void setParameterValuesToStatement(PreparedStatement pstmt)
- throws SQLException {
- for (int i = 0; i < parameters.size(); i++) {
- if (parameters.get(i) == null) {
- handleNullValue(i, pstmt);
- } else {
- pstmt.setObject(i + 1, parameters.get(i));
- }
- }
-
- /*
- * The following list contains the data types supported by
- * PreparedStatement but not supported by SQLContainer:
- *
- * [The list is provided as PreparedStatement method signatures]
- *
- * setNCharacterStream(int parameterIndex, Reader value)
- *
- * setNClob(int parameterIndex, NClob value)
- *
- * setNString(int parameterIndex, String value)
- *
- * setRef(int parameterIndex, Ref x)
- *
- * setRowId(int parameterIndex, RowId x)
- *
- * setSQLXML(int parameterIndex, SQLXML xmlObject)
- *
- * setBytes(int parameterIndex, byte[] x)
- *
- * setCharacterStream(int parameterIndex, Reader reader)
- *
- * setClob(int parameterIndex, Clob x)
- *
- * setURL(int parameterIndex, URL x)
- *
- * setArray(int parameterIndex, Array x)
- *
- * setAsciiStream(int parameterIndex, InputStream x)
- *
- * setBinaryStream(int parameterIndex, InputStream x)
- *
- * setBlob(int parameterIndex, Blob x)
- */
- }
-
- private void handleNullValue(int i, PreparedStatement pstmt)
- throws SQLException {
- if (BigDecimal.class.equals(dataTypes.get(i))) {
- pstmt.setBigDecimal(i + 1, null);
- } else if (Boolean.class.equals(dataTypes.get(i))) {
- pstmt.setNull(i + 1, Types.BOOLEAN);
- } else if (Byte.class.equals(dataTypes.get(i))) {
- pstmt.setNull(i + 1, Types.SMALLINT);
- } else if (Date.class.equals(dataTypes.get(i))) {
- pstmt.setDate(i + 1, null);
- } else if (Double.class.equals(dataTypes.get(i))) {
- pstmt.setNull(i + 1, Types.DOUBLE);
- } else if (Float.class.equals(dataTypes.get(i))) {
- pstmt.setNull(i + 1, Types.FLOAT);
- } else if (Integer.class.equals(dataTypes.get(i))) {
- pstmt.setNull(i + 1, Types.INTEGER);
- } else if (Long.class.equals(dataTypes.get(i))) {
- pstmt.setNull(i + 1, Types.BIGINT);
- } else if (Short.class.equals(dataTypes.get(i))) {
- pstmt.setNull(i + 1, Types.SMALLINT);
- } else if (String.class.equals(dataTypes.get(i))) {
- pstmt.setString(i + 1, null);
- } else if (Time.class.equals(dataTypes.get(i))) {
- pstmt.setTime(i + 1, null);
- } else if (Timestamp.class.equals(dataTypes.get(i))) {
- pstmt.setTimestamp(i + 1, null);
- } else {
- throw new SQLException("Data type not supported by SQLContainer: "
- + parameters.get(i).getClass().toString());
- }
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.util.sqlcontainer.query.generator;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * StatementHelper is a simple helper class that assists TableQuery and the
+ * query generators in filling a PreparedStatement. The actual statement is
+ * generated by the query generator methods, but the resulting statement and all
+ * the parameter values are stored in an instance of StatementHelper.
+ *
+ * This class will also fill the values with correct setters into the
+ * PreparedStatement on request.
+ */
+public class StatementHelper implements Serializable {
+
+ private String queryString;
+
+ private List<Object> parameters = new ArrayList<Object>();
+ private Map<Integer, Class<?>> dataTypes = new HashMap<Integer, Class<?>>();
+
+ public StatementHelper() {
+ }
+
+ public void setQueryString(String queryString) {
+ this.queryString = queryString;
+ }
+
+ public String getQueryString() {
+ return queryString;
+ }
+
+ public void addParameterValue(Object parameter) {
+ if (parameter != null) {
+ parameters.add(parameter);
+ dataTypes.put(parameters.size() - 1, parameter.getClass());
+ }
+ }
+
+ public void addParameterValue(Object parameter, Class<?> type) {
+ parameters.add(parameter);
+ dataTypes.put(parameters.size() - 1, type);
+ }
+
+ public void setParameterValuesToStatement(PreparedStatement pstmt)
+ throws SQLException {
+ for (int i = 0; i < parameters.size(); i++) {
+ if (parameters.get(i) == null) {
+ handleNullValue(i, pstmt);
+ } else {
+ pstmt.setObject(i + 1, parameters.get(i));
+ }
+ }
+
+ /*
+ * The following list contains the data types supported by
+ * PreparedStatement but not supported by SQLContainer:
+ *
+ * [The list is provided as PreparedStatement method signatures]
+ *
+ * setNCharacterStream(int parameterIndex, Reader value)
+ *
+ * setNClob(int parameterIndex, NClob value)
+ *
+ * setNString(int parameterIndex, String value)
+ *
+ * setRef(int parameterIndex, Ref x)
+ *
+ * setRowId(int parameterIndex, RowId x)
+ *
+ * setSQLXML(int parameterIndex, SQLXML xmlObject)
+ *
+ * setBytes(int parameterIndex, byte[] x)
+ *
+ * setCharacterStream(int parameterIndex, Reader reader)
+ *
+ * setClob(int parameterIndex, Clob x)
+ *
+ * setURL(int parameterIndex, URL x)
+ *
+ * setArray(int parameterIndex, Array x)
+ *
+ * setAsciiStream(int parameterIndex, InputStream x)
+ *
+ * setBinaryStream(int parameterIndex, InputStream x)
+ *
+ * setBlob(int parameterIndex, Blob x)
+ */
+ }
+
+ private void handleNullValue(int i, PreparedStatement pstmt)
+ throws SQLException {
+ if (BigDecimal.class.equals(dataTypes.get(i))) {
+ pstmt.setBigDecimal(i + 1, null);
+ } else if (Boolean.class.equals(dataTypes.get(i))) {
+ pstmt.setNull(i + 1, Types.BOOLEAN);
+ } else if (Byte.class.equals(dataTypes.get(i))) {
+ pstmt.setNull(i + 1, Types.SMALLINT);
+ } else if (Date.class.equals(dataTypes.get(i))) {
+ pstmt.setDate(i + 1, null);
+ } else if (Double.class.equals(dataTypes.get(i))) {
+ pstmt.setNull(i + 1, Types.DOUBLE);
+ } else if (Float.class.equals(dataTypes.get(i))) {
+ pstmt.setNull(i + 1, Types.FLOAT);
+ } else if (Integer.class.equals(dataTypes.get(i))) {
+ pstmt.setNull(i + 1, Types.INTEGER);
+ } else if (Long.class.equals(dataTypes.get(i))) {
+ pstmt.setNull(i + 1, Types.BIGINT);
+ } else if (Short.class.equals(dataTypes.get(i))) {
+ pstmt.setNull(i + 1, Types.SMALLINT);
+ } else if (String.class.equals(dataTypes.get(i))) {
+ pstmt.setString(i + 1, null);
+ } else if (Time.class.equals(dataTypes.get(i))) {
+ pstmt.setTime(i + 1, null);
+ } else if (Timestamp.class.equals(dataTypes.get(i))) {
+ pstmt.setTimestamp(i + 1, null);
+ } else {
+ throw new SQLException("Data type not supported by SQLContainer: "
+ + parameters.get(i).getClass().toString());
+ }
+ }
+}
diff --git a/src/com/vaadin/event/FieldEvents.java b/src/com/vaadin/event/FieldEvents.java
index 202abba078..28fd6bb4f7 100644
--- a/src/com/vaadin/event/FieldEvents.java
+++ b/src/com/vaadin/event/FieldEvents.java
@@ -1,250 +1,250 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.event;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-
-import com.vaadin.terminal.gwt.client.EventId;
-import com.vaadin.tools.ReflectTools;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.Field;
-import com.vaadin.ui.Field.ValueChangeEvent;
-import com.vaadin.ui.TextField;
-
-/**
- * Interface that serves as a wrapper for {@link Field} related events.
- */
-public interface FieldEvents {
-
- /**
- * The interface for adding and removing <code>FocusEvent</code> listeners.
- * By implementing this interface a class explicitly announces that it will
- * generate a <code>FocusEvent</code> when it receives keyboard focus.
- * <p>
- * Note: The general Java convention is not to explicitly declare that a
- * class generates events, but to directly define the
- * <code>addListener</code> and <code>removeListener</code> methods. That
- * way the caller of these methods has no real way of finding out if the
- * class really will send the events, or if it just defines the methods to
- * be able to implement an interface.
- * </p>
- *
- * @since 6.2
- * @see FocusListener
- * @see FocusEvent
- */
- public interface FocusNotifier extends Serializable {
- /**
- * Adds a <code>FocusListener</code> to the Component which gets fired
- * when a <code>Field</code> receives keyboard focus.
- *
- * @param listener
- * @see FocusListener
- * @since 6.2
- */
- public void addListener(FocusListener listener);
-
- /**
- * Removes a <code>FocusListener</code> from the Component.
- *
- * @param listener
- * @see FocusListener
- * @since 6.2
- */
- public void removeListener(FocusListener listener);
- }
-
- /**
- * The interface for adding and removing <code>BlurEvent</code> listeners.
- * By implementing this interface a class explicitly announces that it will
- * generate a <code>BlurEvent</code> when it loses keyboard focus.
- * <p>
- * Note: The general Java convention is not to explicitly declare that a
- * class generates events, but to directly define the
- * <code>addListener</code> and <code>removeListener</code> methods. That
- * way the caller of these methods has no real way of finding out if the
- * class really will send the events, or if it just defines the methods to
- * be able to implement an interface.
- * </p>
- *
- * @since 6.2
- * @see BlurListener
- * @see BlurEvent
- */
- public interface BlurNotifier extends Serializable {
- /**
- * Adds a <code>BlurListener</code> to the Component which gets fired
- * when a <code>Field</code> loses keyboard focus.
- *
- * @param listener
- * @see BlurListener
- * @since 6.2
- */
- public void addListener(BlurListener listener);
-
- /**
- * Removes a <code>BlurListener</code> from the Component.
- *
- * @param listener
- * @see BlurListener
- * @since 6.2
- */
- public void removeListener(BlurListener listener);
- }
-
- /**
- * <code>FocusEvent</code> class for holding additional event information.
- * Fired when a <code>Field</code> receives keyboard focus.
- *
- * @since 6.2
- */
- @SuppressWarnings("serial")
- public class FocusEvent extends Component.Event {
-
- /**
- * Identifier for event that can be used in {@link EventRouter}
- */
- public static final String EVENT_ID = EventId.FOCUS;
-
- public FocusEvent(Component source) {
- super(source);
- }
- }
-
- /**
- * <code>FocusListener</code> interface for listening for
- * <code>FocusEvent</code> fired by a <code>Field</code>.
- *
- * @see FocusEvent
- * @since 6.2
- */
- public interface FocusListener extends ComponentEventListener {
-
- public static final Method focusMethod = ReflectTools.findMethod(
- FocusListener.class, "focus", FocusEvent.class);
-
- /**
- * Component has been focused
- *
- * @param event
- * Component focus event.
- */
- public void focus(FocusEvent event);
- }
-
- /**
- * <code>BlurEvent</code> class for holding additional event information.
- * Fired when a <code>Field</code> loses keyboard focus.
- *
- * @since 6.2
- */
- @SuppressWarnings("serial")
- public class BlurEvent extends Component.Event {
-
- /**
- * Identifier for event that can be used in {@link EventRouter}
- */
- public static final String EVENT_ID = EventId.BLUR;
-
- public BlurEvent(Component source) {
- super(source);
- }
- }
-
- /**
- * <code>BlurListener</code> interface for listening for
- * <code>BlurEvent</code> fired by a <code>Field</code>.
- *
- * @see BlurEvent
- * @since 6.2
- */
- public interface BlurListener extends ComponentEventListener {
-
- public static final Method blurMethod = ReflectTools.findMethod(
- BlurListener.class, "blur", BlurEvent.class);
-
- /**
- * Component has been blurred
- *
- * @param event
- * Component blur event.
- */
- public void blur(BlurEvent event);
- }
-
- /**
- * TextChangeEvents are fired when the user is editing the text content of a
- * field. Most commonly text change events are triggered by typing text with
- * keyboard, but e.g. pasting content from clip board to a text field also
- * triggers an event.
- * <p>
- * TextChangeEvents differ from {@link ValueChangeEvent}s so that they are
- * triggered repeatedly while the end user is filling the field.
- * ValueChangeEvents are not fired until the user for example hits enter or
- * focuses another field. Also note the difference that TextChangeEvents are
- * only fired if the change is triggered from the user, while
- * ValueChangeEvents are also fired if the field value is set by the
- * application code.
- * <p>
- * The {@link TextChangeNotifier}s implementation may decide when exactly
- * TextChangeEvents are fired. TextChangeEvents are not necessary fire for
- * example on each key press, but buffered with a small delay. The
- * {@link TextField} component supports different modes for triggering
- * TextChangeEvents.
- *
- * @see TextChangeListener
- * @see TextChangeNotifier
- * @see TextField#setTextChangeEventMode(com.vaadin.ui.TextField.TextChangeEventMode)
- * @since 6.5
- */
- public static abstract class TextChangeEvent extends Component.Event {
- public TextChangeEvent(Component source) {
- super(source);
- }
-
- /**
- * @return the text content of the field after the
- * {@link TextChangeEvent}
- */
- public abstract String getText();
-
- /**
- * @return the cursor position during after the {@link TextChangeEvent}
- */
- public abstract int getCursorPosition();
- }
-
- /**
- * A listener for {@link TextChangeEvent}s.
- *
- * @since 6.5
- */
- public interface TextChangeListener extends ComponentEventListener {
-
- public static String EVENT_ID = "ie";
- public static Method EVENT_METHOD = ReflectTools.findMethod(
- TextChangeListener.class, "textChange", TextChangeEvent.class);
-
- /**
- * This method is called repeatedly while the text is edited by a user.
- *
- * @param event
- * the event providing details of the text change
- */
- public void textChange(TextChangeEvent event);
- }
-
- /**
- * An interface implemented by a {@link Field} supporting
- * {@link TextChangeEvent}s. An example a {@link TextField} supports
- * {@link TextChangeListener}s.
- */
- public interface TextChangeNotifier extends Serializable {
- public void addListener(TextChangeListener listener);
-
- public void removeListener(TextChangeListener listener);
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.event;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+import com.vaadin.terminal.gwt.client.EventId;
+import com.vaadin.tools.ReflectTools;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Field;
+import com.vaadin.ui.Field.ValueChangeEvent;
+import com.vaadin.ui.TextField;
+
+/**
+ * Interface that serves as a wrapper for {@link Field} related events.
+ */
+public interface FieldEvents {
+
+ /**
+ * The interface for adding and removing <code>FocusEvent</code> listeners.
+ * By implementing this interface a class explicitly announces that it will
+ * generate a <code>FocusEvent</code> when it receives keyboard focus.
+ * <p>
+ * Note: The general Java convention is not to explicitly declare that a
+ * class generates events, but to directly define the
+ * <code>addListener</code> and <code>removeListener</code> methods. That
+ * way the caller of these methods has no real way of finding out if the
+ * class really will send the events, or if it just defines the methods to
+ * be able to implement an interface.
+ * </p>
+ *
+ * @since 6.2
+ * @see FocusListener
+ * @see FocusEvent
+ */
+ public interface FocusNotifier extends Serializable {
+ /**
+ * Adds a <code>FocusListener</code> to the Component which gets fired
+ * when a <code>Field</code> receives keyboard focus.
+ *
+ * @param listener
+ * @see FocusListener
+ * @since 6.2
+ */
+ public void addListener(FocusListener listener);
+
+ /**
+ * Removes a <code>FocusListener</code> from the Component.
+ *
+ * @param listener
+ * @see FocusListener
+ * @since 6.2
+ */
+ public void removeListener(FocusListener listener);
+ }
+
+ /**
+ * The interface for adding and removing <code>BlurEvent</code> listeners.
+ * By implementing this interface a class explicitly announces that it will
+ * generate a <code>BlurEvent</code> when it loses keyboard focus.
+ * <p>
+ * Note: The general Java convention is not to explicitly declare that a
+ * class generates events, but to directly define the
+ * <code>addListener</code> and <code>removeListener</code> methods. That
+ * way the caller of these methods has no real way of finding out if the
+ * class really will send the events, or if it just defines the methods to
+ * be able to implement an interface.
+ * </p>
+ *
+ * @since 6.2
+ * @see BlurListener
+ * @see BlurEvent
+ */
+ public interface BlurNotifier extends Serializable {
+ /**
+ * Adds a <code>BlurListener</code> to the Component which gets fired
+ * when a <code>Field</code> loses keyboard focus.
+ *
+ * @param listener
+ * @see BlurListener
+ * @since 6.2
+ */
+ public void addListener(BlurListener listener);
+
+ /**
+ * Removes a <code>BlurListener</code> from the Component.
+ *
+ * @param listener
+ * @see BlurListener
+ * @since 6.2
+ */
+ public void removeListener(BlurListener listener);
+ }
+
+ /**
+ * <code>FocusEvent</code> class for holding additional event information.
+ * Fired when a <code>Field</code> receives keyboard focus.
+ *
+ * @since 6.2
+ */
+ @SuppressWarnings("serial")
+ public class FocusEvent extends Component.Event {
+
+ /**
+ * Identifier for event that can be used in {@link EventRouter}
+ */
+ public static final String EVENT_ID = EventId.FOCUS;
+
+ public FocusEvent(Component source) {
+ super(source);
+ }
+ }
+
+ /**
+ * <code>FocusListener</code> interface for listening for
+ * <code>FocusEvent</code> fired by a <code>Field</code>.
+ *
+ * @see FocusEvent
+ * @since 6.2
+ */
+ public interface FocusListener extends ComponentEventListener {
+
+ public static final Method focusMethod = ReflectTools.findMethod(
+ FocusListener.class, "focus", FocusEvent.class);
+
+ /**
+ * Component has been focused
+ *
+ * @param event
+ * Component focus event.
+ */
+ public void focus(FocusEvent event);
+ }
+
+ /**
+ * <code>BlurEvent</code> class for holding additional event information.
+ * Fired when a <code>Field</code> loses keyboard focus.
+ *
+ * @since 6.2
+ */
+ @SuppressWarnings("serial")
+ public class BlurEvent extends Component.Event {
+
+ /**
+ * Identifier for event that can be used in {@link EventRouter}
+ */
+ public static final String EVENT_ID = EventId.BLUR;
+
+ public BlurEvent(Component source) {
+ super(source);
+ }
+ }
+
+ /**
+ * <code>BlurListener</code> interface for listening for
+ * <code>BlurEvent</code> fired by a <code>Field</code>.
+ *
+ * @see BlurEvent
+ * @since 6.2
+ */
+ public interface BlurListener extends ComponentEventListener {
+
+ public static final Method blurMethod = ReflectTools.findMethod(
+ BlurListener.class, "blur", BlurEvent.class);
+
+ /**
+ * Component has been blurred
+ *
+ * @param event
+ * Component blur event.
+ */
+ public void blur(BlurEvent event);
+ }
+
+ /**
+ * TextChangeEvents are fired when the user is editing the text content of a
+ * field. Most commonly text change events are triggered by typing text with
+ * keyboard, but e.g. pasting content from clip board to a text field also
+ * triggers an event.
+ * <p>
+ * TextChangeEvents differ from {@link ValueChangeEvent}s so that they are
+ * triggered repeatedly while the end user is filling the field.
+ * ValueChangeEvents are not fired until the user for example hits enter or
+ * focuses another field. Also note the difference that TextChangeEvents are
+ * only fired if the change is triggered from the user, while
+ * ValueChangeEvents are also fired if the field value is set by the
+ * application code.
+ * <p>
+ * The {@link TextChangeNotifier}s implementation may decide when exactly
+ * TextChangeEvents are fired. TextChangeEvents are not necessary fire for
+ * example on each key press, but buffered with a small delay. The
+ * {@link TextField} component supports different modes for triggering
+ * TextChangeEvents.
+ *
+ * @see TextChangeListener
+ * @see TextChangeNotifier
+ * @see TextField#setTextChangeEventMode(com.vaadin.ui.TextField.TextChangeEventMode)
+ * @since 6.5
+ */
+ public static abstract class TextChangeEvent extends Component.Event {
+ public TextChangeEvent(Component source) {
+ super(source);
+ }
+
+ /**
+ * @return the text content of the field after the
+ * {@link TextChangeEvent}
+ */
+ public abstract String getText();
+
+ /**
+ * @return the cursor position during after the {@link TextChangeEvent}
+ */
+ public abstract int getCursorPosition();
+ }
+
+ /**
+ * A listener for {@link TextChangeEvent}s.
+ *
+ * @since 6.5
+ */
+ public interface TextChangeListener extends ComponentEventListener {
+
+ public static String EVENT_ID = "ie";
+ public static Method EVENT_METHOD = ReflectTools.findMethod(
+ TextChangeListener.class, "textChange", TextChangeEvent.class);
+
+ /**
+ * This method is called repeatedly while the text is edited by a user.
+ *
+ * @param event
+ * the event providing details of the text change
+ */
+ public void textChange(TextChangeEvent event);
+ }
+
+ /**
+ * An interface implemented by a {@link Field} supporting
+ * {@link TextChangeEvent}s. An example a {@link TextField} supports
+ * {@link TextChangeListener}s.
+ */
+ public interface TextChangeNotifier extends Serializable {
+ public void addListener(TextChangeListener listener);
+
+ public void removeListener(TextChangeListener listener);
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/DateTimeService.java b/src/com/vaadin/terminal/gwt/client/DateTimeService.java
index d368d655af..c0151d2819 100644
--- a/src/com/vaadin/terminal/gwt/client/DateTimeService.java
+++ b/src/com/vaadin/terminal/gwt/client/DateTimeService.java
@@ -1,439 +1,439 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client;
-
-import java.util.Date;
-
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.i18n.client.LocaleInfo;
-import com.vaadin.terminal.gwt.client.ui.VDateField;
-
-/**
- * This class provides date/time parsing services to all components on the
- * client side.
- *
- * @author Vaadin Ltd.
- *
- */
-@SuppressWarnings("deprecation")
-public class DateTimeService {
-
- private String currentLocale;
-
- private static int[] maxDaysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30,
- 31, 30, 31 };
-
- /**
- * Creates a new date time service with the application default locale.
- */
- public DateTimeService() {
- currentLocale = LocaleService.getDefaultLocale();
- }
-
- /**
- * Creates a new date time service with a given locale.
- *
- * @param locale
- * e.g. fi, en etc.
- * @throws LocaleNotLoadedException
- */
- public DateTimeService(String locale) throws LocaleNotLoadedException {
- setLocale(locale);
- }
-
- public void setLocale(String locale) throws LocaleNotLoadedException {
- if (LocaleService.getAvailableLocales().contains(locale)) {
- currentLocale = locale;
- } else {
- throw new LocaleNotLoadedException(locale);
- }
- }
-
- public String getLocale() {
- return currentLocale;
- }
-
- public String getMonth(int month) {
- try {
- return LocaleService.getMonthNames(currentLocale)[month];
- } catch (final LocaleNotLoadedException e) {
- VConsole.error(e);
- return null;
- }
- }
-
- public String getShortMonth(int month) {
- try {
- return LocaleService.getShortMonthNames(currentLocale)[month];
- } catch (final LocaleNotLoadedException e) {
- VConsole.error(e);
- return null;
- }
- }
-
- public String getDay(int day) {
- try {
- return LocaleService.getDayNames(currentLocale)[day];
- } catch (final LocaleNotLoadedException e) {
- VConsole.error(e);
- return null;
- }
- }
-
- public String getShortDay(int day) {
- try {
- return LocaleService.getShortDayNames(currentLocale)[day];
- } catch (final LocaleNotLoadedException e) {
- VConsole.error(e);
- return null;
- }
- }
-
- public int getFirstDayOfWeek() {
- try {
- return LocaleService.getFirstDayOfWeek(currentLocale);
- } catch (final LocaleNotLoadedException e) {
- VConsole.error(e);
- return 0;
- }
- }
-
- public boolean isTwelveHourClock() {
- try {
- return LocaleService.isTwelveHourClock(currentLocale);
- } catch (final LocaleNotLoadedException e) {
- VConsole.error(e);
- return false;
- }
- }
-
- public String getClockDelimeter() {
- try {
- return LocaleService.getClockDelimiter(currentLocale);
- } catch (final LocaleNotLoadedException e) {
- VConsole.error(e);
- return ":";
- }
- }
-
- private static final String[] DEFAULT_AMPM_STRINGS = { "AM", "PM" };
-
- public String[] getAmPmStrings() {
- try {
- return LocaleService.getAmPmStrings(currentLocale);
- } catch (final LocaleNotLoadedException e) {
- // TODO can this practically even happen? Should die instead?
- VConsole.error("Locale not loaded, using fallback : AM/PM");
- VConsole.error(e);
- return DEFAULT_AMPM_STRINGS;
- }
- }
-
- public int getStartWeekDay(Date date) {
- final Date dateForFirstOfThisMonth = new Date(date.getYear(),
- date.getMonth(), 1);
- int firstDay;
- try {
- firstDay = LocaleService.getFirstDayOfWeek(currentLocale);
- } catch (final LocaleNotLoadedException e) {
- VConsole.error("Locale not loaded, using fallback 0");
- VConsole.error(e);
- firstDay = 0;
- }
- int start = dateForFirstOfThisMonth.getDay() - firstDay;
- if (start < 0) {
- start = 6;
- }
- return start;
- }
-
- public static void setMilliseconds(Date date, int ms) {
- date.setTime(date.getTime() / 1000 * 1000 + ms);
- }
-
- public static int getMilliseconds(Date date) {
- if (date == null) {
- return 0;
- }
-
- return (int) (date.getTime() - date.getTime() / 1000 * 1000);
- }
-
- public static int getNumberOfDaysInMonth(Date date) {
- final int month = date.getMonth();
- if (month == 1 && true == isLeapYear(date)) {
- return 29;
- }
- return maxDaysInMonth[month];
- }
-
- public static boolean isLeapYear(Date date) {
- // Instantiate the date for 1st March of that year
- final Date firstMarch = new Date(date.getYear(), 2, 1);
-
- // Go back 1 day
- final long firstMarchTime = firstMarch.getTime();
- final long lastDayTimeFeb = firstMarchTime - (24 * 60 * 60 * 1000); // NUM_MILLISECS_A_DAY
-
- // Instantiate new Date with this time
- final Date febLastDay = new Date(lastDayTimeFeb);
-
- // Check for date in this new instance
- return (29 == febLastDay.getDate()) ? true : false;
- }
-
- public static boolean isSameDay(Date d1, Date d2) {
- return (getDayInt(d1) == getDayInt(d2));
- }
-
- public static boolean isInRange(Date date, Date rangeStart, Date rangeEnd,
- int resolution) {
- Date s;
- Date e;
- if (rangeStart.after(rangeEnd)) {
- s = rangeEnd;
- e = rangeStart;
- } else {
- e = rangeEnd;
- s = rangeStart;
- }
- long start = s.getYear() * 10000000000l;
- long end = e.getYear() * 10000000000l;
- long target = date.getYear() * 10000000000l;
-
- if (resolution == VDateField.RESOLUTION_YEAR) {
- return (start <= target && end >= target);
- }
- start += s.getMonth() * 100000000l;
- end += e.getMonth() * 100000000l;
- target += date.getMonth() * 100000000l;
- if (resolution == VDateField.RESOLUTION_MONTH) {
- return (start <= target && end >= target);
- }
- start += s.getDate() * 1000000l;
- end += e.getDate() * 1000000l;
- target += date.getDate() * 1000000l;
- if (resolution == VDateField.RESOLUTION_DAY) {
- return (start <= target && end >= target);
- }
- start += s.getHours() * 10000l;
- end += e.getHours() * 10000l;
- target += date.getHours() * 10000l;
- if (resolution == VDateField.RESOLUTION_HOUR) {
- return (start <= target && end >= target);
- }
- start += s.getMinutes() * 100l;
- end += e.getMinutes() * 100l;
- target += date.getMinutes() * 100l;
- if (resolution == VDateField.RESOLUTION_MIN) {
- return (start <= target && end >= target);
- }
- start += s.getSeconds();
- end += e.getSeconds();
- target += date.getSeconds();
- return (start <= target && end >= target);
-
- }
-
- private static int getDayInt(Date date) {
- final int y = date.getYear();
- final int m = date.getMonth();
- final int d = date.getDate();
-
- return ((y + 1900) * 10000 + m * 100 + d) * 1000000000;
- }
-
- /**
- * Returns the ISO-8601 week number of the given date.
- *
- * @param date
- * The date for which the week number should be resolved
- * @return The ISO-8601 week number for {@literal date}
- */
- public static int getISOWeekNumber(Date date) {
- final long MILLISECONDS_PER_DAY = 24 * 3600 * 1000;
- int dayOfWeek = date.getDay(); // 0 == sunday
-
- // ISO 8601 use weeks that start on monday so we use
- // mon=1,tue=2,...sun=7;
- if (dayOfWeek == 0) {
- dayOfWeek = 7;
- }
- // Find nearest thursday (defines the week in ISO 8601). The week number
- // for the nearest thursday is the same as for the target date.
- int nearestThursdayDiff = 4 - dayOfWeek; // 4 is thursday
- Date nearestThursday = new Date(date.getTime() + nearestThursdayDiff
- * MILLISECONDS_PER_DAY);
-
- Date firstOfJanuary = new Date(nearestThursday.getYear(), 0, 1);
- long timeDiff = nearestThursday.getTime() - firstOfJanuary.getTime();
- int daysSinceFirstOfJanuary = (int) (timeDiff / MILLISECONDS_PER_DAY);
-
- int weekNumber = (daysSinceFirstOfJanuary) / 7 + 1;
-
- return weekNumber;
- }
-
- /**
- * Check if format contains the month name. If it does we manually convert
- * it to the month name since DateTimeFormat.format always uses the current
- * locale and will replace the month name wrong if current locale is
- * different from the locale set for the DateField.
- *
- * MMMM is converted into long month name, MMM is converted into short month
- * name. '' are added around the name to avoid that DateTimeFormat parses
- * the month name as a pattern.
- *
- * @param date
- * The date to convert
- * @param formatStr
- * The format string that might contain MMM or MMMM
- * @param dateTimeService
- * Reference to the Vaadin DateTimeService
- * @return
- */
- public String formatDate(Date date, String formatStr) {
- /*
- * Format month names separately when locale for the DateTimeService is
- * not the same as the browser locale
- */
- formatStr = formatMonthNames(date, formatStr);
-
- // Format uses the browser locale
- DateTimeFormat format = DateTimeFormat.getFormat(formatStr);
-
- String result = format.format(date);
-
- return result;
- }
-
- private String formatMonthNames(Date date, String formatStr) {
- if (formatStr.contains("MMMM")) {
- String monthName = getMonth(date.getMonth());
-
- if (monthName != null) {
- /*
- * Replace 4 or more M:s with the quoted month name. Also
- * concatenate generated string with any other string prepending
- * or following the MMMM pattern, i.e. 'MMMM'ta ' becomes
- * 'MONTHta ' and not 'MONTH''ta ', 'ab'MMMM becomes 'abMONTH',
- * 'x'MMMM'y' becomes 'xMONTHy'.
- */
- formatStr = formatStr.replaceAll("'([M]{4,})'", monthName);
- formatStr = formatStr.replaceAll("([M]{4,})'", "'" + monthName);
- formatStr = formatStr.replaceAll("'([M]{4,})", monthName + "'");
- formatStr = formatStr.replaceAll("[M]{4,}", "'" + monthName
- + "'");
- }
- }
-
- if (formatStr.contains("MMM")) {
-
- String monthName = getShortMonth(date.getMonth());
-
- if (monthName != null) {
- /*
- * Replace 3 or more M:s with the quoted month name. Also
- * concatenate generated string with any other string prepending
- * or following the MMM pattern, i.e. 'MMM'ta ' becomes 'MONTHta
- * ' and not 'MONTH''ta ', 'ab'MMM becomes 'abMONTH', 'x'MMM'y'
- * becomes 'xMONTHy'.
- */
- formatStr = formatStr.replaceAll("'([M]{3,})'", monthName);
- formatStr = formatStr.replaceAll("([M]{3,})'", "'" + monthName);
- formatStr = formatStr.replaceAll("'([M]{3,})", monthName + "'");
- formatStr = formatStr.replaceAll("[M]{3,}", "'" + monthName
- + "'");
- }
- }
-
- return formatStr;
- }
-
- /**
- * Replaces month names in the entered date with the name in the current
- * browser locale.
- *
- * @param enteredDate
- * Date string e.g. "5 May 2010"
- * @param formatString
- * Format string e.g. "d M yyyy"
- * @return The date string where the month names have been replaced by the
- * browser locale version
- */
- private String parseMonthName(String enteredDate, String formatString) {
- LocaleInfo browserLocale = LocaleInfo.getCurrentLocale();
- if (browserLocale.getLocaleName().equals(getLocale())) {
- // No conversion needs to be done when locales match
- return enteredDate;
- }
- String[] browserMonthNames = browserLocale.getDateTimeConstants()
- .months();
- String[] browserShortMonthNames = browserLocale.getDateTimeConstants()
- .shortMonths();
-
- if (formatString.contains("MMMM")) {
- // Full month name
- for (int i = 0; i < 12; i++) {
- enteredDate = enteredDate.replaceAll(getMonth(i),
- browserMonthNames[i]);
- }
- }
- if (formatString.contains("MMM")) {
- // Short month name
- for (int i = 0; i < 12; i++) {
- enteredDate = enteredDate.replaceAll(getShortMonth(i),
- browserShortMonthNames[i]);
- }
- }
-
- return enteredDate;
- }
-
- /**
- * Parses the given date string using the given format string and the locale
- * set in this DateTimeService instance.
- *
- * @param dateString
- * Date string e.g. "1 February 2010"
- * @param formatString
- * Format string e.g. "d MMMM yyyy"
- * @param lenient
- * true to use lenient parsing, false to use strict parsing
- * @return A Date object representing the dateString. Never returns null.
- * @throws IllegalArgumentException
- * if the parsing fails
- *
- */
- public Date parseDate(String dateString, String formatString,
- boolean lenient) throws IllegalArgumentException {
- /* DateTimeFormat uses the browser's locale */
- DateTimeFormat format = DateTimeFormat.getFormat(formatString);
-
- /*
- * Parse month names separately when locale for the DateTimeService is
- * not the same as the browser locale
- */
- dateString = parseMonthName(dateString, formatString);
-
- Date date;
-
- if (lenient) {
- date = format.parse(dateString);
- } else {
- date = format.parseStrict(dateString);
- }
-
- // Some version of Firefox sets the timestamp to 0 if parsing fails.
- if (date != null && date.getTime() == 0) {
- throw new IllegalArgumentException("Parsing of '" + dateString
- + "' failed");
- }
-
- return date;
-
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client;
+
+import java.util.Date;
+
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.i18n.client.LocaleInfo;
+import com.vaadin.terminal.gwt.client.ui.VDateField;
+
+/**
+ * This class provides date/time parsing services to all components on the
+ * client side.
+ *
+ * @author Vaadin Ltd.
+ *
+ */
+@SuppressWarnings("deprecation")
+public class DateTimeService {
+
+ private String currentLocale;
+
+ private static int[] maxDaysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30,
+ 31, 30, 31 };
+
+ /**
+ * Creates a new date time service with the application default locale.
+ */
+ public DateTimeService() {
+ currentLocale = LocaleService.getDefaultLocale();
+ }
+
+ /**
+ * Creates a new date time service with a given locale.
+ *
+ * @param locale
+ * e.g. fi, en etc.
+ * @throws LocaleNotLoadedException
+ */
+ public DateTimeService(String locale) throws LocaleNotLoadedException {
+ setLocale(locale);
+ }
+
+ public void setLocale(String locale) throws LocaleNotLoadedException {
+ if (LocaleService.getAvailableLocales().contains(locale)) {
+ currentLocale = locale;
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+ }
+
+ public String getLocale() {
+ return currentLocale;
+ }
+
+ public String getMonth(int month) {
+ try {
+ return LocaleService.getMonthNames(currentLocale)[month];
+ } catch (final LocaleNotLoadedException e) {
+ VConsole.error(e);
+ return null;
+ }
+ }
+
+ public String getShortMonth(int month) {
+ try {
+ return LocaleService.getShortMonthNames(currentLocale)[month];
+ } catch (final LocaleNotLoadedException e) {
+ VConsole.error(e);
+ return null;
+ }
+ }
+
+ public String getDay(int day) {
+ try {
+ return LocaleService.getDayNames(currentLocale)[day];
+ } catch (final LocaleNotLoadedException e) {
+ VConsole.error(e);
+ return null;
+ }
+ }
+
+ public String getShortDay(int day) {
+ try {
+ return LocaleService.getShortDayNames(currentLocale)[day];
+ } catch (final LocaleNotLoadedException e) {
+ VConsole.error(e);
+ return null;
+ }
+ }
+
+ public int getFirstDayOfWeek() {
+ try {
+ return LocaleService.getFirstDayOfWeek(currentLocale);
+ } catch (final LocaleNotLoadedException e) {
+ VConsole.error(e);
+ return 0;
+ }
+ }
+
+ public boolean isTwelveHourClock() {
+ try {
+ return LocaleService.isTwelveHourClock(currentLocale);
+ } catch (final LocaleNotLoadedException e) {
+ VConsole.error(e);
+ return false;
+ }
+ }
+
+ public String getClockDelimeter() {
+ try {
+ return LocaleService.getClockDelimiter(currentLocale);
+ } catch (final LocaleNotLoadedException e) {
+ VConsole.error(e);
+ return ":";
+ }
+ }
+
+ private static final String[] DEFAULT_AMPM_STRINGS = { "AM", "PM" };
+
+ public String[] getAmPmStrings() {
+ try {
+ return LocaleService.getAmPmStrings(currentLocale);
+ } catch (final LocaleNotLoadedException e) {
+ // TODO can this practically even happen? Should die instead?
+ VConsole.error("Locale not loaded, using fallback : AM/PM");
+ VConsole.error(e);
+ return DEFAULT_AMPM_STRINGS;
+ }
+ }
+
+ public int getStartWeekDay(Date date) {
+ final Date dateForFirstOfThisMonth = new Date(date.getYear(),
+ date.getMonth(), 1);
+ int firstDay;
+ try {
+ firstDay = LocaleService.getFirstDayOfWeek(currentLocale);
+ } catch (final LocaleNotLoadedException e) {
+ VConsole.error("Locale not loaded, using fallback 0");
+ VConsole.error(e);
+ firstDay = 0;
+ }
+ int start = dateForFirstOfThisMonth.getDay() - firstDay;
+ if (start < 0) {
+ start = 6;
+ }
+ return start;
+ }
+
+ public static void setMilliseconds(Date date, int ms) {
+ date.setTime(date.getTime() / 1000 * 1000 + ms);
+ }
+
+ public static int getMilliseconds(Date date) {
+ if (date == null) {
+ return 0;
+ }
+
+ return (int) (date.getTime() - date.getTime() / 1000 * 1000);
+ }
+
+ public static int getNumberOfDaysInMonth(Date date) {
+ final int month = date.getMonth();
+ if (month == 1 && true == isLeapYear(date)) {
+ return 29;
+ }
+ return maxDaysInMonth[month];
+ }
+
+ public static boolean isLeapYear(Date date) {
+ // Instantiate the date for 1st March of that year
+ final Date firstMarch = new Date(date.getYear(), 2, 1);
+
+ // Go back 1 day
+ final long firstMarchTime = firstMarch.getTime();
+ final long lastDayTimeFeb = firstMarchTime - (24 * 60 * 60 * 1000); // NUM_MILLISECS_A_DAY
+
+ // Instantiate new Date with this time
+ final Date febLastDay = new Date(lastDayTimeFeb);
+
+ // Check for date in this new instance
+ return (29 == febLastDay.getDate()) ? true : false;
+ }
+
+ public static boolean isSameDay(Date d1, Date d2) {
+ return (getDayInt(d1) == getDayInt(d2));
+ }
+
+ public static boolean isInRange(Date date, Date rangeStart, Date rangeEnd,
+ int resolution) {
+ Date s;
+ Date e;
+ if (rangeStart.after(rangeEnd)) {
+ s = rangeEnd;
+ e = rangeStart;
+ } else {
+ e = rangeEnd;
+ s = rangeStart;
+ }
+ long start = s.getYear() * 10000000000l;
+ long end = e.getYear() * 10000000000l;
+ long target = date.getYear() * 10000000000l;
+
+ if (resolution == VDateField.RESOLUTION_YEAR) {
+ return (start <= target && end >= target);
+ }
+ start += s.getMonth() * 100000000l;
+ end += e.getMonth() * 100000000l;
+ target += date.getMonth() * 100000000l;
+ if (resolution == VDateField.RESOLUTION_MONTH) {
+ return (start <= target && end >= target);
+ }
+ start += s.getDate() * 1000000l;
+ end += e.getDate() * 1000000l;
+ target += date.getDate() * 1000000l;
+ if (resolution == VDateField.RESOLUTION_DAY) {
+ return (start <= target && end >= target);
+ }
+ start += s.getHours() * 10000l;
+ end += e.getHours() * 10000l;
+ target += date.getHours() * 10000l;
+ if (resolution == VDateField.RESOLUTION_HOUR) {
+ return (start <= target && end >= target);
+ }
+ start += s.getMinutes() * 100l;
+ end += e.getMinutes() * 100l;
+ target += date.getMinutes() * 100l;
+ if (resolution == VDateField.RESOLUTION_MIN) {
+ return (start <= target && end >= target);
+ }
+ start += s.getSeconds();
+ end += e.getSeconds();
+ target += date.getSeconds();
+ return (start <= target && end >= target);
+
+ }
+
+ private static int getDayInt(Date date) {
+ final int y = date.getYear();
+ final int m = date.getMonth();
+ final int d = date.getDate();
+
+ return ((y + 1900) * 10000 + m * 100 + d) * 1000000000;
+ }
+
+ /**
+ * Returns the ISO-8601 week number of the given date.
+ *
+ * @param date
+ * The date for which the week number should be resolved
+ * @return The ISO-8601 week number for {@literal date}
+ */
+ public static int getISOWeekNumber(Date date) {
+ final long MILLISECONDS_PER_DAY = 24 * 3600 * 1000;
+ int dayOfWeek = date.getDay(); // 0 == sunday
+
+ // ISO 8601 use weeks that start on monday so we use
+ // mon=1,tue=2,...sun=7;
+ if (dayOfWeek == 0) {
+ dayOfWeek = 7;
+ }
+ // Find nearest thursday (defines the week in ISO 8601). The week number
+ // for the nearest thursday is the same as for the target date.
+ int nearestThursdayDiff = 4 - dayOfWeek; // 4 is thursday
+ Date nearestThursday = new Date(date.getTime() + nearestThursdayDiff
+ * MILLISECONDS_PER_DAY);
+
+ Date firstOfJanuary = new Date(nearestThursday.getYear(), 0, 1);
+ long timeDiff = nearestThursday.getTime() - firstOfJanuary.getTime();
+ int daysSinceFirstOfJanuary = (int) (timeDiff / MILLISECONDS_PER_DAY);
+
+ int weekNumber = (daysSinceFirstOfJanuary) / 7 + 1;
+
+ return weekNumber;
+ }
+
+ /**
+ * Check if format contains the month name. If it does we manually convert
+ * it to the month name since DateTimeFormat.format always uses the current
+ * locale and will replace the month name wrong if current locale is
+ * different from the locale set for the DateField.
+ *
+ * MMMM is converted into long month name, MMM is converted into short month
+ * name. '' are added around the name to avoid that DateTimeFormat parses
+ * the month name as a pattern.
+ *
+ * @param date
+ * The date to convert
+ * @param formatStr
+ * The format string that might contain MMM or MMMM
+ * @param dateTimeService
+ * Reference to the Vaadin DateTimeService
+ * @return
+ */
+ public String formatDate(Date date, String formatStr) {
+ /*
+ * Format month names separately when locale for the DateTimeService is
+ * not the same as the browser locale
+ */
+ formatStr = formatMonthNames(date, formatStr);
+
+ // Format uses the browser locale
+ DateTimeFormat format = DateTimeFormat.getFormat(formatStr);
+
+ String result = format.format(date);
+
+ return result;
+ }
+
+ private String formatMonthNames(Date date, String formatStr) {
+ if (formatStr.contains("MMMM")) {
+ String monthName = getMonth(date.getMonth());
+
+ if (monthName != null) {
+ /*
+ * Replace 4 or more M:s with the quoted month name. Also
+ * concatenate generated string with any other string prepending
+ * or following the MMMM pattern, i.e. 'MMMM'ta ' becomes
+ * 'MONTHta ' and not 'MONTH''ta ', 'ab'MMMM becomes 'abMONTH',
+ * 'x'MMMM'y' becomes 'xMONTHy'.
+ */
+ formatStr = formatStr.replaceAll("'([M]{4,})'", monthName);
+ formatStr = formatStr.replaceAll("([M]{4,})'", "'" + monthName);
+ formatStr = formatStr.replaceAll("'([M]{4,})", monthName + "'");
+ formatStr = formatStr.replaceAll("[M]{4,}", "'" + monthName
+ + "'");
+ }
+ }
+
+ if (formatStr.contains("MMM")) {
+
+ String monthName = getShortMonth(date.getMonth());
+
+ if (monthName != null) {
+ /*
+ * Replace 3 or more M:s with the quoted month name. Also
+ * concatenate generated string with any other string prepending
+ * or following the MMM pattern, i.e. 'MMM'ta ' becomes 'MONTHta
+ * ' and not 'MONTH''ta ', 'ab'MMM becomes 'abMONTH', 'x'MMM'y'
+ * becomes 'xMONTHy'.
+ */
+ formatStr = formatStr.replaceAll("'([M]{3,})'", monthName);
+ formatStr = formatStr.replaceAll("([M]{3,})'", "'" + monthName);
+ formatStr = formatStr.replaceAll("'([M]{3,})", monthName + "'");
+ formatStr = formatStr.replaceAll("[M]{3,}", "'" + monthName
+ + "'");
+ }
+ }
+
+ return formatStr;
+ }
+
+ /**
+ * Replaces month names in the entered date with the name in the current
+ * browser locale.
+ *
+ * @param enteredDate
+ * Date string e.g. "5 May 2010"
+ * @param formatString
+ * Format string e.g. "d M yyyy"
+ * @return The date string where the month names have been replaced by the
+ * browser locale version
+ */
+ private String parseMonthName(String enteredDate, String formatString) {
+ LocaleInfo browserLocale = LocaleInfo.getCurrentLocale();
+ if (browserLocale.getLocaleName().equals(getLocale())) {
+ // No conversion needs to be done when locales match
+ return enteredDate;
+ }
+ String[] browserMonthNames = browserLocale.getDateTimeConstants()
+ .months();
+ String[] browserShortMonthNames = browserLocale.getDateTimeConstants()
+ .shortMonths();
+
+ if (formatString.contains("MMMM")) {
+ // Full month name
+ for (int i = 0; i < 12; i++) {
+ enteredDate = enteredDate.replaceAll(getMonth(i),
+ browserMonthNames[i]);
+ }
+ }
+ if (formatString.contains("MMM")) {
+ // Short month name
+ for (int i = 0; i < 12; i++) {
+ enteredDate = enteredDate.replaceAll(getShortMonth(i),
+ browserShortMonthNames[i]);
+ }
+ }
+
+ return enteredDate;
+ }
+
+ /**
+ * Parses the given date string using the given format string and the locale
+ * set in this DateTimeService instance.
+ *
+ * @param dateString
+ * Date string e.g. "1 February 2010"
+ * @param formatString
+ * Format string e.g. "d MMMM yyyy"
+ * @param lenient
+ * true to use lenient parsing, false to use strict parsing
+ * @return A Date object representing the dateString. Never returns null.
+ * @throws IllegalArgumentException
+ * if the parsing fails
+ *
+ */
+ public Date parseDate(String dateString, String formatString,
+ boolean lenient) throws IllegalArgumentException {
+ /* DateTimeFormat uses the browser's locale */
+ DateTimeFormat format = DateTimeFormat.getFormat(formatString);
+
+ /*
+ * Parse month names separately when locale for the DateTimeService is
+ * not the same as the browser locale
+ */
+ dateString = parseMonthName(dateString, formatString);
+
+ Date date;
+
+ if (lenient) {
+ date = format.parse(dateString);
+ } else {
+ date = format.parseStrict(dateString);
+ }
+
+ // Some version of Firefox sets the timestamp to 0 if parsing fails.
+ if (date != null && date.getTime() == 0) {
+ throw new IllegalArgumentException("Parsing of '" + dateString
+ + "' failed");
+ }
+
+ return date;
+
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/LocaleNotLoadedException.java b/src/com/vaadin/terminal/gwt/client/LocaleNotLoadedException.java
index 4d0a9faf97..871495c79e 100644
--- a/src/com/vaadin/terminal/gwt/client/LocaleNotLoadedException.java
+++ b/src/com/vaadin/terminal/gwt/client/LocaleNotLoadedException.java
@@ -1,13 +1,13 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client;
-
-@SuppressWarnings("serial")
-public class LocaleNotLoadedException extends Exception {
-
- public LocaleNotLoadedException(String locale) {
- super(locale);
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client;
+
+@SuppressWarnings("serial")
+public class LocaleNotLoadedException extends Exception {
+
+ public LocaleNotLoadedException(String locale) {
+ super(locale);
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/LocaleService.java b/src/com/vaadin/terminal/gwt/client/LocaleService.java
index 9ae1b04118..0f22ae705b 100644
--- a/src/com/vaadin/terminal/gwt/client/LocaleService.java
+++ b/src/com/vaadin/terminal/gwt/client/LocaleService.java
@@ -1,148 +1,148 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import com.google.gwt.core.client.JsArray;
-
-/**
- * Date / time etc. localisation service for all widgets. Caches all loaded
- * locales as JSONObjects.
- *
- * @author Vaadin Ltd.
- *
- */
-public class LocaleService {
-
- private static Map<String, ValueMap> cache = new HashMap<String, ValueMap>();
- private static String defaultLocale;
-
- public static void addLocale(ValueMap valueMap) {
-
- final String key = valueMap.getString("name");
- if (cache.containsKey(key)) {
- cache.remove(key);
- }
- cache.put(key, valueMap);
- if (cache.size() == 1) {
- setDefaultLocale(key);
- }
- }
-
- public static void setDefaultLocale(String locale) {
- defaultLocale = locale;
- }
-
- public static String getDefaultLocale() {
- return defaultLocale;
- }
-
- public static Set<String> getAvailableLocales() {
- return cache.keySet();
- }
-
- public static String[] getMonthNames(String locale)
- throws LocaleNotLoadedException {
- if (cache.containsKey(locale)) {
- final ValueMap l = cache.get(locale);
- return l.getStringArray("mn");
- } else {
- throw new LocaleNotLoadedException(locale);
- }
- }
-
- public static String[] getShortMonthNames(String locale)
- throws LocaleNotLoadedException {
- if (cache.containsKey(locale)) {
- final ValueMap l = cache.get(locale);
- return l.getStringArray("smn");
- } else {
- throw new LocaleNotLoadedException(locale);
- }
- }
-
- public static String[] getDayNames(String locale)
- throws LocaleNotLoadedException {
- if (cache.containsKey(locale)) {
- final ValueMap l = cache.get(locale);
- return l.getStringArray("dn");
- } else {
- throw new LocaleNotLoadedException(locale);
- }
- }
-
- public static String[] getShortDayNames(String locale)
- throws LocaleNotLoadedException {
- if (cache.containsKey(locale)) {
- final ValueMap l = cache.get(locale);
- return l.getStringArray("sdn");
- } else {
- throw new LocaleNotLoadedException(locale);
- }
- }
-
- public static int getFirstDayOfWeek(String locale)
- throws LocaleNotLoadedException {
- if (cache.containsKey(locale)) {
- final ValueMap l = cache.get(locale);
- return l.getInt("fdow");
- } else {
- throw new LocaleNotLoadedException(locale);
- }
- }
-
- public static String getDateFormat(String locale)
- throws LocaleNotLoadedException {
- if (cache.containsKey(locale)) {
- final ValueMap l = cache.get(locale);
- return l.getString("df");
- } else {
- throw new LocaleNotLoadedException(locale);
- }
- }
-
- public static boolean isTwelveHourClock(String locale)
- throws LocaleNotLoadedException {
- if (cache.containsKey(locale)) {
- final ValueMap l = cache.get(locale);
- return l.getBoolean("thc");
- } else {
- throw new LocaleNotLoadedException(locale);
- }
- }
-
- public static String getClockDelimiter(String locale)
- throws LocaleNotLoadedException {
- if (cache.containsKey(locale)) {
- final ValueMap l = cache.get(locale);
- return l.getString("hmd");
- } else {
- throw new LocaleNotLoadedException(locale);
- }
- }
-
- public static String[] getAmPmStrings(String locale)
- throws LocaleNotLoadedException {
- if (cache.containsKey(locale)) {
- final ValueMap l = cache.get(locale);
- return l.getStringArray("ampm");
- } else {
- throw new LocaleNotLoadedException(locale);
- }
-
- }
-
- public static void addLocales(JsArray<ValueMap> valueMapArray) {
- for (int i = 0; i < valueMapArray.length(); i++) {
- addLocale(valueMapArray.get(i));
-
- }
-
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.gwt.core.client.JsArray;
+
+/**
+ * Date / time etc. localisation service for all widgets. Caches all loaded
+ * locales as JSONObjects.
+ *
+ * @author Vaadin Ltd.
+ *
+ */
+public class LocaleService {
+
+ private static Map<String, ValueMap> cache = new HashMap<String, ValueMap>();
+ private static String defaultLocale;
+
+ public static void addLocale(ValueMap valueMap) {
+
+ final String key = valueMap.getString("name");
+ if (cache.containsKey(key)) {
+ cache.remove(key);
+ }
+ cache.put(key, valueMap);
+ if (cache.size() == 1) {
+ setDefaultLocale(key);
+ }
+ }
+
+ public static void setDefaultLocale(String locale) {
+ defaultLocale = locale;
+ }
+
+ public static String getDefaultLocale() {
+ return defaultLocale;
+ }
+
+ public static Set<String> getAvailableLocales() {
+ return cache.keySet();
+ }
+
+ public static String[] getMonthNames(String locale)
+ throws LocaleNotLoadedException {
+ if (cache.containsKey(locale)) {
+ final ValueMap l = cache.get(locale);
+ return l.getStringArray("mn");
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+ }
+
+ public static String[] getShortMonthNames(String locale)
+ throws LocaleNotLoadedException {
+ if (cache.containsKey(locale)) {
+ final ValueMap l = cache.get(locale);
+ return l.getStringArray("smn");
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+ }
+
+ public static String[] getDayNames(String locale)
+ throws LocaleNotLoadedException {
+ if (cache.containsKey(locale)) {
+ final ValueMap l = cache.get(locale);
+ return l.getStringArray("dn");
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+ }
+
+ public static String[] getShortDayNames(String locale)
+ throws LocaleNotLoadedException {
+ if (cache.containsKey(locale)) {
+ final ValueMap l = cache.get(locale);
+ return l.getStringArray("sdn");
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+ }
+
+ public static int getFirstDayOfWeek(String locale)
+ throws LocaleNotLoadedException {
+ if (cache.containsKey(locale)) {
+ final ValueMap l = cache.get(locale);
+ return l.getInt("fdow");
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+ }
+
+ public static String getDateFormat(String locale)
+ throws LocaleNotLoadedException {
+ if (cache.containsKey(locale)) {
+ final ValueMap l = cache.get(locale);
+ return l.getString("df");
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+ }
+
+ public static boolean isTwelveHourClock(String locale)
+ throws LocaleNotLoadedException {
+ if (cache.containsKey(locale)) {
+ final ValueMap l = cache.get(locale);
+ return l.getBoolean("thc");
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+ }
+
+ public static String getClockDelimiter(String locale)
+ throws LocaleNotLoadedException {
+ if (cache.containsKey(locale)) {
+ final ValueMap l = cache.get(locale);
+ return l.getString("hmd");
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+ }
+
+ public static String[] getAmPmStrings(String locale)
+ throws LocaleNotLoadedException {
+ if (cache.containsKey(locale)) {
+ final ValueMap l = cache.get(locale);
+ return l.getStringArray("ampm");
+ } else {
+ throw new LocaleNotLoadedException(locale);
+ }
+
+ }
+
+ public static void addLocales(JsArray<ValueMap> valueMapArray) {
+ for (int i = 0; i < valueMapArray.length(); i++) {
+ addLocale(valueMapArray.get(i));
+
+ }
+
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java
index e1189ccb14..aaef981bab 100644
--- a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java
+++ b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java
@@ -1,305 +1,305 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client;
-
-import java.io.Serializable;
-
-import com.vaadin.terminal.gwt.server.WebBrowser;
-
-/**
- * Class that parses the user agent string from the browser and provides
- * information about the browser. Used internally by {@link BrowserInfo} and
- * {@link WebBrowser}. Should not be used directly.
- *
- * @author Vaadin Ltd.
- * @version @VERSION@
- * @since 6.3
- */
-public class VBrowserDetails implements Serializable {
-
- private boolean isGecko = false;
- private boolean isWebKit = false;
- private boolean isPresto = false;
-
- private boolean isSafari = false;
- private boolean isChrome = false;
- private boolean isFirefox = false;
- private boolean isOpera = false;
- private boolean isIE = false;
-
- private boolean isWindows = false;
- private boolean isMacOSX = false;
- private boolean isLinux = false;
-
- private float browserEngineVersion = -1;
- private int browserMajorVersion = -1;
- private int browserMinorVersion = -1;
-
- /**
- * Create an instance based on the given user agent.
- *
- * @param userAgent
- * User agent as provided by the browser.
- */
- public VBrowserDetails(String userAgent) {
- userAgent = userAgent.toLowerCase();
-
- // browser engine name
- isGecko = userAgent.indexOf("gecko") != -1
- && userAgent.indexOf("webkit") == -1;
- isWebKit = userAgent.indexOf("applewebkit") != -1;
- isPresto = userAgent.indexOf(" presto/") != -1;
-
- // browser name
- isChrome = userAgent.indexOf(" chrome/") != -1;
- isSafari = !isChrome && userAgent.indexOf("safari") != -1;
- isOpera = userAgent.indexOf("opera") != -1;
- isIE = userAgent.indexOf("msie") != -1 && !isOpera
- && (userAgent.indexOf("webtv") == -1);
- isFirefox = userAgent.indexOf(" firefox/") != -1;
-
- // Rendering engine version
- try {
- if (isGecko) {
- int rvPos = userAgent.indexOf("rv:");
- if (rvPos >= 0) {
- String tmp = userAgent.substring(rvPos + 3);
- tmp = tmp.replaceFirst("(\\.[0-9]+).+", "$1");
- browserEngineVersion = Float.parseFloat(tmp);
- }
- } else if (isWebKit) {
- String tmp = userAgent
- .substring(userAgent.indexOf("webkit/") + 7);
- tmp = tmp.replaceFirst("([0-9]+)[^0-9].+", "$1");
- browserEngineVersion = Float.parseFloat(tmp);
- }
- } catch (Exception e) {
- // Browser engine version parsing failed
- System.err.println("Browser engine version parsing failed for: "
- + userAgent);
- }
-
- // Browser version
- try {
- if (isIE) {
- String ieVersionString = userAgent.substring(userAgent
- .indexOf("msie ") + 5);
- ieVersionString = safeSubstring(ieVersionString, 0,
- ieVersionString.indexOf(";"));
- parseVersionString(ieVersionString);
- } else if (isFirefox) {
- int i = userAgent.indexOf(" firefox/") + 9;
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- } else if (isChrome) {
- int i = userAgent.indexOf(" chrome/") + 8;
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- } else if (isSafari) {
- int i = userAgent.indexOf(" version/") + 9;
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- } else if (isOpera) {
- int i = userAgent.indexOf(" version/");
- if (i != -1) {
- // Version present in Opera 10 and newer
- i += 9; // " version/".length
- } else {
- i = userAgent.indexOf("opera/") + 6;
- }
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- }
- } catch (Exception e) {
- // Browser version parsing failed
- System.err.println("Browser version parsing failed for: "
- + userAgent);
- }
-
- // Operating system
- if (userAgent.contains("windows ")) {
- isWindows = true;
- } else if (userAgent.contains("linux")) {
- isLinux = true;
- } else if (userAgent.contains("macintosh")
- || userAgent.contains("mac osx")
- || userAgent.contains("mac os x")) {
- isMacOSX = true;
- }
- }
-
- private void parseVersionString(String versionString) {
- int idx = versionString.indexOf('.');
- if (idx < 0) {
- idx = versionString.length();
- }
- browserMajorVersion = Integer.parseInt(safeSubstring(versionString, 0,
- idx));
-
- int idx2 = versionString.indexOf('.', idx + 1);
- if (idx2 < 0) {
- idx2 = versionString.length();
- }
- try {
- browserMinorVersion = Integer.parseInt(safeSubstring(versionString,
- idx + 1, idx2).replaceAll("[^0-9].*", ""));
- } catch (NumberFormatException e) {
- // leave the minor version unmodified (-1 = unknown)
- }
- }
-
- private String safeSubstring(String string, int beginIndex, int endIndex) {
- if (beginIndex < 0) {
- beginIndex = 0;
- }
- if (endIndex < 0 || endIndex > string.length()) {
- endIndex = string.length();
- }
- return string.substring(beginIndex, endIndex);
- }
-
- /**
- * Tests if the browser is Firefox.
- *
- * @return true if it is Firefox, false otherwise
- */
- public boolean isFirefox() {
- return isFirefox;
- }
-
- /**
- * Tests if the browser is using the Gecko engine
- *
- * @return true if it is Gecko, false otherwise
- */
- public boolean isGecko() {
- return isGecko;
- }
-
- /**
- * Tests if the browser is using the WebKit engine
- *
- * @return true if it is WebKit, false otherwise
- */
- public boolean isWebKit() {
- return isWebKit;
- }
-
- /**
- * Tests if the browser is using the Presto engine
- *
- * @return true if it is Presto, false otherwise
- */
- public boolean isPresto() {
- return isPresto;
- }
-
- /**
- * Tests if the browser is Safari.
- *
- * @return true if it is Safari, false otherwise
- */
- public boolean isSafari() {
- return isSafari;
- }
-
- /**
- * Tests if the browser is Chrome.
- *
- * @return true if it is Chrome, false otherwise
- */
- public boolean isChrome() {
- return isChrome;
- }
-
- /**
- * Tests if the browser is Opera.
- *
- * @return true if it is Opera, false otherwise
- */
- public boolean isOpera() {
- return isOpera;
- }
-
- /**
- * Tests if the browser is Internet Explorer.
- *
- * @return true if it is Internet Explorer, false otherwise
- */
- public boolean isIE() {
- return isIE;
- }
-
- /**
- * Returns the version of the browser engine. For WebKit this is an integer
- * e.g., 532.0. For gecko it is a float e.g., 1.8 or 1.9.
- *
- * @return The version of the browser engine
- */
- public float getBrowserEngineVersion() {
- return browserEngineVersion;
- }
-
- /**
- * Returns the browser major version e.g., 3 for Firefox 3.5, 4 for Chrome
- * 4, 8 for Internet Explorer 8.
- * <p>
- * Note that Internet Explorer 8 and newer will return the document mode so
- * IE8 rendering as IE7 will return 7.
- * </p>
- *
- * @return The major version of the browser.
- */
- public final int getBrowserMajorVersion() {
- return browserMajorVersion;
- }
-
- /**
- * Returns the browser minor version e.g., 5 for Firefox 3.5.
- *
- * @see #getBrowserMajorVersion()
- *
- * @return The minor version of the browser, or -1 if not known/parsed.
- */
- public final int getBrowserMinorVersion() {
- return browserMinorVersion;
- }
-
- /**
- * Sets the version for IE based on the documentMode. This is used to return
- * the correct the correct IE version when the version from the user agent
- * string and the value of the documentMode property do not match.
- *
- * @param documentMode
- * The current document mode
- */
- public void setIEMode(int documentMode) {
- browserMajorVersion = documentMode;
- browserMinorVersion = 0;
- }
-
- /**
- * Tests if the browser is run on Windows.
- *
- * @return true if run on Windows, false otherwise
- */
- public boolean isWindows() {
- return isWindows;
- }
-
- /**
- * Tests if the browser is run on Mac OSX.
- *
- * @return true if run on Mac OSX, false otherwise
- */
- public boolean isMacOSX() {
- return isMacOSX;
- }
-
- /**
- * Tests if the browser is run on Linux.
- *
- * @return true if run on Linux, false otherwise
- */
- public boolean isLinux() {
- return isLinux;
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client;
+
+import java.io.Serializable;
+
+import com.vaadin.terminal.gwt.server.WebBrowser;
+
+/**
+ * Class that parses the user agent string from the browser and provides
+ * information about the browser. Used internally by {@link BrowserInfo} and
+ * {@link WebBrowser}. Should not be used directly.
+ *
+ * @author Vaadin Ltd.
+ * @version @VERSION@
+ * @since 6.3
+ */
+public class VBrowserDetails implements Serializable {
+
+ private boolean isGecko = false;
+ private boolean isWebKit = false;
+ private boolean isPresto = false;
+
+ private boolean isSafari = false;
+ private boolean isChrome = false;
+ private boolean isFirefox = false;
+ private boolean isOpera = false;
+ private boolean isIE = false;
+
+ private boolean isWindows = false;
+ private boolean isMacOSX = false;
+ private boolean isLinux = false;
+
+ private float browserEngineVersion = -1;
+ private int browserMajorVersion = -1;
+ private int browserMinorVersion = -1;
+
+ /**
+ * Create an instance based on the given user agent.
+ *
+ * @param userAgent
+ * User agent as provided by the browser.
+ */
+ public VBrowserDetails(String userAgent) {
+ userAgent = userAgent.toLowerCase();
+
+ // browser engine name
+ isGecko = userAgent.indexOf("gecko") != -1
+ && userAgent.indexOf("webkit") == -1;
+ isWebKit = userAgent.indexOf("applewebkit") != -1;
+ isPresto = userAgent.indexOf(" presto/") != -1;
+
+ // browser name
+ isChrome = userAgent.indexOf(" chrome/") != -1;
+ isSafari = !isChrome && userAgent.indexOf("safari") != -1;
+ isOpera = userAgent.indexOf("opera") != -1;
+ isIE = userAgent.indexOf("msie") != -1 && !isOpera
+ && (userAgent.indexOf("webtv") == -1);
+ isFirefox = userAgent.indexOf(" firefox/") != -1;
+
+ // Rendering engine version
+ try {
+ if (isGecko) {
+ int rvPos = userAgent.indexOf("rv:");
+ if (rvPos >= 0) {
+ String tmp = userAgent.substring(rvPos + 3);
+ tmp = tmp.replaceFirst("(\\.[0-9]+).+", "$1");
+ browserEngineVersion = Float.parseFloat(tmp);
+ }
+ } else if (isWebKit) {
+ String tmp = userAgent
+ .substring(userAgent.indexOf("webkit/") + 7);
+ tmp = tmp.replaceFirst("([0-9]+)[^0-9].+", "$1");
+ browserEngineVersion = Float.parseFloat(tmp);
+ }
+ } catch (Exception e) {
+ // Browser engine version parsing failed
+ System.err.println("Browser engine version parsing failed for: "
+ + userAgent);
+ }
+
+ // Browser version
+ try {
+ if (isIE) {
+ String ieVersionString = userAgent.substring(userAgent
+ .indexOf("msie ") + 5);
+ ieVersionString = safeSubstring(ieVersionString, 0,
+ ieVersionString.indexOf(";"));
+ parseVersionString(ieVersionString);
+ } else if (isFirefox) {
+ int i = userAgent.indexOf(" firefox/") + 9;
+ parseVersionString(safeSubstring(userAgent, i, i + 5));
+ } else if (isChrome) {
+ int i = userAgent.indexOf(" chrome/") + 8;
+ parseVersionString(safeSubstring(userAgent, i, i + 5));
+ } else if (isSafari) {
+ int i = userAgent.indexOf(" version/") + 9;
+ parseVersionString(safeSubstring(userAgent, i, i + 5));
+ } else if (isOpera) {
+ int i = userAgent.indexOf(" version/");
+ if (i != -1) {
+ // Version present in Opera 10 and newer
+ i += 9; // " version/".length
+ } else {
+ i = userAgent.indexOf("opera/") + 6;
+ }
+ parseVersionString(safeSubstring(userAgent, i, i + 5));
+ }
+ } catch (Exception e) {
+ // Browser version parsing failed
+ System.err.println("Browser version parsing failed for: "
+ + userAgent);
+ }
+
+ // Operating system
+ if (userAgent.contains("windows ")) {
+ isWindows = true;
+ } else if (userAgent.contains("linux")) {
+ isLinux = true;
+ } else if (userAgent.contains("macintosh")
+ || userAgent.contains("mac osx")
+ || userAgent.contains("mac os x")) {
+ isMacOSX = true;
+ }
+ }
+
+ private void parseVersionString(String versionString) {
+ int idx = versionString.indexOf('.');
+ if (idx < 0) {
+ idx = versionString.length();
+ }
+ browserMajorVersion = Integer.parseInt(safeSubstring(versionString, 0,
+ idx));
+
+ int idx2 = versionString.indexOf('.', idx + 1);
+ if (idx2 < 0) {
+ idx2 = versionString.length();
+ }
+ try {
+ browserMinorVersion = Integer.parseInt(safeSubstring(versionString,
+ idx + 1, idx2).replaceAll("[^0-9].*", ""));
+ } catch (NumberFormatException e) {
+ // leave the minor version unmodified (-1 = unknown)
+ }
+ }
+
+ private String safeSubstring(String string, int beginIndex, int endIndex) {
+ if (beginIndex < 0) {
+ beginIndex = 0;
+ }
+ if (endIndex < 0 || endIndex > string.length()) {
+ endIndex = string.length();
+ }
+ return string.substring(beginIndex, endIndex);
+ }
+
+ /**
+ * Tests if the browser is Firefox.
+ *
+ * @return true if it is Firefox, false otherwise
+ */
+ public boolean isFirefox() {
+ return isFirefox;
+ }
+
+ /**
+ * Tests if the browser is using the Gecko engine
+ *
+ * @return true if it is Gecko, false otherwise
+ */
+ public boolean isGecko() {
+ return isGecko;
+ }
+
+ /**
+ * Tests if the browser is using the WebKit engine
+ *
+ * @return true if it is WebKit, false otherwise
+ */
+ public boolean isWebKit() {
+ return isWebKit;
+ }
+
+ /**
+ * Tests if the browser is using the Presto engine
+ *
+ * @return true if it is Presto, false otherwise
+ */
+ public boolean isPresto() {
+ return isPresto;
+ }
+
+ /**
+ * Tests if the browser is Safari.
+ *
+ * @return true if it is Safari, false otherwise
+ */
+ public boolean isSafari() {
+ return isSafari;
+ }
+
+ /**
+ * Tests if the browser is Chrome.
+ *
+ * @return true if it is Chrome, false otherwise
+ */
+ public boolean isChrome() {
+ return isChrome;
+ }
+
+ /**
+ * Tests if the browser is Opera.
+ *
+ * @return true if it is Opera, false otherwise
+ */
+ public boolean isOpera() {
+ return isOpera;
+ }
+
+ /**
+ * Tests if the browser is Internet Explorer.
+ *
+ * @return true if it is Internet Explorer, false otherwise
+ */
+ public boolean isIE() {
+ return isIE;
+ }
+
+ /**
+ * Returns the version of the browser engine. For WebKit this is an integer
+ * e.g., 532.0. For gecko it is a float e.g., 1.8 or 1.9.
+ *
+ * @return The version of the browser engine
+ */
+ public float getBrowserEngineVersion() {
+ return browserEngineVersion;
+ }
+
+ /**
+ * Returns the browser major version e.g., 3 for Firefox 3.5, 4 for Chrome
+ * 4, 8 for Internet Explorer 8.
+ * <p>
+ * Note that Internet Explorer 8 and newer will return the document mode so
+ * IE8 rendering as IE7 will return 7.
+ * </p>
+ *
+ * @return The major version of the browser.
+ */
+ public final int getBrowserMajorVersion() {
+ return browserMajorVersion;
+ }
+
+ /**
+ * Returns the browser minor version e.g., 5 for Firefox 3.5.
+ *
+ * @see #getBrowserMajorVersion()
+ *
+ * @return The minor version of the browser, or -1 if not known/parsed.
+ */
+ public final int getBrowserMinorVersion() {
+ return browserMinorVersion;
+ }
+
+ /**
+ * Sets the version for IE based on the documentMode. This is used to return
+ * the correct the correct IE version when the version from the user agent
+ * string and the value of the documentMode property do not match.
+ *
+ * @param documentMode
+ * The current document mode
+ */
+ public void setIEMode(int documentMode) {
+ browserMajorVersion = documentMode;
+ browserMinorVersion = 0;
+ }
+
+ /**
+ * Tests if the browser is run on Windows.
+ *
+ * @return true if run on Windows, false otherwise
+ */
+ public boolean isWindows() {
+ return isWindows;
+ }
+
+ /**
+ * Tests if the browser is run on Mac OSX.
+ *
+ * @return true if run on Mac OSX, false otherwise
+ */
+ public boolean isMacOSX() {
+ return isMacOSX;
+ }
+
+ /**
+ * Tests if the browser is run on Linux.
+ *
+ * @return true if run on Linux, false otherwise
+ */
+ public boolean isLinux() {
+ return isLinux;
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/VSchedulerImpl.java b/src/com/vaadin/terminal/gwt/client/VSchedulerImpl.java
index 6bef0c409c..65d5d6a9a2 100644
--- a/src/com/vaadin/terminal/gwt/client/VSchedulerImpl.java
+++ b/src/com/vaadin/terminal/gwt/client/VSchedulerImpl.java
@@ -1,32 +1,32 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client;
-
-import com.google.gwt.core.client.impl.SchedulerImpl;
-
-public class VSchedulerImpl extends SchedulerImpl {
-
- /**
- * Keeps track of if there are deferred commands that are being executed. 0
- * == no deferred commands currently in progress, > 0 otherwise.
- */
- private int deferredCommandTrackers = 0;
-
- @Override
- public void scheduleDeferred(ScheduledCommand cmd) {
- deferredCommandTrackers++;
- super.scheduleDeferred(cmd);
- super.scheduleDeferred(new ScheduledCommand() {
-
- public void execute() {
- deferredCommandTrackers--;
- }
- });
- }
-
- public boolean hasWorkQueued() {
- boolean hasWorkQueued = (deferredCommandTrackers != 0);
- return hasWorkQueued;
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client;
+
+import com.google.gwt.core.client.impl.SchedulerImpl;
+
+public class VSchedulerImpl extends SchedulerImpl {
+
+ /**
+ * Keeps track of if there are deferred commands that are being executed. 0
+ * == no deferred commands currently in progress, > 0 otherwise.
+ */
+ private int deferredCommandTrackers = 0;
+
+ @Override
+ public void scheduleDeferred(ScheduledCommand cmd) {
+ deferredCommandTrackers++;
+ super.scheduleDeferred(cmd);
+ super.scheduleDeferred(new ScheduledCommand() {
+
+ public void execute() {
+ deferredCommandTrackers--;
+ }
+ });
+ }
+
+ public boolean hasWorkQueued() {
+ boolean hasWorkQueued = (deferredCommandTrackers != 0);
+ return hasWorkQueued;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/CalendarEntry.java b/src/com/vaadin/terminal/gwt/client/ui/CalendarEntry.java
index cf18c693c6..1577d60ab7 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/CalendarEntry.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/CalendarEntry.java
@@ -1,128 +1,128 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Date;
-
-import com.vaadin.terminal.gwt.client.DateTimeService;
-
-public class CalendarEntry {
- private final String styleName;
- private Date start;
- private Date end;
- private String title;
- private String description;
- private boolean notime;
-
- @SuppressWarnings("deprecation")
- public CalendarEntry(String styleName, Date start, Date end, String title,
- String description, boolean notime) {
- this.styleName = styleName;
- if (notime) {
- Date d = new Date(start.getTime());
- d.setSeconds(0);
- d.setMinutes(0);
- this.start = d;
- if (end != null) {
- d = new Date(end.getTime());
- d.setSeconds(0);
- d.setMinutes(0);
- this.end = d;
- } else {
- end = start;
- }
- } else {
- this.start = start;
- this.end = end;
- }
- this.title = title;
- this.description = description;
- this.notime = notime;
- }
-
- public CalendarEntry(String styleName, Date start, Date end, String title,
- String description) {
- this(styleName, start, end, title, description, false);
- }
-
- public String getStyleName() {
- return styleName;
- }
-
- public Date getStart() {
- return start;
- }
-
- public void setStart(Date start) {
- this.start = start;
- }
-
- public Date getEnd() {
- return end;
- }
-
- public void setEnd(Date end) {
- this.end = end;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public boolean isNotime() {
- return notime;
- }
-
- public void setNotime(boolean notime) {
- this.notime = notime;
- }
-
- @SuppressWarnings("deprecation")
- public String getStringForDate(Date d) {
- // TODO format from DateTimeService
- String s = "";
- if (!notime) {
- if (!DateTimeService.isSameDay(d, start)) {
- s += (start.getYear() + 1900) + "." + (start.getMonth() + 1)
- + "." + start.getDate() + " ";
- }
- int i = start.getHours();
- s += (i < 10 ? "0" : "") + i;
- s += ":";
- i = start.getMinutes();
- s += (i < 10 ? "0" : "") + i;
- if (!start.equals(end)) {
- s += " - ";
- if (!DateTimeService.isSameDay(start, end)) {
- s += (end.getYear() + 1900) + "." + (end.getMonth() + 1)
- + "." + end.getDate() + " ";
- }
- i = end.getHours();
- s += (i < 10 ? "0" : "") + i;
- s += ":";
- i = end.getMinutes();
- s += (i < 10 ? "0" : "") + i;
- }
- s += " ";
- }
- if (title != null) {
- s += title;
- }
- return s;
- }
-
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Date;
+
+import com.vaadin.terminal.gwt.client.DateTimeService;
+
+public class CalendarEntry {
+ private final String styleName;
+ private Date start;
+ private Date end;
+ private String title;
+ private String description;
+ private boolean notime;
+
+ @SuppressWarnings("deprecation")
+ public CalendarEntry(String styleName, Date start, Date end, String title,
+ String description, boolean notime) {
+ this.styleName = styleName;
+ if (notime) {
+ Date d = new Date(start.getTime());
+ d.setSeconds(0);
+ d.setMinutes(0);
+ this.start = d;
+ if (end != null) {
+ d = new Date(end.getTime());
+ d.setSeconds(0);
+ d.setMinutes(0);
+ this.end = d;
+ } else {
+ end = start;
+ }
+ } else {
+ this.start = start;
+ this.end = end;
+ }
+ this.title = title;
+ this.description = description;
+ this.notime = notime;
+ }
+
+ public CalendarEntry(String styleName, Date start, Date end, String title,
+ String description) {
+ this(styleName, start, end, title, description, false);
+ }
+
+ public String getStyleName() {
+ return styleName;
+ }
+
+ public Date getStart() {
+ return start;
+ }
+
+ public void setStart(Date start) {
+ this.start = start;
+ }
+
+ public Date getEnd() {
+ return end;
+ }
+
+ public void setEnd(Date end) {
+ this.end = end;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public boolean isNotime() {
+ return notime;
+ }
+
+ public void setNotime(boolean notime) {
+ this.notime = notime;
+ }
+
+ @SuppressWarnings("deprecation")
+ public String getStringForDate(Date d) {
+ // TODO format from DateTimeService
+ String s = "";
+ if (!notime) {
+ if (!DateTimeService.isSameDay(d, start)) {
+ s += (start.getYear() + 1900) + "." + (start.getMonth() + 1)
+ + "." + start.getDate() + " ";
+ }
+ int i = start.getHours();
+ s += (i < 10 ? "0" : "") + i;
+ s += ":";
+ i = start.getMinutes();
+ s += (i < 10 ? "0" : "") + i;
+ if (!start.equals(end)) {
+ s += " - ";
+ if (!DateTimeService.isSameDay(start, end)) {
+ s += (end.getYear() + 1900) + "." + (end.getMonth() + 1)
+ + "." + end.getDate() + " ";
+ }
+ i = end.getHours();
+ s += (i < 10 ? "0" : "") + i;
+ s += ":";
+ i = end.getMinutes();
+ s += (i < 10 ? "0" : "") + i;
+ }
+ s += " ";
+ }
+ if (title != null) {
+ s += title;
+ }
+ return s;
+ }
+
} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/ui/FocusableFlowPanel.java b/src/com/vaadin/terminal/gwt/client/ui/FocusableFlowPanel.java
index 0ca97d2bf8..831add049b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/FocusableFlowPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/FocusableFlowPanel.java
@@ -1,100 +1,100 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.HasBlurHandlers;
-import com.google.gwt.event.dom.client.HasFocusHandlers;
-import com.google.gwt.event.dom.client.HasKeyDownHandlers;
-import com.google.gwt.event.dom.client.HasKeyPressHandlers;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.impl.FocusImpl;
-import com.vaadin.terminal.gwt.client.Focusable;
-
-public class FocusableFlowPanel extends FlowPanel implements HasFocusHandlers,
- HasBlurHandlers, HasKeyDownHandlers, HasKeyPressHandlers, Focusable {
-
- /**
- * Constructor
- */
- public FocusableFlowPanel() {
- // make focusable, as we don't need access key magic we don't need to
- // use FocusImpl.createFocusable
- getElement().setTabIndex(0);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com.
- * google.gwt.event.dom.client.FocusHandler)
- */
- public HandlerRegistration addFocusHandler(FocusHandler handler) {
- return addDomHandler(handler, FocusEvent.getType());
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.HasBlurHandlers#addBlurHandler(com.google
- * .gwt.event.dom.client.BlurHandler)
- */
- public HandlerRegistration addBlurHandler(BlurHandler handler) {
- return addDomHandler(handler, BlurEvent.getType());
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.HasKeyDownHandlers#addKeyDownHandler(
- * com.google.gwt.event.dom.client.KeyDownHandler)
- */
- public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
- return addDomHandler(handler, KeyDownEvent.getType());
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.HasKeyPressHandlers#addKeyPressHandler
- * (com.google.gwt.event.dom.client.KeyPressHandler)
- */
- public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
- return addDomHandler(handler, KeyPressEvent.getType());
- }
-
- /**
- * Sets/Removes the keyboard focus to the panel.
- *
- * @param focus
- * If set to true then the focus is moved to the panel, if set to
- * false the focus is removed
- */
- public void setFocus(boolean focus) {
- if (focus) {
- FocusImpl.getFocusImplForPanel().focus(getElement());
- } else {
- FocusImpl.getFocusImplForPanel().blur(getElement());
- }
- }
-
- /**
- * Focus the panel
- */
- public void focus() {
- setFocus(true);
- }
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.HasBlurHandlers;
+import com.google.gwt.event.dom.client.HasFocusHandlers;
+import com.google.gwt.event.dom.client.HasKeyDownHandlers;
+import com.google.gwt.event.dom.client.HasKeyPressHandlers;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.impl.FocusImpl;
+import com.vaadin.terminal.gwt.client.Focusable;
+
+public class FocusableFlowPanel extends FlowPanel implements HasFocusHandlers,
+ HasBlurHandlers, HasKeyDownHandlers, HasKeyPressHandlers, Focusable {
+
+ /**
+ * Constructor
+ */
+ public FocusableFlowPanel() {
+ // make focusable, as we don't need access key magic we don't need to
+ // use FocusImpl.createFocusable
+ getElement().setTabIndex(0);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com.
+ * google.gwt.event.dom.client.FocusHandler)
+ */
+ public HandlerRegistration addFocusHandler(FocusHandler handler) {
+ return addDomHandler(handler, FocusEvent.getType());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.HasBlurHandlers#addBlurHandler(com.google
+ * .gwt.event.dom.client.BlurHandler)
+ */
+ public HandlerRegistration addBlurHandler(BlurHandler handler) {
+ return addDomHandler(handler, BlurEvent.getType());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.HasKeyDownHandlers#addKeyDownHandler(
+ * com.google.gwt.event.dom.client.KeyDownHandler)
+ */
+ public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
+ return addDomHandler(handler, KeyDownEvent.getType());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.HasKeyPressHandlers#addKeyPressHandler
+ * (com.google.gwt.event.dom.client.KeyPressHandler)
+ */
+ public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
+ return addDomHandler(handler, KeyPressEvent.getType());
+ }
+
+ /**
+ * Sets/Removes the keyboard focus to the panel.
+ *
+ * @param focus
+ * If set to true then the focus is moved to the panel, if set to
+ * false the focus is removed
+ */
+ public void setFocus(boolean focus) {
+ if (focus) {
+ FocusImpl.getFocusImplForPanel().focus(getElement());
+ } else {
+ FocusImpl.getFocusImplForPanel().blur(getElement());
+ }
+ }
+
+ /**
+ * Focus the panel
+ */
+ public void focus() {
+ setFocus(true);
+ }
} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/ui/TreeImages.java b/src/com/vaadin/terminal/gwt/client/ui/TreeImages.java
index 8a153da98c..37f8889463 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/TreeImages.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/TreeImages.java
@@ -1,29 +1,29 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-
-public interface TreeImages extends com.google.gwt.user.client.ui.TreeImages {
-
- /**
- * An image indicating an open branch.
- *
- * @return a prototype of this image
- * @gwt.resource com/vaadin/terminal/gwt/public/default/tree/img/expanded
- * .png
- */
- AbstractImagePrototype treeOpen();
-
- /**
- * An image indicating a closed branch.
- *
- * @return a prototype of this image
- * @gwt.resource com/vaadin/terminal/gwt/public/default/tree/img/collapsed
- * .png
- */
- AbstractImagePrototype treeClosed();
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
+
+public interface TreeImages extends com.google.gwt.user.client.ui.TreeImages {
+
+ /**
+ * An image indicating an open branch.
+ *
+ * @return a prototype of this image
+ * @gwt.resource com/vaadin/terminal/gwt/public/default/tree/img/expanded
+ * .png
+ */
+ AbstractImagePrototype treeOpen();
+
+ /**
+ * An image indicating a closed branch.
+ *
+ * @return a prototype of this image
+ * @gwt.resource com/vaadin/terminal/gwt/public/default/tree/img/collapsed
+ * .png
+ */
+ AbstractImagePrototype treeClosed();
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java
index fb5070d9a2..e35bd93f67 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java
@@ -1,1787 +1,1792 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Date;
-import java.util.Iterator;
-
-import com.google.gwt.dom.client.Node;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ChangeHandler;
-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.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.MouseDownEvent;
-import com.google.gwt.event.dom.client.MouseDownHandler;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOutHandler;
-import com.google.gwt.event.dom.client.MouseUpEvent;
-import com.google.gwt.event.dom.client.MouseUpHandler;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.InlineHTML;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.DateTimeService;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VConsole;
-
-@SuppressWarnings("deprecation")
-public class VCalendarPanel extends FocusableFlexTable implements
- KeyDownHandler, KeyPressHandler, MouseOutHandler, MouseDownHandler,
- MouseUpHandler, BlurHandler, FocusHandler, SubPartAware {
-
- public interface SubmitListener {
-
- /**
- * Called when calendar user triggers a submitting operation in calendar
- * panel. Eg. clicking on day or hitting enter.
- */
- void onSubmit();
-
- /**
- * On eg. ESC key.
- */
- void onCancel();
- }
-
- /**
- * Blur listener that listens to blur event from the panel
- */
- public interface FocusOutListener {
- /**
- * @return true if the calendar panel is not used after focus moves out
- */
- boolean onFocusOut(DomEvent<?> event);
- }
-
- /**
- * FocusChangeListener is notified when the panel changes its _focused_
- * value.
- */
- public interface FocusChangeListener {
- void focusChanged(Date focusedDate);
- }
-
- /**
- * Dispatches an event when the panel when time is changed
- */
- public interface TimeChangeListener {
-
- void changed(int hour, int min, int sec, int msec);
- }
-
- /**
- * Represents a Date button in the calendar
- */
- private class VEventButton extends Button {
- public VEventButton() {
- addMouseDownHandler(VCalendarPanel.this);
- addMouseOutHandler(VCalendarPanel.this);
- addMouseUpHandler(VCalendarPanel.this);
- }
- }
-
- private static final String CN_FOCUSED = "focused";
-
- private static final String CN_TODAY = "today";
-
- 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
- */
- private ClickHandler dayClickHandler = new ClickHandler() {
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt
- * .event.dom.client.ClickEvent)
- */
- public void onClick(ClickEvent event) {
- Day day = (Day) event.getSource();
- focusDay(day.getDate());
- selectFocused();
- onSubmit();
- }
- };
-
- private VEventButton prevYear;
-
- private VEventButton nextYear;
-
- private VEventButton prevMonth;
-
- private VEventButton nextMonth;
-
- private VTime time;
-
- private FlexTable days = new FlexTable();
-
- private int resolution = VDateField.RESOLUTION_YEAR;
-
- private int focusedRow;
-
- private Timer mouseTimer;
-
- private Date value;
-
- private boolean enabled = true;
-
- private boolean readonly = false;
-
- private DateTimeService dateTimeService;
-
- private boolean showISOWeekNumbers;
-
- private Date displayedMonth;
-
- private Date focusedDate;
-
- private Day selectedDay;
-
- private Day focusedDay;
-
- private FocusOutListener focusOutListener;
-
- private SubmitListener submitListener;
-
- private FocusChangeListener focusChangeListener;
-
- private TimeChangeListener timeChangeListener;
-
- private boolean hasFocus = false;
-
- public VCalendarPanel() {
-
- setStyleName(VDateField.CLASSNAME + "-calendarpanel");
-
- /*
- * Firefox auto-repeat works correctly only if we use a key press
- * handler, other browsers handle it correctly when using a key down
- * handler
- */
- if (BrowserInfo.get().isGecko()) {
- addKeyPressHandler(this);
- } else {
- addKeyDownHandler(this);
- }
- addFocusHandler(this);
- addBlurHandler(this);
-
- }
-
- /**
- * Sets the focus to given date in the current view. Used when moving in the
- * calendar with the keyboard.
- *
- * @param date
- * A Date representing the day of month to be focused. Must be
- * one of the days currently visible.
- */
- private void focusDay(Date date) {
- // Only used when calender body is present
- if (resolution > VDateField.RESOLUTION_MONTH) {
- if (focusedDay != null) {
- focusedDay.removeStyleDependentName(CN_FOCUSED);
- }
-
- if (date != null && focusedDate != null) {
- focusedDate.setTime(date.getTime());
- int rowCount = days.getRowCount();
- for (int i = 0; i < rowCount; i++) {
- int cellCount = days.getCellCount(i);
- for (int j = 0; j < cellCount; j++) {
- Widget widget = days.getWidget(i, j);
- if (widget != null && widget instanceof Day) {
- Day curday = (Day) widget;
- if (curday.getDate().equals(date)) {
- curday.addStyleDependentName(CN_FOCUSED);
- focusedDay = curday;
- focusedRow = i;
- return;
- }
- }
- }
- }
- }
- }
- }
-
- /**
- * Sets the selection highlight to a given day in the current view
- *
- * @param date
- * A Date representing the day of month to be selected. Must be
- * one of the days currently visible.
- *
- */
- private void selectDate(Date date) {
- if (selectedDay != null) {
- selectedDay.removeStyleDependentName(CN_SELECTED);
- }
-
- int rowCount = days.getRowCount();
- for (int i = 0; i < rowCount; i++) {
- int cellCount = days.getCellCount(i);
- for (int j = 0; j < cellCount; j++) {
- Widget widget = days.getWidget(i, j);
- if (widget != null && widget instanceof Day) {
- Day curday = (Day) widget;
- if (curday.getDate().equals(date)) {
- curday.addStyleDependentName(CN_SELECTED);
- selectedDay = curday;
- return;
- }
- }
- }
- }
- }
-
- /**
- * Updates year, month, day from focusedDate to value
- */
- private void selectFocused() {
- if (focusedDate != null) {
- if (value == null) {
- // No previously selected value (set to null on server side).
- // Create a new date using current date and time
- value = new Date();
- }
- /*
- * #5594 set Date (day) to 1 in order to prevent any kind of
- * wrapping of months when later setting the month. (e.g. 31 ->
- * month with 30 days -> wraps to the 1st of the following month,
- * e.g. 31st of May -> 31st of April = 1st of May)
- */
- value.setDate(1);
- if (value.getYear() != focusedDate.getYear()) {
- value.setYear(focusedDate.getYear());
- }
- if (value.getMonth() != focusedDate.getMonth()) {
- value.setMonth(focusedDate.getMonth());
- }
- if (value.getDate() != focusedDate.getDate()) {
- }
- // We always need to set the date, even if it hasn't changed, since
- // it was forced to 1 above.
- value.setDate(focusedDate.getDate());
-
- selectDate(focusedDate);
- } else {
- VConsole.log("Trying to select a the focused date which is NULL!");
- }
- }
-
- protected boolean onValueChange() {
- return false;
- }
-
- public int getResolution() {
- return resolution;
- }
-
- public void setResolution(int resolution) {
- this.resolution = resolution;
- if (time != null) {
- time.removeFromParent();
- time = null;
- }
- }
-
- private boolean isReadonly() {
- return readonly;
- }
-
- private boolean isEnabled() {
- return enabled;
- }
-
- private void clearCalendarBody(boolean remove) {
- if (!remove) {
- // Leave the cells in place but clear their contents
-
- // This has the side effect of ensuring that the calendar always
- // contain 7 rows.
- for (int row = 1; row < 7; row++) {
- for (int col = 0; col < 8; col++) {
- days.setHTML(row, col, "&nbsp;");
- }
- }
- } else if (getRowCount() > 1) {
- removeRow(1);
- days.clear();
- }
- }
-
- /**
- * Builds the top buttons and current month and year header.
- *
- * @param needsMonth
- * Should the month buttons be visible?
- */
- private void buildCalendarHeader(boolean needsMonth) {
-
- getRowFormatter().addStyleName(0,
- VDateField.CLASSNAME + "-calendarpanel-header");
-
- if (prevMonth == null && needsMonth) {
- prevMonth = new VEventButton();
- prevMonth.setHTML("&lsaquo;");
- prevMonth.setStyleName("v-button-prevmonth");
- prevMonth.setTabIndex(-1);
- nextMonth = new VEventButton();
- nextMonth.setHTML("&rsaquo;");
- nextMonth.setStyleName("v-button-nextmonth");
- nextMonth.setTabIndex(-1);
- getFlexCellFormatter().setStyleName(0, 3,
- VDateField.CLASSNAME + "-calendarpanel-nextmonth");
- getFlexCellFormatter().setStyleName(0, 1,
- VDateField.CLASSNAME + "-calendarpanel-prevmonth");
-
- setWidget(0, 3, nextMonth);
- setWidget(0, 1, prevMonth);
- } else if (prevMonth != null && !needsMonth) {
- // Remove month traverse buttons
- remove(prevMonth);
- remove(nextMonth);
- prevMonth = null;
- nextMonth = null;
- }
-
- if (prevYear == null) {
- prevYear = new VEventButton();
- prevYear.setHTML("&laquo;");
- prevYear.setStyleName("v-button-prevyear");
- prevYear.setTabIndex(-1);
- nextYear = new VEventButton();
- nextYear.setHTML("&raquo;");
- nextYear.setStyleName("v-button-nextyear");
- nextYear.setTabIndex(-1);
- setWidget(0, 0, prevYear);
- setWidget(0, 4, nextYear);
- getFlexCellFormatter().setStyleName(0, 0,
- VDateField.CLASSNAME + "-calendarpanel-prevyear");
- getFlexCellFormatter().setStyleName(0, 4,
- VDateField.CLASSNAME + "-calendarpanel-nextyear");
- }
-
- final String monthName = needsMonth ? getDateTimeService().getMonth(
- focusedDate.getMonth()) : "";
- final int year = focusedDate.getYear() + 1900;
- getFlexCellFormatter().setStyleName(0, 2,
- VDateField.CLASSNAME + "-calendarpanel-month");
- setHTML(0, 2, "<span class=\"" + VDateField.CLASSNAME
- + "-calendarpanel-month\">" + monthName + " " + year
- + "</span>");
- }
-
- private DateTimeService getDateTimeService() {
- return dateTimeService;
- }
-
- public void setDateTimeService(DateTimeService dateTimeService) {
- this.dateTimeService = dateTimeService;
- }
-
- /**
- * Returns whether ISO 8601 week numbers should be shown in the value
- * selector or not. ISO 8601 defines that a week always starts with a Monday
- * so the week numbers are only shown if this is the case.
- *
- * @return true if week number should be shown, false otherwise
- */
- public boolean isShowISOWeekNumbers() {
- return showISOWeekNumbers;
- }
-
- public void setShowISOWeekNumbers(boolean showISOWeekNumbers) {
- this.showISOWeekNumbers = showISOWeekNumbers;
- }
-
- /**
- * Builds the day and time selectors of the calendar.
- */
- private void buildCalendarBody() {
-
- final int weekColumn = 0;
- final int firstWeekdayColumn = 1;
- final int headerRow = 0;
-
- setWidget(1, 0, days);
- setCellPadding(0);
- setCellSpacing(0);
- getFlexCellFormatter().setColSpan(1, 0, 5);
- getFlexCellFormatter().setStyleName(1, 0,
- VDateField.CLASSNAME + "-calendarpanel-body");
-
- days.getFlexCellFormatter().setStyleName(headerRow, weekColumn,
- "v-week");
- days.setHTML(headerRow, weekColumn, "<strong></strong>");
- // Hide the week column if week numbers are not to be displayed.
- days.getFlexCellFormatter().setVisible(headerRow, weekColumn,
- isShowISOWeekNumbers());
-
- days.getRowFormatter().setStyleName(headerRow,
- VDateField.CLASSNAME + "-calendarpanel-weekdays");
-
- if (isShowISOWeekNumbers()) {
- days.getFlexCellFormatter().setStyleName(headerRow, weekColumn,
- "v-first");
- days.getFlexCellFormatter().setStyleName(headerRow,
- firstWeekdayColumn, "");
- days.getRowFormatter().addStyleName(headerRow,
- VDateField.CLASSNAME + "-calendarpanel-weeknumbers");
- } else {
- days.getFlexCellFormatter().setStyleName(headerRow, weekColumn, "");
- days.getFlexCellFormatter().setStyleName(headerRow,
- firstWeekdayColumn, "v-first");
- }
-
- days.getFlexCellFormatter().setStyleName(headerRow,
- firstWeekdayColumn + 6, "v-last");
-
- // Print weekday names
- final int firstDay = getDateTimeService().getFirstDayOfWeek();
- for (int i = 0; i < 7; i++) {
- int day = i + firstDay;
- if (day > 6) {
- day = 0;
- }
- if (getResolution() > VDateField.RESOLUTION_MONTH) {
- days.setHTML(headerRow, firstWeekdayColumn + i, "<strong>"
- + getDateTimeService().getShortDay(day) + "</strong>");
- } else {
- days.setHTML(headerRow, firstWeekdayColumn + i, "");
- }
- }
-
- // 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 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++) {
- for (int dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) {
-
- // Actually write the day of month
- Day day = new Day((Date) curr.clone());
-
- 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);
- }
-
- days.setWidget(weekOfMonth, firstWeekdayColumn + dayOfWeek, day);
-
- // ISO week numbers if requested
- 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>");
- }
- curr.setDate(curr.getDate() + 1);
- }
- }
- }
-
- /**
- * Do we need the time selector
- *
- * @return True if it is required
- */
- private boolean isTimeSelectorNeeded() {
- return getResolution() > VDateField.RESOLUTION_DAY;
- }
-
- /**
- * Updates the calendar and text field with the selected dates.
- */
- public void renderCalendar() {
- if (focusedDate == null) {
- focusedDate = new Date();
- }
-
- if (getResolution() <= VDateField.RESOLUTION_MONTH
- && focusChangeListener != null) {
- focusChangeListener.focusChanged(new Date(focusedDate.getTime()));
- }
-
- final boolean needsMonth = getResolution() > VDateField.RESOLUTION_YEAR;
- boolean needsBody = getResolution() >= VDateField.RESOLUTION_DAY;
- buildCalendarHeader(needsMonth);
- clearCalendarBody(!needsBody);
- if (needsBody) {
- buildCalendarBody();
- }
-
- if (isTimeSelectorNeeded() && time == null) {
- time = new VTime();
- setWidget(2, 0, time);
- getFlexCellFormatter().setColSpan(2, 0, 5);
- getFlexCellFormatter().setStyleName(2, 0,
- VDateField.CLASSNAME + "-calendarpanel-time");
- } else if (isTimeSelectorNeeded()) {
- time.updateTimes();
- } else if (time != null) {
- remove(time);
- }
-
- }
-
- /**
- * Selects the next month
- */
- private void focusNextMonth() {
-
- int currentMonth = focusedDate.getMonth();
- focusedDate.setMonth(currentMonth + 1);
- int requestedMonth = (currentMonth + 1) % 12;
-
- /*
- * If the selected value was e.g. 31.3 the new value would be 31.4 but
- * this value is invalid so the new value will be 1.5. This is taken
- * care of by decreasing the value until we have the correct month.
- */
- while (focusedDate.getMonth() != requestedMonth) {
- focusedDate.setDate(focusedDate.getDate() - 1);
- }
- displayedMonth.setMonth(displayedMonth.getMonth() + 1);
-
- renderCalendar();
- }
-
- /**
- * Selects the previous month
- */
- private void focusPreviousMonth() {
- int currentMonth = focusedDate.getMonth();
- focusedDate.setMonth(currentMonth - 1);
-
- /*
- * If the selected value was e.g. 31.12 the new value would be 31.11 but
- * this value is invalid so the new value will be 1.12. This is taken
- * care of by decreasing the value until we have the correct month.
- */
- while (focusedDate.getMonth() == currentMonth) {
- focusedDate.setDate(focusedDate.getDate() - 1);
- }
- displayedMonth.setMonth(displayedMonth.getMonth() - 1);
-
- renderCalendar();
- }
-
- /**
- * Selects the previous year
- */
- private void focusPreviousYear(int years) {
- focusedDate.setYear(focusedDate.getYear() - years);
- displayedMonth.setYear(displayedMonth.getYear() - years);
- renderCalendar();
- }
-
- /**
- * Selects the next year
- */
- private void focusNextYear(int years) {
- focusedDate.setYear(focusedDate.getYear() + years);
- displayedMonth.setYear(displayedMonth.getYear() + years);
- renderCalendar();
- }
-
- /**
- * Handles a user click on the component
- *
- * @param sender
- * The component that was clicked
- * @param updateVariable
- * Should the value field be updated
- *
- */
- private void processClickEvent(Widget sender) {
- if (!isEnabled() || isReadonly()) {
- return;
- }
- if (sender == prevYear) {
- focusPreviousYear(1);
- } else if (sender == nextYear) {
- focusNextYear(1);
- } else if (sender == prevMonth) {
- focusPreviousMonth();
- } else if (sender == nextMonth) {
- focusNextMonth();
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt
- * .event.dom.client.KeyDownEvent)
- */
- public void onKeyDown(KeyDownEvent event) {
- handleKeyPress(event);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.KeyPressHandler#onKeyPress(com.google
- * .gwt.event.dom.client.KeyPressEvent)
- */
- public void onKeyPress(KeyPressEvent event) {
- handleKeyPress(event);
- }
-
- /**
- * Handles the keypress from both the onKeyPress event and the onKeyDown
- * event
- *
- * @param event
- * The keydown/keypress event
- */
- private void handleKeyPress(DomEvent<?> event) {
- if (time != null
- && time.getElement().isOrHasChild(
- (Node) event.getNativeEvent().getEventTarget().cast())) {
- int nativeKeyCode = event.getNativeEvent().getKeyCode();
- if (nativeKeyCode == getSelectKey()) {
- onSubmit(); // submit happens if enter key hit down on listboxes
- event.preventDefault();
- event.stopPropagation();
- }
- return;
- }
-
- // Check tabs
- int keycode = event.getNativeEvent().getKeyCode();
- if (keycode == KeyCodes.KEY_TAB && event.getNativeEvent().getShiftKey()) {
- if (onTabOut(event)) {
- return;
- }
- }
-
- // Handle the navigation
- if (handleNavigation(keycode, event.getNativeEvent().getCtrlKey()
- || event.getNativeEvent().getMetaKey(), event.getNativeEvent()
- .getShiftKey())) {
- event.preventDefault();
- }
-
- }
-
- /**
- * Notifies submit-listeners of a submit event
- */
- private void onSubmit() {
- if (getSubmitListener() != null) {
- getSubmitListener().onSubmit();
- }
- }
-
- /**
- * Notifies submit-listeners of a cancel event
- */
- private void onCancel() {
- if (getSubmitListener() != null) {
- getSubmitListener().onCancel();
- }
- }
-
- /**
- * Handles the keyboard navigation when the resolution is set to years.
- *
- * @param keycode
- * The keycode to process
- * @param ctrl
- * Is ctrl pressed?
- * @param shift
- * is shift pressed
- * @return Returns true if the keycode was processed, else false
- */
- protected boolean handleNavigationYearMode(int keycode, boolean ctrl,
- boolean shift) {
-
- // Ctrl and Shift selection not supported
- if (ctrl || shift) {
- return false;
- }
-
- else if (keycode == getPreviousKey()) {
- focusNextYear(10); // Add 10 years
- return true;
- }
-
- else if (keycode == getForwardKey()) {
- focusNextYear(1); // Add 1 year
- return true;
- }
-
- else if (keycode == getNextKey()) {
- focusPreviousYear(10); // Subtract 10 years
- return true;
- }
-
- else if (keycode == getBackwardKey()) {
- focusPreviousYear(1); // Subtract 1 year
- return true;
-
- } else if (keycode == getSelectKey()) {
- value = (Date) focusedDate.clone();
- onSubmit();
- return true;
-
- } else if (keycode == getResetKey()) {
- // Restore showing value the selected value
- focusedDate.setTime(value.getTime());
- renderCalendar();
- return true;
-
- } else if (keycode == getCloseKey()) {
- // TODO fire listener, on users responsibility??
-
- return true;
- }
- return false;
- }
-
- /**
- * Handle the keyboard navigation when the resolution is set to MONTH
- *
- * @param keycode
- * The keycode to handle
- * @param ctrl
- * Was the ctrl key pressed?
- * @param shift
- * Was the shift key pressed?
- * @return
- */
- protected boolean handleNavigationMonthMode(int keycode, boolean ctrl,
- boolean shift) {
-
- // Ctrl selection not supported
- if (ctrl) {
- return false;
-
- } else if (keycode == getPreviousKey()) {
- focusNextYear(1); // Add 1 year
- return true;
-
- } else if (keycode == getForwardKey()) {
- focusNextMonth(); // Add 1 month
- return true;
-
- } else if (keycode == getNextKey()) {
- focusPreviousYear(1); // Subtract 1 year
- return true;
-
- } else if (keycode == getBackwardKey()) {
- focusPreviousMonth(); // Subtract 1 month
- return true;
-
- } else if (keycode == getSelectKey()) {
- value = (Date) focusedDate.clone();
- onSubmit();
- return true;
-
- } else if (keycode == getResetKey()) {
- // Restore showing value the selected value
- focusedDate.setTime(value.getTime());
- renderCalendar();
- return true;
-
- } else if (keycode == getCloseKey() || keycode == KeyCodes.KEY_TAB) {
-
- // TODO fire close event
-
- return true;
- }
-
- return false;
- }
-
- /**
- * Handle keyboard navigation what the resolution is set to DAY
- *
- * @param keycode
- * The keycode to handle
- * @param ctrl
- * Was the ctrl key pressed?
- * @param shift
- * Was the shift key pressed?
- * @return Return true if the key press was handled by the method, else
- * return false.
- */
- protected boolean handleNavigationDayMode(int keycode, boolean ctrl,
- boolean shift) {
-
- // Ctrl key is not in use
- if (ctrl) {
- return false;
- }
-
- /*
- * Jumps to the next day.
- */
- if (keycode == getForwardKey() && !shift) {
- // Calculate new showing value
-
- Date newCurrentDate = (Date) focusedDate.clone();
-
- newCurrentDate.setDate(newCurrentDate.getDate() + 1);
-
- if (newCurrentDate.getMonth() == focusedDate.getMonth()) {
- // Month did not change, only move the selection
- focusDay(newCurrentDate);
- } else {
- // If the month changed we need to re-render the calendar
- focusedDate.setDate(focusedDate.getDate() + 1);
- renderCalendar();
- }
-
- return true;
-
- /*
- * Jumps to the previous day
- */
- } else if (keycode == getBackwardKey() && !shift) {
- // Calculate new showing value
- Date newCurrentDate = (Date) focusedDate.clone();
- newCurrentDate.setDate(newCurrentDate.getDate() - 1);
-
- if (newCurrentDate.getMonth() == focusedDate.getMonth()) {
- // Month did not change, only move the selection
- focusDay(newCurrentDate);
- } else {
- // If the month changed we need to re-render the calendar
- focusedDate.setDate(focusedDate.getDate() - 1);
- renderCalendar();
- }
-
- return true;
-
- /*
- * Jumps one week back in the calendar
- */
- } else if (keycode == getPreviousKey() && !shift) {
- // Calculate new showing value
- Date newCurrentDate = (Date) focusedDate.clone();
- newCurrentDate.setDate(newCurrentDate.getDate() - 7);
-
- if (newCurrentDate.getMonth() == focusedDate.getMonth()
- && focusedRow > 1) {
- // Month did not change, only move the selection
- focusDay(newCurrentDate);
- } else {
- // If the month changed we need to re-render the calendar
- focusedDate = newCurrentDate;
- renderCalendar();
- }
-
- return true;
-
- /*
- * Jumps one week forward in the calendar
- */
- } else if (keycode == getNextKey() && !ctrl && !shift) {
- // Calculate new showing value
- Date newCurrentDate = (Date) focusedDate.clone();
- newCurrentDate.setDate(newCurrentDate.getDate() + 7);
-
- if (newCurrentDate.getMonth() == focusedDate.getMonth()) {
- // Month did not change, only move the selection
- focusDay(newCurrentDate);
- } else {
- // If the month changed we need to re-render the calendar
- focusedDate = newCurrentDate;
- renderCalendar();
-
- }
-
- return true;
-
- /*
- * Selects the value that is chosen
- */
- } else if (keycode == getSelectKey() && !shift) {
- selectFocused();
- onSubmit(); // submit
- return true;
- } else if (keycode == getCloseKey()) {
- onCancel();
- // TODO close event
-
- return true;
-
- /*
- * Jumps to the next month
- */
- } else if (shift && keycode == getForwardKey()) {
- focusNextMonth();
- return true;
-
- /*
- * Jumps to the previous month
- */
- } else if (shift && keycode == getBackwardKey()) {
- focusPreviousMonth();
- return true;
-
- /*
- * Jumps to the next year
- */
- } else if (shift && keycode == getPreviousKey()) {
- focusNextYear(1);
- return true;
-
- /*
- * Jumps to the previous year
- */
- } else if (shift && keycode == getNextKey()) {
- focusPreviousYear(1);
- return true;
-
- /*
- * Resets the selection
- */
- } else if (keycode == getResetKey() && !shift) {
- // Restore showing value the selected value
- focusedDate.setTime(value.getTime());
- renderCalendar();
- return true;
- }
-
- return false;
- }
-
- /**
- * Handles the keyboard navigation
- *
- * @param keycode
- * The key code that was pressed
- * @param ctrl
- * Was the ctrl key pressed
- * @param shift
- * Was the shift key pressed
- * @return Return true if key press was handled by the component, else
- * return false
- */
- protected boolean handleNavigation(int keycode, boolean ctrl, boolean shift) {
- if (!isEnabled() || isReadonly()) {
- return false;
- }
-
- else if (resolution == VDateField.RESOLUTION_YEAR) {
- return handleNavigationYearMode(keycode, ctrl, shift);
- }
-
- else if (resolution == VDateField.RESOLUTION_MONTH) {
- return handleNavigationMonthMode(keycode, ctrl, shift);
- }
-
- else if (resolution == VDateField.RESOLUTION_DAY) {
- return handleNavigationDayMode(keycode, ctrl, shift);
- }
-
- else {
- return handleNavigationDayMode(keycode, ctrl, shift);
- }
-
- }
-
- /**
- * Returns the reset key which will reset the calendar to the previous
- * selection. By default this is backspace but it can be overriden to change
- * the key to whatever you want.
- *
- * @return
- */
- protected int getResetKey() {
- return KeyCodes.KEY_BACKSPACE;
- }
-
- /**
- * Returns the select key which selects the value. By default this is the
- * enter key but it can be changed to whatever you like by overriding this
- * method.
- *
- * @return
- */
- protected int getSelectKey() {
- return KeyCodes.KEY_ENTER;
- }
-
- /**
- * Returns the key that closes the popup window if this is a VPopopCalendar.
- * Else this does nothing. By default this is the Escape key but you can
- * change the key to whatever you want by overriding this method.
- *
- * @return
- */
- protected int getCloseKey() {
- return KeyCodes.KEY_ESCAPE;
- }
-
- /**
- * The key that selects the next day in the calendar. By default this is the
- * right arrow key but by overriding this method it can be changed to
- * whatever you like.
- *
- * @return
- */
- protected int getForwardKey() {
- return KeyCodes.KEY_RIGHT;
- }
-
- /**
- * The key that selects the previous day in the calendar. By default this is
- * the left arrow key but by overriding this method it can be changed to
- * whatever you like.
- *
- * @return
- */
- protected int getBackwardKey() {
- return KeyCodes.KEY_LEFT;
- }
-
- /**
- * The key that selects the next week in the calendar. By default this is
- * the down arrow key but by overriding this method it can be changed to
- * whatever you like.
- *
- * @return
- */
- protected int getNextKey() {
- return KeyCodes.KEY_DOWN;
- }
-
- /**
- * The key that selects the previous week in the calendar. By default this
- * is the up arrow key but by overriding this method it can be changed to
- * whatever you like.
- *
- * @return
- */
- protected int getPreviousKey() {
- return KeyCodes.KEY_UP;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.MouseOutHandler#onMouseOut(com.google
- * .gwt.event.dom.client.MouseOutEvent)
- */
- public void onMouseOut(MouseOutEvent event) {
- if (mouseTimer != null) {
- mouseTimer.cancel();
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google
- * .gwt.event.dom.client.MouseDownEvent)
- */
- public void onMouseDown(MouseDownEvent event) {
- // Allow user to click-n-hold for fast-forward or fast-rewind.
- // Timer is first used for a 500ms delay after mousedown. After that has
- // elapsed, another timer is triggered to go off every 150ms. Both
- // timers are cancelled on mouseup or mouseout.
- if (event.getSource() instanceof VEventButton) {
- final Widget sender = (Widget) event.getSource();
- processClickEvent(sender);
- mouseTimer = new Timer() {
- @Override
- public void run() {
- mouseTimer = new Timer() {
- @Override
- public void run() {
- processClickEvent(sender);
- }
- };
- mouseTimer.scheduleRepeating(150);
- }
- };
- mouseTimer.schedule(500);
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.MouseUpHandler#onMouseUp(com.google.gwt
- * .event.dom.client.MouseUpEvent)
- */
- public void onMouseUp(MouseUpEvent event) {
- if (mouseTimer != null) {
- mouseTimer.cancel();
- }
- }
-
- /**
- * Sets the data of the Panel.
- *
- * @param currentDate
- * The date to set
- */
- public void setDate(Date currentDate) {
-
- // Check that we are not re-rendering an already active date
- if (currentDate == value && currentDate != null) {
- return;
- }
-
- Date oldDisplayedMonth = displayedMonth;
- value = currentDate;
-
- if (value == 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 (oldDisplayedMonth == null || value == null
- || oldDisplayedMonth.getYear() != value.getYear()
- || oldDisplayedMonth.getMonth() != value.getMonth()) {
- renderCalendar();
- } else {
- focusDay(currentDate);
- selectFocused();
- }
-
- if (!hasFocus) {
- focusDay((Date) null);
- }
- }
-
- /**
- * TimeSelector is a widget consisting of list boxes that modifie the Date
- * object that is given for.
- *
- */
- public class VTime extends FlowPanel implements ChangeHandler {
-
- private ListBox hours;
-
- private ListBox mins;
-
- private ListBox sec;
-
- private ListBox msec;
-
- private ListBox ampm;
-
- /**
- * Constructor
- */
- public VTime() {
- super();
- setStyleName(VDateField.CLASSNAME + "-time");
- buildTime();
- }
-
- private ListBox createListBox() {
- ListBox lb = new ListBox();
- lb.setStyleName(VNativeSelect.CLASSNAME);
- lb.addChangeHandler(this);
- lb.addBlurHandler(VCalendarPanel.this);
- lb.addFocusHandler(VCalendarPanel.this);
- return lb;
- }
-
- /**
- * Constructs the ListBoxes and updates their value
- *
- * @param redraw
- * Should new instances of the listboxes be created
- */
- private void buildTime() {
- clear();
-
- hours = createListBox();
- if (getDateTimeService().isTwelveHourClock()) {
- hours.addItem("12");
- for (int i = 1; i < 12; i++) {
- hours.addItem((i < 10) ? "0" + i : "" + i);
- }
- } else {
- for (int i = 0; i < 24; i++) {
- hours.addItem((i < 10) ? "0" + i : "" + i);
- }
- }
-
- hours.addChangeHandler(this);
- if (getDateTimeService().isTwelveHourClock()) {
- ampm = createListBox();
- final String[] ampmText = getDateTimeService().getAmPmStrings();
- ampm.addItem(ampmText[0]);
- ampm.addItem(ampmText[1]);
- ampm.addChangeHandler(this);
- }
-
- if (getResolution() >= VDateField.RESOLUTION_MIN) {
- mins = createListBox();
- for (int i = 0; i < 60; i++) {
- mins.addItem((i < 10) ? "0" + i : "" + i);
- }
- mins.addChangeHandler(this);
- }
- if (getResolution() >= VDateField.RESOLUTION_SEC) {
- sec = createListBox();
- for (int i = 0; i < 60; i++) {
- sec.addItem((i < 10) ? "0" + i : "" + i);
- }
- sec.addChangeHandler(this);
- }
- if (getResolution() == VDateField.RESOLUTION_MSEC) {
- msec = createListBox();
- for (int i = 0; i < 1000; i++) {
- if (i < 10) {
- msec.addItem("00" + i);
- } else if (i < 100) {
- msec.addItem("0" + i);
- } else {
- msec.addItem("" + i);
- }
- }
- msec.addChangeHandler(this);
- }
-
- final String delimiter = getDateTimeService().getClockDelimeter();
- if (isReadonly()) {
- int h = 0;
- if (value != null) {
- h = value.getHours();
- }
- if (getDateTimeService().isTwelveHourClock()) {
- h -= h < 12 ? 0 : 12;
- }
- add(new VLabel(h < 10 ? "0" + h : "" + h));
- } else {
- add(hours);
- }
-
- if (getResolution() >= VDateField.RESOLUTION_MIN) {
- add(new VLabel(delimiter));
- if (isReadonly()) {
- final int m = mins.getSelectedIndex();
- add(new VLabel(m < 10 ? "0" + m : "" + m));
- } else {
- add(mins);
- }
- }
- if (getResolution() >= VDateField.RESOLUTION_SEC) {
- add(new VLabel(delimiter));
- if (isReadonly()) {
- final int s = sec.getSelectedIndex();
- add(new VLabel(s < 10 ? "0" + s : "" + s));
- } else {
- add(sec);
- }
- }
- if (getResolution() == VDateField.RESOLUTION_MSEC) {
- add(new VLabel("."));
- if (isReadonly()) {
- final int m = getMilliseconds();
- final String ms = m < 100 ? "0" + m : "" + m;
- add(new VLabel(m < 10 ? "0" + ms : ms));
- } else {
- add(msec);
- }
- }
- if (getResolution() == VDateField.RESOLUTION_HOUR) {
- add(new VLabel(delimiter + "00")); // o'clock
- }
- if (getDateTimeService().isTwelveHourClock()) {
- add(new VLabel("&nbsp;"));
- if (isReadonly()) {
- int i = 0;
- if (value != null) {
- i = (value.getHours() < 12) ? 0 : 1;
- }
- add(new VLabel(ampm.getItemText(i)));
- } else {
- add(ampm);
- }
- }
-
- if (isReadonly()) {
- return;
- }
-
- // Update times
- updateTimes();
-
- ListBox lastDropDown = getLastDropDown();
- lastDropDown.addKeyDownHandler(new KeyDownHandler() {
- public void onKeyDown(KeyDownEvent event) {
- boolean shiftKey = event.getNativeEvent().getShiftKey();
- if (shiftKey) {
- return;
- } else {
- int nativeKeyCode = event.getNativeKeyCode();
- if (nativeKeyCode == KeyCodes.KEY_TAB) {
- onTabOut(event);
- }
- }
- }
- });
-
- }
-
- private ListBox getLastDropDown() {
- int i = getWidgetCount() - 1;
- while (i >= 0) {
- Widget widget = getWidget(i);
- if (widget instanceof ListBox) {
- return (ListBox) widget;
- }
- i--;
- }
- return null;
- }
-
- /**
- * Updates the valus to correspond to the values in value
- */
- public void updateTimes() {
- boolean selected = true;
- if (value == null) {
- value = new Date();
- selected = false;
- }
- if (getDateTimeService().isTwelveHourClock()) {
- int h = value.getHours();
- ampm.setSelectedIndex(h < 12 ? 0 : 1);
- h -= ampm.getSelectedIndex() * 12;
- hours.setSelectedIndex(h);
- } else {
- hours.setSelectedIndex(value.getHours());
- }
- if (getResolution() >= VDateField.RESOLUTION_MIN) {
- mins.setSelectedIndex(value.getMinutes());
- }
- if (getResolution() >= VDateField.RESOLUTION_SEC) {
- sec.setSelectedIndex(value.getSeconds());
- }
- if (getResolution() == VDateField.RESOLUTION_MSEC) {
- if (selected) {
- msec.setSelectedIndex(getMilliseconds());
- } else {
- msec.setSelectedIndex(0);
- }
- }
- if (getDateTimeService().isTwelveHourClock()) {
- ampm.setSelectedIndex(value.getHours() < 12 ? 0 : 1);
- }
-
- hours.setEnabled(isEnabled());
- if (mins != null) {
- mins.setEnabled(isEnabled());
- }
- if (sec != null) {
- sec.setEnabled(isEnabled());
- }
- if (msec != null) {
- msec.setEnabled(isEnabled());
- }
- if (ampm != null) {
- ampm.setEnabled(isEnabled());
- }
-
- }
-
- private int getMilliseconds() {
- return DateTimeService.getMilliseconds(value);
- }
-
- private DateTimeService getDateTimeService() {
- if (dateTimeService == null) {
- dateTimeService = new DateTimeService();
- }
- return dateTimeService;
- }
-
- /*
- * (non-Javadoc) VT
- *
- * @see
- * com.google.gwt.event.dom.client.ChangeHandler#onChange(com.google.gwt
- * .event.dom.client.ChangeEvent)
- */
- public void onChange(ChangeEvent event) {
- /*
- * Value from dropdowns gets always set for the value. Like year and
- * month when resolution is month or year.
- */
- if (event.getSource() == hours) {
- int h = hours.getSelectedIndex();
- if (getDateTimeService().isTwelveHourClock()) {
- h = h + ampm.getSelectedIndex() * 12;
- }
- value.setHours(h);
- if (timeChangeListener != null) {
- timeChangeListener.changed(h, value.getMinutes(),
- value.getSeconds(),
- DateTimeService.getMilliseconds(value));
- }
- event.preventDefault();
- event.stopPropagation();
- } else if (event.getSource() == mins) {
- final int m = mins.getSelectedIndex();
- value.setMinutes(m);
- if (timeChangeListener != null) {
- timeChangeListener.changed(value.getHours(), m,
- value.getSeconds(),
- DateTimeService.getMilliseconds(value));
- }
- event.preventDefault();
- event.stopPropagation();
- } else if (event.getSource() == sec) {
- final int s = sec.getSelectedIndex();
- value.setSeconds(s);
- if (timeChangeListener != null) {
- timeChangeListener.changed(value.getHours(),
- value.getMinutes(), s,
- DateTimeService.getMilliseconds(value));
- }
- event.preventDefault();
- event.stopPropagation();
- } else if (event.getSource() == msec) {
- final int ms = msec.getSelectedIndex();
- DateTimeService.setMilliseconds(value, ms);
- if (timeChangeListener != null) {
- timeChangeListener.changed(value.getHours(),
- value.getMinutes(), value.getSeconds(), ms);
- }
- event.preventDefault();
- event.stopPropagation();
- } else if (event.getSource() == ampm) {
- final int h = hours.getSelectedIndex()
- + (ampm.getSelectedIndex() * 12);
- value.setHours(h);
- if (timeChangeListener != null) {
- timeChangeListener.changed(h, value.getMinutes(),
- value.getSeconds(),
- DateTimeService.getMilliseconds(value));
- }
- event.preventDefault();
- event.stopPropagation();
- }
- }
-
- }
-
- /**
- * A widget representing a single day in the calendar panel.
- */
- private class Day extends InlineHTML {
- private static final String BASECLASS = VDateField.CLASSNAME
- + "-calendarpanel-day";
- private final Date date;
-
- Day(Date date) {
- super("" + date.getDate());
- setStyleName(BASECLASS);
- this.date = date;
- addClickHandler(dayClickHandler);
- }
-
- public Date getDate() {
- return date;
- }
- }
-
- public Date getDate() {
- return value;
- }
-
- /**
- * If true should be returned if the panel will not be used after this
- * event.
- *
- * @param event
- * @return
- */
- protected boolean onTabOut(DomEvent<?> event) {
- if (focusOutListener != null) {
- return focusOutListener.onFocusOut(event);
- }
- return false;
- }
-
- /**
- * A focus out listener is triggered when the panel loosed focus. This can
- * happen either after a user clicks outside the panel or tabs out.
- *
- * @param listener
- * The listener to trigger
- */
- public void setFocusOutListener(FocusOutListener listener) {
- focusOutListener = listener;
- }
-
- /**
- * The submit listener is called when the user selects a value from the
- * calender either by clicking the day or selects it by keyboard.
- *
- * @param submitListener
- * The listener to trigger
- */
- public void setSubmitListener(SubmitListener submitListener) {
- this.submitListener = submitListener;
- }
-
- /**
- * The given FocusChangeListener is notified when the focused date changes
- * by user either clicking on a new date or by using the keyboard.
- *
- * @param listener
- * The FocusChangeListener to be notified
- */
- public void setFocusChangeListener(FocusChangeListener listener) {
- focusChangeListener = listener;
- }
-
- /**
- * The time change listener is triggered when the user changes the time.
- *
- * @param listener
- */
- public void setTimeChangeListener(TimeChangeListener listener) {
- timeChangeListener = listener;
- }
-
- /**
- * Returns the submit listener that listens to selection made from the panel
- *
- * @return The listener or NULL if no listener has been set
- */
- public SubmitListener getSubmitListener() {
- return submitListener;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event
- * .dom.client.BlurEvent)
- */
- public void onBlur(final BlurEvent event) {
- if (event.getSource() instanceof VCalendarPanel) {
- hasFocus = false;
- focusDay(null);
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event
- * .dom.client.FocusEvent)
- */
- public void onFocus(FocusEvent event) {
- if (event.getSource() instanceof VCalendarPanel) {
- hasFocus = true;
-
- // Focuses the current day if the calendar shows the days
- if (focusedDay != null) {
- focusDay(focusedDate);
- }
- }
- }
-
- private static final String SUBPART_NEXT_MONTH = "nextmon";
- private static final String SUBPART_PREV_MONTH = "prevmon";
-
- private static final String SUBPART_NEXT_YEAR = "nexty";
- private static final String SUBPART_PREV_YEAR = "prevy";
- private static final String SUBPART_HOUR_SELECT = "h";
- private static final String SUBPART_MINUTE_SELECT = "m";
- private static final String SUBPART_SECS_SELECT = "s";
- private static final String SUBPART_MSECS_SELECT = "ms";
- private static final String SUBPART_AMPM_SELECT = "ampm";
- private static final String SUBPART_DAY = "day";
- private static final String SUBPART_MONTH_YEAR_HEADER = "header";
-
- public String getSubPartName(Element subElement) {
- if (contains(nextMonth, subElement)) {
- return SUBPART_NEXT_MONTH;
- } else if (contains(prevMonth, subElement)) {
- return SUBPART_PREV_MONTH;
- } else if (contains(nextYear, subElement)) {
- return SUBPART_NEXT_YEAR;
- } else if (contains(prevYear, subElement)) {
- return SUBPART_PREV_YEAR;
- } else if (contains(days, subElement)) {
- // Day, find out which dayOfMonth and use that as the identifier
- Day day = Util.findWidget(subElement, Day.class);
- if (day != null) {
- Date date = day.getDate();
- int id = date.getDate();
- // Zero or negative ids map to days of the preceding month,
- // past-the-end-of-month ids to days of the following month
- 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)) {
- return SUBPART_HOUR_SELECT;
- } else if (contains(time.mins, subElement)) {
- return SUBPART_MINUTE_SELECT;
- } else if (contains(time.sec, subElement)) {
- return SUBPART_SECS_SELECT;
- } else if (contains(time.msec, subElement)) {
- return SUBPART_MSECS_SELECT;
- } else if (contains(time.ampm, subElement)) {
- return SUBPART_AMPM_SELECT;
-
- }
- } else if (getCellFormatter().getElement(0, 2).isOrHasChild(subElement)) {
- return SUBPART_MONTH_YEAR_HEADER;
- }
-
- return null;
- }
-
- /**
- * Checks if subElement is inside the widget DOM hierarchy.
- *
- * @param w
- * @param subElement
- * @return true if {@code w} is a parent of subElement, false otherwise.
- */
- private boolean contains(Widget w, Element subElement) {
- if (w == null || w.getElement() == null) {
- return false;
- }
-
- return w.getElement().isOrHasChild(subElement);
- }
-
- public Element getSubPartElement(String subPart) {
- if (SUBPART_NEXT_MONTH.equals(subPart)) {
- return nextMonth.getElement();
- }
- if (SUBPART_PREV_MONTH.equals(subPart)) {
- return prevMonth.getElement();
- }
- if (SUBPART_NEXT_YEAR.equals(subPart)) {
- return nextYear.getElement();
- }
- if (SUBPART_PREV_YEAR.equals(subPart)) {
- return prevYear.getElement();
- }
- if (SUBPART_HOUR_SELECT.equals(subPart)) {
- return time.hours.getElement();
- }
- if (SUBPART_MINUTE_SELECT.equals(subPart)) {
- return time.mins.getElement();
- }
- if (SUBPART_SECS_SELECT.equals(subPart)) {
- return time.sec.getElement();
- }
- if (SUBPART_MSECS_SELECT.equals(subPart)) {
- return time.msec.getElement();
- }
- if (SUBPART_AMPM_SELECT.equals(subPart)) {
- return time.ampm.getElement();
- }
- if (subPart.startsWith(SUBPART_DAY)) {
- // Zero or negative ids map to days in the preceding month,
- // past-the-end-of-month ids to days in the following month
- 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.getDate().equals(date)) {
- return day.getElement();
- }
- }
- }
- }
-
- if (SUBPART_MONTH_YEAR_HEADER.equals(subPart)) {
- return (Element) getCellFormatter().getElement(0, 2).getChild(0);
- }
- return null;
- }
-
- @Override
- protected void onDetach() {
- super.onDetach();
- if (mouseTimer != null) {
- mouseTimer.cancel();
- }
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Date;
+import java.util.Iterator;
+
+import com.google.gwt.dom.client.Node;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+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.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlexTable;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.InlineHTML;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.DateTimeService;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.VConsole;
+
+@SuppressWarnings("deprecation")
+public class VCalendarPanel extends FocusableFlexTable implements
+ KeyDownHandler, KeyPressHandler, MouseOutHandler, MouseDownHandler,
+ MouseUpHandler, BlurHandler, FocusHandler, SubPartAware {
+
+ public interface SubmitListener {
+
+ /**
+ * Called when calendar user triggers a submitting operation in calendar
+ * panel. Eg. clicking on day or hitting enter.
+ */
+ void onSubmit();
+
+ /**
+ * On eg. ESC key.
+ */
+ void onCancel();
+ }
+
+ /**
+ * Blur listener that listens to blur event from the panel
+ */
+ public interface FocusOutListener {
+ /**
+ * @return true if the calendar panel is not used after focus moves out
+ */
+ boolean onFocusOut(DomEvent<?> event);
+ }
+
+ /**
+ * FocusChangeListener is notified when the panel changes its _focused_
+ * value. It can be set with
+ */
+ public interface FocusChangeListener {
+ void focusChanged(Date focusedDate);
+ }
+
+ /**
+ * Dispatches an event when the panel when time is changed
+ */
+ public interface TimeChangeListener {
+
+ void changed(int hour, int min, int sec, int msec);
+ }
+
+ /**
+ * Represents a Date button in the calendar
+ */
+ private class VEventButton extends Button {
+ public VEventButton() {
+ addMouseDownHandler(VCalendarPanel.this);
+ addMouseOutHandler(VCalendarPanel.this);
+ addMouseUpHandler(VCalendarPanel.this);
+ }
+ }
+
+ private static final String CN_FOCUSED = "focused";
+
+ private static final String CN_TODAY = "today";
+
+ private static final String CN_SELECTED = "selected";
+
+ /**
+ * Represents a click handler for when a user selects a value by using the
+ * mouse
+ */
+ private ClickHandler dayClickHandler = new ClickHandler() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt
+ * .event.dom.client.ClickEvent)
+ */
+ public void onClick(ClickEvent event) {
+ Day day = (Day) event.getSource();
+ focusDay(day.getDay());
+ selectFocused();
+ onSubmit();
+ }
+ };
+
+ private VEventButton prevYear;
+
+ private VEventButton nextYear;
+
+ private VEventButton prevMonth;
+
+ private VEventButton nextMonth;
+
+ private VTime time;
+
+ private FlexTable days = new FlexTable();
+
+ private int resolution = VDateField.RESOLUTION_YEAR;
+
+ private int focusedRow;
+
+ private Timer mouseTimer;
+
+ private Date value;
+
+ private boolean enabled = true;
+
+ private boolean readonly = false;
+
+ private DateTimeService dateTimeService;
+
+ private boolean showISOWeekNumbers;
+
+ private Date focusedDate;
+
+ private Day selectedDay;
+
+ private Day focusedDay;
+
+ private FocusOutListener focusOutListener;
+
+ private SubmitListener submitListener;
+
+ private FocusChangeListener focusChangeListener;
+
+ private TimeChangeListener timeChangeListener;
+
+ private boolean hasFocus = false;
+
+ public VCalendarPanel() {
+
+ setStyleName(VDateField.CLASSNAME + "-calendarpanel");
+
+ /*
+ * Firefox auto-repeat works correctly only if we use a key press
+ * handler, other browsers handle it correctly when using a key down
+ * handler
+ */
+ if (BrowserInfo.get().isGecko()) {
+ addKeyPressHandler(this);
+ } else {
+ addKeyDownHandler(this);
+ }
+ addFocusHandler(this);
+ addBlurHandler(this);
+
+ }
+
+ /**
+ * Sets the focus to given day of current time. Used when moving in the
+ * calender with the keyboard.
+ *
+ * @param day
+ * The day number from by Date.getDate()
+ */
+ private void focusDay(int 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);
+ int rowCount = days.getRowCount();
+ for (int i = 0; i < rowCount; i++) {
+ int cellCount = days.getCellCount(i);
+ for (int j = 0; j < cellCount; j++) {
+ Widget widget = days.getWidget(i, j);
+ if (widget != null && widget instanceof Day) {
+ Day curday = (Day) widget;
+ if (curday.getDay() == day) {
+ curday.addStyleDependentName(CN_FOCUSED);
+ focusedDay = curday;
+ focusedRow = i;
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the selection hightlight to a given date of current time
+ *
+ * @param day
+ */
+ private void selectDate(int day) {
+ if (selectedDay != null) {
+ selectedDay.removeStyleDependentName(CN_SELECTED);
+ }
+
+ int rowCount = days.getRowCount();
+ for (int i = 0; i < rowCount; i++) {
+ int cellCount = days.getCellCount(i);
+ for (int j = 0; j < cellCount; j++) {
+ Widget widget = days.getWidget(i, j);
+ if (widget != null && widget instanceof Day) {
+ Day curday = (Day) widget;
+ if (curday.getDay() == day) {
+ curday.addStyleDependentName(CN_SELECTED);
+ selectedDay = curday;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates year, month, day from focusedDate to value
+ */
+ private void selectFocused() {
+ if (focusedDate != null) {
+ if (value == null) {
+ // No previously selected value (set to null on server side).
+ // Create a new date using current date and time
+ value = new Date();
+ }
+ /*
+ * #5594 set Date (day) to 1 in order to prevent any kind of
+ * wrapping of months when later setting the month. (e.g. 31 ->
+ * month with 30 days -> wraps to the 1st of the following month,
+ * e.g. 31st of May -> 31st of April = 1st of May)
+ */
+ value.setDate(1);
+ if (value.getYear() != focusedDate.getYear()) {
+ value.setYear(focusedDate.getYear());
+ }
+ if (value.getMonth() != focusedDate.getMonth()) {
+ value.setMonth(focusedDate.getMonth());
+ }
+ if (value.getDate() != focusedDate.getDate()) {
+ }
+ // We always need to set the date, even if it hasn't changed, since
+ // it was forced to 1 above.
+ value.setDate(focusedDate.getDate());
+
+ selectDate(focusedDate.getDate());
+ } else {
+ VConsole.log("Trying to select a the focused date which is NULL!");
+ }
+ }
+
+ protected boolean onValueChange() {
+ return false;
+ }
+
+ public int getResolution() {
+ return resolution;
+ }
+
+ public void setResolution(int resolution) {
+ this.resolution = resolution;
+ if (time != null) {
+ time.removeFromParent();
+ time = null;
+ }
+ }
+
+ private boolean isReadonly() {
+ return readonly;
+ }
+
+ private boolean isEnabled() {
+ return enabled;
+ }
+
+ private void clearCalendarBody(boolean remove) {
+ if (!remove) {
+ // Leave the cells in place but clear their contents
+
+ // This has the side effect of ensuring that the calendar always
+ // contain 7 rows.
+ for (int row = 1; row < 7; row++) {
+ for (int col = 0; col < 8; col++) {
+ days.setHTML(row, col, "&nbsp;");
+ }
+ }
+ } else if (getRowCount() > 1) {
+ removeRow(1);
+ days.clear();
+ }
+ }
+
+ /**
+ * Builds the top buttons and current month and year header.
+ *
+ * @param needsMonth
+ * Should the month buttons be visible?
+ */
+ private void buildCalendarHeader(boolean needsMonth) {
+
+ getRowFormatter().addStyleName(0,
+ VDateField.CLASSNAME + "-calendarpanel-header");
+
+ if (prevMonth == null && needsMonth) {
+ prevMonth = new VEventButton();
+ prevMonth.setHTML("&lsaquo;");
+ prevMonth.setStyleName("v-button-prevmonth");
+ prevMonth.setTabIndex(-1);
+ nextMonth = new VEventButton();
+ nextMonth.setHTML("&rsaquo;");
+ nextMonth.setStyleName("v-button-nextmonth");
+ nextMonth.setTabIndex(-1);
+ getFlexCellFormatter().setStyleName(0, 3,
+ VDateField.CLASSNAME + "-calendarpanel-nextmonth");
+ getFlexCellFormatter().setStyleName(0, 1,
+ VDateField.CLASSNAME + "-calendarpanel-prevmonth");
+
+ setWidget(0, 3, nextMonth);
+ setWidget(0, 1, prevMonth);
+ } else if (prevMonth != null && !needsMonth) {
+ // Remove month traverse buttons
+ remove(prevMonth);
+ remove(nextMonth);
+ prevMonth = null;
+ nextMonth = null;
+ }
+
+ if (prevYear == null) {
+ prevYear = new VEventButton();
+ prevYear.setHTML("&laquo;");
+ prevYear.setStyleName("v-button-prevyear");
+ prevYear.setTabIndex(-1);
+ nextYear = new VEventButton();
+ nextYear.setHTML("&raquo;");
+ nextYear.setStyleName("v-button-nextyear");
+ nextYear.setTabIndex(-1);
+ setWidget(0, 0, prevYear);
+ setWidget(0, 4, nextYear);
+ getFlexCellFormatter().setStyleName(0, 0,
+ VDateField.CLASSNAME + "-calendarpanel-prevyear");
+ getFlexCellFormatter().setStyleName(0, 4,
+ VDateField.CLASSNAME + "-calendarpanel-nextyear");
+ }
+
+ final String monthName = needsMonth ? getDateTimeService().getMonth(
+ focusedDate.getMonth()) : "";
+ final int year = focusedDate.getYear() + 1900;
+ getFlexCellFormatter().setStyleName(0, 2,
+ VDateField.CLASSNAME + "-calendarpanel-month");
+ setHTML(0, 2, "<span class=\"" + VDateField.CLASSNAME
+ + "-calendarpanel-month\">" + monthName + " " + year
+ + "</span>");
+ }
+
+ private DateTimeService getDateTimeService() {
+ return dateTimeService;
+ }
+
+ public void setDateTimeService(DateTimeService dateTimeService) {
+ this.dateTimeService = dateTimeService;
+ }
+
+ /**
+ * Returns whether ISO 8601 week numbers should be shown in the value
+ * selector or not. ISO 8601 defines that a week always starts with a Monday
+ * so the week numbers are only shown if this is the case.
+ *
+ * @return true if week number should be shown, false otherwise
+ */
+ public boolean isShowISOWeekNumbers() {
+ return showISOWeekNumbers;
+ }
+
+ public void setShowISOWeekNumbers(boolean showISOWeekNumbers) {
+ this.showISOWeekNumbers = showISOWeekNumbers;
+ }
+
+ /**
+ * Builds the day and time selectors of the calendar.
+ */
+ private void buildCalendarBody() {
+
+ final int weekColumn = 0;
+ final int firstWeekdayColumn = 1;
+ final int headerRow = 0;
+
+ setWidget(1, 0, days);
+ setCellPadding(0);
+ setCellSpacing(0);
+ getFlexCellFormatter().setColSpan(1, 0, 5);
+ getFlexCellFormatter().setStyleName(1, 0,
+ VDateField.CLASSNAME + "-calendarpanel-body");
+
+ days.getFlexCellFormatter().setStyleName(headerRow, weekColumn,
+ "v-week");
+ days.setHTML(headerRow, weekColumn, "<strong></strong>");
+ // Hide the week column if week numbers are not to be displayed.
+ days.getFlexCellFormatter().setVisible(headerRow, weekColumn,
+ isShowISOWeekNumbers());
+
+ days.getRowFormatter().setStyleName(headerRow,
+ VDateField.CLASSNAME + "-calendarpanel-weekdays");
+
+ if (isShowISOWeekNumbers()) {
+ days.getFlexCellFormatter().setStyleName(headerRow, weekColumn,
+ "v-first");
+ days.getFlexCellFormatter().setStyleName(headerRow,
+ firstWeekdayColumn, "");
+ days.getRowFormatter().addStyleName(headerRow,
+ VDateField.CLASSNAME + "-calendarpanel-weeknumbers");
+ } else {
+ days.getFlexCellFormatter().setStyleName(headerRow, weekColumn, "");
+ days.getFlexCellFormatter().setStyleName(headerRow,
+ firstWeekdayColumn, "v-first");
+ }
+
+ days.getFlexCellFormatter().setStyleName(headerRow,
+ firstWeekdayColumn + 6, "v-last");
+
+ // Print weekday names
+ final int firstDay = getDateTimeService().getFirstDayOfWeek();
+ for (int i = 0; i < 7; i++) {
+ int day = i + firstDay;
+ if (day > 6) {
+ day = 0;
+ }
+ if (getResolution() > VDateField.RESOLUTION_MONTH) {
+ days.setHTML(headerRow, firstWeekdayColumn + i, "<strong>"
+ + getDateTimeService().getShortDay(day) + "</strong>");
+ } else {
+ days.setHTML(headerRow, firstWeekdayColumn + i, "");
+ }
+ }
+
+ // 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();
+ }
+
+ final int startWeekDay = getDateTimeService().getStartWeekDay(
+ focusedDate);
+ final int daysInMonth = DateTimeService
+ .getNumberOfDaysInMonth(focusedDate);
+
+ int dayCount = 0;
+ final Date curr = new Date(focusedDate.getTime());
+
+ // 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);
+
+ if (dayOfMonthSelected == dayOfMonth) {
+ day.addStyleDependentName(CN_SELECTED);
+ selectedDay = day;
+ }
+
+ if (dayOfMonthToday == dayOfMonth) {
+ day.addStyleDependentName(CN_TODAY);
+ }
+
+ if (dayOfMonth == focusedDate.getDate()) {
+ focusedDay = day;
+ focusedRow = weekOfMonth;
+ if (hasFocus) {
+ day.addStyleDependentName(CN_FOCUSED);
+ }
+ }
+
+ 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;
+ }
+
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Do we need the time selector
+ *
+ * @return True if it is required
+ */
+ private boolean isTimeSelectorNeeded() {
+ return getResolution() > VDateField.RESOLUTION_DAY;
+ }
+
+ /**
+ * Updates the calendar and text field with the selected dates.
+ */
+ public void renderCalendar() {
+ if (focusedDate == null) {
+ focusedDate = new Date();
+ }
+
+ if (getResolution() <= VDateField.RESOLUTION_MONTH
+ && focusChangeListener != null) {
+ focusChangeListener.focusChanged(new Date(focusedDate.getTime()));
+ }
+
+ final boolean needsMonth = getResolution() > VDateField.RESOLUTION_YEAR;
+ boolean needsBody = getResolution() >= VDateField.RESOLUTION_DAY;
+ buildCalendarHeader(needsMonth);
+ clearCalendarBody(!needsBody);
+ if (needsBody) {
+ buildCalendarBody();
+ }
+
+ if (isTimeSelectorNeeded() && time == null) {
+ time = new VTime();
+ setWidget(2, 0, time);
+ getFlexCellFormatter().setColSpan(2, 0, 5);
+ getFlexCellFormatter().setStyleName(2, 0,
+ VDateField.CLASSNAME + "-calendarpanel-time");
+ } else if (isTimeSelectorNeeded()) {
+ time.updateTimes();
+ } else if (time != null) {
+ remove(time);
+ }
+
+ }
+
+ /**
+ * Selects the next month
+ */
+ private void focusNextMonth() {
+
+ int currentMonth = focusedDate.getMonth();
+ focusedDate.setMonth(currentMonth + 1);
+ int requestedMonth = (currentMonth + 1) % 12;
+
+ /*
+ * If the selected value was e.g. 31.3 the new value would be 31.4 but
+ * this value is invalid so the new value will be 1.5. This is taken
+ * care of by decreasing the value until we have the correct month.
+ */
+ while (focusedDate.getMonth() != requestedMonth) {
+ focusedDate.setDate(focusedDate.getDate() - 1);
+ }
+
+ renderCalendar();
+ }
+
+ /**
+ * Selects the previous month
+ */
+ private void focusPreviousMonth() {
+ int currentMonth = focusedDate.getMonth();
+ focusedDate.setMonth(currentMonth - 1);
+
+ /*
+ * If the selected value was e.g. 31.12 the new value would be 31.11 but
+ * this value is invalid so the new value will be 1.12. This is taken
+ * care of by decreasing the value until we have the correct month.
+ */
+ while (focusedDate.getMonth() == currentMonth) {
+ focusedDate.setDate(focusedDate.getDate() - 1);
+ }
+
+ renderCalendar();
+ }
+
+ /**
+ * Selects the previous year
+ */
+ private void focusPreviousYear(int years) {
+ focusedDate.setYear(focusedDate.getYear() - years);
+ renderCalendar();
+ }
+
+ /**
+ * Selects the next year
+ */
+ private void focusNextYear(int years) {
+ focusedDate.setYear(focusedDate.getYear() + years);
+ renderCalendar();
+ }
+
+ /**
+ * Handles a user click on the component
+ *
+ * @param sender
+ * The component that was clicked
+ * @param updateVariable
+ * Should the value field be updated
+ *
+ */
+ private void processClickEvent(Widget sender) {
+ if (!isEnabled() || isReadonly()) {
+ return;
+ }
+ if (sender == prevYear) {
+ focusPreviousYear(1);
+ } else if (sender == nextYear) {
+ focusNextYear(1);
+ } else if (sender == prevMonth) {
+ focusPreviousMonth();
+ } else if (sender == nextMonth) {
+ focusNextMonth();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt
+ * .event.dom.client.KeyDownEvent)
+ */
+ public void onKeyDown(KeyDownEvent event) {
+ handleKeyPress(event);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.KeyPressHandler#onKeyPress(com.google
+ * .gwt.event.dom.client.KeyPressEvent)
+ */
+ public void onKeyPress(KeyPressEvent event) {
+ handleKeyPress(event);
+ }
+
+ /**
+ * Handles the keypress from both the onKeyPress event and the onKeyDown
+ * event
+ *
+ * @param event
+ * The keydown/keypress event
+ */
+ private void handleKeyPress(DomEvent<?> event) {
+ if (time != null
+ && time.getElement().isOrHasChild(
+ (Node) event.getNativeEvent().getEventTarget().cast())) {
+ int nativeKeyCode = event.getNativeEvent().getKeyCode();
+ if (nativeKeyCode == getSelectKey()) {
+ onSubmit(); // submit happens if enter key hit down on listboxes
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ return;
+ }
+
+ // Check tabs
+ int keycode = event.getNativeEvent().getKeyCode();
+ if (keycode == KeyCodes.KEY_TAB && event.getNativeEvent().getShiftKey()) {
+ if (onTabOut(event)) {
+ return;
+ }
+ }
+
+ // Handle the navigation
+ if (handleNavigation(keycode, event.getNativeEvent().getCtrlKey()
+ || event.getNativeEvent().getMetaKey(), event.getNativeEvent()
+ .getShiftKey())) {
+ event.preventDefault();
+ }
+
+ }
+
+ /**
+ * Notifies submit-listeners of a submit event
+ */
+ private void onSubmit() {
+ if (getSubmitListener() != null) {
+ getSubmitListener().onSubmit();
+ }
+ }
+
+ /**
+ * Notifies submit-listeners of a cancel event
+ */
+ private void onCancel() {
+ if (getSubmitListener() != null) {
+ getSubmitListener().onCancel();
+ }
+ }
+
+ /**
+ * Handles the keyboard navigation when the resolution is set to years.
+ *
+ * @param keycode
+ * The keycode to process
+ * @param ctrl
+ * Is ctrl pressed?
+ * @param shift
+ * is shift pressed
+ * @return Returns true if the keycode was processed, else false
+ */
+ protected boolean handleNavigationYearMode(int keycode, boolean ctrl,
+ boolean shift) {
+
+ // Ctrl and Shift selection not supported
+ if (ctrl || shift) {
+ return false;
+ }
+
+ else if (keycode == getPreviousKey()) {
+ focusNextYear(10); // Add 10 years
+ return true;
+ }
+
+ else if (keycode == getForwardKey()) {
+ focusNextYear(1); // Add 1 year
+ return true;
+ }
+
+ else if (keycode == getNextKey()) {
+ focusPreviousYear(10); // Subtract 10 years
+ return true;
+ }
+
+ else if (keycode == getBackwardKey()) {
+ focusPreviousYear(1); // Subtract 1 year
+ return true;
+
+ } else if (keycode == getSelectKey()) {
+ value = (Date) focusedDate.clone();
+ onSubmit();
+ return true;
+
+ } else if (keycode == getResetKey()) {
+ // Restore showing value the selected value
+ focusedDate.setTime(value.getTime());
+ renderCalendar();
+ return true;
+
+ } else if (keycode == getCloseKey()) {
+ // TODO fire listener, on users responsibility??
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Handle the keyboard navigation when the resolution is set to MONTH
+ *
+ * @param keycode
+ * The keycode to handle
+ * @param ctrl
+ * Was the ctrl key pressed?
+ * @param shift
+ * Was the shift key pressed?
+ * @return
+ */
+ protected boolean handleNavigationMonthMode(int keycode, boolean ctrl,
+ boolean shift) {
+
+ // Ctrl selection not supported
+ if (ctrl) {
+ return false;
+
+ } else if (keycode == getPreviousKey()) {
+ focusNextYear(1); // Add 1 year
+ return true;
+
+ } else if (keycode == getForwardKey()) {
+ focusNextMonth(); // Add 1 month
+ return true;
+
+ } else if (keycode == getNextKey()) {
+ focusPreviousYear(1); // Subtract 1 year
+ return true;
+
+ } else if (keycode == getBackwardKey()) {
+ focusPreviousMonth(); // Subtract 1 month
+ return true;
+
+ } else if (keycode == getSelectKey()) {
+ value = (Date) focusedDate.clone();
+ onSubmit();
+ return true;
+
+ } else if (keycode == getResetKey()) {
+ // Restore showing value the selected value
+ focusedDate.setTime(value.getTime());
+ renderCalendar();
+ return true;
+
+ } else if (keycode == getCloseKey() || keycode == KeyCodes.KEY_TAB) {
+
+ // TODO fire close event
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Handle keyboard navigation what the resolution is set to DAY
+ *
+ * @param keycode
+ * The keycode to handle
+ * @param ctrl
+ * Was the ctrl key pressed?
+ * @param shift
+ * Was the shift key pressed?
+ * @return Return true if the key press was handled by the method, else
+ * return false.
+ */
+ protected boolean handleNavigationDayMode(int keycode, boolean ctrl,
+ boolean shift) {
+
+ // Ctrl key is not in use
+ if (ctrl) {
+ return false;
+ }
+
+ /*
+ * Jumps to the next day.
+ */
+ if (keycode == getForwardKey() && !shift) {
+ // Calculate new showing value
+
+ Date newCurrentDate = (Date) focusedDate.clone();
+
+ newCurrentDate.setDate(newCurrentDate.getDate() + 1);
+
+ if (newCurrentDate.getMonth() == focusedDate.getMonth()) {
+ // Month did not change, only move the selection
+ focusDay(focusedDate.getDate() + 1);
+ } else {
+ // If the month changed we need to re-render the calendar
+ focusedDate.setDate(focusedDate.getDate() + 1);
+ renderCalendar();
+ }
+
+ return true;
+
+ /*
+ * Jumps to the previous day
+ */
+ } else if (keycode == getBackwardKey() && !shift) {
+ // Calculate new showing value
+ Date newCurrentDate = (Date) focusedDate.clone();
+ newCurrentDate.setDate(newCurrentDate.getDate() - 1);
+
+ if (newCurrentDate.getMonth() == focusedDate.getMonth()) {
+ // Month did not change, only move the selection
+ focusDay(focusedDate.getDate() - 1);
+ } else {
+ // If the month changed we need to re-render the calendar
+ focusedDate.setDate(focusedDate.getDate() - 1);
+ renderCalendar();
+ }
+
+ return true;
+
+ /*
+ * Jumps one week back in the calendar
+ */
+ } else if (keycode == getPreviousKey() && !shift) {
+ // Calculate new showing value
+ Date newCurrentDate = (Date) focusedDate.clone();
+ newCurrentDate.setDate(newCurrentDate.getDate() - 7);
+
+ if (newCurrentDate.getMonth() == focusedDate.getMonth()
+ && focusedRow > 1) {
+ // Month did not change, only move the selection
+ focusDay(focusedDate.getDate() - 7);
+ } else {
+ // If the month changed we need to re-render the calendar
+ focusedDate.setDate(focusedDate.getDate() - 7);
+ renderCalendar();
+ }
+
+ return true;
+
+ /*
+ * Jumps one week forward in the calendar
+ */
+ } else if (keycode == getNextKey() && !ctrl && !shift) {
+ // Calculate new showing value
+ Date newCurrentDate = (Date) focusedDate.clone();
+ newCurrentDate.setDate(newCurrentDate.getDate() + 7);
+
+ if (newCurrentDate.getMonth() == focusedDate.getMonth()) {
+ // Month did not change, only move the selection
+ focusDay(focusedDate.getDate() + 7);
+ } else {
+ // If the month changed we need to re-render the calendar
+ focusedDate.setDate(focusedDate.getDate() + 7);
+ renderCalendar();
+
+ }
+
+ return true;
+
+ /*
+ * Selects the value that is chosen
+ */
+ } else if (keycode == getSelectKey() && !shift) {
+ selectFocused();
+ onSubmit(); // submit
+ return true;
+ } else if (keycode == getCloseKey()) {
+ onCancel();
+ // TODO close event
+
+ return true;
+
+ /*
+ * Jumps to the next month
+ */
+ } else if (shift && keycode == getForwardKey()) {
+ focusNextMonth();
+ return true;
+
+ /*
+ * Jumps to the previous month
+ */
+ } else if (shift && keycode == getBackwardKey()) {
+ focusPreviousMonth();
+ return true;
+
+ /*
+ * Jumps to the next year
+ */
+ } else if (shift && keycode == getPreviousKey()) {
+ focusNextYear(1);
+ return true;
+
+ /*
+ * Jumps to the previous year
+ */
+ } else if (shift && keycode == getNextKey()) {
+ focusPreviousYear(1);
+ return true;
+
+ /*
+ * Resets the selection
+ */
+ } else if (keycode == getResetKey() && !shift) {
+ // Restore showing value the selected value
+ focusedDate.setTime(value.getTime());
+ renderCalendar();
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Handles the keyboard navigation
+ *
+ * @param keycode
+ * The key code that was pressed
+ * @param ctrl
+ * Was the ctrl key pressed
+ * @param shift
+ * Was the shift key pressed
+ * @return Return true if key press was handled by the component, else
+ * return false
+ */
+ protected boolean handleNavigation(int keycode, boolean ctrl, boolean shift) {
+ if (!isEnabled() || isReadonly()) {
+ return false;
+ }
+
+ else if (resolution == VDateField.RESOLUTION_YEAR) {
+ return handleNavigationYearMode(keycode, ctrl, shift);
+ }
+
+ else if (resolution == VDateField.RESOLUTION_MONTH) {
+ return handleNavigationMonthMode(keycode, ctrl, shift);
+ }
+
+ else if (resolution == VDateField.RESOLUTION_DAY) {
+ return handleNavigationDayMode(keycode, ctrl, shift);
+ }
+
+ else {
+ return handleNavigationDayMode(keycode, ctrl, shift);
+ }
+
+ }
+
+ /**
+ * Returns the reset key which will reset the calendar to the previous
+ * selection. By default this is backspace but it can be overriden to change
+ * the key to whatever you want.
+ *
+ * @return
+ */
+ protected int getResetKey() {
+ return KeyCodes.KEY_BACKSPACE;
+ }
+
+ /**
+ * Returns the select key which selects the value. By default this is the
+ * enter key but it can be changed to whatever you like by overriding this
+ * method.
+ *
+ * @return
+ */
+ protected int getSelectKey() {
+ return KeyCodes.KEY_ENTER;
+ }
+
+ /**
+ * Returns the key that closes the popup window if this is a VPopopCalendar.
+ * Else this does nothing. By default this is the Escape key but you can
+ * change the key to whatever you want by overriding this method.
+ *
+ * @return
+ */
+ protected int getCloseKey() {
+ return KeyCodes.KEY_ESCAPE;
+ }
+
+ /**
+ * The key that selects the next day in the calendar. By default this is the
+ * right arrow key but by overriding this method it can be changed to
+ * whatever you like.
+ *
+ * @return
+ */
+ protected int getForwardKey() {
+ return KeyCodes.KEY_RIGHT;
+ }
+
+ /**
+ * The key that selects the previous day in the calendar. By default this is
+ * the left arrow key but by overriding this method it can be changed to
+ * whatever you like.
+ *
+ * @return
+ */
+ protected int getBackwardKey() {
+ return KeyCodes.KEY_LEFT;
+ }
+
+ /**
+ * The key that selects the next week in the calendar. By default this is
+ * the down arrow key but by overriding this method it can be changed to
+ * whatever you like.
+ *
+ * @return
+ */
+ protected int getNextKey() {
+ return KeyCodes.KEY_DOWN;
+ }
+
+ /**
+ * The key that selects the previous week in the calendar. By default this
+ * is the up arrow key but by overriding this method it can be changed to
+ * whatever you like.
+ *
+ * @return
+ */
+ protected int getPreviousKey() {
+ return KeyCodes.KEY_UP;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.MouseOutHandler#onMouseOut(com.google
+ * .gwt.event.dom.client.MouseOutEvent)
+ */
+ public void onMouseOut(MouseOutEvent event) {
+ if (mouseTimer != null) {
+ mouseTimer.cancel();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google
+ * .gwt.event.dom.client.MouseDownEvent)
+ */
+ public void onMouseDown(MouseDownEvent event) {
+ // Allow user to click-n-hold for fast-forward or fast-rewind.
+ // Timer is first used for a 500ms delay after mousedown. After that has
+ // elapsed, another timer is triggered to go off every 150ms. Both
+ // timers are cancelled on mouseup or mouseout.
+ if (event.getSource() instanceof VEventButton) {
+ final Widget sender = (Widget) event.getSource();
+ processClickEvent(sender);
+ mouseTimer = new Timer() {
+ @Override
+ public void run() {
+ mouseTimer = new Timer() {
+ @Override
+ public void run() {
+ processClickEvent(sender);
+ }
+ };
+ mouseTimer.scheduleRepeating(150);
+ }
+ };
+ mouseTimer.schedule(500);
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.MouseUpHandler#onMouseUp(com.google.gwt
+ * .event.dom.client.MouseUpEvent)
+ */
+ public void onMouseUp(MouseUpEvent event) {
+ if (mouseTimer != null) {
+ mouseTimer.cancel();
+ }
+ }
+
+ /**
+ * Sets the data of the Panel.
+ *
+ * @param currentDate
+ * The date to set
+ */
+ public void setDate(Date currentDate) {
+
+ // Check that we are not re-rendering an already active date
+ if (currentDate == value && currentDate != null) {
+ return;
+ }
+
+ Date oldFocusedValue = focusedDate;
+ value = currentDate;
+
+ if (value == null) {
+ focusedDate = null;
+ } else {
+ focusedDate = (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()) {
+ renderCalendar();
+ } else {
+ focusDay(currentDate.getDate());
+ selectFocused();
+ }
+
+ if (!hasFocus) {
+ focusDay(-1);
+ }
+ }
+
+ /**
+ * TimeSelector is a widget consisting of list boxes that modifie the Date
+ * object that is given for.
+ *
+ */
+ public class VTime extends FlowPanel implements ChangeHandler {
+
+ private ListBox hours;
+
+ private ListBox mins;
+
+ private ListBox sec;
+
+ private ListBox msec;
+
+ private ListBox ampm;
+
+ /**
+ * Constructor
+ */
+ public VTime() {
+ super();
+ setStyleName(VDateField.CLASSNAME + "-time");
+ buildTime();
+ }
+
+ private ListBox createListBox() {
+ ListBox lb = new ListBox();
+ lb.setStyleName(VNativeSelect.CLASSNAME);
+ lb.addChangeHandler(this);
+ lb.addBlurHandler(VCalendarPanel.this);
+ lb.addFocusHandler(VCalendarPanel.this);
+ return lb;
+ }
+
+ /**
+ * Constructs the ListBoxes and updates their value
+ *
+ * @param redraw
+ * Should new instances of the listboxes be created
+ */
+ private void buildTime() {
+ clear();
+
+ hours = createListBox();
+ if (getDateTimeService().isTwelveHourClock()) {
+ hours.addItem("12");
+ for (int i = 1; i < 12; i++) {
+ hours.addItem((i < 10) ? "0" + i : "" + i);
+ }
+ } else {
+ for (int i = 0; i < 24; i++) {
+ hours.addItem((i < 10) ? "0" + i : "" + i);
+ }
+ }
+
+ hours.addChangeHandler(this);
+ if (getDateTimeService().isTwelveHourClock()) {
+ ampm = createListBox();
+ final String[] ampmText = getDateTimeService().getAmPmStrings();
+ ampm.addItem(ampmText[0]);
+ ampm.addItem(ampmText[1]);
+ ampm.addChangeHandler(this);
+ }
+
+ if (getResolution() >= VDateField.RESOLUTION_MIN) {
+ mins = createListBox();
+ for (int i = 0; i < 60; i++) {
+ mins.addItem((i < 10) ? "0" + i : "" + i);
+ }
+ mins.addChangeHandler(this);
+ }
+ if (getResolution() >= VDateField.RESOLUTION_SEC) {
+ sec = createListBox();
+ for (int i = 0; i < 60; i++) {
+ sec.addItem((i < 10) ? "0" + i : "" + i);
+ }
+ sec.addChangeHandler(this);
+ }
+ if (getResolution() == VDateField.RESOLUTION_MSEC) {
+ msec = createListBox();
+ for (int i = 0; i < 1000; i++) {
+ if (i < 10) {
+ msec.addItem("00" + i);
+ } else if (i < 100) {
+ msec.addItem("0" + i);
+ } else {
+ msec.addItem("" + i);
+ }
+ }
+ msec.addChangeHandler(this);
+ }
+
+ final String delimiter = getDateTimeService().getClockDelimeter();
+ if (isReadonly()) {
+ int h = 0;
+ if (value != null) {
+ h = value.getHours();
+ }
+ if (getDateTimeService().isTwelveHourClock()) {
+ h -= h < 12 ? 0 : 12;
+ }
+ add(new VLabel(h < 10 ? "0" + h : "" + h));
+ } else {
+ add(hours);
+ }
+
+ if (getResolution() >= VDateField.RESOLUTION_MIN) {
+ add(new VLabel(delimiter));
+ if (isReadonly()) {
+ final int m = mins.getSelectedIndex();
+ add(new VLabel(m < 10 ? "0" + m : "" + m));
+ } else {
+ add(mins);
+ }
+ }
+ if (getResolution() >= VDateField.RESOLUTION_SEC) {
+ add(new VLabel(delimiter));
+ if (isReadonly()) {
+ final int s = sec.getSelectedIndex();
+ add(new VLabel(s < 10 ? "0" + s : "" + s));
+ } else {
+ add(sec);
+ }
+ }
+ if (getResolution() == VDateField.RESOLUTION_MSEC) {
+ add(new VLabel("."));
+ if (isReadonly()) {
+ final int m = getMilliseconds();
+ final String ms = m < 100 ? "0" + m : "" + m;
+ add(new VLabel(m < 10 ? "0" + ms : ms));
+ } else {
+ add(msec);
+ }
+ }
+ if (getResolution() == VDateField.RESOLUTION_HOUR) {
+ add(new VLabel(delimiter + "00")); // o'clock
+ }
+ if (getDateTimeService().isTwelveHourClock()) {
+ add(new VLabel("&nbsp;"));
+ if (isReadonly()) {
+ int i = 0;
+ if (value != null) {
+ i = (value.getHours() < 12) ? 0 : 1;
+ }
+ add(new VLabel(ampm.getItemText(i)));
+ } else {
+ add(ampm);
+ }
+ }
+
+ if (isReadonly()) {
+ return;
+ }
+
+ // Update times
+ updateTimes();
+
+ ListBox lastDropDown = getLastDropDown();
+ lastDropDown.addKeyDownHandler(new KeyDownHandler() {
+ public void onKeyDown(KeyDownEvent event) {
+ boolean shiftKey = event.getNativeEvent().getShiftKey();
+ if (shiftKey) {
+ return;
+ } else {
+ int nativeKeyCode = event.getNativeKeyCode();
+ if (nativeKeyCode == KeyCodes.KEY_TAB) {
+ onTabOut(event);
+ }
+ }
+ }
+ });
+
+ }
+
+ private ListBox getLastDropDown() {
+ int i = getWidgetCount() - 1;
+ while (i >= 0) {
+ Widget widget = getWidget(i);
+ if (widget instanceof ListBox) {
+ return (ListBox) widget;
+ }
+ i--;
+ }
+ return null;
+ }
+
+ /**
+ * Updates the valus to correspond to the values in value
+ */
+ public void updateTimes() {
+ boolean selected = true;
+ if (value == null) {
+ value = new Date();
+ selected = false;
+ }
+ if (getDateTimeService().isTwelveHourClock()) {
+ int h = value.getHours();
+ ampm.setSelectedIndex(h < 12 ? 0 : 1);
+ h -= ampm.getSelectedIndex() * 12;
+ hours.setSelectedIndex(h);
+ } else {
+ hours.setSelectedIndex(value.getHours());
+ }
+ if (getResolution() >= VDateField.RESOLUTION_MIN) {
+ mins.setSelectedIndex(value.getMinutes());
+ }
+ if (getResolution() >= VDateField.RESOLUTION_SEC) {
+ sec.setSelectedIndex(value.getSeconds());
+ }
+ if (getResolution() == VDateField.RESOLUTION_MSEC) {
+ if (selected) {
+ msec.setSelectedIndex(getMilliseconds());
+ } else {
+ msec.setSelectedIndex(0);
+ }
+ }
+ if (getDateTimeService().isTwelveHourClock()) {
+ ampm.setSelectedIndex(value.getHours() < 12 ? 0 : 1);
+ }
+
+ hours.setEnabled(isEnabled());
+ if (mins != null) {
+ mins.setEnabled(isEnabled());
+ }
+ if (sec != null) {
+ sec.setEnabled(isEnabled());
+ }
+ if (msec != null) {
+ msec.setEnabled(isEnabled());
+ }
+ if (ampm != null) {
+ ampm.setEnabled(isEnabled());
+ }
+
+ }
+
+ private int getMilliseconds() {
+ return DateTimeService.getMilliseconds(value);
+ }
+
+ private DateTimeService getDateTimeService() {
+ if (dateTimeService == null) {
+ dateTimeService = new DateTimeService();
+ }
+ return dateTimeService;
+ }
+
+ /*
+ * (non-Javadoc) VT
+ *
+ * @see
+ * com.google.gwt.event.dom.client.ChangeHandler#onChange(com.google.gwt
+ * .event.dom.client.ChangeEvent)
+ */
+ public void onChange(ChangeEvent event) {
+ /*
+ * Value from dropdowns gets always set for the value. Like year and
+ * month when resolution is month or year.
+ */
+ if (event.getSource() == hours) {
+ int h = hours.getSelectedIndex();
+ if (getDateTimeService().isTwelveHourClock()) {
+ h = h + ampm.getSelectedIndex() * 12;
+ }
+ value.setHours(h);
+ if (timeChangeListener != null) {
+ timeChangeListener.changed(h, value.getMinutes(),
+ value.getSeconds(),
+ DateTimeService.getMilliseconds(value));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ } else if (event.getSource() == mins) {
+ final int m = mins.getSelectedIndex();
+ value.setMinutes(m);
+ if (timeChangeListener != null) {
+ timeChangeListener.changed(value.getHours(), m,
+ value.getSeconds(),
+ DateTimeService.getMilliseconds(value));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ } else if (event.getSource() == sec) {
+ final int s = sec.getSelectedIndex();
+ value.setSeconds(s);
+ if (timeChangeListener != null) {
+ timeChangeListener.changed(value.getHours(),
+ value.getMinutes(), s,
+ DateTimeService.getMilliseconds(value));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ } else if (event.getSource() == msec) {
+ final int ms = msec.getSelectedIndex();
+ DateTimeService.setMilliseconds(value, ms);
+ if (timeChangeListener != null) {
+ timeChangeListener.changed(value.getHours(),
+ value.getMinutes(), value.getSeconds(), ms);
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ } else if (event.getSource() == ampm) {
+ final int h = hours.getSelectedIndex()
+ + (ampm.getSelectedIndex() * 12);
+ value.setHours(h);
+ if (timeChangeListener != null) {
+ timeChangeListener.changed(h, value.getMinutes(),
+ value.getSeconds(),
+ DateTimeService.getMilliseconds(value));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ }
+
+ private class Day extends InlineHTML {
+ private static final String BASECLASS = VDateField.CLASSNAME
+ + "-calendarpanel-day";
+ private final int day;
+
+ Day(int dayOfMonth) {
+ super("" + dayOfMonth);
+ setStyleName(BASECLASS);
+ day = dayOfMonth;
+ addClickHandler(dayClickHandler);
+ }
+
+ public int getDay() {
+ return day;
+ }
+ }
+
+ public Date getDate() {
+ return value;
+ }
+
+ /**
+ * If true should be returned if the panel will not be used after this
+ * event.
+ *
+ * @param event
+ * @return
+ */
+ protected boolean onTabOut(DomEvent<?> event) {
+ if (focusOutListener != null) {
+ return focusOutListener.onFocusOut(event);
+ }
+ return false;
+ }
+
+ /**
+ * A focus out listener is triggered when the panel loosed focus. This can
+ * happen either after a user clicks outside the panel or tabs out.
+ *
+ * @param listener
+ * The listener to trigger
+ */
+ public void setFocusOutListener(FocusOutListener listener) {
+ focusOutListener = listener;
+ }
+
+ /**
+ * The submit listener is called when the user selects a value from the
+ * calender either by clicking the day or selects it by keyboard.
+ *
+ * @param submitListener
+ * The listener to trigger
+ */
+ public void setSubmitListener(SubmitListener submitListener) {
+ this.submitListener = submitListener;
+ }
+
+ /**
+ * The given FocusChangeListener is notified when the focused date changes
+ * by user either clicking on a new date or by using the keyboard.
+ *
+ * @param listener
+ * The FocusChangeListener to be notified
+ */
+ public void setFocusChangeListener(FocusChangeListener listener) {
+ focusChangeListener = listener;
+ }
+
+ /**
+ * The time change listener is triggered when the user changes the time.
+ *
+ * @param listener
+ */
+ public void setTimeChangeListener(TimeChangeListener listener) {
+ timeChangeListener = listener;
+ }
+
+ /**
+ * Returns the submit listener that listens to selection made from the panel
+ *
+ * @return The listener or NULL if no listener has been set
+ */
+ public SubmitListener getSubmitListener() {
+ return submitListener;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event
+ * .dom.client.BlurEvent)
+ */
+ public void onBlur(final BlurEvent event) {
+ if (event.getSource() instanceof VCalendarPanel) {
+ hasFocus = false;
+ focusDay(-1);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event
+ * .dom.client.FocusEvent)
+ */
+ public void onFocus(FocusEvent event) {
+ if (event.getSource() instanceof VCalendarPanel) {
+ hasFocus = true;
+
+ // Focuses the current day if the calendar shows the days
+ if (focusedDay != null) {
+ focusDay(focusedDay.getDay());
+ }
+ }
+ }
+
+ private static final String SUBPART_NEXT_MONTH = "nextmon";
+ private static final String SUBPART_PREV_MONTH = "prevmon";
+
+ private static final String SUBPART_NEXT_YEAR = "nexty";
+ private static final String SUBPART_PREV_YEAR = "prevy";
+ private static final String SUBPART_HOUR_SELECT = "h";
+ private static final String SUBPART_MINUTE_SELECT = "m";
+ private static final String SUBPART_SECS_SELECT = "s";
+ private static final String SUBPART_MSECS_SELECT = "ms";
+ private static final String SUBPART_AMPM_SELECT = "ampm";
+ private static final String SUBPART_DAY = "day";
+ private static final String SUBPART_MONTH_YEAR_HEADER = "header";
+
+ public String getSubPartName(Element subElement) {
+ if (contains(nextMonth, subElement)) {
+ return SUBPART_NEXT_MONTH;
+ } else if (contains(prevMonth, subElement)) {
+ return SUBPART_PREV_MONTH;
+ } else if (contains(nextYear, subElement)) {
+ return SUBPART_NEXT_YEAR;
+ } else if (contains(prevYear, subElement)) {
+ return SUBPART_PREV_YEAR;
+ } else if (contains(days, subElement)) {
+ // 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();
+ }
+ } else if (time != null) {
+ if (contains(time.hours, subElement)) {
+ return SUBPART_HOUR_SELECT;
+ } else if (contains(time.mins, subElement)) {
+ return SUBPART_MINUTE_SELECT;
+ } else if (contains(time.sec, subElement)) {
+ return SUBPART_SECS_SELECT;
+ } else if (contains(time.msec, subElement)) {
+ return SUBPART_MSECS_SELECT;
+ } else if (contains(time.ampm, subElement)) {
+ return SUBPART_AMPM_SELECT;
+
+ }
+ } else if (getCellFormatter().getElement(0, 2).isOrHasChild(subElement)) {
+ return SUBPART_MONTH_YEAR_HEADER;
+ }
+
+ return null;
+ }
+
+ /**
+ * Checks if subElement is inside the widget DOM hierarchy.
+ *
+ * @param w
+ * @param subElement
+ * @return true if {@code w} is a parent of subElement, false otherwise.
+ */
+ private boolean contains(Widget w, Element subElement) {
+ if (w == null || w.getElement() == null) {
+ return false;
+ }
+
+ return w.getElement().isOrHasChild(subElement);
+ }
+
+ public Element getSubPartElement(String subPart) {
+ if (SUBPART_NEXT_MONTH.equals(subPart)) {
+ return nextMonth.getElement();
+ }
+ if (SUBPART_PREV_MONTH.equals(subPart)) {
+ return prevMonth.getElement();
+ }
+ if (SUBPART_NEXT_YEAR.equals(subPart)) {
+ return nextYear.getElement();
+ }
+ if (SUBPART_PREV_YEAR.equals(subPart)) {
+ return prevYear.getElement();
+ }
+ if (SUBPART_HOUR_SELECT.equals(subPart)) {
+ return time.hours.getElement();
+ }
+ if (SUBPART_MINUTE_SELECT.equals(subPart)) {
+ return time.mins.getElement();
+ }
+ if (SUBPART_SECS_SELECT.equals(subPart)) {
+ return time.sec.getElement();
+ }
+ if (SUBPART_MSECS_SELECT.equals(subPart)) {
+ return time.msec.getElement();
+ }
+ if (SUBPART_AMPM_SELECT.equals(subPart)) {
+ return time.ampm.getElement();
+ }
+ if (subPart.startsWith(SUBPART_DAY)) {
+ int dayOfMonth = Integer.parseInt(subPart.substring(SUBPART_DAY
+ .length()));
+ Iterator<Widget> iter = days.iterator();
+ while (iter.hasNext()) {
+ Widget w = iter.next();
+ if (w instanceof Day) {
+ Day day = (Day) w;
+ if (day.getDay() == dayOfMonth) {
+ return day.getElement();
+ }
+ }
+ }
+ }
+
+ if (SUBPART_MONTH_YEAR_HEADER.equals(subPart)) {
+ return (Element) getCellFormatter().getElement(0, 2).getChild(0);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onDetach() {
+ super.onDetach();
+ if (mouseTimer != null) {
+ mouseTimer.cancel();
+ }
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDateField.java b/src/com/vaadin/terminal/gwt/client/ui/VDateField.java
index 1ac697baa9..bc228675b2 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VDateField.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VDateField.java
@@ -1,277 +1,277 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Date;
-
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.DateTimeService;
-import com.vaadin.terminal.gwt.client.LocaleNotLoadedException;
-import com.vaadin.terminal.gwt.client.Paintable;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.VTooltip;
-
-public class VDateField extends FlowPanel implements Paintable, Field {
-
- public static final String CLASSNAME = "v-datefield";
-
- private String id;
-
- private ApplicationConnection client;
-
- protected boolean immediate;
-
- public static final int RESOLUTION_YEAR = 1;
- public static final int RESOLUTION_MONTH = 2;
- public static final int RESOLUTION_DAY = 4;
- public static final int RESOLUTION_HOUR = 8;
- public static final int RESOLUTION_MIN = 16;
- public static final int RESOLUTION_SEC = 32;
- public static final int RESOLUTION_MSEC = 64;
-
- public static final String WEEK_NUMBERS = "wn";
-
- static String resolutionToString(int res) {
- if (res > RESOLUTION_DAY) {
- return "full";
- }
- if (res == RESOLUTION_DAY) {
- return "day";
- }
- if (res == RESOLUTION_MONTH) {
- return "month";
- }
- return "year";
- }
-
- protected int currentResolution = RESOLUTION_YEAR;
-
- protected String currentLocale;
-
- protected boolean readonly;
-
- protected boolean enabled;
-
- /**
- * The date that is selected in the date field. Null if an invalid date is
- * specified.
- */
- private Date date = null;
-
- protected DateTimeService dts;
-
- private boolean showISOWeekNumbers = false;
-
- public VDateField() {
- setStyleName(CLASSNAME);
- dts = new DateTimeService();
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
- }
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- // Ensure correct implementation and let layout manage caption
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- // Save details
- this.client = client;
- id = uidl.getId();
- immediate = uidl.getBooleanAttribute("immediate");
-
- readonly = uidl.getBooleanAttribute("readonly");
- enabled = !uidl.getBooleanAttribute("disabled");
-
- if (uidl.hasAttribute("locale")) {
- final String locale = uidl.getStringAttribute("locale");
- try {
- dts.setLocale(locale);
- currentLocale = locale;
- } catch (final LocaleNotLoadedException e) {
- currentLocale = dts.getLocale();
- VConsole.error("Tried to use an unloaded locale \"" + locale
- + "\". Using default locale (" + currentLocale + ").");
- VConsole.error(e);
- }
- }
-
- // We show week numbers only if the week starts with Monday, as ISO 8601
- // specifies
- showISOWeekNumbers = uidl.getBooleanAttribute(WEEK_NUMBERS)
- && dts.getFirstDayOfWeek() == 1;
-
- int newResolution;
- if (uidl.hasVariable("msec")) {
- newResolution = RESOLUTION_MSEC;
- } else if (uidl.hasVariable("sec")) {
- newResolution = RESOLUTION_SEC;
- } else if (uidl.hasVariable("min")) {
- newResolution = RESOLUTION_MIN;
- } else if (uidl.hasVariable("hour")) {
- newResolution = RESOLUTION_HOUR;
- } else if (uidl.hasVariable("day")) {
- newResolution = RESOLUTION_DAY;
- } else if (uidl.hasVariable("month")) {
- newResolution = RESOLUTION_MONTH;
- } else {
- newResolution = RESOLUTION_YEAR;
- }
-
- currentResolution = newResolution;
-
- // Add stylename that indicates current resolution
- addStyleName(CLASSNAME + "-" + resolutionToString(currentResolution));
-
- final int year = uidl.getIntVariable("year");
- final int month = (currentResolution >= RESOLUTION_MONTH) ? uidl
- .getIntVariable("month") : -1;
- final int day = (currentResolution >= RESOLUTION_DAY) ? uidl
- .getIntVariable("day") : -1;
- final int hour = (currentResolution >= RESOLUTION_HOUR) ? uidl
- .getIntVariable("hour") : 0;
- final int min = (currentResolution >= RESOLUTION_MIN) ? uidl
- .getIntVariable("min") : 0;
- final int sec = (currentResolution >= RESOLUTION_SEC) ? uidl
- .getIntVariable("sec") : 0;
- final int msec = (currentResolution >= RESOLUTION_MSEC) ? uidl
- .getIntVariable("msec") : 0;
-
- // Construct new date for this datefield (only if not null)
- if (year > -1) {
- setCurrentDate(new Date((long) getTime(year, month, day, hour, min,
- sec, msec)));
- } else {
- setCurrentDate(null);
- }
- }
-
- /*
- * We need this redundant native function because Java's Date object doesn't
- * have a setMilliseconds method.
- */
- private static native double getTime(int y, int m, int d, int h, int mi,
- int s, int ms)
- /*-{
- try {
- var date = new Date(2000,1,1,1); // don't use current date here
- if(y && y >= 0) date.setFullYear(y);
- if(m && m >= 1) date.setMonth(m-1);
- if(d && d >= 0) date.setDate(d);
- if(h >= 0) date.setHours(h);
- if(mi >= 0) date.setMinutes(mi);
- if(s >= 0) date.setSeconds(s);
- if(ms >= 0) date.setMilliseconds(ms);
- return date.getTime();
- } catch (e) {
- // TODO print some error message on the console
- //console.log(e);
- return (new Date()).getTime();
- }
- }-*/;
-
- public int getMilliseconds() {
- return DateTimeService.getMilliseconds(date);
- }
-
- public void setMilliseconds(int ms) {
- DateTimeService.setMilliseconds(date, ms);
- }
-
- public int getCurrentResolution() {
- return currentResolution;
- }
-
- public void setCurrentResolution(int currentResolution) {
- this.currentResolution = currentResolution;
- }
-
- public String getCurrentLocale() {
- return currentLocale;
- }
-
- public void setCurrentLocale(String currentLocale) {
- this.currentLocale = currentLocale;
- }
-
- public Date getCurrentDate() {
- return date;
- }
-
- public void setCurrentDate(Date date) {
- this.date = date;
- }
-
- public boolean isImmediate() {
- return immediate;
- }
-
- public boolean isReadonly() {
- return readonly;
- }
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public DateTimeService getDateTimeService() {
- return dts;
- }
-
- public String getId() {
- return id;
- }
-
- public ApplicationConnection getClient() {
- return client;
- }
-
- /**
- * Returns whether ISO 8601 week numbers should be shown in the date
- * selector or not. ISO 8601 defines that a week always starts with a Monday
- * so the week numbers are only shown if this is the case.
- *
- * @return true if week number should be shown, false otherwise
- */
- public boolean isShowISOWeekNumbers() {
- return showISOWeekNumbers;
- }
-
- /**
- * Returns a copy of the current date. Modifying the returned date will not
- * modify the value of this VDateField. Use {@link #setDate(Date)} to change
- * the current date.
- *
- * @return A copy of the current date
- */
- protected Date getDate() {
- Date current = getCurrentDate();
- if (current == null) {
- return null;
- } else {
- return (Date) getCurrentDate().clone();
- }
- }
-
- /**
- * Sets the current date for this VDateField.
- *
- * @param date
- * The new date to use
- */
- protected void setDate(Date date) {
- this.date = date;
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Date;
+
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.DateTimeService;
+import com.vaadin.terminal.gwt.client.LocaleNotLoadedException;
+import com.vaadin.terminal.gwt.client.Paintable;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.VTooltip;
+
+public class VDateField extends FlowPanel implements Paintable, Field {
+
+ public static final String CLASSNAME = "v-datefield";
+
+ private String id;
+
+ private ApplicationConnection client;
+
+ protected boolean immediate;
+
+ public static final int RESOLUTION_YEAR = 1;
+ public static final int RESOLUTION_MONTH = 2;
+ public static final int RESOLUTION_DAY = 4;
+ public static final int RESOLUTION_HOUR = 8;
+ public static final int RESOLUTION_MIN = 16;
+ public static final int RESOLUTION_SEC = 32;
+ public static final int RESOLUTION_MSEC = 64;
+
+ public static final String WEEK_NUMBERS = "wn";
+
+ static String resolutionToString(int res) {
+ if (res > RESOLUTION_DAY) {
+ return "full";
+ }
+ if (res == RESOLUTION_DAY) {
+ return "day";
+ }
+ if (res == RESOLUTION_MONTH) {
+ return "month";
+ }
+ return "year";
+ }
+
+ protected int currentResolution = RESOLUTION_YEAR;
+
+ protected String currentLocale;
+
+ protected boolean readonly;
+
+ protected boolean enabled;
+
+ /**
+ * The date that is selected in the date field. Null if an invalid date is
+ * specified.
+ */
+ private Date date = null;
+
+ protected DateTimeService dts;
+
+ private boolean showISOWeekNumbers = false;
+
+ public VDateField() {
+ setStyleName(CLASSNAME);
+ dts = new DateTimeService();
+ sinkEvents(VTooltip.TOOLTIP_EVENTS);
+ }
+
+ @Override
+ public void onBrowserEvent(Event event) {
+ super.onBrowserEvent(event);
+ if (client != null) {
+ client.handleTooltipEvent(event, this);
+ }
+ }
+
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ // Ensure correct implementation and let layout manage caption
+ if (client.updateComponent(this, uidl, true)) {
+ return;
+ }
+
+ // Save details
+ this.client = client;
+ id = uidl.getId();
+ immediate = uidl.getBooleanAttribute("immediate");
+
+ readonly = uidl.getBooleanAttribute("readonly");
+ enabled = !uidl.getBooleanAttribute("disabled");
+
+ if (uidl.hasAttribute("locale")) {
+ final String locale = uidl.getStringAttribute("locale");
+ try {
+ dts.setLocale(locale);
+ currentLocale = locale;
+ } catch (final LocaleNotLoadedException e) {
+ currentLocale = dts.getLocale();
+ VConsole.error("Tried to use an unloaded locale \"" + locale
+ + "\". Using default locale (" + currentLocale + ").");
+ VConsole.error(e);
+ }
+ }
+
+ // We show week numbers only if the week starts with Monday, as ISO 8601
+ // specifies
+ showISOWeekNumbers = uidl.getBooleanAttribute(WEEK_NUMBERS)
+ && dts.getFirstDayOfWeek() == 1;
+
+ int newResolution;
+ if (uidl.hasVariable("msec")) {
+ newResolution = RESOLUTION_MSEC;
+ } else if (uidl.hasVariable("sec")) {
+ newResolution = RESOLUTION_SEC;
+ } else if (uidl.hasVariable("min")) {
+ newResolution = RESOLUTION_MIN;
+ } else if (uidl.hasVariable("hour")) {
+ newResolution = RESOLUTION_HOUR;
+ } else if (uidl.hasVariable("day")) {
+ newResolution = RESOLUTION_DAY;
+ } else if (uidl.hasVariable("month")) {
+ newResolution = RESOLUTION_MONTH;
+ } else {
+ newResolution = RESOLUTION_YEAR;
+ }
+
+ currentResolution = newResolution;
+
+ // Add stylename that indicates current resolution
+ addStyleName(CLASSNAME + "-" + resolutionToString(currentResolution));
+
+ final int year = uidl.getIntVariable("year");
+ final int month = (currentResolution >= RESOLUTION_MONTH) ? uidl
+ .getIntVariable("month") : -1;
+ final int day = (currentResolution >= RESOLUTION_DAY) ? uidl
+ .getIntVariable("day") : -1;
+ final int hour = (currentResolution >= RESOLUTION_HOUR) ? uidl
+ .getIntVariable("hour") : 0;
+ final int min = (currentResolution >= RESOLUTION_MIN) ? uidl
+ .getIntVariable("min") : 0;
+ final int sec = (currentResolution >= RESOLUTION_SEC) ? uidl
+ .getIntVariable("sec") : 0;
+ final int msec = (currentResolution >= RESOLUTION_MSEC) ? uidl
+ .getIntVariable("msec") : 0;
+
+ // Construct new date for this datefield (only if not null)
+ if (year > -1) {
+ setCurrentDate(new Date((long) getTime(year, month, day, hour, min,
+ sec, msec)));
+ } else {
+ setCurrentDate(null);
+ }
+ }
+
+ /*
+ * We need this redundant native function because Java's Date object doesn't
+ * have a setMilliseconds method.
+ */
+ private static native double getTime(int y, int m, int d, int h, int mi,
+ int s, int ms)
+ /*-{
+ try {
+ var date = new Date(2000,1,1,1); // don't use current date here
+ if(y && y >= 0) date.setFullYear(y);
+ if(m && m >= 1) date.setMonth(m-1);
+ if(d && d >= 0) date.setDate(d);
+ if(h >= 0) date.setHours(h);
+ if(mi >= 0) date.setMinutes(mi);
+ if(s >= 0) date.setSeconds(s);
+ if(ms >= 0) date.setMilliseconds(ms);
+ return date.getTime();
+ } catch (e) {
+ // TODO print some error message on the console
+ //console.log(e);
+ return (new Date()).getTime();
+ }
+ }-*/;
+
+ public int getMilliseconds() {
+ return DateTimeService.getMilliseconds(date);
+ }
+
+ public void setMilliseconds(int ms) {
+ DateTimeService.setMilliseconds(date, ms);
+ }
+
+ public int getCurrentResolution() {
+ return currentResolution;
+ }
+
+ public void setCurrentResolution(int currentResolution) {
+ this.currentResolution = currentResolution;
+ }
+
+ public String getCurrentLocale() {
+ return currentLocale;
+ }
+
+ public void setCurrentLocale(String currentLocale) {
+ this.currentLocale = currentLocale;
+ }
+
+ public Date getCurrentDate() {
+ return date;
+ }
+
+ public void setCurrentDate(Date date) {
+ this.date = date;
+ }
+
+ public boolean isImmediate() {
+ return immediate;
+ }
+
+ public boolean isReadonly() {
+ return readonly;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public DateTimeService getDateTimeService() {
+ return dts;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public ApplicationConnection getClient() {
+ return client;
+ }
+
+ /**
+ * Returns whether ISO 8601 week numbers should be shown in the date
+ * selector or not. ISO 8601 defines that a week always starts with a Monday
+ * so the week numbers are only shown if this is the case.
+ *
+ * @return true if week number should be shown, false otherwise
+ */
+ public boolean isShowISOWeekNumbers() {
+ return showISOWeekNumbers;
+ }
+
+ /**
+ * Returns a copy of the current date. Modifying the returned date will not
+ * modify the value of this VDateField. Use {@link #setDate(Date)} to change
+ * the current date.
+ *
+ * @return A copy of the current date
+ */
+ protected Date getDate() {
+ Date current = getCurrentDate();
+ if (current == null) {
+ return null;
+ } else {
+ return (Date) getCurrentDate().clone();
+ }
+ }
+
+ /**
+ * Sets the current date for this VDateField.
+ *
+ * @param date
+ * The new date to use
+ */
+ protected void setDate(Date date) {
+ this.date = date;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java
index 73bfe27700..91388edcaf 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java
@@ -1,153 +1,153 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Date;
-
-import com.google.gwt.event.dom.client.DomEvent;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.DateTimeService;
-import com.vaadin.terminal.gwt.client.UIDL;
-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;
-
-/**
- * A client side implementation for InlineDateField
- */
-public class VDateFieldCalendar extends VDateField {
-
- private final VCalendarPanel calendarPanel;
-
- public VDateFieldCalendar() {
- super();
- calendarPanel = new VCalendarPanel();
- add(calendarPanel);
- calendarPanel.setSubmitListener(new SubmitListener() {
- public void onSubmit() {
- updateValueFromPanel();
- }
-
- public void onCancel() {
- // TODO Auto-generated method stub
-
- }
- });
- calendarPanel.setFocusOutListener(new FocusOutListener() {
- public boolean onFocusOut(DomEvent<?> event) {
- updateValueFromPanel();
- return false;
- }
- });
- }
-
- @Override
- @SuppressWarnings("deprecation")
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- super.updateFromUIDL(uidl, client);
- calendarPanel.setShowISOWeekNumbers(isShowISOWeekNumbers());
- calendarPanel.setDateTimeService(getDateTimeService());
- calendarPanel.setResolution(getCurrentResolution());
- Date currentDate = getCurrentDate();
- if (currentDate != null) {
- calendarPanel.setDate(new Date(currentDate.getTime()));
- } else {
- calendarPanel.setDate(null);
- }
-
- if (currentResolution > RESOLUTION_DAY) {
- calendarPanel.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) calendarPanel.getDate().clone();
- }
- d.setHours(hour);
- d.setMinutes(min);
- d.setSeconds(sec);
- DateTimeService.setMilliseconds(d, msec);
-
- // Always update time changes to the server
- calendarPanel.setDate(d);
- updateValueFromPanel();
- }
- });
- }
-
- if (currentResolution <= RESOLUTION_MONTH) {
- calendarPanel.setFocusChangeListener(new FocusChangeListener() {
- public void focusChanged(Date date) {
- Date date2 = new Date();
- if (calendarPanel.getDate() != null) {
- date2.setTime(calendarPanel.getDate().getTime());
- }
- /*
- * Update the value of calendarPanel
- */
- date2.setYear(date.getYear());
- date2.setMonth(date.getMonth());
- calendarPanel.setDate(date2);
- /*
- * Then update the value from panel to server
- */
- updateValueFromPanel();
- }
- });
- } else {
- calendarPanel.setFocusChangeListener(null);
- }
-
- // Update possible changes
- calendarPanel.renderCalendar();
- }
-
- /**
- * TODO refactor: almost same method as in VPopupCalendar.updateValue
- */
- @SuppressWarnings("deprecation")
- private void updateValueFromPanel() {
- Date date2 = calendarPanel.getDate();
- Date currentDate = getCurrentDate();
- if (currentDate == null || date2.getTime() != currentDate.getTime()) {
- setCurrentDate((Date) date2.clone());
- getClient().updateVariable(getId(), "year", date2.getYear() + 1900,
- false);
- if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) {
- getClient().updateVariable(getId(), "month",
- date2.getMonth() + 1, false);
- if (getCurrentResolution() > RESOLUTION_MONTH) {
- getClient().updateVariable(getId(), "day", date2.getDate(),
- false);
- if (getCurrentResolution() > RESOLUTION_DAY) {
- getClient().updateVariable(getId(), "hour",
- date2.getHours(), false);
- if (getCurrentResolution() > RESOLUTION_HOUR) {
- getClient().updateVariable(getId(), "min",
- date2.getMinutes(), false);
- if (getCurrentResolution() > RESOLUTION_MIN) {
- getClient().updateVariable(getId(), "sec",
- date2.getSeconds(), false);
- if (getCurrentResolution() > RESOLUTION_SEC) {
- getClient().updateVariable(
- getId(),
- "msec",
- DateTimeService
- .getMilliseconds(date2),
- false);
- }
- }
- }
- }
- }
- }
- if (isImmediate()) {
- getClient().sendPendingVariableChanges();
- }
- }
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Date;
+
+import com.google.gwt.event.dom.client.DomEvent;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.DateTimeService;
+import com.vaadin.terminal.gwt.client.UIDL;
+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;
+
+/**
+ * A client side implementation for InlineDateField
+ */
+public class VDateFieldCalendar extends VDateField {
+
+ private final VCalendarPanel calendarPanel;
+
+ public VDateFieldCalendar() {
+ super();
+ calendarPanel = new VCalendarPanel();
+ add(calendarPanel);
+ calendarPanel.setSubmitListener(new SubmitListener() {
+ public void onSubmit() {
+ updateValueFromPanel();
+ }
+
+ public void onCancel() {
+ // TODO Auto-generated method stub
+
+ }
+ });
+ calendarPanel.setFocusOutListener(new FocusOutListener() {
+ public boolean onFocusOut(DomEvent<?> event) {
+ updateValueFromPanel();
+ return false;
+ }
+ });
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ super.updateFromUIDL(uidl, client);
+ calendarPanel.setShowISOWeekNumbers(isShowISOWeekNumbers());
+ calendarPanel.setDateTimeService(getDateTimeService());
+ calendarPanel.setResolution(getCurrentResolution());
+ Date currentDate = getCurrentDate();
+ if (currentDate != null) {
+ calendarPanel.setDate(new Date(currentDate.getTime()));
+ } else {
+ calendarPanel.setDate(null);
+ }
+
+ if (currentResolution > RESOLUTION_DAY) {
+ calendarPanel.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) calendarPanel.getDate().clone();
+ }
+ d.setHours(hour);
+ d.setMinutes(min);
+ d.setSeconds(sec);
+ DateTimeService.setMilliseconds(d, msec);
+
+ // Always update time changes to the server
+ calendarPanel.setDate(d);
+ updateValueFromPanel();
+ }
+ });
+ }
+
+ if (currentResolution <= RESOLUTION_MONTH) {
+ calendarPanel.setFocusChangeListener(new FocusChangeListener() {
+ public void focusChanged(Date date) {
+ Date date2 = new Date();
+ if (calendarPanel.getDate() != null) {
+ date2.setTime(calendarPanel.getDate().getTime());
+ }
+ /*
+ * Update the value of calendarPanel
+ */
+ date2.setYear(date.getYear());
+ date2.setMonth(date.getMonth());
+ calendarPanel.setDate(date2);
+ /*
+ * Then update the value from panel to server
+ */
+ updateValueFromPanel();
+ }
+ });
+ } else {
+ calendarPanel.setFocusChangeListener(null);
+ }
+
+ // Update possible changes
+ calendarPanel.renderCalendar();
+ }
+
+ /**
+ * TODO refactor: almost same method as in VPopupCalendar.updateValue
+ */
+ @SuppressWarnings("deprecation")
+ private void updateValueFromPanel() {
+ Date date2 = calendarPanel.getDate();
+ Date currentDate = getCurrentDate();
+ if (currentDate == null || date2.getTime() != currentDate.getTime()) {
+ setCurrentDate((Date) date2.clone());
+ getClient().updateVariable(getId(), "year", date2.getYear() + 1900,
+ false);
+ if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) {
+ getClient().updateVariable(getId(), "month",
+ date2.getMonth() + 1, false);
+ if (getCurrentResolution() > RESOLUTION_MONTH) {
+ getClient().updateVariable(getId(), "day", date2.getDate(),
+ false);
+ if (getCurrentResolution() > RESOLUTION_DAY) {
+ getClient().updateVariable(getId(), "hour",
+ date2.getHours(), false);
+ if (getCurrentResolution() > RESOLUTION_HOUR) {
+ getClient().updateVariable(getId(), "min",
+ date2.getMinutes(), false);
+ if (getCurrentResolution() > RESOLUTION_MIN) {
+ getClient().updateVariable(getId(), "sec",
+ date2.getSeconds(), false);
+ if (getCurrentResolution() > RESOLUTION_SEC) {
+ getClient().updateVariable(
+ getId(),
+ "msec",
+ DateTimeService
+ .getMilliseconds(date2),
+ false);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (isImmediate()) {
+ getClient().sendPendingVariableChanges();
+ }
+ }
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VForm.java b/src/com/vaadin/terminal/gwt/client/ui/VForm.java
index 3b38ecb487..c0a6e5b275 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VForm.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VForm.java
@@ -1,331 +1,331 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Set;
-
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-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.ComplexPanel;
-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.Paintable;
-import com.vaadin.terminal.gwt.client.RenderInformation;
-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.VConsole;
-import com.vaadin.terminal.gwt.client.VErrorMessage;
-
-public class VForm extends ComplexPanel implements Container, KeyDownHandler {
-
- protected String id;
-
- private String height = "";
-
- private String width = "";
-
- public static final String CLASSNAME = "v-form";
-
- private Container lo;
- private Element legend = DOM.createLegend();
- private Element caption = DOM.createSpan();
- private Element errorIndicatorElement = DOM.createDiv();
- private Element desc = DOM.createDiv();
- private Icon icon;
- private VErrorMessage errorMessage = new VErrorMessage();
-
- private Element fieldContainer = DOM.createDiv();
-
- private Element footerContainer = DOM.createDiv();
-
- private Element fieldSet = DOM.createFieldSet();
-
- private Container footer;
-
- private ApplicationConnection client;
-
- private RenderInformation renderInformation = new RenderInformation();
-
- private int borderPaddingHorizontal = -1;
-
- private boolean rendering = false;
-
- ShortcutActionHandler shortcutHandler;
-
- private HandlerRegistration keyDownRegistration;
-
- public VForm() {
- setElement(DOM.createDiv());
- getElement().appendChild(fieldSet);
- setStyleName(CLASSNAME);
- fieldSet.appendChild(legend);
- legend.appendChild(caption);
- errorIndicatorElement.setClassName("v-errorindicator");
- errorIndicatorElement.getStyle().setDisplay(Display.NONE);
- errorIndicatorElement.setInnerText(" "); // needed for IE
- desc.setClassName("v-form-description");
- fieldSet.appendChild(desc); // Adding description for initial padding
- // measurements, removed later if no
- // description is set
- fieldSet.appendChild(fieldContainer);
- errorMessage.setVisible(false);
- errorMessage.setStyleName(CLASSNAME + "-errormessage");
- fieldSet.appendChild(errorMessage.getElement());
- fieldSet.appendChild(footerContainer);
- }
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- rendering = true;
- this.client = client;
- id = uidl.getId();
-
- if (client.updateComponent(this, uidl, false)) {
- rendering = false;
- return;
- }
-
- boolean legendEmpty = true;
- if (uidl.hasAttribute("caption")) {
- caption.setInnerText(uidl.getStringAttribute("caption"));
- legendEmpty = false;
- } else {
- caption.setInnerText("");
- }
- if (uidl.hasAttribute("icon")) {
- if (icon == null) {
- icon = new Icon(client);
- legend.insertFirst(icon.getElement());
- }
- icon.setUri(uidl.getStringAttribute("icon"));
- legendEmpty = false;
- } else {
- if (icon != null) {
- legend.removeChild(icon.getElement());
- }
- }
- if (legendEmpty) {
- addStyleDependentName("nocaption");
- } else {
- removeStyleDependentName("nocaption");
- }
-
- if (uidl.hasAttribute("error")) {
- final UIDL errorUidl = uidl.getErrors();
- errorMessage.updateFromUIDL(errorUidl);
- errorMessage.setVisible(true);
-
- } else {
- errorMessage.setVisible(false);
- }
-
- if (uidl.hasAttribute("description")) {
- desc.setInnerHTML(uidl.getStringAttribute("description"));
- if (desc.getParentElement() == null) {
- fieldSet.insertAfter(desc, legend);
- }
- } else {
- desc.setInnerHTML("");
- if (desc.getParentElement() != null) {
- fieldSet.removeChild(desc);
- }
- }
-
- updateSize();
-
- // first render footer so it will be easier to handle relative height of
- // main layout
- if (uidl.getChildCount() > 1
- && !uidl.getChildUIDL(1).getTag().equals("actions")) {
- // render footer
- Container newFooter = (Container) client.getPaintable(uidl
- .getChildUIDL(1));
- if (footer == null) {
- add((Widget) newFooter, footerContainer);
- footer = newFooter;
- } else if (newFooter != footer) {
- remove((Widget) footer);
- client.unregisterPaintable(footer);
- add((Widget) newFooter, footerContainer);
- }
- footer = newFooter;
- footer.updateFromUIDL(uidl.getChildUIDL(1), client);
- // needed for the main layout to know the space it has available
- updateSize();
- } else {
- if (footer != null) {
- remove((Widget) footer);
- client.unregisterPaintable(footer);
- // needed for the main layout to know the space it has available
- updateSize();
- }
- }
-
- final UIDL layoutUidl = uidl.getChildUIDL(0);
- Container newLo = (Container) client.getPaintable(layoutUidl);
- if (lo == null) {
- lo = newLo;
- add((Widget) lo, fieldContainer);
- } else if (lo != newLo) {
- client.unregisterPaintable(lo);
- remove((Widget) lo);
- lo = newLo;
- add((Widget) lo, fieldContainer);
- }
- lo.updateFromUIDL(layoutUidl, client);
-
- // also recalculates size of the footer if undefined size form - see
- // #3710
- updateSize();
- client.runDescendentsLayout(this);
-
- // We may have actions attached
- if (uidl.getChildCount() > 1) {
- UIDL childUidl = uidl.getChildByTagName("actions");
- if (childUidl != null) {
- if (shortcutHandler == null) {
- shortcutHandler = new ShortcutActionHandler(id, client);
- keyDownRegistration = addDomHandler(this,
- KeyDownEvent.getType());
- }
- shortcutHandler.updateActionMap(childUidl);
- }
- } else if (shortcutHandler != null) {
- keyDownRegistration.removeHandler();
- shortcutHandler = null;
- keyDownRegistration = null;
- }
-
- rendering = false;
- }
-
- public void updateSize() {
-
- renderInformation.updateSize(getElement());
-
- renderInformation.setContentAreaHeight(renderInformation
- .getRenderedSize().getHeight() - getSpaceConsumedVertically());
- if (BrowserInfo.get().isIE6()) {
- getElement().getStyle().setProperty("overflow", "hidden");
- }
- renderInformation.setContentAreaWidth(renderInformation
- .getRenderedSize().getWidth() - borderPaddingHorizontal);
- }
-
- public RenderSpace getAllocatedSpace(Widget child) {
- if (child == lo) {
- return renderInformation.getContentAreaSize();
- } else if (child == footer) {
- return new RenderSpace(renderInformation.getContentAreaSize()
- .getWidth(), 0);
- } else {
- VConsole.error("Invalid child requested RenderSpace information");
- return null;
- }
- }
-
- public boolean hasChildComponent(Widget component) {
- return component != null && (component == lo || component == footer);
- }
-
- public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
- if (!hasChildComponent(oldComponent)) {
- throw new IllegalArgumentException(
- "Old component is not inside this Container");
- }
- remove(oldComponent);
- if (oldComponent == lo) {
- lo = (Container) newComponent;
- add((Widget) lo, fieldContainer);
- } else {
- footer = (Container) newComponent;
- add((Widget) footer, footerContainer);
- }
-
- }
-
- public boolean requestLayout(Set<Paintable> child) {
-
- if (height != null && !"".equals(height) && width != null
- && !"".equals(width)) {
- /*
- * If the height and width has been specified the child components
- * cannot make the size of the layout change
- */
-
- return true;
- }
-
- if (renderInformation.updateSize(getElement())) {
- return false;
- } else {
- return true;
- }
-
- }
-
- public void updateCaption(Paintable component, UIDL uidl) {
- // NOP form don't render caption for neither field layout nor footer
- // layout
- }
-
- @Override
- public void setHeight(String height) {
- if (this.height.equals(height)) {
- return;
- }
-
- this.height = height;
- super.setHeight(height);
-
- updateSize();
- }
-
- /**
- * @return pixels consumed by decoration, captions, descrioptiosn etc.. In
- * other words space, not used by the actual layout in form.
- */
- private int getSpaceConsumedVertically() {
- int offsetHeight2 = fieldSet.getOffsetHeight();
- int offsetHeight3 = fieldContainer.getOffsetHeight();
- int borderPadding = offsetHeight2 - offsetHeight3;
- return borderPadding;
- }
-
- @Override
- public void setWidth(String width) {
- if (borderPaddingHorizontal < 0) {
- // measure excess size lazily after stylename setting, but before
- // setting width
- int ow = getOffsetWidth();
- int dow = desc.getOffsetWidth();
- borderPaddingHorizontal = ow - dow;
- }
- if (Util.equals(this.width, width)) {
- return;
- }
-
- this.width = width;
- super.setWidth(width);
-
- updateSize();
-
- if (!rendering && height.equals("")) {
- // Width might affect height
- Util.updateRelativeChildrenAndSendSizeUpdateEvent(client, this);
- }
- }
-
- public void onKeyDown(KeyDownEvent event) {
- shortcutHandler.handleKeyboardEvent(Event.as(event.getNativeEvent()));
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Set;
+
+import com.google.gwt.dom.client.Style.Display;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+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.ComplexPanel;
+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.Paintable;
+import com.vaadin.terminal.gwt.client.RenderInformation;
+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.VConsole;
+import com.vaadin.terminal.gwt.client.VErrorMessage;
+
+public class VForm extends ComplexPanel implements Container, KeyDownHandler {
+
+ protected String id;
+
+ private String height = "";
+
+ private String width = "";
+
+ public static final String CLASSNAME = "v-form";
+
+ private Container lo;
+ private Element legend = DOM.createLegend();
+ private Element caption = DOM.createSpan();
+ private Element errorIndicatorElement = DOM.createDiv();
+ private Element desc = DOM.createDiv();
+ private Icon icon;
+ private VErrorMessage errorMessage = new VErrorMessage();
+
+ private Element fieldContainer = DOM.createDiv();
+
+ private Element footerContainer = DOM.createDiv();
+
+ private Element fieldSet = DOM.createFieldSet();
+
+ private Container footer;
+
+ private ApplicationConnection client;
+
+ private RenderInformation renderInformation = new RenderInformation();
+
+ private int borderPaddingHorizontal = -1;
+
+ private boolean rendering = false;
+
+ ShortcutActionHandler shortcutHandler;
+
+ private HandlerRegistration keyDownRegistration;
+
+ public VForm() {
+ setElement(DOM.createDiv());
+ getElement().appendChild(fieldSet);
+ setStyleName(CLASSNAME);
+ fieldSet.appendChild(legend);
+ legend.appendChild(caption);
+ errorIndicatorElement.setClassName("v-errorindicator");
+ errorIndicatorElement.getStyle().setDisplay(Display.NONE);
+ errorIndicatorElement.setInnerText(" "); // needed for IE
+ desc.setClassName("v-form-description");
+ fieldSet.appendChild(desc); // Adding description for initial padding
+ // measurements, removed later if no
+ // description is set
+ fieldSet.appendChild(fieldContainer);
+ errorMessage.setVisible(false);
+ errorMessage.setStyleName(CLASSNAME + "-errormessage");
+ fieldSet.appendChild(errorMessage.getElement());
+ fieldSet.appendChild(footerContainer);
+ }
+
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ rendering = true;
+ this.client = client;
+ id = uidl.getId();
+
+ if (client.updateComponent(this, uidl, false)) {
+ rendering = false;
+ return;
+ }
+
+ boolean legendEmpty = true;
+ if (uidl.hasAttribute("caption")) {
+ caption.setInnerText(uidl.getStringAttribute("caption"));
+ legendEmpty = false;
+ } else {
+ caption.setInnerText("");
+ }
+ if (uidl.hasAttribute("icon")) {
+ if (icon == null) {
+ icon = new Icon(client);
+ legend.insertFirst(icon.getElement());
+ }
+ icon.setUri(uidl.getStringAttribute("icon"));
+ legendEmpty = false;
+ } else {
+ if (icon != null) {
+ legend.removeChild(icon.getElement());
+ }
+ }
+ if (legendEmpty) {
+ addStyleDependentName("nocaption");
+ } else {
+ removeStyleDependentName("nocaption");
+ }
+
+ if (uidl.hasAttribute("error")) {
+ final UIDL errorUidl = uidl.getErrors();
+ errorMessage.updateFromUIDL(errorUidl);
+ errorMessage.setVisible(true);
+
+ } else {
+ errorMessage.setVisible(false);
+ }
+
+ if (uidl.hasAttribute("description")) {
+ desc.setInnerHTML(uidl.getStringAttribute("description"));
+ if (desc.getParentElement() == null) {
+ fieldSet.insertAfter(desc, legend);
+ }
+ } else {
+ desc.setInnerHTML("");
+ if (desc.getParentElement() != null) {
+ fieldSet.removeChild(desc);
+ }
+ }
+
+ updateSize();
+
+ // first render footer so it will be easier to handle relative height of
+ // main layout
+ if (uidl.getChildCount() > 1
+ && !uidl.getChildUIDL(1).getTag().equals("actions")) {
+ // render footer
+ Container newFooter = (Container) client.getPaintable(uidl
+ .getChildUIDL(1));
+ if (footer == null) {
+ add((Widget) newFooter, footerContainer);
+ footer = newFooter;
+ } else if (newFooter != footer) {
+ remove((Widget) footer);
+ client.unregisterPaintable(footer);
+ add((Widget) newFooter, footerContainer);
+ }
+ footer = newFooter;
+ footer.updateFromUIDL(uidl.getChildUIDL(1), client);
+ // needed for the main layout to know the space it has available
+ updateSize();
+ } else {
+ if (footer != null) {
+ remove((Widget) footer);
+ client.unregisterPaintable(footer);
+ // needed for the main layout to know the space it has available
+ updateSize();
+ }
+ }
+
+ final UIDL layoutUidl = uidl.getChildUIDL(0);
+ Container newLo = (Container) client.getPaintable(layoutUidl);
+ if (lo == null) {
+ lo = newLo;
+ add((Widget) lo, fieldContainer);
+ } else if (lo != newLo) {
+ client.unregisterPaintable(lo);
+ remove((Widget) lo);
+ lo = newLo;
+ add((Widget) lo, fieldContainer);
+ }
+ lo.updateFromUIDL(layoutUidl, client);
+
+ // also recalculates size of the footer if undefined size form - see
+ // #3710
+ updateSize();
+ client.runDescendentsLayout(this);
+
+ // We may have actions attached
+ if (uidl.getChildCount() > 1) {
+ UIDL childUidl = uidl.getChildByTagName("actions");
+ if (childUidl != null) {
+ if (shortcutHandler == null) {
+ shortcutHandler = new ShortcutActionHandler(id, client);
+ keyDownRegistration = addDomHandler(this,
+ KeyDownEvent.getType());
+ }
+ shortcutHandler.updateActionMap(childUidl);
+ }
+ } else if (shortcutHandler != null) {
+ keyDownRegistration.removeHandler();
+ shortcutHandler = null;
+ keyDownRegistration = null;
+ }
+
+ rendering = false;
+ }
+
+ public void updateSize() {
+
+ renderInformation.updateSize(getElement());
+
+ renderInformation.setContentAreaHeight(renderInformation
+ .getRenderedSize().getHeight() - getSpaceConsumedVertically());
+ if (BrowserInfo.get().isIE6()) {
+ getElement().getStyle().setProperty("overflow", "hidden");
+ }
+ renderInformation.setContentAreaWidth(renderInformation
+ .getRenderedSize().getWidth() - borderPaddingHorizontal);
+ }
+
+ public RenderSpace getAllocatedSpace(Widget child) {
+ if (child == lo) {
+ return renderInformation.getContentAreaSize();
+ } else if (child == footer) {
+ return new RenderSpace(renderInformation.getContentAreaSize()
+ .getWidth(), 0);
+ } else {
+ VConsole.error("Invalid child requested RenderSpace information");
+ return null;
+ }
+ }
+
+ public boolean hasChildComponent(Widget component) {
+ return component != null && (component == lo || component == footer);
+ }
+
+ public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
+ if (!hasChildComponent(oldComponent)) {
+ throw new IllegalArgumentException(
+ "Old component is not inside this Container");
+ }
+ remove(oldComponent);
+ if (oldComponent == lo) {
+ lo = (Container) newComponent;
+ add((Widget) lo, fieldContainer);
+ } else {
+ footer = (Container) newComponent;
+ add((Widget) footer, footerContainer);
+ }
+
+ }
+
+ public boolean requestLayout(Set<Paintable> child) {
+
+ if (height != null && !"".equals(height) && width != null
+ && !"".equals(width)) {
+ /*
+ * If the height and width has been specified the child components
+ * cannot make the size of the layout change
+ */
+
+ return true;
+ }
+
+ if (renderInformation.updateSize(getElement())) {
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+ public void updateCaption(Paintable component, UIDL uidl) {
+ // NOP form don't render caption for neither field layout nor footer
+ // layout
+ }
+
+ @Override
+ public void setHeight(String height) {
+ if (this.height.equals(height)) {
+ return;
+ }
+
+ this.height = height;
+ super.setHeight(height);
+
+ updateSize();
+ }
+
+ /**
+ * @return pixels consumed by decoration, captions, descrioptiosn etc.. In
+ * other words space, not used by the actual layout in form.
+ */
+ private int getSpaceConsumedVertically() {
+ int offsetHeight2 = fieldSet.getOffsetHeight();
+ int offsetHeight3 = fieldContainer.getOffsetHeight();
+ int borderPadding = offsetHeight2 - offsetHeight3;
+ return borderPadding;
+ }
+
+ @Override
+ public void setWidth(String width) {
+ if (borderPaddingHorizontal < 0) {
+ // measure excess size lazily after stylename setting, but before
+ // setting width
+ int ow = getOffsetWidth();
+ int dow = desc.getOffsetWidth();
+ borderPaddingHorizontal = ow - dow;
+ }
+ if (Util.equals(this.width, width)) {
+ return;
+ }
+
+ this.width = width;
+ super.setWidth(width);
+
+ updateSize();
+
+ if (!rendering && height.equals("")) {
+ // Width might affect height
+ Util.updateRelativeChildrenAndSendSizeUpdateEvent(client, this);
+ }
+ }
+
+ public void onKeyDown(KeyDownEvent event) {
+ shortcutHandler.handleKeyboardEvent(Event.as(event.getNativeEvent()));
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VLazyExecutor.java b/src/com/vaadin/terminal/gwt/client/ui/VLazyExecutor.java
index 018df57327..aac8ca5ee7 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VLazyExecutor.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VLazyExecutor.java
@@ -1,52 +1,52 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.user.client.Timer;
-
-/**
- * Executes the given command {@code delayMs} milliseconds after a call to
- * {@link #trigger()}. Calling {@link #trigger()} again before the command has
- * been executed causes the execution to be rescheduled to {@code delayMs} after
- * the second call.
- *
- */
-public class VLazyExecutor {
-
- private Timer timer;
- private int delayMs;
- private ScheduledCommand cmd;
-
- /**
- * @param delayMs
- * Delay in milliseconds to wait before executing the command
- * @param cmd
- * The command to execute
- */
- public VLazyExecutor(int delayMs, ScheduledCommand cmd) {
- this.delayMs = delayMs;
- this.cmd = cmd;
- }
-
- /**
- * Triggers execution of the command. Each call reschedules any existing
- * execution to {@link #delayMs} milliseconds from that point in time.
- */
- public void trigger() {
- if (timer == null) {
- timer = new Timer() {
- @Override
- public void run() {
- timer = null;
- cmd.execute();
- }
- };
- }
- // Schedule automatically cancels any old schedule
- timer.schedule(delayMs);
-
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.user.client.Timer;
+
+/**
+ * Executes the given command {@code delayMs} milliseconds after a call to
+ * {@link #trigger()}. Calling {@link #trigger()} again before the command has
+ * been executed causes the execution to be rescheduled to {@code delayMs} after
+ * the second call.
+ *
+ */
+public class VLazyExecutor {
+
+ private Timer timer;
+ private int delayMs;
+ private ScheduledCommand cmd;
+
+ /**
+ * @param delayMs
+ * Delay in milliseconds to wait before executing the command
+ * @param cmd
+ * The command to execute
+ */
+ public VLazyExecutor(int delayMs, ScheduledCommand cmd) {
+ this.delayMs = delayMs;
+ this.cmd = cmd;
+ }
+
+ /**
+ * Triggers execution of the command. Each call reschedules any existing
+ * execution to {@link #delayMs} milliseconds from that point in time.
+ */
+ public void trigger() {
+ if (timer == null) {
+ timer = new Timer() {
+ @Override
+ public void run() {
+ timer = null;
+ cmd.execute();
+ }
+ };
+ }
+ // Schedule automatically cancels any old schedule
+ timer.schedule(delayMs);
+
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VNotification.java b/src/com/vaadin/terminal/gwt/client/ui/VNotification.java
index 128e3bd597..27407c55aa 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VNotification.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VNotification.java
@@ -1,417 +1,417 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.EventObject;
-import java.util.Iterator;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.KeyCodes;
-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.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.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-
-public class VNotification extends VOverlay {
-
- public static final int CENTERED = 1;
- public static final int CENTERED_TOP = 2;
- public static final int CENTERED_BOTTOM = 3;
- public static final int TOP_LEFT = 4;
- public static final int TOP_RIGHT = 5;
- public static final int BOTTOM_LEFT = 6;
- public static final int BOTTOM_RIGHT = 7;
-
- public static final int DELAY_FOREVER = -1;
- public static final int DELAY_NONE = 0;
-
- private static final String STYLENAME = "v-Notification";
- private static final int mouseMoveThreshold = 7;
- private static final int Z_INDEX_BASE = 20000;
- public static final String STYLE_SYSTEM = "system";
- private static final int FADE_ANIMATION_INTERVAL = 50; // == 20 fps
-
- private int startOpacity = 90;
- private int fadeMsec = 400;
- private int delayMsec = 1000;
-
- private Timer fader;
- private Timer delay;
-
- private int x = -1;
- private int y = -1;
-
- private String temporaryStyle;
-
- private ArrayList<EventListener> listeners;
- private static final int TOUCH_DEVICE_IDLE_DELAY = 1000;
-
- /**
- * Default constructor. You should use GWT.create instead.
- */
- public VNotification() {
- setStyleName(STYLENAME);
- sinkEvents(Event.ONCLICK);
- DOM.setStyleAttribute(getElement(), "zIndex", "" + Z_INDEX_BASE);
- }
-
- /**
- * @deprecated Use static {@link #createNotification(int)} instead to enable
- * GWT deferred binding.
- *
- * @param delayMsec
- */
- @Deprecated
- public VNotification(int delayMsec) {
- this();
- this.delayMsec = delayMsec;
- if (BrowserInfo.get().isTouchDevice()) {
- new Timer() {
- @Override
- public void run() {
- if (isAttached()) {
- fade();
- }
- }
- }.schedule(delayMsec + TOUCH_DEVICE_IDLE_DELAY);
- }
- }
-
- /**
- * @deprecated Use static {@link #createNotification(int, int, int)} instead
- * to enable GWT deferred binding.
- *
- * @param delayMsec
- * @param fadeMsec
- * @param startOpacity
- */
- @Deprecated
- public VNotification(int delayMsec, int fadeMsec, int startOpacity) {
- this(delayMsec);
- this.fadeMsec = fadeMsec;
- this.startOpacity = startOpacity;
- }
-
- public void startDelay() {
- DOM.removeEventPreview(this);
- if (delayMsec > 0) {
- if (delay == null) {
- delay = new Timer() {
- @Override
- public void run() {
- fade();
- }
- };
- delay.schedule(delayMsec);
- }
- } else if (delayMsec == 0) {
- fade();
- }
- }
-
- @Override
- public void show() {
- show(CENTERED);
- }
-
- public void show(String style) {
- show(CENTERED, style);
- }
-
- public void show(int position) {
- show(position, null);
- }
-
- public void show(Widget widget, int position, String style) {
- setWidget(widget);
- show(position, style);
- }
-
- public void show(String html, int position, String style) {
- setWidget(new HTML(html));
- show(position, style);
- }
-
- public void show(int position, String style) {
- setOpacity(getElement(), startOpacity);
- if (style != null) {
- temporaryStyle = style;
- addStyleName(style);
- addStyleDependentName(style);
- }
- super.show();
- setPosition(position);
- }
-
- @Override
- public void hide() {
- DOM.removeEventPreview(this);
- cancelDelay();
- cancelFade();
- if (temporaryStyle != null) {
- removeStyleName(temporaryStyle);
- removeStyleDependentName(temporaryStyle);
- temporaryStyle = null;
- }
- super.hide();
- fireEvent(new HideEvent(this));
- }
-
- public void fade() {
- DOM.removeEventPreview(this);
- cancelDelay();
- if (fader == null) {
- fader = new Timer() {
- private final long start = new Date().getTime();
-
- @Override
- public void run() {
- /*
- * To make animation smooth, don't count that event happens
- * on time. Reduce opacity according to the actual time
- * spent instead of fixed decrement.
- */
- long now = new Date().getTime();
- long timeEplaced = now - start;
- float remainingFraction = 1 - timeEplaced
- / (float) fadeMsec;
- int opacity = (int) (startOpacity * remainingFraction);
- if (opacity <= 0) {
- cancel();
- hide();
- if (BrowserInfo.get().isOpera()) {
- // tray notification on opera needs to explicitly
- // define
- // size, reset it
- DOM.setStyleAttribute(getElement(), "width", "");
- DOM.setStyleAttribute(getElement(), "height", "");
- }
- } else {
- setOpacity(getElement(), opacity);
- }
- }
- };
- fader.scheduleRepeating(FADE_ANIMATION_INTERVAL);
- }
- }
-
- public void setPosition(int position) {
- final Element el = getElement();
- DOM.setStyleAttribute(el, "top", "");
- DOM.setStyleAttribute(el, "left", "");
- DOM.setStyleAttribute(el, "bottom", "");
- DOM.setStyleAttribute(el, "right", "");
- switch (position) {
- case TOP_LEFT:
- DOM.setStyleAttribute(el, "top", "0px");
- DOM.setStyleAttribute(el, "left", "0px");
- break;
- case TOP_RIGHT:
- DOM.setStyleAttribute(el, "top", "0px");
- DOM.setStyleAttribute(el, "right", "0px");
- break;
- case BOTTOM_RIGHT:
- DOM.setStyleAttribute(el, "position", "absolute");
- if (BrowserInfo.get().isOpera()) {
- // tray notification on opera needs explicitly defined size
- DOM.setStyleAttribute(el, "width", getOffsetWidth() + "px");
- DOM.setStyleAttribute(el, "height", getOffsetHeight() + "px");
- }
- DOM.setStyleAttribute(el, "bottom", "0px");
- DOM.setStyleAttribute(el, "right", "0px");
- break;
- case BOTTOM_LEFT:
- DOM.setStyleAttribute(el, "bottom", "0px");
- DOM.setStyleAttribute(el, "left", "0px");
- break;
- case CENTERED_TOP:
- center();
- DOM.setStyleAttribute(el, "top", "0px");
- break;
- case CENTERED_BOTTOM:
- center();
- DOM.setStyleAttribute(el, "top", "");
- DOM.setStyleAttribute(el, "bottom", "0px");
- break;
- default:
- case CENTERED:
- center();
- break;
- }
- }
-
- private void cancelFade() {
- if (fader != null) {
- fader.cancel();
- fader = null;
- }
- }
-
- private void cancelDelay() {
- if (delay != null) {
- delay.cancel();
- delay = null;
- }
- }
-
- private void setOpacity(Element el, int opacity) {
- DOM.setStyleAttribute(el, "opacity", "" + (opacity / 100.0));
- if (BrowserInfo.get().isIE()) {
- DOM.setStyleAttribute(el, "filter", "Alpha(opacity=" + opacity
- + ")");
- }
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- DOM.removeEventPreview(this);
- if (fader == null) {
- fade();
- }
- }
-
- @Override
- public boolean onEventPreview(Event event) {
- int type = DOM.eventGetType(event);
- // "modal"
- if (delayMsec == -1 || temporaryStyle == STYLE_SYSTEM) {
- if (type == Event.ONCLICK) {
- if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event))) {
- fade();
- return false;
- }
- } else if (type == Event.ONKEYDOWN
- && event.getKeyCode() == KeyCodes.KEY_ESCAPE) {
- fade();
- return false;
- }
- if (temporaryStyle == STYLE_SYSTEM) {
- return true;
- } else {
- return false;
- }
- }
- // default
- switch (type) {
- case Event.ONMOUSEMOVE:
-
- if (x < 0) {
- x = DOM.eventGetClientX(event);
- y = DOM.eventGetClientY(event);
- } else if (Math.abs(DOM.eventGetClientX(event) - x) > mouseMoveThreshold
- || Math.abs(DOM.eventGetClientY(event) - y) > mouseMoveThreshold) {
- startDelay();
- }
- break;
- case Event.ONMOUSEDOWN:
- case Event.ONMOUSEWHEEL:
- case Event.ONSCROLL:
- startDelay();
- break;
- case Event.ONKEYDOWN:
- if (event.getRepeat()) {
- return true;
- }
- startDelay();
- break;
- default:
- break;
- }
- return true;
- }
-
- public void addEventListener(EventListener listener) {
- if (listeners == null) {
- listeners = new ArrayList<EventListener>();
- }
- listeners.add(listener);
- }
-
- public void removeEventListener(EventListener listener) {
- if (listeners == null) {
- return;
- }
- listeners.remove(listener);
- }
-
- private void fireEvent(HideEvent event) {
- if (listeners != null) {
- for (Iterator<EventListener> it = listeners.iterator(); it
- .hasNext();) {
- EventListener l = it.next();
- l.notificationHidden(event);
- }
- }
- }
-
- public static void showNotification(ApplicationConnection client,
- final UIDL notification) {
- boolean onlyPlainText = notification
- .hasAttribute(VView.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED);
- String html = "";
- if (notification.hasAttribute("icon")) {
- final String parsedUri = client.translateVaadinUri(notification
- .getStringAttribute("icon"));
- html += "<img src=\"" + Util.escapeAttribute(parsedUri) + "\" />";
- }
- if (notification.hasAttribute("caption")) {
- String caption = notification.getStringAttribute("caption");
- if (onlyPlainText) {
- caption = Util.escapeHTML(caption);
- caption = caption.replaceAll("\\n", "<br />");
- }
- html += "<h1>" + caption + "</h1>";
- }
- if (notification.hasAttribute("message")) {
- String message = notification.getStringAttribute("message");
- if (onlyPlainText) {
- message = Util.escapeHTML(message);
- message = message.replaceAll("\\n", "<br />");
- }
- html += "<p>" + message + "</p>";
- }
-
- final String style = notification.hasAttribute("style") ? notification
- .getStringAttribute("style") : null;
- final int position = notification.getIntAttribute("position");
- final int delay = notification.getIntAttribute("delay");
- createNotification(delay).show(html, position, style);
- }
-
- public static VNotification createNotification(int delayMsec) {
- final VNotification notification = GWT.create(VNotification.class);
- notification.delayMsec = delayMsec;
- if (BrowserInfo.get().isTouchDevice()) {
- new Timer() {
- @Override
- public void run() {
- if (notification.isAttached()) {
- notification.fade();
- }
- }
- }.schedule(notification.delayMsec + TOUCH_DEVICE_IDLE_DELAY);
- }
- return notification;
- }
-
- public class HideEvent extends EventObject {
-
- public HideEvent(Object source) {
- super(source);
- }
- }
-
- public interface EventListener extends java.util.EventListener {
- public void notificationHidden(HideEvent event);
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.EventObject;
+import java.util.Iterator;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.KeyCodes;
+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.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.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
+
+public class VNotification extends VOverlay {
+
+ public static final int CENTERED = 1;
+ public static final int CENTERED_TOP = 2;
+ public static final int CENTERED_BOTTOM = 3;
+ public static final int TOP_LEFT = 4;
+ public static final int TOP_RIGHT = 5;
+ public static final int BOTTOM_LEFT = 6;
+ public static final int BOTTOM_RIGHT = 7;
+
+ public static final int DELAY_FOREVER = -1;
+ public static final int DELAY_NONE = 0;
+
+ private static final String STYLENAME = "v-Notification";
+ private static final int mouseMoveThreshold = 7;
+ private static final int Z_INDEX_BASE = 20000;
+ public static final String STYLE_SYSTEM = "system";
+ private static final int FADE_ANIMATION_INTERVAL = 50; // == 20 fps
+
+ private int startOpacity = 90;
+ private int fadeMsec = 400;
+ private int delayMsec = 1000;
+
+ private Timer fader;
+ private Timer delay;
+
+ private int x = -1;
+ private int y = -1;
+
+ private String temporaryStyle;
+
+ private ArrayList<EventListener> listeners;
+ private static final int TOUCH_DEVICE_IDLE_DELAY = 1000;
+
+ /**
+ * Default constructor. You should use GWT.create instead.
+ */
+ public VNotification() {
+ setStyleName(STYLENAME);
+ sinkEvents(Event.ONCLICK);
+ DOM.setStyleAttribute(getElement(), "zIndex", "" + Z_INDEX_BASE);
+ }
+
+ /**
+ * @deprecated Use static {@link #createNotification(int)} instead to enable
+ * GWT deferred binding.
+ *
+ * @param delayMsec
+ */
+ @Deprecated
+ public VNotification(int delayMsec) {
+ this();
+ this.delayMsec = delayMsec;
+ if (BrowserInfo.get().isTouchDevice()) {
+ new Timer() {
+ @Override
+ public void run() {
+ if (isAttached()) {
+ fade();
+ }
+ }
+ }.schedule(delayMsec + TOUCH_DEVICE_IDLE_DELAY);
+ }
+ }
+
+ /**
+ * @deprecated Use static {@link #createNotification(int, int, int)} instead
+ * to enable GWT deferred binding.
+ *
+ * @param delayMsec
+ * @param fadeMsec
+ * @param startOpacity
+ */
+ @Deprecated
+ public VNotification(int delayMsec, int fadeMsec, int startOpacity) {
+ this(delayMsec);
+ this.fadeMsec = fadeMsec;
+ this.startOpacity = startOpacity;
+ }
+
+ public void startDelay() {
+ DOM.removeEventPreview(this);
+ if (delayMsec > 0) {
+ if (delay == null) {
+ delay = new Timer() {
+ @Override
+ public void run() {
+ fade();
+ }
+ };
+ delay.schedule(delayMsec);
+ }
+ } else if (delayMsec == 0) {
+ fade();
+ }
+ }
+
+ @Override
+ public void show() {
+ show(CENTERED);
+ }
+
+ public void show(String style) {
+ show(CENTERED, style);
+ }
+
+ public void show(int position) {
+ show(position, null);
+ }
+
+ public void show(Widget widget, int position, String style) {
+ setWidget(widget);
+ show(position, style);
+ }
+
+ public void show(String html, int position, String style) {
+ setWidget(new HTML(html));
+ show(position, style);
+ }
+
+ public void show(int position, String style) {
+ setOpacity(getElement(), startOpacity);
+ if (style != null) {
+ temporaryStyle = style;
+ addStyleName(style);
+ addStyleDependentName(style);
+ }
+ super.show();
+ setPosition(position);
+ }
+
+ @Override
+ public void hide() {
+ DOM.removeEventPreview(this);
+ cancelDelay();
+ cancelFade();
+ if (temporaryStyle != null) {
+ removeStyleName(temporaryStyle);
+ removeStyleDependentName(temporaryStyle);
+ temporaryStyle = null;
+ }
+ super.hide();
+ fireEvent(new HideEvent(this));
+ }
+
+ public void fade() {
+ DOM.removeEventPreview(this);
+ cancelDelay();
+ if (fader == null) {
+ fader = new Timer() {
+ private final long start = new Date().getTime();
+
+ @Override
+ public void run() {
+ /*
+ * To make animation smooth, don't count that event happens
+ * on time. Reduce opacity according to the actual time
+ * spent instead of fixed decrement.
+ */
+ long now = new Date().getTime();
+ long timeEplaced = now - start;
+ float remainingFraction = 1 - timeEplaced
+ / (float) fadeMsec;
+ int opacity = (int) (startOpacity * remainingFraction);
+ if (opacity <= 0) {
+ cancel();
+ hide();
+ if (BrowserInfo.get().isOpera()) {
+ // tray notification on opera needs to explicitly
+ // define
+ // size, reset it
+ DOM.setStyleAttribute(getElement(), "width", "");
+ DOM.setStyleAttribute(getElement(), "height", "");
+ }
+ } else {
+ setOpacity(getElement(), opacity);
+ }
+ }
+ };
+ fader.scheduleRepeating(FADE_ANIMATION_INTERVAL);
+ }
+ }
+
+ public void setPosition(int position) {
+ final Element el = getElement();
+ DOM.setStyleAttribute(el, "top", "");
+ DOM.setStyleAttribute(el, "left", "");
+ DOM.setStyleAttribute(el, "bottom", "");
+ DOM.setStyleAttribute(el, "right", "");
+ switch (position) {
+ case TOP_LEFT:
+ DOM.setStyleAttribute(el, "top", "0px");
+ DOM.setStyleAttribute(el, "left", "0px");
+ break;
+ case TOP_RIGHT:
+ DOM.setStyleAttribute(el, "top", "0px");
+ DOM.setStyleAttribute(el, "right", "0px");
+ break;
+ case BOTTOM_RIGHT:
+ DOM.setStyleAttribute(el, "position", "absolute");
+ if (BrowserInfo.get().isOpera()) {
+ // tray notification on opera needs explicitly defined size
+ DOM.setStyleAttribute(el, "width", getOffsetWidth() + "px");
+ DOM.setStyleAttribute(el, "height", getOffsetHeight() + "px");
+ }
+ DOM.setStyleAttribute(el, "bottom", "0px");
+ DOM.setStyleAttribute(el, "right", "0px");
+ break;
+ case BOTTOM_LEFT:
+ DOM.setStyleAttribute(el, "bottom", "0px");
+ DOM.setStyleAttribute(el, "left", "0px");
+ break;
+ case CENTERED_TOP:
+ center();
+ DOM.setStyleAttribute(el, "top", "0px");
+ break;
+ case CENTERED_BOTTOM:
+ center();
+ DOM.setStyleAttribute(el, "top", "");
+ DOM.setStyleAttribute(el, "bottom", "0px");
+ break;
+ default:
+ case CENTERED:
+ center();
+ break;
+ }
+ }
+
+ private void cancelFade() {
+ if (fader != null) {
+ fader.cancel();
+ fader = null;
+ }
+ }
+
+ private void cancelDelay() {
+ if (delay != null) {
+ delay.cancel();
+ delay = null;
+ }
+ }
+
+ private void setOpacity(Element el, int opacity) {
+ DOM.setStyleAttribute(el, "opacity", "" + (opacity / 100.0));
+ if (BrowserInfo.get().isIE()) {
+ DOM.setStyleAttribute(el, "filter", "Alpha(opacity=" + opacity
+ + ")");
+ }
+ }
+
+ @Override
+ public void onBrowserEvent(Event event) {
+ DOM.removeEventPreview(this);
+ if (fader == null) {
+ fade();
+ }
+ }
+
+ @Override
+ public boolean onEventPreview(Event event) {
+ int type = DOM.eventGetType(event);
+ // "modal"
+ if (delayMsec == -1 || temporaryStyle == STYLE_SYSTEM) {
+ if (type == Event.ONCLICK) {
+ if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event))) {
+ fade();
+ return false;
+ }
+ } else if (type == Event.ONKEYDOWN
+ && event.getKeyCode() == KeyCodes.KEY_ESCAPE) {
+ fade();
+ return false;
+ }
+ if (temporaryStyle == STYLE_SYSTEM) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ // default
+ switch (type) {
+ case Event.ONMOUSEMOVE:
+
+ if (x < 0) {
+ x = DOM.eventGetClientX(event);
+ y = DOM.eventGetClientY(event);
+ } else if (Math.abs(DOM.eventGetClientX(event) - x) > mouseMoveThreshold
+ || Math.abs(DOM.eventGetClientY(event) - y) > mouseMoveThreshold) {
+ startDelay();
+ }
+ break;
+ case Event.ONMOUSEDOWN:
+ case Event.ONMOUSEWHEEL:
+ case Event.ONSCROLL:
+ startDelay();
+ break;
+ case Event.ONKEYDOWN:
+ if (event.getRepeat()) {
+ return true;
+ }
+ startDelay();
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ public void addEventListener(EventListener listener) {
+ if (listeners == null) {
+ listeners = new ArrayList<EventListener>();
+ }
+ listeners.add(listener);
+ }
+
+ public void removeEventListener(EventListener listener) {
+ if (listeners == null) {
+ return;
+ }
+ listeners.remove(listener);
+ }
+
+ private void fireEvent(HideEvent event) {
+ if (listeners != null) {
+ for (Iterator<EventListener> it = listeners.iterator(); it
+ .hasNext();) {
+ EventListener l = it.next();
+ l.notificationHidden(event);
+ }
+ }
+ }
+
+ public static void showNotification(ApplicationConnection client,
+ final UIDL notification) {
+ boolean onlyPlainText = notification
+ .hasAttribute(VView.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED);
+ String html = "";
+ if (notification.hasAttribute("icon")) {
+ final String parsedUri = client.translateVaadinUri(notification
+ .getStringAttribute("icon"));
+ html += "<img src=\"" + Util.escapeAttribute(parsedUri) + "\" />";
+ }
+ if (notification.hasAttribute("caption")) {
+ String caption = notification.getStringAttribute("caption");
+ if (onlyPlainText) {
+ caption = Util.escapeHTML(caption);
+ caption = caption.replaceAll("\\n", "<br />");
+ }
+ html += "<h1>" + caption + "</h1>";
+ }
+ if (notification.hasAttribute("message")) {
+ String message = notification.getStringAttribute("message");
+ if (onlyPlainText) {
+ message = Util.escapeHTML(message);
+ message = message.replaceAll("\\n", "<br />");
+ }
+ html += "<p>" + message + "</p>";
+ }
+
+ final String style = notification.hasAttribute("style") ? notification
+ .getStringAttribute("style") : null;
+ final int position = notification.getIntAttribute("position");
+ final int delay = notification.getIntAttribute("delay");
+ createNotification(delay).show(html, position, style);
+ }
+
+ public static VNotification createNotification(int delayMsec) {
+ final VNotification notification = GWT.create(VNotification.class);
+ notification.delayMsec = delayMsec;
+ if (BrowserInfo.get().isTouchDevice()) {
+ new Timer() {
+ @Override
+ public void run() {
+ if (notification.isAttached()) {
+ notification.fade();
+ }
+ }
+ }.schedule(notification.delayMsec + TOUCH_DEVICE_IDLE_DELAY);
+ }
+ return notification;
+ }
+
+ public class HideEvent extends EventObject {
+
+ public HideEvent(Object source) {
+ super(source);
+ }
+ }
+
+ public interface EventListener extends java.util.EventListener {
+ public void notificationHidden(HideEvent event);
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOptionGroup.java b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroup.java
index 1b6c681773..662f195fcd 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VOptionGroup.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroup.java
@@ -1,235 +1,235 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.LoadEvent;
-import com.google.gwt.event.dom.client.LoadHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FocusWidget;
-import com.google.gwt.user.client.ui.Focusable;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.RadioButton;
-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.EventId;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-
-public class VOptionGroup extends VOptionGroupBase implements FocusHandler,
- BlurHandler {
-
- public static final String HTML_CONTENT_ALLOWED = "usehtml";
-
- public static final String CLASSNAME = "v-select-optiongroup";
-
- private final Panel panel;
-
- private final Map<CheckBox, String> optionsToKeys;
-
- private boolean sendFocusEvents = false;
- private boolean sendBlurEvents = false;
- private List<HandlerRegistration> focusHandlers = null;
- private List<HandlerRegistration> blurHandlers = null;
-
- private final LoadHandler iconLoadHandler = new LoadHandler() {
- public void onLoad(LoadEvent event) {
- if (BrowserInfo.get().isIE6()) {
- Util.doIE6PngFix((Element) Element.as(event.getNativeEvent()
- .getEventTarget()));
- }
- Util.notifyParentOfSizeChange(VOptionGroup.this, true);
- }
- };
-
- /**
- * used to check whether a blur really was a blur of the complete
- * optiongroup: if a control inside this optiongroup gains focus right after
- * blur of another control inside this optiongroup (meaning: if onFocus
- * fires after onBlur has fired), the blur and focus won't be sent to the
- * server side as only a focus change inside this optiongroup occured
- */
- private boolean blurOccured = false;
-
- private boolean htmlContentAllowed = false;
-
- public VOptionGroup() {
- super(CLASSNAME);
- panel = (Panel) optionsContainer;
- optionsToKeys = new HashMap<CheckBox, String>();
- }
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- htmlContentAllowed = uidl.hasAttribute(HTML_CONTENT_ALLOWED);
-
- super.updateFromUIDL(uidl, client);
-
- sendFocusEvents = client.hasEventListeners(this, EventId.FOCUS);
- sendBlurEvents = client.hasEventListeners(this, EventId.BLUR);
-
- if (focusHandlers != null) {
- for (HandlerRegistration reg : focusHandlers) {
- reg.removeHandler();
- }
- focusHandlers.clear();
- focusHandlers = null;
-
- for (HandlerRegistration reg : blurHandlers) {
- reg.removeHandler();
- }
- blurHandlers.clear();
- blurHandlers = null;
- }
-
- if (sendFocusEvents || sendBlurEvents) {
- focusHandlers = new ArrayList<HandlerRegistration>();
- blurHandlers = new ArrayList<HandlerRegistration>();
-
- // add focus and blur handlers to checkboxes / radio buttons
- for (Widget wid : panel) {
- if (wid instanceof CheckBox) {
- focusHandlers.add(((CheckBox) wid).addFocusHandler(this));
- blurHandlers.add(((CheckBox) wid).addBlurHandler(this));
- }
- }
- }
- }
-
- /*
- * Return true if no elements were changed, false otherwise.
- */
- @Override
- protected void buildOptions(UIDL uidl) {
- panel.clear();
- for (final Iterator<?> it = uidl.getChildIterator(); it.hasNext();) {
- final UIDL opUidl = (UIDL) it.next();
- CheckBox op;
-
- String itemHtml = opUidl.getStringAttribute("caption");
- if (!htmlContentAllowed) {
- itemHtml = Util.escapeHTML(itemHtml);
- }
-
- String icon = opUidl.getStringAttribute("icon");
- if (icon != null && icon.length() != 0) {
- String iconUrl = client.translateVaadinUri(icon);
- itemHtml = "<img src=\"" + iconUrl + "\" class=\""
- + Icon.CLASSNAME + "\" alt=\"\" />" + itemHtml;
- }
-
- if (isMultiselect()) {
- op = new VCheckBox();
- op.setHTML(itemHtml);
- } else {
- op = new RadioButton(id, itemHtml, true);
- op.setStyleName("v-radiobutton");
- }
-
- if (icon != null && icon.length() != 0) {
- Util.sinkOnloadForImages(op.getElement());
- op.addHandler(iconLoadHandler, LoadEvent.getType());
- }
-
- op.addStyleName(CLASSNAME_OPTION);
- op.setValue(opUidl.getBooleanAttribute("selected"));
- boolean enabled = !opUidl.getBooleanAttribute("disabled")
- && !isReadonly() && !isDisabled();
- op.setEnabled(enabled);
- setStyleName(op.getElement(),
- ApplicationConnection.DISABLED_CLASSNAME, !enabled);
- op.addClickHandler(this);
- optionsToKeys.put(op, opUidl.getStringAttribute("key"));
- panel.add(op);
- }
- }
-
- @Override
- protected String[] getSelectedItems() {
- return selectedKeys.toArray(new String[selectedKeys.size()]);
- }
-
- @Override
- public void onClick(ClickEvent event) {
- super.onClick(event);
- if (event.getSource() instanceof CheckBox) {
- final boolean selected = ((CheckBox) event.getSource()).getValue();
- final String key = optionsToKeys.get(event.getSource());
- if (!isMultiselect()) {
- selectedKeys.clear();
- }
- if (selected) {
- selectedKeys.add(key);
- } else {
- selectedKeys.remove(key);
- }
- client.updateVariable(id, "selected", getSelectedItems(),
- isImmediate());
- }
- }
-
- @Override
- protected void setTabIndex(int tabIndex) {
- for (Iterator<Widget> iterator = panel.iterator(); iterator.hasNext();) {
- FocusWidget widget = (FocusWidget) iterator.next();
- widget.setTabIndex(tabIndex);
- }
- }
-
- public void focus() {
- Iterator<Widget> iterator = panel.iterator();
- if (iterator.hasNext()) {
- ((Focusable) iterator.next()).setFocus(true);
- }
- }
-
- public void onFocus(FocusEvent arg0) {
- if (!blurOccured) {
- // no blur occured before this focus event
- // panel was blurred => fire the event to the server side if
- // requested by server side
- if (sendFocusEvents) {
- client.updateVariable(id, EventId.FOCUS, "", true);
- }
- } else {
- // blur occured before this focus event
- // another control inside the panel (checkbox / radio box) was
- // blurred => do not fire the focus and set blurOccured to false, so
- // blur will not be fired, too
- blurOccured = false;
- }
- }
-
- public void onBlur(BlurEvent arg0) {
- blurOccured = true;
- if (sendBlurEvents) {
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- // check whether blurOccured still is true and then send the
- // event out to the server
- if (blurOccured) {
- client.updateVariable(id, EventId.BLUR, "", true);
- blurOccured = false;
- }
- }
- });
- }
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.LoadEvent;
+import com.google.gwt.event.dom.client.LoadHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.FocusWidget;
+import com.google.gwt.user.client.ui.Focusable;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.RadioButton;
+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.EventId;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
+
+public class VOptionGroup extends VOptionGroupBase implements FocusHandler,
+ BlurHandler {
+
+ public static final String HTML_CONTENT_ALLOWED = "usehtml";
+
+ public static final String CLASSNAME = "v-select-optiongroup";
+
+ private final Panel panel;
+
+ private final Map<CheckBox, String> optionsToKeys;
+
+ private boolean sendFocusEvents = false;
+ private boolean sendBlurEvents = false;
+ private List<HandlerRegistration> focusHandlers = null;
+ private List<HandlerRegistration> blurHandlers = null;
+
+ private final LoadHandler iconLoadHandler = new LoadHandler() {
+ public void onLoad(LoadEvent event) {
+ if (BrowserInfo.get().isIE6()) {
+ Util.doIE6PngFix((Element) Element.as(event.getNativeEvent()
+ .getEventTarget()));
+ }
+ Util.notifyParentOfSizeChange(VOptionGroup.this, true);
+ }
+ };
+
+ /**
+ * used to check whether a blur really was a blur of the complete
+ * optiongroup: if a control inside this optiongroup gains focus right after
+ * blur of another control inside this optiongroup (meaning: if onFocus
+ * fires after onBlur has fired), the blur and focus won't be sent to the
+ * server side as only a focus change inside this optiongroup occured
+ */
+ private boolean blurOccured = false;
+
+ private boolean htmlContentAllowed = false;
+
+ public VOptionGroup() {
+ super(CLASSNAME);
+ panel = (Panel) optionsContainer;
+ optionsToKeys = new HashMap<CheckBox, String>();
+ }
+
+ @Override
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ htmlContentAllowed = uidl.hasAttribute(HTML_CONTENT_ALLOWED);
+
+ super.updateFromUIDL(uidl, client);
+
+ sendFocusEvents = client.hasEventListeners(this, EventId.FOCUS);
+ sendBlurEvents = client.hasEventListeners(this, EventId.BLUR);
+
+ if (focusHandlers != null) {
+ for (HandlerRegistration reg : focusHandlers) {
+ reg.removeHandler();
+ }
+ focusHandlers.clear();
+ focusHandlers = null;
+
+ for (HandlerRegistration reg : blurHandlers) {
+ reg.removeHandler();
+ }
+ blurHandlers.clear();
+ blurHandlers = null;
+ }
+
+ if (sendFocusEvents || sendBlurEvents) {
+ focusHandlers = new ArrayList<HandlerRegistration>();
+ blurHandlers = new ArrayList<HandlerRegistration>();
+
+ // add focus and blur handlers to checkboxes / radio buttons
+ for (Widget wid : panel) {
+ if (wid instanceof CheckBox) {
+ focusHandlers.add(((CheckBox) wid).addFocusHandler(this));
+ blurHandlers.add(((CheckBox) wid).addBlurHandler(this));
+ }
+ }
+ }
+ }
+
+ /*
+ * Return true if no elements were changed, false otherwise.
+ */
+ @Override
+ protected void buildOptions(UIDL uidl) {
+ panel.clear();
+ for (final Iterator<?> it = uidl.getChildIterator(); it.hasNext();) {
+ final UIDL opUidl = (UIDL) it.next();
+ CheckBox op;
+
+ String itemHtml = opUidl.getStringAttribute("caption");
+ if (!htmlContentAllowed) {
+ itemHtml = Util.escapeHTML(itemHtml);
+ }
+
+ String icon = opUidl.getStringAttribute("icon");
+ if (icon != null && icon.length() != 0) {
+ String iconUrl = client.translateVaadinUri(icon);
+ itemHtml = "<img src=\"" + iconUrl + "\" class=\""
+ + Icon.CLASSNAME + "\" alt=\"\" />" + itemHtml;
+ }
+
+ if (isMultiselect()) {
+ op = new VCheckBox();
+ op.setHTML(itemHtml);
+ } else {
+ op = new RadioButton(id, itemHtml, true);
+ op.setStyleName("v-radiobutton");
+ }
+
+ if (icon != null && icon.length() != 0) {
+ Util.sinkOnloadForImages(op.getElement());
+ op.addHandler(iconLoadHandler, LoadEvent.getType());
+ }
+
+ op.addStyleName(CLASSNAME_OPTION);
+ op.setValue(opUidl.getBooleanAttribute("selected"));
+ boolean enabled = !opUidl.getBooleanAttribute("disabled")
+ && !isReadonly() && !isDisabled();
+ op.setEnabled(enabled);
+ setStyleName(op.getElement(),
+ ApplicationConnection.DISABLED_CLASSNAME, !enabled);
+ op.addClickHandler(this);
+ optionsToKeys.put(op, opUidl.getStringAttribute("key"));
+ panel.add(op);
+ }
+ }
+
+ @Override
+ protected String[] getSelectedItems() {
+ return selectedKeys.toArray(new String[selectedKeys.size()]);
+ }
+
+ @Override
+ public void onClick(ClickEvent event) {
+ super.onClick(event);
+ if (event.getSource() instanceof CheckBox) {
+ final boolean selected = ((CheckBox) event.getSource()).getValue();
+ final String key = optionsToKeys.get(event.getSource());
+ if (!isMultiselect()) {
+ selectedKeys.clear();
+ }
+ if (selected) {
+ selectedKeys.add(key);
+ } else {
+ selectedKeys.remove(key);
+ }
+ client.updateVariable(id, "selected", getSelectedItems(),
+ isImmediate());
+ }
+ }
+
+ @Override
+ protected void setTabIndex(int tabIndex) {
+ for (Iterator<Widget> iterator = panel.iterator(); iterator.hasNext();) {
+ FocusWidget widget = (FocusWidget) iterator.next();
+ widget.setTabIndex(tabIndex);
+ }
+ }
+
+ public void focus() {
+ Iterator<Widget> iterator = panel.iterator();
+ if (iterator.hasNext()) {
+ ((Focusable) iterator.next()).setFocus(true);
+ }
+ }
+
+ public void onFocus(FocusEvent arg0) {
+ if (!blurOccured) {
+ // no blur occured before this focus event
+ // panel was blurred => fire the event to the server side if
+ // requested by server side
+ if (sendFocusEvents) {
+ client.updateVariable(id, EventId.FOCUS, "", true);
+ }
+ } else {
+ // blur occured before this focus event
+ // another control inside the panel (checkbox / radio box) was
+ // blurred => do not fire the focus and set blurOccured to false, so
+ // blur will not be fired, too
+ blurOccured = false;
+ }
+ }
+
+ public void onBlur(BlurEvent arg0) {
+ blurOccured = true;
+ if (sendBlurEvents) {
+ Scheduler.get().scheduleDeferred(new Command() {
+ public void execute() {
+ // check whether blurOccured still is true and then send the
+ // event out to the server
+ if (blurOccured) {
+ client.updateVariable(id, EventId.BLUR, "", true);
+ blurOccured = false;
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java
index 8be0aff3f0..50a9f8cb98 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java
@@ -1,227 +1,227 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Set;
-
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ChangeHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.Focusable;
-import com.vaadin.terminal.gwt.client.Paintable;
-import com.vaadin.terminal.gwt.client.UIDL;
-
-abstract class VOptionGroupBase extends Composite implements Paintable, Field,
- ClickHandler, ChangeHandler, KeyPressHandler, Focusable {
-
- public static final String CLASSNAME_OPTION = "v-select-option";
-
- protected ApplicationConnection client;
-
- protected String id;
-
- protected Set<String> selectedKeys;
-
- private boolean immediate;
-
- private boolean multiselect;
-
- private boolean disabled;
-
- private boolean readonly;
-
- private int cols = 0;
-
- private int rows = 0;
-
- private boolean nullSelectionAllowed = true;
-
- private boolean nullSelectionItemAvailable = false;
-
- /**
- * Widget holding the different options (e.g. ListBox or Panel for radio
- * buttons) (optional, fallbacks to container Panel)
- */
- protected Widget optionsContainer;
-
- /**
- * Panel containing the component
- */
- private final Panel container;
-
- private VTextField newItemField;
-
- private VNativeButton newItemButton;
-
- public VOptionGroupBase(String classname) {
- container = new FlowPanel();
- initWidget(container);
- optionsContainer = container;
- container.setStyleName(classname);
- immediate = false;
- multiselect = false;
- }
-
- /*
- * Call this if you wish to specify your own container for the option
- * elements (e.g. SELECT)
- */
- public VOptionGroupBase(Widget w, String classname) {
- this(classname);
- optionsContainer = w;
- container.add(optionsContainer);
- }
-
- protected boolean isImmediate() {
- return immediate;
- }
-
- protected boolean isMultiselect() {
- return multiselect;
- }
-
- protected boolean isDisabled() {
- return disabled;
- }
-
- protected boolean isReadonly() {
- return readonly;
- }
-
- protected boolean isNullSelectionAllowed() {
- return nullSelectionAllowed;
- }
-
- protected boolean isNullSelectionItemAvailable() {
- return nullSelectionItemAvailable;
- }
-
- /**
- * @return "cols" specified in uidl, 0 if not specified
- */
- protected int getColumns() {
- return cols;
- }
-
- /**
- * @return "rows" specified in uidl, 0 if not specified
- */
-
- protected int getRows() {
- return rows;
- }
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- this.client = client;
- id = uidl.getId();
-
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- selectedKeys = uidl.getStringArrayVariableAsSet("selected");
-
- readonly = uidl.getBooleanAttribute("readonly");
- disabled = uidl.getBooleanAttribute("disabled");
- multiselect = "multi".equals(uidl.getStringAttribute("selectmode"));
- immediate = uidl.getBooleanAttribute("immediate");
- nullSelectionAllowed = uidl.getBooleanAttribute("nullselect");
- nullSelectionItemAvailable = uidl.getBooleanAttribute("nullselectitem");
-
- if (uidl.hasAttribute("cols")) {
- cols = uidl.getIntAttribute("cols");
- }
- if (uidl.hasAttribute("rows")) {
- rows = uidl.getIntAttribute("rows");
- }
-
- final UIDL ops = uidl.getChildUIDL(0);
-
- if (getColumns() > 0) {
- container.setWidth(getColumns() + "em");
- if (container != optionsContainer) {
- optionsContainer.setWidth("100%");
- }
- }
-
- buildOptions(ops);
-
- if (uidl.getBooleanAttribute("allownewitem")) {
- if (newItemField == null) {
- newItemButton = new VNativeButton();
- newItemButton.setText("+");
- newItemButton.addClickHandler(this);
- newItemField = new VTextField();
- newItemField.addKeyPressHandler(this);
- }
- newItemField.setEnabled(!disabled && !readonly);
- newItemButton.setEnabled(!disabled && !readonly);
-
- if (newItemField == null || newItemField.getParent() != container) {
- container.add(newItemField);
- container.add(newItemButton);
- final int w = container.getOffsetWidth()
- - newItemButton.getOffsetWidth();
- newItemField.setWidth(Math.max(w, 0) + "px");
- }
- } else if (newItemField != null) {
- container.remove(newItemField);
- container.remove(newItemButton);
- }
-
- setTabIndex(uidl.hasAttribute("tabindex") ? uidl
- .getIntAttribute("tabindex") : 0);
-
- }
-
- abstract protected void setTabIndex(int tabIndex);
-
- public void onClick(ClickEvent event) {
- if (event.getSource() == newItemButton
- && !newItemField.getText().equals("")) {
- client.updateVariable(id, "newitem", newItemField.getText(), true);
- newItemField.setText("");
- }
- }
-
- public void onChange(ChangeEvent event) {
- if (multiselect) {
- client.updateVariable(id, "selected", getSelectedItems(), immediate);
- } else {
- client.updateVariable(id, "selected", new String[] { ""
- + getSelectedItem() }, immediate);
- }
- }
-
- public void onKeyPress(KeyPressEvent event) {
- if (event.getSource() == newItemField
- && event.getCharCode() == KeyCodes.KEY_ENTER) {
- newItemButton.click();
- }
- }
-
- protected abstract void buildOptions(UIDL uidl);
-
- protected abstract String[] getSelectedItems();
-
- protected String getSelectedItem() {
- final String[] sel = getSelectedItems();
- if (sel.length > 0) {
- return sel[0];
- } else {
- return null;
- }
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Set;
+
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.Focusable;
+import com.vaadin.terminal.gwt.client.Paintable;
+import com.vaadin.terminal.gwt.client.UIDL;
+
+abstract class VOptionGroupBase extends Composite implements Paintable, Field,
+ ClickHandler, ChangeHandler, KeyPressHandler, Focusable {
+
+ public static final String CLASSNAME_OPTION = "v-select-option";
+
+ protected ApplicationConnection client;
+
+ protected String id;
+
+ protected Set<String> selectedKeys;
+
+ private boolean immediate;
+
+ private boolean multiselect;
+
+ private boolean disabled;
+
+ private boolean readonly;
+
+ private int cols = 0;
+
+ private int rows = 0;
+
+ private boolean nullSelectionAllowed = true;
+
+ private boolean nullSelectionItemAvailable = false;
+
+ /**
+ * Widget holding the different options (e.g. ListBox or Panel for radio
+ * buttons) (optional, fallbacks to container Panel)
+ */
+ protected Widget optionsContainer;
+
+ /**
+ * Panel containing the component
+ */
+ private final Panel container;
+
+ private VTextField newItemField;
+
+ private VNativeButton newItemButton;
+
+ public VOptionGroupBase(String classname) {
+ container = new FlowPanel();
+ initWidget(container);
+ optionsContainer = container;
+ container.setStyleName(classname);
+ immediate = false;
+ multiselect = false;
+ }
+
+ /*
+ * Call this if you wish to specify your own container for the option
+ * elements (e.g. SELECT)
+ */
+ public VOptionGroupBase(Widget w, String classname) {
+ this(classname);
+ optionsContainer = w;
+ container.add(optionsContainer);
+ }
+
+ protected boolean isImmediate() {
+ return immediate;
+ }
+
+ protected boolean isMultiselect() {
+ return multiselect;
+ }
+
+ protected boolean isDisabled() {
+ return disabled;
+ }
+
+ protected boolean isReadonly() {
+ return readonly;
+ }
+
+ protected boolean isNullSelectionAllowed() {
+ return nullSelectionAllowed;
+ }
+
+ protected boolean isNullSelectionItemAvailable() {
+ return nullSelectionItemAvailable;
+ }
+
+ /**
+ * @return "cols" specified in uidl, 0 if not specified
+ */
+ protected int getColumns() {
+ return cols;
+ }
+
+ /**
+ * @return "rows" specified in uidl, 0 if not specified
+ */
+
+ protected int getRows() {
+ return rows;
+ }
+
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ this.client = client;
+ id = uidl.getId();
+
+ if (client.updateComponent(this, uidl, true)) {
+ return;
+ }
+
+ selectedKeys = uidl.getStringArrayVariableAsSet("selected");
+
+ readonly = uidl.getBooleanAttribute("readonly");
+ disabled = uidl.getBooleanAttribute("disabled");
+ multiselect = "multi".equals(uidl.getStringAttribute("selectmode"));
+ immediate = uidl.getBooleanAttribute("immediate");
+ nullSelectionAllowed = uidl.getBooleanAttribute("nullselect");
+ nullSelectionItemAvailable = uidl.getBooleanAttribute("nullselectitem");
+
+ if (uidl.hasAttribute("cols")) {
+ cols = uidl.getIntAttribute("cols");
+ }
+ if (uidl.hasAttribute("rows")) {
+ rows = uidl.getIntAttribute("rows");
+ }
+
+ final UIDL ops = uidl.getChildUIDL(0);
+
+ if (getColumns() > 0) {
+ container.setWidth(getColumns() + "em");
+ if (container != optionsContainer) {
+ optionsContainer.setWidth("100%");
+ }
+ }
+
+ buildOptions(ops);
+
+ if (uidl.getBooleanAttribute("allownewitem")) {
+ if (newItemField == null) {
+ newItemButton = new VNativeButton();
+ newItemButton.setText("+");
+ newItemButton.addClickHandler(this);
+ newItemField = new VTextField();
+ newItemField.addKeyPressHandler(this);
+ }
+ newItemField.setEnabled(!disabled && !readonly);
+ newItemButton.setEnabled(!disabled && !readonly);
+
+ if (newItemField == null || newItemField.getParent() != container) {
+ container.add(newItemField);
+ container.add(newItemButton);
+ final int w = container.getOffsetWidth()
+ - newItemButton.getOffsetWidth();
+ newItemField.setWidth(Math.max(w, 0) + "px");
+ }
+ } else if (newItemField != null) {
+ container.remove(newItemField);
+ container.remove(newItemButton);
+ }
+
+ setTabIndex(uidl.hasAttribute("tabindex") ? uidl
+ .getIntAttribute("tabindex") : 0);
+
+ }
+
+ abstract protected void setTabIndex(int tabIndex);
+
+ public void onClick(ClickEvent event) {
+ if (event.getSource() == newItemButton
+ && !newItemField.getText().equals("")) {
+ client.updateVariable(id, "newitem", newItemField.getText(), true);
+ newItemField.setText("");
+ }
+ }
+
+ public void onChange(ChangeEvent event) {
+ if (multiselect) {
+ client.updateVariable(id, "selected", getSelectedItems(), immediate);
+ } else {
+ client.updateVariable(id, "selected", new String[] { ""
+ + getSelectedItem() }, immediate);
+ }
+ }
+
+ public void onKeyPress(KeyPressEvent event) {
+ if (event.getSource() == newItemField
+ && event.getCharCode() == KeyCodes.KEY_ENTER) {
+ newItemButton.click();
+ }
+ }
+
+ protected abstract void buildOptions(UIDL uidl);
+
+ protected abstract String[] getSelectedItems();
+
+ protected String getSelectedItem() {
+ final String[] sel = getSelectedItems();
+ if (sel.length > 0) {
+ return sel[0];
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java
index 84a22bc272..ecdb171ec4 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java
@@ -885,7 +885,7 @@ public class VOrderedLayout extends CellBasedLayout {
protected void updateAlignmentsAndExpandRatios(UIDL uidl,
ArrayList<Widget> renderedWidgets) {
- /*
+ /*
*/
alignments = uidl.getMapAttribute("alignments");
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPasswordField.java b/src/com/vaadin/terminal/gwt/client/ui/VPasswordField.java
index 945f0d85e6..5182457067 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VPasswordField.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VPasswordField.java
@@ -1,21 +1,21 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.user.client.DOM;
-
-/**
- * This class represents a password field.
- *
- * @author Vaadin Ltd.
- *
- */
-public class VPasswordField extends VTextField {
-
- public VPasswordField() {
- super(DOM.createInputPassword());
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.user.client.DOM;
+
+/**
+ * This class represents a password field.
+ *
+ * @author Vaadin Ltd.
+ *
+ */
+public class VPasswordField extends VTextField {
+
+ public VPasswordField() {
+ super(DOM.createInputPassword());
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java
index 549248aab3..8bf2f6bfbf 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java
@@ -1,482 +1,482 @@
-/*
-@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.Paintable;
-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 Paintable, 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 (getCurrentResolution() == RESOLUTION_MSEC) {
- getClient().updateVariable(
- getId(),
- "msec",
- DateTimeService
- .getMilliseconds(newDate),
- 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 IE6/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.Paintable;
+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 Paintable, 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 (getCurrentResolution() == RESOLUTION_MSEC) {
+ getClient().updateVariable(
+ getId(),
+ "msec",
+ DateTimeService
+ .getMilliseconds(newDate),
+ 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 IE6/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/VSlider.java b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java
index 9dfab44b93..a001ca7f13 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java
@@ -1,599 +1,603 @@
-/*
-@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.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.Paintable;
-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 Paintable, 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 boolean scrollbarStyle;
-
- private int acceleration = 1;
- private int handleSize;
- private double min;
- private double max;
- private int resolution;
- private Double value;
- private boolean vertical;
- private boolean arrows;
-
- 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");
- arrows = uidl.hasAttribute("arrows");
-
- String style = "";
- if (uidl.hasAttribute("style")) {
- style = uidl.getStringAttribute("style");
- }
-
- scrollbarStyle = style.indexOf("scrollbar") > -1;
-
- if (arrows) {
- DOM.setStyleAttribute(smaller, "display", "block");
- DOM.setStyleAttribute(bigger, "display", "block");
- }
-
- 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);
-
- handleSize = uidl.getIntAttribute("hsize");
-
- 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 styleAttribute = vertical ? "height" : "width";
- final String handleAttribute = vertical ? "marginTop" : "marginLeft";
- final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
-
- DOM.setStyleAttribute(handle, handleAttribute, "0");
-
- if (scrollbarStyle) {
- // Only stretch the handle if scrollbar style is set.
- int s = (int) (Double.parseDouble(DOM.getElementProperty(base,
- domProperty)) / 100 * handleSize);
- if (handleSize == -1) {
- final int baseS = Integer.parseInt(DOM.getElementProperty(base,
- domProperty));
- final double range = (max - min) * (resolution + 1) * 3;
- s = (int) (baseS - range);
- }
- if (s < 3) {
- s = 3;
- }
- DOM.setStyleAttribute(handle, styleAttribute, s + "px");
- } else {
- DOM.setStyleAttribute(handle, styleAttribute, "");
- }
-
- // 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) {
- // IE6 rounding behaves a little unstable, reduce one pixel so the
- // containing element (base) won't expand without limits
- p = range - p - (BrowserInfo.get().isIE6() ? 1 : 0);
- }
- 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;
- }
-}
+/*
+@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.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.Paintable;
+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 Paintable, 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 boolean scrollbarStyle;
+
+ private int acceleration = 1;
+ private int handleSize;
+ private double min;
+ private double max;
+ private int resolution;
+ private Double value;
+ private boolean vertical;
+ private boolean arrows;
+
+ 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");
+ arrows = uidl.hasAttribute("arrows");
+
+ String style = "";
+ if (uidl.hasAttribute("style")) {
+ style = uidl.getStringAttribute("style");
+ }
+
+ scrollbarStyle = style.indexOf("scrollbar") > -1;
+
+ if (arrows) {
+ DOM.setStyleAttribute(smaller, "display", "block");
+ DOM.setStyleAttribute(bigger, "display", "block");
+ }
+
+ 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);
+
+ handleSize = uidl.getIntAttribute("hsize");
+
+ 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 styleAttribute = vertical ? "height" : "width";
+ final String handleAttribute = vertical ? "marginTop" : "marginLeft";
+ final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
+
+ DOM.setStyleAttribute(handle, handleAttribute, "0");
+
+ if (scrollbarStyle) {
+ // Only stretch the handle if scrollbar style is set.
+ int s = (int) (Double.parseDouble(DOM.getElementProperty(base,
+ domProperty)) / 100 * handleSize);
+ if (handleSize == -1) {
+ final int baseS = Integer.parseInt(DOM.getElementProperty(base,
+ domProperty));
+ final double range = (max - min) * (resolution + 1) * 3;
+ s = (int) (baseS - range);
+ }
+ if (s < 3) {
+ s = 3;
+ }
+ DOM.setStyleAttribute(handle, styleAttribute, s + "px");
+ } else {
+ DOM.setStyleAttribute(handle, styleAttribute, "");
+ }
+
+ // 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) {
+ // IE6 rounding behaves a little unstable, reduce one pixel so the
+ // containing element (base) won't expand without limits
+ p = range - p - (BrowserInfo.get().isIE6() ? 1 : 0);
+ }
+ 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;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java
index c33daed440..126b0ebea1 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java
@@ -1,214 +1,214 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.dom.client.Node;
-import com.google.gwt.dom.client.NodeList;
-import com.google.gwt.event.dom.client.TouchStartEvent;
-import com.google.gwt.event.dom.client.TouchStartHandler;
-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.ComplexPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.Util;
-
-/**
- * A panel that displays all of its child widgets in a 'deck', where only one
- * can be visible at a time. It is used by
- * {@link com.vaadin.terminal.gwt.client.ui.VTabsheet}.
- *
- * This class has the same basic functionality as the GWT DeckPanel
- * {@link com.google.gwt.user.client.ui.DeckPanel}, with the exception that it
- * doesn't manipulate the child widgets' width and height attributes.
- */
-public class VTabsheetPanel extends ComplexPanel {
-
- private Widget visibleWidget;
- private TouchScrollDelegate touchScrollDelegate;
-
- /**
- * Creates an empty tabsheet panel.
- */
- public VTabsheetPanel() {
- setElement(DOM.createDiv());
- sinkEvents(Event.TOUCHEVENTS);
- addDomHandler(new TouchStartHandler() {
- public void onTouchStart(TouchStartEvent event) {
- /*
- * All container elements needs to be scrollable by one finger.
- * Update the scrollable element list of touch delegate on each
- * touch start.
- */
- NodeList<Node> childNodes = getElement().getChildNodes();
- Element[] elements = new Element[childNodes.getLength()];
- for (int i = 0; i < elements.length; i++) {
- elements[i] = (Element) childNodes.getItem(i);
- }
- getTouchScrollDelegate().setElements(elements);
- getTouchScrollDelegate().onTouchStart(event);
- }
- }, TouchStartEvent.getType());
- }
-
- protected TouchScrollDelegate getTouchScrollDelegate() {
- if (touchScrollDelegate == null) {
- touchScrollDelegate = new TouchScrollDelegate();
- }
- return touchScrollDelegate;
-
- }
-
- /**
- * Adds the specified widget to the deck.
- *
- * @param w
- * the widget to be added
- */
- @Override
- public void add(Widget w) {
- Element el = createContainerElement();
- DOM.appendChild(getElement(), el);
- super.add(w, el);
- }
-
- private Element createContainerElement() {
- Element el = DOM.createDiv();
- DOM.setStyleAttribute(el, "position", "absolute");
- DOM.setStyleAttribute(el, "overflow", "auto");
- hide(el);
- return el;
- }
-
- /**
- * Gets the index of the currently-visible widget.
- *
- * @return the visible widget's index
- */
- public int getVisibleWidget() {
- return getWidgetIndex(visibleWidget);
- }
-
- /**
- * Inserts a widget before the specified index.
- *
- * @param w
- * the widget to be inserted
- * @param beforeIndex
- * the index before which it will be inserted
- * @throws IndexOutOfBoundsException
- * if <code>beforeIndex</code> is out of range
- */
- public void insert(Widget w, int beforeIndex) {
- Element el = createContainerElement();
- DOM.insertChild(getElement(), el, beforeIndex);
- super.insert(w, el, beforeIndex, false);
- }
-
- @Override
- public boolean remove(Widget w) {
- Element child = w.getElement();
- Element parent = null;
- if (child != null) {
- parent = DOM.getParent(child);
- }
- final boolean removed = super.remove(w);
- if (removed) {
- if (visibleWidget == w) {
- visibleWidget = null;
- }
- if (parent != null) {
- DOM.removeChild(getElement(), parent);
- }
- }
- return removed;
- }
-
- /**
- * Shows the widget at the specified index. This causes the currently-
- * visible widget to be hidden.
- *
- * @param index
- * the index of the widget to be shown
- */
- public void showWidget(int index) {
- checkIndexBoundsForAccess(index);
- Widget newVisible = getWidget(index);
- if (visibleWidget != newVisible) {
- if (visibleWidget != null) {
- hide(DOM.getParent(visibleWidget.getElement()));
- }
- visibleWidget = newVisible;
- unHide(DOM.getParent(visibleWidget.getElement()));
- }
- }
-
- private void hide(Element e) {
- DOM.setStyleAttribute(e, "visibility", "hidden");
- DOM.setStyleAttribute(e, "top", "-100000px");
- DOM.setStyleAttribute(e, "left", "-100000px");
- }
-
- private void unHide(Element e) {
- DOM.setStyleAttribute(e, "top", "0px");
- DOM.setStyleAttribute(e, "left", "0px");
- DOM.setStyleAttribute(e, "visibility", "");
- }
-
- public void fixVisibleTabSize(int width, int height, int minWidth) {
- if (visibleWidget == null) {
- return;
- }
-
- boolean dynamicHeight = false;
-
- if (height < 0) {
- height = visibleWidget.getOffsetHeight();
- dynamicHeight = true;
- }
- if (width < 0) {
- width = visibleWidget.getOffsetWidth();
- }
- if (width < minWidth) {
- width = minWidth;
- }
-
- Element wrapperDiv = (Element) visibleWidget.getElement()
- .getParentElement();
-
- // width first
- getElement().getStyle().setPropertyPx("width", width);
- wrapperDiv.getStyle().setPropertyPx("width", width);
-
- if (dynamicHeight) {
- // height of widget might have changed due wrapping
- height = visibleWidget.getOffsetHeight();
- }
- // v-tabsheet-tabsheetpanel height
- getElement().getStyle().setPropertyPx("height", height);
-
- // widget wrapper height
- wrapperDiv.getStyle().setPropertyPx("height", height);
- runWebkitOverflowAutoFix();
- }
-
- public void runWebkitOverflowAutoFix() {
- if (visibleWidget != null) {
- Util.runWebkitOverflowAutoFix(DOM.getParent(visibleWidget
- .getElement()));
- }
-
- }
-
- public void replaceComponent(Widget oldComponent, Widget newComponent) {
- boolean isVisible = (visibleWidget == oldComponent);
- int widgetIndex = getWidgetIndex(oldComponent);
- remove(oldComponent);
- insert(newComponent, widgetIndex);
- if (isVisible) {
- showWidget(widgetIndex);
- }
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.dom.client.Node;
+import com.google.gwt.dom.client.NodeList;
+import com.google.gwt.event.dom.client.TouchStartEvent;
+import com.google.gwt.event.dom.client.TouchStartHandler;
+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.ComplexPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.Util;
+
+/**
+ * A panel that displays all of its child widgets in a 'deck', where only one
+ * can be visible at a time. It is used by
+ * {@link com.vaadin.terminal.gwt.client.ui.VTabsheet}.
+ *
+ * This class has the same basic functionality as the GWT DeckPanel
+ * {@link com.google.gwt.user.client.ui.DeckPanel}, with the exception that it
+ * doesn't manipulate the child widgets' width and height attributes.
+ */
+public class VTabsheetPanel extends ComplexPanel {
+
+ private Widget visibleWidget;
+ private TouchScrollDelegate touchScrollDelegate;
+
+ /**
+ * Creates an empty tabsheet panel.
+ */
+ public VTabsheetPanel() {
+ setElement(DOM.createDiv());
+ sinkEvents(Event.TOUCHEVENTS);
+ addDomHandler(new TouchStartHandler() {
+ public void onTouchStart(TouchStartEvent event) {
+ /*
+ * All container elements needs to be scrollable by one finger.
+ * Update the scrollable element list of touch delegate on each
+ * touch start.
+ */
+ NodeList<Node> childNodes = getElement().getChildNodes();
+ Element[] elements = new Element[childNodes.getLength()];
+ for (int i = 0; i < elements.length; i++) {
+ elements[i] = (Element) childNodes.getItem(i);
+ }
+ getTouchScrollDelegate().setElements(elements);
+ getTouchScrollDelegate().onTouchStart(event);
+ }
+ }, TouchStartEvent.getType());
+ }
+
+ protected TouchScrollDelegate getTouchScrollDelegate() {
+ if (touchScrollDelegate == null) {
+ touchScrollDelegate = new TouchScrollDelegate();
+ }
+ return touchScrollDelegate;
+
+ }
+
+ /**
+ * Adds the specified widget to the deck.
+ *
+ * @param w
+ * the widget to be added
+ */
+ @Override
+ public void add(Widget w) {
+ Element el = createContainerElement();
+ DOM.appendChild(getElement(), el);
+ super.add(w, el);
+ }
+
+ private Element createContainerElement() {
+ Element el = DOM.createDiv();
+ DOM.setStyleAttribute(el, "position", "absolute");
+ DOM.setStyleAttribute(el, "overflow", "auto");
+ hide(el);
+ return el;
+ }
+
+ /**
+ * Gets the index of the currently-visible widget.
+ *
+ * @return the visible widget's index
+ */
+ public int getVisibleWidget() {
+ return getWidgetIndex(visibleWidget);
+ }
+
+ /**
+ * Inserts a widget before the specified index.
+ *
+ * @param w
+ * the widget to be inserted
+ * @param beforeIndex
+ * the index before which it will be inserted
+ * @throws IndexOutOfBoundsException
+ * if <code>beforeIndex</code> is out of range
+ */
+ public void insert(Widget w, int beforeIndex) {
+ Element el = createContainerElement();
+ DOM.insertChild(getElement(), el, beforeIndex);
+ super.insert(w, el, beforeIndex, false);
+ }
+
+ @Override
+ public boolean remove(Widget w) {
+ Element child = w.getElement();
+ Element parent = null;
+ if (child != null) {
+ parent = DOM.getParent(child);
+ }
+ final boolean removed = super.remove(w);
+ if (removed) {
+ if (visibleWidget == w) {
+ visibleWidget = null;
+ }
+ if (parent != null) {
+ DOM.removeChild(getElement(), parent);
+ }
+ }
+ return removed;
+ }
+
+ /**
+ * Shows the widget at the specified index. This causes the currently-
+ * visible widget to be hidden.
+ *
+ * @param index
+ * the index of the widget to be shown
+ */
+ public void showWidget(int index) {
+ checkIndexBoundsForAccess(index);
+ Widget newVisible = getWidget(index);
+ if (visibleWidget != newVisible) {
+ if (visibleWidget != null) {
+ hide(DOM.getParent(visibleWidget.getElement()));
+ }
+ visibleWidget = newVisible;
+ unHide(DOM.getParent(visibleWidget.getElement()));
+ }
+ }
+
+ private void hide(Element e) {
+ DOM.setStyleAttribute(e, "visibility", "hidden");
+ DOM.setStyleAttribute(e, "top", "-100000px");
+ DOM.setStyleAttribute(e, "left", "-100000px");
+ }
+
+ private void unHide(Element e) {
+ DOM.setStyleAttribute(e, "top", "0px");
+ DOM.setStyleAttribute(e, "left", "0px");
+ DOM.setStyleAttribute(e, "visibility", "");
+ }
+
+ public void fixVisibleTabSize(int width, int height, int minWidth) {
+ if (visibleWidget == null) {
+ return;
+ }
+
+ boolean dynamicHeight = false;
+
+ if (height < 0) {
+ height = visibleWidget.getOffsetHeight();
+ dynamicHeight = true;
+ }
+ if (width < 0) {
+ width = visibleWidget.getOffsetWidth();
+ }
+ if (width < minWidth) {
+ width = minWidth;
+ }
+
+ Element wrapperDiv = (Element) visibleWidget.getElement()
+ .getParentElement();
+
+ // width first
+ getElement().getStyle().setPropertyPx("width", width);
+ wrapperDiv.getStyle().setPropertyPx("width", width);
+
+ if (dynamicHeight) {
+ // height of widget might have changed due wrapping
+ height = visibleWidget.getOffsetHeight();
+ }
+ // v-tabsheet-tabsheetpanel height
+ getElement().getStyle().setPropertyPx("height", height);
+
+ // widget wrapper height
+ wrapperDiv.getStyle().setPropertyPx("height", height);
+ runWebkitOverflowAutoFix();
+ }
+
+ public void runWebkitOverflowAutoFix() {
+ if (visibleWidget != null) {
+ Util.runWebkitOverflowAutoFix(DOM.getParent(visibleWidget
+ .getElement()));
+ }
+
+ }
+
+ public void replaceComponent(Widget oldComponent, Widget newComponent) {
+ boolean isVisible = (visibleWidget == oldComponent);
+ int widgetIndex = getWidgetIndex(oldComponent);
+ remove(oldComponent);
+ insert(newComponent, widgetIndex);
+ if (isVisible) {
+ showWidget(widgetIndex);
+ }
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java b/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java
index cd09e24d67..c6107e3b0e 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java
@@ -1,79 +1,79 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.Scheduler;
-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.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-
-/**
- * This class represents a multiline textfield (textarea).
- *
- * TODO consider replacing this with a RichTextArea based implementation. IE
- * does not support CSS height for textareas in Strict mode :-(
- *
- * @author Vaadin Ltd.
- *
- */
-public class VTextArea extends VTextField {
- public static final String CLASSNAME = "v-textarea";
-
- public VTextArea() {
- super(DOM.createTextArea());
- setStyleName(CLASSNAME);
- }
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- // Call parent renderer explicitly
- super.updateFromUIDL(uidl, client);
-
- if (uidl.hasAttribute("rows")) {
- setRows(uidl.getIntAttribute("rows"));
- }
-
- if (getMaxLength() >= 0) {
- sinkEvents(Event.ONKEYUP);
- }
- }
-
- public void setRows(int rows) {
- setRows(getElement(), rows);
- }
-
- private native void setRows(Element e, int r)
- /*-{
- try {
- if(e.tagName.toLowerCase() == "textarea")
- e.rows = r;
- } catch (e) {}
- }-*/;
-
- @Override
- public void onBrowserEvent(Event event) {
- if (getMaxLength() >= 0 && event.getTypeInt() == Event.ONKEYUP) {
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- if (getText().length() > getMaxLength()) {
- setText(getText().substring(0, getMaxLength()));
- }
- }
- });
- }
- 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());
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.core.client.Scheduler;
+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.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.UIDL;
+
+/**
+ * This class represents a multiline textfield (textarea).
+ *
+ * TODO consider replacing this with a RichTextArea based implementation. IE
+ * does not support CSS height for textareas in Strict mode :-(
+ *
+ * @author Vaadin Ltd.
+ *
+ */
+public class VTextArea extends VTextField {
+ public static final String CLASSNAME = "v-textarea";
+
+ public VTextArea() {
+ super(DOM.createTextArea());
+ setStyleName(CLASSNAME);
+ }
+
+ @Override
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ // Call parent renderer explicitly
+ super.updateFromUIDL(uidl, client);
+
+ if (uidl.hasAttribute("rows")) {
+ setRows(uidl.getIntAttribute("rows"));
+ }
+
+ if (getMaxLength() >= 0) {
+ sinkEvents(Event.ONKEYUP);
+ }
+ }
+
+ public void setRows(int rows) {
+ setRows(getElement(), rows);
+ }
+
+ private native void setRows(Element e, int r)
+ /*-{
+ try {
+ if(e.tagName.toLowerCase() == "textarea")
+ e.rows = r;
+ } catch (e) {}
+ }-*/;
+
+ @Override
+ public void onBrowserEvent(Event event) {
+ if (getMaxLength() >= 0 && event.getTypeInt() == Event.ONKEYUP) {
+ Scheduler.get().scheduleDeferred(new Command() {
+ public void execute() {
+ if (getText().length() > getMaxLength()) {
+ setText(getText().substring(0, getMaxLength()));
+ }
+ }
+ });
+ }
+ 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/VTwinColSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java
index 1353915d01..b569dbc94e 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java
@@ -1,645 +1,645 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import com.google.gwt.dom.client.Style.Overflow;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.DoubleClickEvent;
-import com.google.gwt.event.dom.client.DoubleClickHandler;
-import com.google.gwt.event.dom.client.HasDoubleClickHandlers;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.MouseDownEvent;
-import com.google.gwt.event.dom.client.MouseDownHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.Panel;
-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 VTwinColSelect extends VOptionGroupBase implements KeyDownHandler,
- MouseDownHandler, DoubleClickHandler, SubPartAware {
-
- private static final String CLASSNAME = "v-select-twincol";
- public static final String ATTRIBUTE_LEFT_CAPTION = "lc";
- public static final String ATTRIBUTE_RIGHT_CAPTION = "rc";
-
- private static final int VISIBLE_COUNT = 10;
-
- private static final int DEFAULT_COLUMN_COUNT = 10;
-
- private final DoubleClickListBox options;
-
- private final DoubleClickListBox selections;
-
- private FlowPanel captionWrapper;
-
- private HTML optionsCaption = null;
-
- private HTML selectionsCaption = null;
-
- private final VButton add;
-
- private final VButton remove;
-
- private final FlowPanel buttons;
-
- private final Panel panel;
-
- private boolean widthSet = false;
-
- /**
- * A ListBox which catches double clicks
- *
- */
- public class DoubleClickListBox extends ListBox implements
- HasDoubleClickHandlers {
- public DoubleClickListBox(boolean isMultipleSelect) {
- super(isMultipleSelect);
- }
-
- public DoubleClickListBox() {
- super();
- }
-
- @Override
- public HandlerRegistration addDoubleClickHandler(
- DoubleClickHandler handler) {
- return addDomHandler(handler, DoubleClickEvent.getType());
- }
- }
-
- public VTwinColSelect() {
- super(CLASSNAME);
-
- captionWrapper = new FlowPanel();
-
- options = new DoubleClickListBox();
- options.addClickHandler(this);
- options.addDoubleClickHandler(this);
- options.setVisibleItemCount(VISIBLE_COUNT);
- options.setStyleName(CLASSNAME + "-options");
-
- selections = new DoubleClickListBox();
- selections.addClickHandler(this);
- selections.addDoubleClickHandler(this);
- selections.setVisibleItemCount(VISIBLE_COUNT);
- selections.setStyleName(CLASSNAME + "-selections");
-
- buttons = new FlowPanel();
- buttons.setStyleName(CLASSNAME + "-buttons");
- add = new VButton();
- add.setText(">>");
- add.addClickHandler(this);
- remove = new VButton();
- remove.setText("<<");
- remove.addClickHandler(this);
-
- panel = ((Panel) optionsContainer);
-
- panel.add(captionWrapper);
- captionWrapper.getElement().getStyle().setOverflow(Overflow.HIDDEN);
- // Hide until there actually is a caption to prevent IE from rendering
- // extra empty space
- captionWrapper.setVisible(false);
-
- panel.add(options);
- buttons.add(add);
- final HTML br = new HTML("<span/>");
- br.setStyleName(CLASSNAME + "-deco");
- buttons.add(br);
- buttons.add(remove);
- panel.add(buttons);
- panel.add(selections);
-
- options.addKeyDownHandler(this);
- options.addMouseDownHandler(this);
-
- selections.addMouseDownHandler(this);
- selections.addKeyDownHandler(this);
- }
-
- public HTML getOptionsCaption() {
- if (optionsCaption == null) {
- optionsCaption = new HTML();
- optionsCaption.setStyleName(CLASSNAME + "-caption-left");
- optionsCaption.getElement().getStyle()
- .setFloat(com.google.gwt.dom.client.Style.Float.LEFT);
- captionWrapper.add(optionsCaption);
- }
-
- return optionsCaption;
- }
-
- public HTML getSelectionsCaption() {
- if (selectionsCaption == null) {
- selectionsCaption = new HTML();
- selectionsCaption.setStyleName(CLASSNAME + "-caption-right");
- selectionsCaption.getElement().getStyle()
- .setFloat(com.google.gwt.dom.client.Style.Float.RIGHT);
- captionWrapper.add(selectionsCaption);
- }
-
- return selectionsCaption;
- }
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- // Captions are updated before super call to ensure the widths are set
- // correctly
- if (!uidl.getBooleanAttribute("cached")) {
- updateCaptions(uidl);
- }
-
- super.updateFromUIDL(uidl, client);
- }
-
- private void updateCaptions(UIDL uidl) {
- String leftCaption = (uidl.hasAttribute(ATTRIBUTE_LEFT_CAPTION) ? uidl
- .getStringAttribute(ATTRIBUTE_LEFT_CAPTION) : null);
- String rightCaption = (uidl.hasAttribute(ATTRIBUTE_RIGHT_CAPTION) ? uidl
- .getStringAttribute(ATTRIBUTE_RIGHT_CAPTION) : null);
-
- boolean hasCaptions = (leftCaption != null || rightCaption != null);
-
- if (leftCaption == null) {
- removeOptionsCaption();
- } else {
- getOptionsCaption().setText(leftCaption);
-
- }
-
- if (rightCaption == null) {
- removeSelectionsCaption();
- } else {
- getSelectionsCaption().setText(rightCaption);
- }
-
- captionWrapper.setVisible(hasCaptions);
- }
-
- private void removeOptionsCaption() {
- if (optionsCaption == null) {
- return;
- }
-
- if (optionsCaption.getParent() != null) {
- captionWrapper.remove(optionsCaption);
- }
-
- optionsCaption = null;
- }
-
- private void removeSelectionsCaption() {
- if (selectionsCaption == null) {
- return;
- }
-
- if (selectionsCaption.getParent() != null) {
- captionWrapper.remove(selectionsCaption);
- }
-
- selectionsCaption = null;
- }
-
- @Override
- protected void buildOptions(UIDL uidl) {
- final boolean enabled = !isDisabled() && !isReadonly();
- options.setMultipleSelect(isMultiselect());
- selections.setMultipleSelect(isMultiselect());
- options.setEnabled(enabled);
- selections.setEnabled(enabled);
- add.setEnabled(enabled);
- remove.setEnabled(enabled);
- options.clear();
- selections.clear();
- for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
- final UIDL optionUidl = (UIDL) i.next();
- if (optionUidl.hasAttribute("selected")) {
- selections.addItem(optionUidl.getStringAttribute("caption"),
- optionUidl.getStringAttribute("key"));
- } else {
- options.addItem(optionUidl.getStringAttribute("caption"),
- optionUidl.getStringAttribute("key"));
- }
- }
-
- int cols = -1;
- if (getColumns() > 0) {
- cols = getColumns();
- } else if (!widthSet) {
- cols = DEFAULT_COLUMN_COUNT;
- }
-
- if (cols >= 0) {
- String colWidth = cols + "em";
- String containerWidth = (2 * cols + 4) + "em";
- // Caption wrapper width == optionsSelect + buttons +
- // selectionsSelect
- String captionWrapperWidth = (2 * cols + 4 - 0.5) + "em";
-
- options.setWidth(colWidth);
- if (optionsCaption != null) {
- optionsCaption.setWidth(colWidth);
- }
- selections.setWidth(colWidth);
- if (selectionsCaption != null) {
- selectionsCaption.setWidth(colWidth);
- }
- buttons.setWidth("3.5em");
- optionsContainer.setWidth(containerWidth);
- captionWrapper.setWidth(captionWrapperWidth);
- }
- if (getRows() > 0) {
- options.setVisibleItemCount(getRows());
- selections.setVisibleItemCount(getRows());
-
- }
-
- }
-
- @Override
- protected String[] getSelectedItems() {
- final ArrayList<String> selectedItemKeys = new ArrayList<String>();
- for (int i = 0; i < selections.getItemCount(); i++) {
- selectedItemKeys.add(selections.getValue(i));
- }
- return selectedItemKeys.toArray(new String[selectedItemKeys.size()]);
- }
-
- private boolean[] getSelectionBitmap(ListBox listBox) {
- final boolean[] selectedIndexes = new boolean[listBox.getItemCount()];
- for (int i = 0; i < listBox.getItemCount(); i++) {
- if (listBox.isItemSelected(i)) {
- selectedIndexes[i] = true;
- } else {
- selectedIndexes[i] = false;
- }
- }
- return selectedIndexes;
- }
-
- private void addItem() {
- Set<String> movedItems = moveSelectedItems(options, selections);
- selectedKeys.addAll(movedItems);
-
- client.updateVariable(id, "selected",
- selectedKeys.toArray(new String[selectedKeys.size()]),
- isImmediate());
- }
-
- private void removeItem() {
- Set<String> movedItems = moveSelectedItems(selections, options);
- selectedKeys.removeAll(movedItems);
-
- client.updateVariable(id, "selected",
- selectedKeys.toArray(new String[selectedKeys.size()]),
- isImmediate());
- }
-
- private Set<String> moveSelectedItems(ListBox source, ListBox target) {
- final boolean[] sel = getSelectionBitmap(source);
- final Set<String> movedItems = new HashSet<String>();
- int lastSelected = 0;
- for (int i = 0; i < sel.length; i++) {
- if (sel[i]) {
- final int optionIndex = i
- - (sel.length - source.getItemCount());
- movedItems.add(source.getValue(optionIndex));
-
- // Move selection to another column
- final String text = source.getItemText(optionIndex);
- final String value = source.getValue(optionIndex);
- target.addItem(text, value);
- target.setItemSelected(target.getItemCount() - 1, true);
- source.removeItem(optionIndex);
-
- if (source.getItemCount() > 0) {
- lastSelected = optionIndex > 0 ? optionIndex - 1 : 0;
- }
- }
- }
-
- if (source.getItemCount() > 0) {
- source.setSelectedIndex(lastSelected);
- }
-
- // If no items are left move the focus to the selections
- if (source.getItemCount() == 0) {
- target.setFocus(true);
- } else {
- source.setFocus(true);
- }
-
- return movedItems;
- }
-
- @Override
- public void onClick(ClickEvent event) {
- super.onClick(event);
- if (event.getSource() == add) {
- addItem();
-
- } else if (event.getSource() == remove) {
- removeItem();
-
- } else if (event.getSource() == options) {
- // unselect all in other list, to avoid mistakes (i.e wrong button)
- final int c = selections.getItemCount();
- for (int i = 0; i < c; i++) {
- selections.setItemSelected(i, false);
- }
- } else if (event.getSource() == selections) {
- // unselect all in other list, to avoid mistakes (i.e wrong button)
- final int c = options.getItemCount();
- for (int i = 0; i < c; i++) {
- options.setItemSelected(i, false);
- }
- }
- }
-
- @Override
- public void setHeight(String height) {
- super.setHeight(height);
- if ("".equals(height)) {
- options.setHeight("");
- selections.setHeight("");
- } else {
- setInternalHeights();
- }
- }
-
- private void setInternalHeights() {
- int captionHeight = 0;
- int totalHeight;
- if (BrowserInfo.get().isIE6()) {
- String o = getElement().getStyle().getOverflow();
-
- getElement().getStyle().setOverflow(Overflow.HIDDEN);
- totalHeight = getOffsetHeight();
- getElement().getStyle().setProperty("overflow", o);
- } else {
- totalHeight = getOffsetHeight();
- }
-
- if (optionsCaption != null) {
- captionHeight = Util.getRequiredHeight(optionsCaption);
- } else if (selectionsCaption != null) {
- captionHeight = Util.getRequiredHeight(selectionsCaption);
- }
- String selectHeight = (totalHeight - captionHeight) + "px";
-
- selections.setHeight(selectHeight);
- options.setHeight(selectHeight);
-
- }
-
- @Override
- public void setWidth(String width) {
- super.setWidth(width);
- if (!"".equals(width) && width != null) {
- setInternalWidths();
- widthSet = true;
- } else {
- widthSet = false;
- }
- }
-
- private void setInternalWidths() {
- DOM.setStyleAttribute(getElement(), "position", "relative");
- int bordersAndPaddings = Util.measureHorizontalPaddingAndBorder(
- buttons.getElement(), 0);
-
- if (BrowserInfo.get().isIE6()) {
- // IE6 sets a border on selects by default..
- bordersAndPaddings += 4;
- }
-
- int buttonWidth = Util.getRequiredWidth(buttons);
- int totalWidth = getOffsetWidth();
-
- int spaceForSelect = (totalWidth - buttonWidth - bordersAndPaddings) / 2;
-
- options.setWidth(spaceForSelect + "px");
- if (optionsCaption != null) {
- optionsCaption.setWidth(spaceForSelect + "px");
- }
-
- selections.setWidth(spaceForSelect + "px");
- if (selectionsCaption != null) {
- selectionsCaption.setWidth(spaceForSelect + "px");
- }
- captionWrapper.setWidth("100%");
- }
-
- @Override
- protected void setTabIndex(int tabIndex) {
- options.setTabIndex(tabIndex);
- selections.setTabIndex(tabIndex);
- add.setTabIndex(tabIndex);
- remove.setTabIndex(tabIndex);
- }
-
- public void focus() {
- options.setFocus(true);
- }
-
- /**
- * Get the key that selects an item in the table. By default it is the Enter
- * key but by overriding this you can change the key to whatever you want.
- *
- * @return
- */
- protected int getNavigationSelectKey() {
- return KeyCodes.KEY_ENTER;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt
- * .event.dom.client.KeyDownEvent)
- */
- public void onKeyDown(KeyDownEvent event) {
- int keycode = event.getNativeKeyCode();
-
- // Catch tab and move between select:s
- if (keycode == KeyCodes.KEY_TAB && event.getSource() == options) {
- // Prevent default behavior
- event.preventDefault();
-
- // Remove current selections
- for (int i = 0; i < options.getItemCount(); i++) {
- options.setItemSelected(i, false);
- }
-
- // Focus selections
- selections.setFocus(true);
- }
-
- if (keycode == KeyCodes.KEY_TAB && event.isShiftKeyDown()
- && event.getSource() == selections) {
- // Prevent default behavior
- event.preventDefault();
-
- // Remove current selections
- for (int i = 0; i < selections.getItemCount(); i++) {
- selections.setItemSelected(i, false);
- }
-
- // Focus options
- options.setFocus(true);
- }
-
- if (keycode == getNavigationSelectKey()) {
- // Prevent default behavior
- event.preventDefault();
-
- // Decide which select the selection was made in
- if (event.getSource() == options) {
- // Prevents the selection to become a single selection when
- // using Enter key
- // as the selection key (default)
- options.setFocus(false);
-
- addItem();
-
- } else if (event.getSource() == selections) {
- // Prevents the selection to become a single selection when
- // using Enter key
- // as the selection key (default)
- selections.setFocus(false);
-
- removeItem();
- }
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google
- * .gwt.event.dom.client.MouseDownEvent)
- */
- public void onMouseDown(MouseDownEvent event) {
- // Ensure that items are deselected when selecting
- // from a different source. See #3699 for details.
- if (event.getSource() == options) {
- for (int i = 0; i < selections.getItemCount(); i++) {
- selections.setItemSelected(i, false);
- }
- } else if (event.getSource() == selections) {
- for (int i = 0; i < options.getItemCount(); i++) {
- options.setItemSelected(i, false);
- }
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.DoubleClickHandler#onDoubleClick(com.
- * google.gwt.event.dom.client.DoubleClickEvent)
- */
- public void onDoubleClick(DoubleClickEvent event) {
- if (event.getSource() == options) {
- addItem();
- options.setSelectedIndex(-1);
- options.setFocus(false);
- } else if (event.getSource() == selections) {
- removeItem();
- selections.setSelectedIndex(-1);
- selections.setFocus(false);
- }
-
- }
-
- private static final String SUBPART_OPTION_SELECT = "leftSelect";
- private static final String SUBPART_OPTION_SELECT_ITEM = SUBPART_OPTION_SELECT
- + "-item";
- private static final String SUBPART_SELECTION_SELECT = "rightSelect";
- private static final String SUBPART_SELECTION_SELECT_ITEM = SUBPART_SELECTION_SELECT
- + "-item";
- private static final String SUBPART_LEFT_CAPTION = "leftCaption";
- private static final String SUBPART_RIGHT_CAPTION = "rightCaption";
- private static final String SUBPART_ADD_BUTTON = "add";
- private static final String SUBPART_REMOVE_BUTTON = "remove";
-
- public Element getSubPartElement(String subPart) {
- if (SUBPART_OPTION_SELECT.equals(subPart)) {
- return options.getElement();
- } else if (subPart.startsWith(SUBPART_OPTION_SELECT_ITEM)) {
- String idx = subPart.substring(SUBPART_OPTION_SELECT_ITEM.length());
- return (Element) options.getElement().getChild(
- Integer.parseInt(idx));
- } else if (SUBPART_SELECTION_SELECT.equals(subPart)) {
- return selections.getElement();
- } else if (subPart.startsWith(SUBPART_SELECTION_SELECT_ITEM)) {
- String idx = subPart.substring(SUBPART_SELECTION_SELECT_ITEM
- .length());
- return (Element) selections.getElement().getChild(
- Integer.parseInt(idx));
- } else if (optionsCaption != null
- && SUBPART_LEFT_CAPTION.equals(subPart)) {
- return optionsCaption.getElement();
- } else if (selectionsCaption != null
- && SUBPART_RIGHT_CAPTION.equals(subPart)) {
- return selectionsCaption.getElement();
- } else if (SUBPART_ADD_BUTTON.equals(subPart)) {
- return add.getElement();
- } else if (SUBPART_REMOVE_BUTTON.equals(subPart)) {
- return remove.getElement();
- }
-
- return null;
- }
-
- public String getSubPartName(Element subElement) {
- if (optionsCaption != null
- && optionsCaption.getElement().isOrHasChild(subElement)) {
- return SUBPART_LEFT_CAPTION;
- } else if (selectionsCaption != null
- && selectionsCaption.getElement().isOrHasChild(subElement)) {
- return SUBPART_RIGHT_CAPTION;
- } else if (options.getElement().isOrHasChild(subElement)) {
- if (options.getElement() == subElement) {
- return SUBPART_OPTION_SELECT;
- } else {
- int idx = Util.getChildElementIndex(subElement);
- return SUBPART_OPTION_SELECT_ITEM + idx;
- }
- } else if (selections.getElement().isOrHasChild(subElement)) {
- if (selections.getElement() == subElement) {
- return SUBPART_SELECTION_SELECT;
- } else {
- int idx = Util.getChildElementIndex(subElement);
- return SUBPART_SELECTION_SELECT_ITEM + idx;
- }
- } else if (add.getElement().isOrHasChild(subElement)) {
- return SUBPART_ADD_BUTTON;
- } else if (remove.getElement().isOrHasChild(subElement)) {
- return SUBPART_REMOVE_BUTTON;
- }
-
- return null;
- }
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import com.google.gwt.dom.client.Style.Overflow;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.DoubleClickEvent;
+import com.google.gwt.event.dom.client.DoubleClickHandler;
+import com.google.gwt.event.dom.client.HasDoubleClickHandlers;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.Panel;
+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 VTwinColSelect extends VOptionGroupBase implements KeyDownHandler,
+ MouseDownHandler, DoubleClickHandler, SubPartAware {
+
+ private static final String CLASSNAME = "v-select-twincol";
+ public static final String ATTRIBUTE_LEFT_CAPTION = "lc";
+ public static final String ATTRIBUTE_RIGHT_CAPTION = "rc";
+
+ private static final int VISIBLE_COUNT = 10;
+
+ private static final int DEFAULT_COLUMN_COUNT = 10;
+
+ private final DoubleClickListBox options;
+
+ private final DoubleClickListBox selections;
+
+ private FlowPanel captionWrapper;
+
+ private HTML optionsCaption = null;
+
+ private HTML selectionsCaption = null;
+
+ private final VButton add;
+
+ private final VButton remove;
+
+ private final FlowPanel buttons;
+
+ private final Panel panel;
+
+ private boolean widthSet = false;
+
+ /**
+ * A ListBox which catches double clicks
+ *
+ */
+ public class DoubleClickListBox extends ListBox implements
+ HasDoubleClickHandlers {
+ public DoubleClickListBox(boolean isMultipleSelect) {
+ super(isMultipleSelect);
+ }
+
+ public DoubleClickListBox() {
+ super();
+ }
+
+ @Override
+ public HandlerRegistration addDoubleClickHandler(
+ DoubleClickHandler handler) {
+ return addDomHandler(handler, DoubleClickEvent.getType());
+ }
+ }
+
+ public VTwinColSelect() {
+ super(CLASSNAME);
+
+ captionWrapper = new FlowPanel();
+
+ options = new DoubleClickListBox();
+ options.addClickHandler(this);
+ options.addDoubleClickHandler(this);
+ options.setVisibleItemCount(VISIBLE_COUNT);
+ options.setStyleName(CLASSNAME + "-options");
+
+ selections = new DoubleClickListBox();
+ selections.addClickHandler(this);
+ selections.addDoubleClickHandler(this);
+ selections.setVisibleItemCount(VISIBLE_COUNT);
+ selections.setStyleName(CLASSNAME + "-selections");
+
+ buttons = new FlowPanel();
+ buttons.setStyleName(CLASSNAME + "-buttons");
+ add = new VButton();
+ add.setText(">>");
+ add.addClickHandler(this);
+ remove = new VButton();
+ remove.setText("<<");
+ remove.addClickHandler(this);
+
+ panel = ((Panel) optionsContainer);
+
+ panel.add(captionWrapper);
+ captionWrapper.getElement().getStyle().setOverflow(Overflow.HIDDEN);
+ // Hide until there actually is a caption to prevent IE from rendering
+ // extra empty space
+ captionWrapper.setVisible(false);
+
+ panel.add(options);
+ buttons.add(add);
+ final HTML br = new HTML("<span/>");
+ br.setStyleName(CLASSNAME + "-deco");
+ buttons.add(br);
+ buttons.add(remove);
+ panel.add(buttons);
+ panel.add(selections);
+
+ options.addKeyDownHandler(this);
+ options.addMouseDownHandler(this);
+
+ selections.addMouseDownHandler(this);
+ selections.addKeyDownHandler(this);
+ }
+
+ public HTML getOptionsCaption() {
+ if (optionsCaption == null) {
+ optionsCaption = new HTML();
+ optionsCaption.setStyleName(CLASSNAME + "-caption-left");
+ optionsCaption.getElement().getStyle()
+ .setFloat(com.google.gwt.dom.client.Style.Float.LEFT);
+ captionWrapper.add(optionsCaption);
+ }
+
+ return optionsCaption;
+ }
+
+ public HTML getSelectionsCaption() {
+ if (selectionsCaption == null) {
+ selectionsCaption = new HTML();
+ selectionsCaption.setStyleName(CLASSNAME + "-caption-right");
+ selectionsCaption.getElement().getStyle()
+ .setFloat(com.google.gwt.dom.client.Style.Float.RIGHT);
+ captionWrapper.add(selectionsCaption);
+ }
+
+ return selectionsCaption;
+ }
+
+ @Override
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ // Captions are updated before super call to ensure the widths are set
+ // correctly
+ if (!uidl.getBooleanAttribute("cached")) {
+ updateCaptions(uidl);
+ }
+
+ super.updateFromUIDL(uidl, client);
+ }
+
+ private void updateCaptions(UIDL uidl) {
+ String leftCaption = (uidl.hasAttribute(ATTRIBUTE_LEFT_CAPTION) ? uidl
+ .getStringAttribute(ATTRIBUTE_LEFT_CAPTION) : null);
+ String rightCaption = (uidl.hasAttribute(ATTRIBUTE_RIGHT_CAPTION) ? uidl
+ .getStringAttribute(ATTRIBUTE_RIGHT_CAPTION) : null);
+
+ boolean hasCaptions = (leftCaption != null || rightCaption != null);
+
+ if (leftCaption == null) {
+ removeOptionsCaption();
+ } else {
+ getOptionsCaption().setText(leftCaption);
+
+ }
+
+ if (rightCaption == null) {
+ removeSelectionsCaption();
+ } else {
+ getSelectionsCaption().setText(rightCaption);
+ }
+
+ captionWrapper.setVisible(hasCaptions);
+ }
+
+ private void removeOptionsCaption() {
+ if (optionsCaption == null) {
+ return;
+ }
+
+ if (optionsCaption.getParent() != null) {
+ captionWrapper.remove(optionsCaption);
+ }
+
+ optionsCaption = null;
+ }
+
+ private void removeSelectionsCaption() {
+ if (selectionsCaption == null) {
+ return;
+ }
+
+ if (selectionsCaption.getParent() != null) {
+ captionWrapper.remove(selectionsCaption);
+ }
+
+ selectionsCaption = null;
+ }
+
+ @Override
+ protected void buildOptions(UIDL uidl) {
+ final boolean enabled = !isDisabled() && !isReadonly();
+ options.setMultipleSelect(isMultiselect());
+ selections.setMultipleSelect(isMultiselect());
+ options.setEnabled(enabled);
+ selections.setEnabled(enabled);
+ add.setEnabled(enabled);
+ remove.setEnabled(enabled);
+ options.clear();
+ selections.clear();
+ for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
+ final UIDL optionUidl = (UIDL) i.next();
+ if (optionUidl.hasAttribute("selected")) {
+ selections.addItem(optionUidl.getStringAttribute("caption"),
+ optionUidl.getStringAttribute("key"));
+ } else {
+ options.addItem(optionUidl.getStringAttribute("caption"),
+ optionUidl.getStringAttribute("key"));
+ }
+ }
+
+ int cols = -1;
+ if (getColumns() > 0) {
+ cols = getColumns();
+ } else if (!widthSet) {
+ cols = DEFAULT_COLUMN_COUNT;
+ }
+
+ if (cols >= 0) {
+ String colWidth = cols + "em";
+ String containerWidth = (2 * cols + 4) + "em";
+ // Caption wrapper width == optionsSelect + buttons +
+ // selectionsSelect
+ String captionWrapperWidth = (2 * cols + 4 - 0.5) + "em";
+
+ options.setWidth(colWidth);
+ if (optionsCaption != null) {
+ optionsCaption.setWidth(colWidth);
+ }
+ selections.setWidth(colWidth);
+ if (selectionsCaption != null) {
+ selectionsCaption.setWidth(colWidth);
+ }
+ buttons.setWidth("3.5em");
+ optionsContainer.setWidth(containerWidth);
+ captionWrapper.setWidth(captionWrapperWidth);
+ }
+ if (getRows() > 0) {
+ options.setVisibleItemCount(getRows());
+ selections.setVisibleItemCount(getRows());
+
+ }
+
+ }
+
+ @Override
+ protected String[] getSelectedItems() {
+ final ArrayList<String> selectedItemKeys = new ArrayList<String>();
+ for (int i = 0; i < selections.getItemCount(); i++) {
+ selectedItemKeys.add(selections.getValue(i));
+ }
+ return selectedItemKeys.toArray(new String[selectedItemKeys.size()]);
+ }
+
+ private boolean[] getSelectionBitmap(ListBox listBox) {
+ final boolean[] selectedIndexes = new boolean[listBox.getItemCount()];
+ for (int i = 0; i < listBox.getItemCount(); i++) {
+ if (listBox.isItemSelected(i)) {
+ selectedIndexes[i] = true;
+ } else {
+ selectedIndexes[i] = false;
+ }
+ }
+ return selectedIndexes;
+ }
+
+ private void addItem() {
+ Set<String> movedItems = moveSelectedItems(options, selections);
+ selectedKeys.addAll(movedItems);
+
+ client.updateVariable(id, "selected",
+ selectedKeys.toArray(new String[selectedKeys.size()]),
+ isImmediate());
+ }
+
+ private void removeItem() {
+ Set<String> movedItems = moveSelectedItems(selections, options);
+ selectedKeys.removeAll(movedItems);
+
+ client.updateVariable(id, "selected",
+ selectedKeys.toArray(new String[selectedKeys.size()]),
+ isImmediate());
+ }
+
+ private Set<String> moveSelectedItems(ListBox source, ListBox target) {
+ final boolean[] sel = getSelectionBitmap(source);
+ final Set<String> movedItems = new HashSet<String>();
+ int lastSelected = 0;
+ for (int i = 0; i < sel.length; i++) {
+ if (sel[i]) {
+ final int optionIndex = i
+ - (sel.length - source.getItemCount());
+ movedItems.add(source.getValue(optionIndex));
+
+ // Move selection to another column
+ final String text = source.getItemText(optionIndex);
+ final String value = source.getValue(optionIndex);
+ target.addItem(text, value);
+ target.setItemSelected(target.getItemCount() - 1, true);
+ source.removeItem(optionIndex);
+
+ if (source.getItemCount() > 0) {
+ lastSelected = optionIndex > 0 ? optionIndex - 1 : 0;
+ }
+ }
+ }
+
+ if (source.getItemCount() > 0) {
+ source.setSelectedIndex(lastSelected);
+ }
+
+ // If no items are left move the focus to the selections
+ if (source.getItemCount() == 0) {
+ target.setFocus(true);
+ } else {
+ source.setFocus(true);
+ }
+
+ return movedItems;
+ }
+
+ @Override
+ public void onClick(ClickEvent event) {
+ super.onClick(event);
+ if (event.getSource() == add) {
+ addItem();
+
+ } else if (event.getSource() == remove) {
+ removeItem();
+
+ } else if (event.getSource() == options) {
+ // unselect all in other list, to avoid mistakes (i.e wrong button)
+ final int c = selections.getItemCount();
+ for (int i = 0; i < c; i++) {
+ selections.setItemSelected(i, false);
+ }
+ } else if (event.getSource() == selections) {
+ // unselect all in other list, to avoid mistakes (i.e wrong button)
+ final int c = options.getItemCount();
+ for (int i = 0; i < c; i++) {
+ options.setItemSelected(i, false);
+ }
+ }
+ }
+
+ @Override
+ public void setHeight(String height) {
+ super.setHeight(height);
+ if ("".equals(height)) {
+ options.setHeight("");
+ selections.setHeight("");
+ } else {
+ setInternalHeights();
+ }
+ }
+
+ private void setInternalHeights() {
+ int captionHeight = 0;
+ int totalHeight;
+ if (BrowserInfo.get().isIE6()) {
+ String o = getElement().getStyle().getOverflow();
+
+ getElement().getStyle().setOverflow(Overflow.HIDDEN);
+ totalHeight = getOffsetHeight();
+ getElement().getStyle().setProperty("overflow", o);
+ } else {
+ totalHeight = getOffsetHeight();
+ }
+
+ if (optionsCaption != null) {
+ captionHeight = Util.getRequiredHeight(optionsCaption);
+ } else if (selectionsCaption != null) {
+ captionHeight = Util.getRequiredHeight(selectionsCaption);
+ }
+ String selectHeight = (totalHeight - captionHeight) + "px";
+
+ selections.setHeight(selectHeight);
+ options.setHeight(selectHeight);
+
+ }
+
+ @Override
+ public void setWidth(String width) {
+ super.setWidth(width);
+ if (!"".equals(width) && width != null) {
+ setInternalWidths();
+ widthSet = true;
+ } else {
+ widthSet = false;
+ }
+ }
+
+ private void setInternalWidths() {
+ DOM.setStyleAttribute(getElement(), "position", "relative");
+ int bordersAndPaddings = Util.measureHorizontalPaddingAndBorder(
+ buttons.getElement(), 0);
+
+ if (BrowserInfo.get().isIE6()) {
+ // IE6 sets a border on selects by default..
+ bordersAndPaddings += 4;
+ }
+
+ int buttonWidth = Util.getRequiredWidth(buttons);
+ int totalWidth = getOffsetWidth();
+
+ int spaceForSelect = (totalWidth - buttonWidth - bordersAndPaddings) / 2;
+
+ options.setWidth(spaceForSelect + "px");
+ if (optionsCaption != null) {
+ optionsCaption.setWidth(spaceForSelect + "px");
+ }
+
+ selections.setWidth(spaceForSelect + "px");
+ if (selectionsCaption != null) {
+ selectionsCaption.setWidth(spaceForSelect + "px");
+ }
+ captionWrapper.setWidth("100%");
+ }
+
+ @Override
+ protected void setTabIndex(int tabIndex) {
+ options.setTabIndex(tabIndex);
+ selections.setTabIndex(tabIndex);
+ add.setTabIndex(tabIndex);
+ remove.setTabIndex(tabIndex);
+ }
+
+ public void focus() {
+ options.setFocus(true);
+ }
+
+ /**
+ * Get the key that selects an item in the table. By default it is the Enter
+ * key but by overriding this you can change the key to whatever you want.
+ *
+ * @return
+ */
+ protected int getNavigationSelectKey() {
+ return KeyCodes.KEY_ENTER;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt
+ * .event.dom.client.KeyDownEvent)
+ */
+ public void onKeyDown(KeyDownEvent event) {
+ int keycode = event.getNativeKeyCode();
+
+ // Catch tab and move between select:s
+ if (keycode == KeyCodes.KEY_TAB && event.getSource() == options) {
+ // Prevent default behavior
+ event.preventDefault();
+
+ // Remove current selections
+ for (int i = 0; i < options.getItemCount(); i++) {
+ options.setItemSelected(i, false);
+ }
+
+ // Focus selections
+ selections.setFocus(true);
+ }
+
+ if (keycode == KeyCodes.KEY_TAB && event.isShiftKeyDown()
+ && event.getSource() == selections) {
+ // Prevent default behavior
+ event.preventDefault();
+
+ // Remove current selections
+ for (int i = 0; i < selections.getItemCount(); i++) {
+ selections.setItemSelected(i, false);
+ }
+
+ // Focus options
+ options.setFocus(true);
+ }
+
+ if (keycode == getNavigationSelectKey()) {
+ // Prevent default behavior
+ event.preventDefault();
+
+ // Decide which select the selection was made in
+ if (event.getSource() == options) {
+ // Prevents the selection to become a single selection when
+ // using Enter key
+ // as the selection key (default)
+ options.setFocus(false);
+
+ addItem();
+
+ } else if (event.getSource() == selections) {
+ // Prevents the selection to become a single selection when
+ // using Enter key
+ // as the selection key (default)
+ selections.setFocus(false);
+
+ removeItem();
+ }
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google
+ * .gwt.event.dom.client.MouseDownEvent)
+ */
+ public void onMouseDown(MouseDownEvent event) {
+ // Ensure that items are deselected when selecting
+ // from a different source. See #3699 for details.
+ if (event.getSource() == options) {
+ for (int i = 0; i < selections.getItemCount(); i++) {
+ selections.setItemSelected(i, false);
+ }
+ } else if (event.getSource() == selections) {
+ for (int i = 0; i < options.getItemCount(); i++) {
+ options.setItemSelected(i, false);
+ }
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.DoubleClickHandler#onDoubleClick(com.
+ * google.gwt.event.dom.client.DoubleClickEvent)
+ */
+ public void onDoubleClick(DoubleClickEvent event) {
+ if (event.getSource() == options) {
+ addItem();
+ options.setSelectedIndex(-1);
+ options.setFocus(false);
+ } else if (event.getSource() == selections) {
+ removeItem();
+ selections.setSelectedIndex(-1);
+ selections.setFocus(false);
+ }
+
+ }
+
+ private static final String SUBPART_OPTION_SELECT = "leftSelect";
+ private static final String SUBPART_OPTION_SELECT_ITEM = SUBPART_OPTION_SELECT
+ + "-item";
+ private static final String SUBPART_SELECTION_SELECT = "rightSelect";
+ private static final String SUBPART_SELECTION_SELECT_ITEM = SUBPART_SELECTION_SELECT
+ + "-item";
+ private static final String SUBPART_LEFT_CAPTION = "leftCaption";
+ private static final String SUBPART_RIGHT_CAPTION = "rightCaption";
+ private static final String SUBPART_ADD_BUTTON = "add";
+ private static final String SUBPART_REMOVE_BUTTON = "remove";
+
+ public Element getSubPartElement(String subPart) {
+ if (SUBPART_OPTION_SELECT.equals(subPart)) {
+ return options.getElement();
+ } else if (subPart.startsWith(SUBPART_OPTION_SELECT_ITEM)) {
+ String idx = subPart.substring(SUBPART_OPTION_SELECT_ITEM.length());
+ return (Element) options.getElement().getChild(
+ Integer.parseInt(idx));
+ } else if (SUBPART_SELECTION_SELECT.equals(subPart)) {
+ return selections.getElement();
+ } else if (subPart.startsWith(SUBPART_SELECTION_SELECT_ITEM)) {
+ String idx = subPart.substring(SUBPART_SELECTION_SELECT_ITEM
+ .length());
+ return (Element) selections.getElement().getChild(
+ Integer.parseInt(idx));
+ } else if (optionsCaption != null
+ && SUBPART_LEFT_CAPTION.equals(subPart)) {
+ return optionsCaption.getElement();
+ } else if (selectionsCaption != null
+ && SUBPART_RIGHT_CAPTION.equals(subPart)) {
+ return selectionsCaption.getElement();
+ } else if (SUBPART_ADD_BUTTON.equals(subPart)) {
+ return add.getElement();
+ } else if (SUBPART_REMOVE_BUTTON.equals(subPart)) {
+ return remove.getElement();
+ }
+
+ return null;
+ }
+
+ public String getSubPartName(Element subElement) {
+ if (optionsCaption != null
+ && optionsCaption.getElement().isOrHasChild(subElement)) {
+ return SUBPART_LEFT_CAPTION;
+ } else if (selectionsCaption != null
+ && selectionsCaption.getElement().isOrHasChild(subElement)) {
+ return SUBPART_RIGHT_CAPTION;
+ } else if (options.getElement().isOrHasChild(subElement)) {
+ if (options.getElement() == subElement) {
+ return SUBPART_OPTION_SELECT;
+ } else {
+ int idx = Util.getChildElementIndex(subElement);
+ return SUBPART_OPTION_SELECT_ITEM + idx;
+ }
+ } else if (selections.getElement().isOrHasChild(subElement)) {
+ if (selections.getElement() == subElement) {
+ return SUBPART_SELECTION_SELECT;
+ } else {
+ int idx = Util.getChildElementIndex(subElement);
+ return SUBPART_SELECTION_SELECT_ITEM + idx;
+ }
+ } else if (add.getElement().isOrHasChild(subElement)) {
+ return SUBPART_ADD_BUTTON;
+ } else if (remove.getElement().isOrHasChild(subElement)) {
+ return SUBPART_REMOVE_BUTTON;
+ }
+
+ return null;
+ }
+}
diff --git a/src/com/vaadin/ui/ComboBox.java b/src/com/vaadin/ui/ComboBox.java
index 0fb8b9d873..bc7ab6f994 100644
--- a/src/com/vaadin/ui/ComboBox.java
+++ b/src/com/vaadin/ui/ComboBox.java
@@ -1,129 +1,129 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.ui;
-
-import java.util.Collection;
-
-import com.vaadin.data.Container;
-import com.vaadin.terminal.PaintException;
-import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.VFilterSelect;
-
-/**
- * A filtering dropdown single-select. Suitable for newItemsAllowed, but it's
- * turned of by default to avoid mistakes. Items are filtered based on user
- * input, and loaded dynamically ("lazy-loading") from the server. You can turn
- * on newItemsAllowed and change filtering mode (and also turn it off), but you
- * can not turn on multi-select mode.
- *
- */
-@SuppressWarnings("serial")
-@ClientWidget(VFilterSelect.class)
-public class ComboBox extends Select {
-
- private String inputPrompt = null;
-
- /**
- * If text input is not allowed, the ComboBox behaves like a pretty
- * NativeSelect - the user can not enter any text and clicking the text
- * field opens the drop down with options
- */
- private boolean textInputAllowed = true;
-
- public ComboBox() {
- setMultiSelect(false);
- setNewItemsAllowed(false);
- }
-
- public ComboBox(String caption, Collection<?> options) {
- super(caption, options);
- setMultiSelect(false);
- setNewItemsAllowed(false);
- }
-
- public ComboBox(String caption, Container dataSource) {
- super(caption, dataSource);
- setMultiSelect(false);
- setNewItemsAllowed(false);
- }
-
- public ComboBox(String caption) {
- super(caption);
- setMultiSelect(false);
- setNewItemsAllowed(false);
- }
-
- @Override
- public void setMultiSelect(boolean multiSelect) {
- if (multiSelect && !isMultiSelect()) {
- throw new UnsupportedOperationException("Multiselect not supported");
- }
- super.setMultiSelect(multiSelect);
- }
-
- /**
- * Gets the current input prompt.
- *
- * @see #setInputPrompt(String)
- * @return the current input prompt, or null if not enabled
- */
- public String getInputPrompt() {
- return inputPrompt;
- }
-
- /**
- * Sets the input prompt - a textual prompt that is displayed when the
- * select would otherwise be empty, to prompt the user for input.
- *
- * @param inputPrompt
- * the desired input prompt, or null to disable
- */
- public void setInputPrompt(String inputPrompt) {
- this.inputPrompt = inputPrompt;
- requestRepaint();
- }
-
- @Override
- public void paintContent(PaintTarget target) throws PaintException {
- if (inputPrompt != null) {
- target.addAttribute("prompt", inputPrompt);
- }
- super.paintContent(target);
-
- if (!textInputAllowed) {
- target.addAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT, true);
- }
- }
-
- /**
- * Sets whether it is possible to input text into the field or whether the
- * field area of the component is just used to show what is selected. By
- * disabling text input, the comboBox will work in the same way as a
- * {@link NativeSelect}
- *
- * @see #isTextInputAllowed()
- *
- * @param textInputAllowed
- * true to allow entering text, false to just show the current
- * selection
- */
- public void setTextInputAllowed(boolean textInputAllowed) {
- this.textInputAllowed = textInputAllowed;
- requestRepaint();
- }
-
- /**
- * Returns true if the user can enter text into the field to either filter
- * the selections or enter a new value if {@link #isNewItemsAllowed()}
- * returns true. If text input is disabled, the comboBox will work in the
- * same way as a {@link NativeSelect}
- *
- * @return
- */
- public boolean isTextInputAllowed() {
- return textInputAllowed;
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.util.Collection;
+
+import com.vaadin.data.Container;
+import com.vaadin.terminal.PaintException;
+import com.vaadin.terminal.PaintTarget;
+import com.vaadin.terminal.gwt.client.ui.VFilterSelect;
+
+/**
+ * A filtering dropdown single-select. Suitable for newItemsAllowed, but it's
+ * turned of by default to avoid mistakes. Items are filtered based on user
+ * input, and loaded dynamically ("lazy-loading") from the server. You can turn
+ * on newItemsAllowed and change filtering mode (and also turn it off), but you
+ * can not turn on multi-select mode.
+ *
+ */
+@SuppressWarnings("serial")
+@ClientWidget(VFilterSelect.class)
+public class ComboBox extends Select {
+
+ private String inputPrompt = null;
+
+ /**
+ * If text input is not allowed, the ComboBox behaves like a pretty
+ * NativeSelect - the user can not enter any text and clicking the text
+ * field opens the drop down with options
+ */
+ private boolean textInputAllowed = true;
+
+ public ComboBox() {
+ setMultiSelect(false);
+ setNewItemsAllowed(false);
+ }
+
+ public ComboBox(String caption, Collection<?> options) {
+ super(caption, options);
+ setMultiSelect(false);
+ setNewItemsAllowed(false);
+ }
+
+ public ComboBox(String caption, Container dataSource) {
+ super(caption, dataSource);
+ setMultiSelect(false);
+ setNewItemsAllowed(false);
+ }
+
+ public ComboBox(String caption) {
+ super(caption);
+ setMultiSelect(false);
+ setNewItemsAllowed(false);
+ }
+
+ @Override
+ public void setMultiSelect(boolean multiSelect) {
+ if (multiSelect && !isMultiSelect()) {
+ throw new UnsupportedOperationException("Multiselect not supported");
+ }
+ super.setMultiSelect(multiSelect);
+ }
+
+ /**
+ * Gets the current input prompt.
+ *
+ * @see #setInputPrompt(String)
+ * @return the current input prompt, or null if not enabled
+ */
+ public String getInputPrompt() {
+ return inputPrompt;
+ }
+
+ /**
+ * Sets the input prompt - a textual prompt that is displayed when the
+ * select would otherwise be empty, to prompt the user for input.
+ *
+ * @param inputPrompt
+ * the desired input prompt, or null to disable
+ */
+ public void setInputPrompt(String inputPrompt) {
+ this.inputPrompt = inputPrompt;
+ requestRepaint();
+ }
+
+ @Override
+ public void paintContent(PaintTarget target) throws PaintException {
+ if (inputPrompt != null) {
+ target.addAttribute("prompt", inputPrompt);
+ }
+ super.paintContent(target);
+
+ if (!textInputAllowed) {
+ target.addAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT, true);
+ }
+ }
+
+ /**
+ * Sets whether it is possible to input text into the field or whether the
+ * field area of the component is just used to show what is selected. By
+ * disabling text input, the comboBox will work in the same way as a
+ * {@link NativeSelect}
+ *
+ * @see #isTextInputAllowed()
+ *
+ * @param textInputAllowed
+ * true to allow entering text, false to just show the current
+ * selection
+ */
+ public void setTextInputAllowed(boolean textInputAllowed) {
+ this.textInputAllowed = textInputAllowed;
+ requestRepaint();
+ }
+
+ /**
+ * Returns true if the user can enter text into the field to either filter
+ * the selections or enter a new value if {@link #isNewItemsAllowed()}
+ * returns true. If text input is disabled, the comboBox will work in the
+ * same way as a {@link NativeSelect}
+ *
+ * @return
+ */
+ public boolean isTextInputAllowed() {
+ return textInputAllowed;
+ }
+
+}
diff --git a/src/com/vaadin/ui/InlineDateField.java b/src/com/vaadin/ui/InlineDateField.java
index 0bf7924d34..50e16d803b 100644
--- a/src/com/vaadin/ui/InlineDateField.java
+++ b/src/com/vaadin/ui/InlineDateField.java
@@ -1,48 +1,48 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.ui;
-
-import java.util.Date;
-
-import com.vaadin.data.Property;
-import com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar;
-
-/**
- * <p>
- * A date entry component, which displays the actual date selector inline.
- *
- * </p>
- *
- * @see DateField
- * @see PopupDateField
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 5.0
- */
-@ClientWidget(VDateFieldCalendar.class)
-public class InlineDateField extends DateField {
-
- public InlineDateField() {
- super();
- }
-
- public InlineDateField(Property dataSource) throws IllegalArgumentException {
- super(dataSource);
- }
-
- public InlineDateField(String caption, Date value) {
- super(caption, value);
- }
-
- public InlineDateField(String caption, Property dataSource) {
- super(caption, dataSource);
- }
-
- public InlineDateField(String caption) {
- super(caption);
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.util.Date;
+
+import com.vaadin.data.Property;
+import com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar;
+
+/**
+ * <p>
+ * A date entry component, which displays the actual date selector inline.
+ *
+ * </p>
+ *
+ * @see DateField
+ * @see PopupDateField
+ * @author Vaadin Ltd.
+ * @version
+ * @VERSION@
+ * @since 5.0
+ */
+@ClientWidget(VDateFieldCalendar.class)
+public class InlineDateField extends DateField {
+
+ public InlineDateField() {
+ super();
+ }
+
+ public InlineDateField(Property dataSource) throws IllegalArgumentException {
+ super(dataSource);
+ }
+
+ public InlineDateField(String caption, Date value) {
+ super(caption, value);
+ }
+
+ public InlineDateField(String caption, Property dataSource) {
+ super(caption, dataSource);
+ }
+
+ public InlineDateField(String caption) {
+ super(caption);
+ }
+
+}
diff --git a/src/com/vaadin/ui/PopupDateField.java b/src/com/vaadin/ui/PopupDateField.java
index d25608a4c4..3688d4035f 100644
--- a/src/com/vaadin/ui/PopupDateField.java
+++ b/src/com/vaadin/ui/PopupDateField.java
@@ -1,80 +1,80 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.ui;
-
-import java.util.Date;
-
-import com.vaadin.data.Property;
-import com.vaadin.terminal.PaintException;
-import com.vaadin.terminal.PaintTarget;
-
-/**
- * <p>
- * A date entry component, which displays the actual date selector as a popup.
- *
- * </p>
- *
- * @see DateField
- * @see InlineDateField
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 5.0
- */
-public class PopupDateField extends DateField {
-
- private String inputPrompt = null;
-
- public PopupDateField() {
- super();
- }
-
- public PopupDateField(Property dataSource) throws IllegalArgumentException {
- super(dataSource);
- }
-
- public PopupDateField(String caption, Date value) {
- super(caption, value);
- }
-
- public PopupDateField(String caption, Property dataSource) {
- super(caption, dataSource);
- }
-
- public PopupDateField(String caption) {
- super(caption);
- }
-
- @Override
- public void paintContent(PaintTarget target) throws PaintException {
- super.paintContent(target);
-
- if (inputPrompt != null) {
- target.addAttribute("prompt", inputPrompt);
- }
- }
-
- /**
- * Gets the current input prompt.
- *
- * @see #setInputPrompt(String)
- * @return the current input prompt, or null if not enabled
- */
- public String getInputPrompt() {
- return inputPrompt;
- }
-
- /**
- * Sets the input prompt - a textual prompt that is displayed when the field
- * would otherwise be empty, to prompt the user for input.
- *
- * @param inputPrompt
- */
- public void setInputPrompt(String inputPrompt) {
- this.inputPrompt = inputPrompt;
- requestRepaint();
- }
-
-}
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.util.Date;
+
+import com.vaadin.data.Property;
+import com.vaadin.terminal.PaintException;
+import com.vaadin.terminal.PaintTarget;
+
+/**
+ * <p>
+ * A date entry component, which displays the actual date selector as a popup.
+ *
+ * </p>
+ *
+ * @see DateField
+ * @see InlineDateField
+ * @author Vaadin Ltd.
+ * @version
+ * @VERSION@
+ * @since 5.0
+ */
+public class PopupDateField extends DateField {
+
+ private String inputPrompt = null;
+
+ public PopupDateField() {
+ super();
+ }
+
+ public PopupDateField(Property dataSource) throws IllegalArgumentException {
+ super(dataSource);
+ }
+
+ public PopupDateField(String caption, Date value) {
+ super(caption, value);
+ }
+
+ public PopupDateField(String caption, Property dataSource) {
+ super(caption, dataSource);
+ }
+
+ public PopupDateField(String caption) {
+ super(caption);
+ }
+
+ @Override
+ public void paintContent(PaintTarget target) throws PaintException {
+ super.paintContent(target);
+
+ if (inputPrompt != null) {
+ target.addAttribute("prompt", inputPrompt);
+ }
+ }
+
+ /**
+ * Gets the current input prompt.
+ *
+ * @see #setInputPrompt(String)
+ * @return the current input prompt, or null if not enabled
+ */
+ public String getInputPrompt() {
+ return inputPrompt;
+ }
+
+ /**
+ * Sets the input prompt - a textual prompt that is displayed when the field
+ * would otherwise be empty, to prompt the user for input.
+ *
+ * @param inputPrompt
+ */
+ public void setInputPrompt(String inputPrompt) {
+ this.inputPrompt = inputPrompt;
+ requestRepaint();
+ }
+
+}