diff options
author | Henri Sara <hesara@vaadin.com> | 2012-02-07 10:49:54 +0200 |
---|---|---|
committer | Henri Sara <hesara@vaadin.com> | 2012-02-07 10:49:54 +0200 |
commit | fc8d7eeaa573957d9a4c80caa1d4d21948e7057e (patch) | |
tree | e8f8bdb4d50d8a2b0d79259486deedb605b13c80 /src | |
parent | dc0268c218c9de44df30f816d541de279e529ef4 (diff) | |
parent | b77b4e6a2ed7253a48eb21fb5ac734f1c11fb6ff (diff) | |
download | vaadin-framework-fc8d7eeaa573957d9a4c80caa1d4d21948e7057e.tar.gz vaadin-framework-fc8d7eeaa573957d9a4c80caa1d4d21948e7057e.zip |
Merge branch 'master' into rpc
Conflicts:
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/client/VPaintableMap.java
Diffstat (limited to 'src')
116 files changed, 14067 insertions, 13947 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/fieldgroup/BeanFieldGroup.java b/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java index 8ca6c95069..2584a4770b 100644 --- a/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java +++ b/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java @@ -1,157 +1,157 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.fieldgroup;
-
-import java.lang.reflect.Method;
-
-import com.vaadin.data.Item;
-import com.vaadin.data.util.BeanItem;
-import com.vaadin.data.validator.BeanValidator;
-import com.vaadin.ui.Field;
-
-public class BeanFieldGroup<T> extends FieldGroup {
-
- private Class<T> beanType;
-
- private static Boolean beanValidationImplementationAvailable = null;
-
- public BeanFieldGroup(Class<T> beanType) {
- this.beanType = beanType;
- }
-
- @Override
- protected Class<?> getPropertyType(Object propertyId) {
- if (getItemDataSource() != null) {
- return super.getPropertyType(propertyId);
- } else {
- // Data source not set so we need to figure out the type manually
- /*
- * toString should never really be needed as propertyId should be of
- * form "fieldName" or "fieldName.subField[.subField2]" but the
- * method declaration comes from parent.
- */
- java.lang.reflect.Field f;
- try {
- f = getField(beanType, propertyId.toString());
- return f.getType();
- } catch (SecurityException e) {
- throw new BindException("Cannot determine type of propertyId '"
- + propertyId + "'.", e);
- } catch (NoSuchFieldException e) {
- throw new BindException("Cannot determine type of propertyId '"
- + propertyId + "'. The propertyId was not found in "
- + beanType.getName(), e);
- }
- }
- }
-
- private static java.lang.reflect.Field getField(Class<?> cls,
- String propertyId) throws SecurityException, NoSuchFieldException {
- if (propertyId.contains(".")) {
- String[] parts = propertyId.split("\\.", 2);
- // Get the type of the field in the "cls" class
- java.lang.reflect.Field field1 = getField(cls, parts[0]);
- // Find the rest from the sub type
- return getField(field1.getType(), parts[1]);
- } else {
- try {
- // Try to find the field directly in the given class
- java.lang.reflect.Field field1 = cls
- .getDeclaredField(propertyId);
- return field1;
- } catch (NoSuchFieldError e) {
- // Try super classes until we reach Object
- Class<?> superClass = cls.getSuperclass();
- if (superClass != Object.class) {
- return getField(superClass, propertyId);
- } else {
- throw e;
- }
- }
- }
- }
-
- /**
- * Helper method for setting the data source directly using a bean. This
- * method wraps the bean in a {@link BeanItem} and calls
- * {@link #setItemDataSource(Item)}.
- *
- * @param bean
- * The bean to use as data source.
- */
- public void setItemDataSource(T bean) {
- setItemDataSource(new BeanItem(bean));
- }
-
- @Override
- public void setItemDataSource(Item item) {
- if (!(item instanceof BeanItem)) {
- throw new RuntimeException(getClass().getSimpleName()
- + " only supports BeanItems as item data source");
- }
- super.setItemDataSource(item);
- }
-
- @Override
- public BeanItem<T> getItemDataSource() {
- return (BeanItem<T>) super.getItemDataSource();
- }
-
- @Override
- public void bind(Field field, Object propertyId) {
- if (getItemDataSource() != null) {
- // The data source is set so the property must be found in the item.
- // If it is not we try to add it.
- try {
- getItemProperty(propertyId);
- } catch (BindException e) {
- // Not found, try to add a nested property;
- // BeanItem property ids are always strings so this is safe
- getItemDataSource().addNestedProperty((String) propertyId);
- }
- }
-
- super.bind(field, propertyId);
- }
-
- @Override
- protected void configureField(Field<?> field) {
- super.configureField(field);
- // Add Bean validators if there are annotations
- if (isBeanValidationImplementationAvailable()) {
- BeanValidator validator = new BeanValidator(
- beanType, getPropertyId(field).toString());
- field.addValidator(validator);
- if (field.getLocale() != null) {
- validator.setLocale(field.getLocale());
- }
- }
- }
-
- /**
- * Checks whether a bean validation implementation (e.g. Hibernate Validator
- * or Apache Bean Validation) is available.
- *
- * TODO move this method to some more generic location
- *
- * @return true if a JSR-303 bean validation implementation is available
- */
- protected static boolean isBeanValidationImplementationAvailable() {
- if (beanValidationImplementationAvailable != null) {
- return beanValidationImplementationAvailable;
- }
- try {
- Class<?> validationClass = Class
- .forName("javax.validation.Validation");
- Method buildFactoryMethod = validationClass
- .getMethod("buildDefaultValidatorFactory");
- Object factory = buildFactoryMethod.invoke(null);
- beanValidationImplementationAvailable = (factory != null);
- } catch (Exception e) {
- // no bean validation implementation available
- beanValidationImplementationAvailable = false;
- }
- return beanValidationImplementationAvailable;
- }
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.data.fieldgroup; + +import java.lang.reflect.Method; + +import com.vaadin.data.Item; +import com.vaadin.data.util.BeanItem; +import com.vaadin.data.validator.BeanValidator; +import com.vaadin.ui.Field; + +public class BeanFieldGroup<T> extends FieldGroup { + + private Class<T> beanType; + + private static Boolean beanValidationImplementationAvailable = null; + + public BeanFieldGroup(Class<T> beanType) { + this.beanType = beanType; + } + + @Override + protected Class<?> getPropertyType(Object propertyId) { + if (getItemDataSource() != null) { + return super.getPropertyType(propertyId); + } else { + // Data source not set so we need to figure out the type manually + /* + * toString should never really be needed as propertyId should be of + * form "fieldName" or "fieldName.subField[.subField2]" but the + * method declaration comes from parent. + */ + java.lang.reflect.Field f; + try { + f = getField(beanType, propertyId.toString()); + return f.getType(); + } catch (SecurityException e) { + throw new BindException("Cannot determine type of propertyId '" + + propertyId + "'.", e); + } catch (NoSuchFieldException e) { + throw new BindException("Cannot determine type of propertyId '" + + propertyId + "'. The propertyId was not found in " + + beanType.getName(), e); + } + } + } + + private static java.lang.reflect.Field getField(Class<?> cls, + String propertyId) throws SecurityException, NoSuchFieldException { + if (propertyId.contains(".")) { + String[] parts = propertyId.split("\\.", 2); + // Get the type of the field in the "cls" class + java.lang.reflect.Field field1 = getField(cls, parts[0]); + // Find the rest from the sub type + return getField(field1.getType(), parts[1]); + } else { + try { + // Try to find the field directly in the given class + java.lang.reflect.Field field1 = cls + .getDeclaredField(propertyId); + return field1; + } catch (NoSuchFieldError e) { + // Try super classes until we reach Object + Class<?> superClass = cls.getSuperclass(); + if (superClass != Object.class) { + return getField(superClass, propertyId); + } else { + throw e; + } + } + } + } + + /** + * Helper method for setting the data source directly using a bean. This + * method wraps the bean in a {@link BeanItem} and calls + * {@link #setItemDataSource(Item)}. + * + * @param bean + * The bean to use as data source. + */ + public void setItemDataSource(T bean) { + setItemDataSource(new BeanItem(bean)); + } + + @Override + public void setItemDataSource(Item item) { + if (!(item instanceof BeanItem)) { + throw new RuntimeException(getClass().getSimpleName() + + " only supports BeanItems as item data source"); + } + super.setItemDataSource(item); + } + + @Override + public BeanItem<T> getItemDataSource() { + return (BeanItem<T>) super.getItemDataSource(); + } + + @Override + public void bind(Field field, Object propertyId) { + if (getItemDataSource() != null) { + // The data source is set so the property must be found in the item. + // If it is not we try to add it. + try { + getItemProperty(propertyId); + } catch (BindException e) { + // Not found, try to add a nested property; + // BeanItem property ids are always strings so this is safe + getItemDataSource().addNestedProperty((String) propertyId); + } + } + + super.bind(field, propertyId); + } + + @Override + protected void configureField(Field<?> field) { + super.configureField(field); + // Add Bean validators if there are annotations + if (isBeanValidationImplementationAvailable()) { + BeanValidator validator = new BeanValidator( + beanType, getPropertyId(field).toString()); + field.addValidator(validator); + if (field.getLocale() != null) { + validator.setLocale(field.getLocale()); + } + } + } + + /** + * Checks whether a bean validation implementation (e.g. Hibernate Validator + * or Apache Bean Validation) is available. + * + * TODO move this method to some more generic location + * + * @return true if a JSR-303 bean validation implementation is available + */ + protected static boolean isBeanValidationImplementationAvailable() { + if (beanValidationImplementationAvailable != null) { + return beanValidationImplementationAvailable; + } + try { + Class<?> validationClass = Class + .forName("javax.validation.Validation"); + Method buildFactoryMethod = validationClass + .getMethod("buildDefaultValidatorFactory"); + Object factory = buildFactoryMethod.invoke(null); + beanValidationImplementationAvailable = (factory != null); + } catch (Exception e) { + // no bean validation implementation available + beanValidationImplementationAvailable = false; + } + return beanValidationImplementationAvailable; + } }
\ No newline at end of file diff --git a/src/com/vaadin/data/fieldgroup/Caption.java b/src/com/vaadin/data/fieldgroup/Caption.java index e9ae01a2d2..b990b720cd 100644 --- a/src/com/vaadin/data/fieldgroup/Caption.java +++ b/src/com/vaadin/data/fieldgroup/Caption.java @@ -1,15 +1,15 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.fieldgroup;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Target({ ElementType.FIELD })
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Caption {
- String value();
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.data.fieldgroup; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Caption { + String value(); +} diff --git a/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java b/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java index 2fc7bc6b7e..569f643998 100644 --- a/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java +++ b/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java @@ -1,156 +1,156 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.fieldgroup;
-
-import java.util.EnumSet;
-
-import com.vaadin.data.Item;
-import com.vaadin.data.fieldgroup.FieldGroup.BindException;
-import com.vaadin.ui.AbstractSelect;
-import com.vaadin.ui.AbstractTextField;
-import com.vaadin.ui.CheckBox;
-import com.vaadin.ui.ComboBox;
-import com.vaadin.ui.Field;
-import com.vaadin.ui.ListSelect;
-import com.vaadin.ui.NativeSelect;
-import com.vaadin.ui.OptionGroup;
-import com.vaadin.ui.RichTextArea;
-import com.vaadin.ui.Table;
-import com.vaadin.ui.TextField;
-
-public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory {
-
- public static final Object CAPTION_PROPERTY_ID = "Caption";
-
- public <T extends Field> T createField(Class<?> type, Class<T> fieldType) {
- if (Enum.class.isAssignableFrom(type)) {
- return createEnumField(type, fieldType);
- } else if (Boolean.class.isAssignableFrom(type)
- || boolean.class.isAssignableFrom(type)) {
- return createBooleanField(fieldType);
- }
- if (AbstractTextField.class.isAssignableFrom(fieldType)) {
- return fieldType.cast(createAbstractTextField(fieldType
- .asSubclass(AbstractTextField.class)));
- } else if (fieldType == RichTextArea.class) {
- return fieldType.cast(createRichTextArea());
- }
- return createDefaultField(type, fieldType);
- }
-
- protected RichTextArea createRichTextArea() {
- RichTextArea rta = new RichTextArea();
- rta.setImmediate(true);
-
- return rta;
- }
-
- private <T extends Field> T createEnumField(Class<?> type,
- Class<T> fieldType) {
- if (AbstractSelect.class.isAssignableFrom(fieldType)) {
- AbstractSelect s = createCompatibleSelect((Class<? extends AbstractSelect>) fieldType);
- populateWithEnumData(s, (Class<? extends Enum>) type);
- return (T) s;
- }
-
- return null;
- }
-
- protected AbstractSelect createCompatibleSelect(
- Class<? extends AbstractSelect> fieldType) {
- AbstractSelect select;
- if (fieldType.isAssignableFrom(ListSelect.class)) {
- select = new ListSelect();
- select.setMultiSelect(false);
- } else if (fieldType.isAssignableFrom(NativeSelect.class)) {
- select = new NativeSelect();
- } else if (fieldType.isAssignableFrom(OptionGroup.class)) {
- select = new OptionGroup();
- select.setMultiSelect(false);
- } else if (fieldType.isAssignableFrom(Table.class)) {
- Table t = new Table();
- t.setSelectable(true);
- select = t;
- } else {
- select = new ComboBox(null);
- }
- select.setImmediate(true);
- select.setNullSelectionAllowed(false);
-
- return select;
- }
-
- protected <T extends Field> T createBooleanField(Class<T> fieldType) {
- if (fieldType.isAssignableFrom(CheckBox.class)) {
- CheckBox cb = new CheckBox(null);
- cb.setImmediate(true);
- return (T) cb;
- } else if (AbstractTextField.class.isAssignableFrom(fieldType)) {
- return (T) createAbstractTextField((Class<? extends AbstractTextField>) fieldType);
- }
-
- return null;
- }
-
- protected <T extends AbstractTextField> T createAbstractTextField(
- Class<T> fieldType) {
- if (fieldType == AbstractTextField.class) {
- fieldType = (Class<T>) TextField.class;
- }
- try {
- T field = fieldType.newInstance();
- field.setImmediate(true);
- return field;
- } catch (Exception e) {
- throw new BindException("Could not create a field of type "
- + fieldType, e);
- }
- }
-
- /**
- * Fallback when no specific field has been created. Typically returns a
- * TextField.
- *
- * @param <T>
- * The type of field to create
- * @param type
- * The type of data that should be edited
- * @param fieldType
- * The type of field to create
- * @return A field capable of editing the data or null if no field could be
- * created
- */
- protected <T extends Field> T createDefaultField(Class<?> type,
- Class<T> fieldType) {
- if (fieldType.isAssignableFrom(TextField.class)) {
- return fieldType.cast(createAbstractTextField(TextField.class));
- }
- return null;
- }
-
- /**
- * Populates the given select with all the enums in the given {@link Enum}
- * class. Uses {@link Enum}.toString() for caption.
- *
- * @param select
- * The select to populate
- * @param enumClass
- * The Enum class to use
- */
- protected void populateWithEnumData(AbstractSelect select,
- Class<? extends Enum> enumClass) {
- select.removeAllItems();
- for (Object p : select.getContainerPropertyIds()) {
- select.removeContainerProperty(p);
- }
- select.addContainerProperty(CAPTION_PROPERTY_ID, String.class, "");
- select.setItemCaptionPropertyId(CAPTION_PROPERTY_ID);
- @SuppressWarnings("unchecked")
- EnumSet<?> enumSet = EnumSet.allOf(enumClass);
- for (Object r : enumSet) {
- Item newItem = select.addItem(r);
- newItem.getItemProperty(CAPTION_PROPERTY_ID).setValue(r.toString());
- }
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.data.fieldgroup; + +import java.util.EnumSet; + +import com.vaadin.data.Item; +import com.vaadin.data.fieldgroup.FieldGroup.BindException; +import com.vaadin.ui.AbstractSelect; +import com.vaadin.ui.AbstractTextField; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.Field; +import com.vaadin.ui.ListSelect; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.OptionGroup; +import com.vaadin.ui.RichTextArea; +import com.vaadin.ui.Table; +import com.vaadin.ui.TextField; + +public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { + + public static final Object CAPTION_PROPERTY_ID = "Caption"; + + public <T extends Field> T createField(Class<?> type, Class<T> fieldType) { + if (Enum.class.isAssignableFrom(type)) { + return createEnumField(type, fieldType); + } else if (Boolean.class.isAssignableFrom(type) + || boolean.class.isAssignableFrom(type)) { + return createBooleanField(fieldType); + } + if (AbstractTextField.class.isAssignableFrom(fieldType)) { + return fieldType.cast(createAbstractTextField(fieldType + .asSubclass(AbstractTextField.class))); + } else if (fieldType == RichTextArea.class) { + return fieldType.cast(createRichTextArea()); + } + return createDefaultField(type, fieldType); + } + + protected RichTextArea createRichTextArea() { + RichTextArea rta = new RichTextArea(); + rta.setImmediate(true); + + return rta; + } + + private <T extends Field> T createEnumField(Class<?> type, + Class<T> fieldType) { + if (AbstractSelect.class.isAssignableFrom(fieldType)) { + AbstractSelect s = createCompatibleSelect((Class<? extends AbstractSelect>) fieldType); + populateWithEnumData(s, (Class<? extends Enum>) type); + return (T) s; + } + + return null; + } + + protected AbstractSelect createCompatibleSelect( + Class<? extends AbstractSelect> fieldType) { + AbstractSelect select; + if (fieldType.isAssignableFrom(ListSelect.class)) { + select = new ListSelect(); + select.setMultiSelect(false); + } else if (fieldType.isAssignableFrom(NativeSelect.class)) { + select = new NativeSelect(); + } else if (fieldType.isAssignableFrom(OptionGroup.class)) { + select = new OptionGroup(); + select.setMultiSelect(false); + } else if (fieldType.isAssignableFrom(Table.class)) { + Table t = new Table(); + t.setSelectable(true); + select = t; + } else { + select = new ComboBox(null); + } + select.setImmediate(true); + select.setNullSelectionAllowed(false); + + return select; + } + + protected <T extends Field> T createBooleanField(Class<T> fieldType) { + if (fieldType.isAssignableFrom(CheckBox.class)) { + CheckBox cb = new CheckBox(null); + cb.setImmediate(true); + return (T) cb; + } else if (AbstractTextField.class.isAssignableFrom(fieldType)) { + return (T) createAbstractTextField((Class<? extends AbstractTextField>) fieldType); + } + + return null; + } + + protected <T extends AbstractTextField> T createAbstractTextField( + Class<T> fieldType) { + if (fieldType == AbstractTextField.class) { + fieldType = (Class<T>) TextField.class; + } + try { + T field = fieldType.newInstance(); + field.setImmediate(true); + return field; + } catch (Exception e) { + throw new BindException("Could not create a field of type " + + fieldType, e); + } + } + + /** + * Fallback when no specific field has been created. Typically returns a + * TextField. + * + * @param <T> + * The type of field to create + * @param type + * The type of data that should be edited + * @param fieldType + * The type of field to create + * @return A field capable of editing the data or null if no field could be + * created + */ + protected <T extends Field> T createDefaultField(Class<?> type, + Class<T> fieldType) { + if (fieldType.isAssignableFrom(TextField.class)) { + return fieldType.cast(createAbstractTextField(TextField.class)); + } + return null; + } + + /** + * Populates the given select with all the enums in the given {@link Enum} + * class. Uses {@link Enum}.toString() for caption. + * + * @param select + * The select to populate + * @param enumClass + * The Enum class to use + */ + protected void populateWithEnumData(AbstractSelect select, + Class<? extends Enum> enumClass) { + select.removeAllItems(); + for (Object p : select.getContainerPropertyIds()) { + select.removeContainerProperty(p); + } + select.addContainerProperty(CAPTION_PROPERTY_ID, String.class, ""); + select.setItemCaptionPropertyId(CAPTION_PROPERTY_ID); + @SuppressWarnings("unchecked") + EnumSet<?> enumSet = EnumSet.allOf(enumClass); + for (Object r : enumSet) { + Item newItem = select.addItem(r); + newItem.getItemProperty(CAPTION_PROPERTY_ID).setValue(r.toString()); + } + } +} diff --git a/src/com/vaadin/data/fieldgroup/FieldGroup.java b/src/com/vaadin/data/fieldgroup/FieldGroup.java index 381f4fef3f..3df19f5bc9 100644 --- a/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -1,978 +1,978 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.fieldgroup;
-
-import java.io.Serializable;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.logging.Logger;
-
-import com.vaadin.data.Item;
-import com.vaadin.data.Property;
-import com.vaadin.data.Validator.InvalidValueException;
-import com.vaadin.data.util.TransactionalPropertyWrapper;
-import com.vaadin.tools.ReflectTools;
-import com.vaadin.ui.DefaultFieldFactory;
-import com.vaadin.ui.Field;
-import com.vaadin.ui.Form;
-
-/**
- * FieldGroup provides an easy way of binding fields to data and handling
- * commits of these fields.
- * <p>
- * The functionality of FieldGroup is similar to {@link Form} but
- * {@link FieldGroup} does not handle layouts in any way. The typical use case
- * is to create a layout outside the FieldGroup and then use FieldGroup to bind
- * the fields to a data source.
- * </p>
- * <p>
- * {@link FieldGroup} is not a UI component so it cannot be added to a layout.
- * Using the buildAndBind methods {@link FieldGroup} can create fields for you
- * using a FieldGroupFieldFactory but you still have to add them to the correct
- * position in your layout.
- * </p>
- *
- * @author Vaadin Ltd
- * @version @version@
- * @since 7.0
- */
-public class FieldGroup implements Serializable {
-
- private static final Logger logger = Logger.getLogger(FieldGroup.class
- .getName());
-
- private Item itemDataSource;
- private boolean buffered = true;
-
- private boolean enabled = true;
- private boolean readOnly = false;
-
- private HashMap<Object, Field<?>> propertyIdToField = new HashMap<Object, Field<?>>();
- private LinkedHashMap<Field<?>, Object> fieldToPropertyId = new LinkedHashMap<Field<?>, Object>();
- private List<CommitHandler> commitHandlers = new ArrayList<CommitHandler>();
-
- /**
- * The field factory used by builder methods.
- */
- private FieldGroupFieldFactory fieldFactory = new DefaultFieldGroupFieldFactory();
-
- /**
- * Constructs a field binder. Use {@link #setItemDataSource(Item)} to set a
- * data source for the field binder.
- *
- */
- public FieldGroup() {
-
- }
-
- /**
- * Constructs a field binder that uses the given data source.
- *
- * @param itemDataSource
- * The data source to bind the fields to
- */
- public FieldGroup(Item itemDataSource) {
- setItemDataSource(itemDataSource);
- }
-
- /**
- * Updates the item that is used by this FieldBinder. Rebinds all fields to
- * the properties in the new item.
- *
- * @param itemDataSource
- * The new item to use
- */
- public void setItemDataSource(Item itemDataSource) {
- this.itemDataSource = itemDataSource;
-
- for (Field<?> f : fieldToPropertyId.keySet()) {
- bind(f, fieldToPropertyId.get(f));
- }
- }
-
- /**
- * Gets the item used by this FieldBinder. Note that you must call
- * {@link #commit()} for the item to be updated unless buffered mode has
- * been switched off.
- *
- * @see #setBuffered(boolean)
- * @see #commit()
- *
- * @return The item used by this FieldBinder
- */
- public Item getItemDataSource() {
- return itemDataSource;
- }
-
- /**
- * Checks the buffered mode for the bound fields.
- * <p>
- *
- * @see #setBuffered(boolean) for more details on buffered mode
- *
- * @see Field#isBuffered()
- * @return true if buffered mode is on, false otherwise
- *
- */
- public boolean isBuffered() {
- return buffered;
- }
-
- /**
- * Sets the buffered mode for the bound fields.
- * <p>
- * When buffered mode is on the item will not be updated until
- * {@link #commit()} is called. If buffered mode is off the item will be
- * updated once the fields are updated.
- * </p>
- * <p>
- * The default is to use buffered mode.
- * </p>
- *
- * @see Field#setBuffered(boolean)
- * @param buffered
- * true to turn on buffered mode, false otherwise
- */
- public void setBuffered(boolean buffered) {
- if (buffered == this.buffered) {
- return;
- }
-
- this.buffered = buffered;
- for (Field<?> field : getFields()) {
- field.setBuffered(buffered);
- }
- }
-
- /**
- * Returns the enabled status for the fields.
- * <p>
- * Note that this will not accurately represent the enabled status of all
- * fields if you change the enabled status of the fields through some other
- * method than {@link #setEnabled(boolean)}.
- *
- * @return true if the fields are enabled, false otherwise
- */
- public boolean isEnabled() {
- return enabled;
- }
-
- /**
- * Updates the enabled state of all bound fields.
- *
- * @param fieldsEnabled
- * true to enable all bound fields, false to disable them
- */
- public void setEnabled(boolean fieldsEnabled) {
- enabled = fieldsEnabled;
- for (Field<?> field : getFields()) {
- field.setEnabled(fieldsEnabled);
- }
- }
-
- /**
- * Returns the read only status for the fields.
- * <p>
- * Note that this will not accurately represent the read only status of all
- * fields if you change the read only status of the fields through some
- * other method than {@link #setReadOnly(boolean)}.
- *
- * @return true if the fields are set to read only, false otherwise
- */
- public boolean isReadOnly() {
- return readOnly;
- }
-
- /**
- * Updates the read only state of all bound fields.
- *
- * @param fieldsReadOnly
- * true to set all bound fields to read only, false to set them
- * to read write
- */
- public void setReadOnly(boolean fieldsReadOnly) {
- readOnly = fieldsReadOnly;
- }
-
- /**
- * Returns a collection of all fields that have been bound.
- * <p>
- * The fields are not returned in any specific order.
- * </p>
- *
- * @return A collection with all bound Fields
- */
- public Collection<Field<?>> getFields() {
- return fieldToPropertyId.keySet();
- }
-
- /**
- * Binds the field with the given propertyId from the current item. If an
- * item has not been set then the binding is postponed until the item is set
- * using {@link #setItemDataSource(Item)}.
- * <p>
- * This method also adds validators when applicable.
- * </p>
- *
- * @param field
- * The field to bind
- * @param propertyId
- * The propertyId to bind to the field
- * @throws BindException
- * If the property id is already bound to another field by this
- * field binder
- */
- public void bind(Field<?> field, Object propertyId) throws BindException {
- if (propertyIdToField.containsKey(propertyId)
- && propertyIdToField.get(propertyId) != field) {
- throw new BindException("Property id " + propertyId
- + " is already bound to another field");
- }
- fieldToPropertyId.put(field, propertyId);
- propertyIdToField.put(propertyId, field);
- if (itemDataSource == null) {
- // Will be bound when data source is set
- return;
- }
-
- field.setPropertyDataSource(wrapInTransactionalProperty(getItemProperty(propertyId)));
- configureField(field);
- }
-
- private <T> Property.Transactional<T> wrapInTransactionalProperty(
- Property<T> itemProperty) {
- return new TransactionalPropertyWrapper<T>(itemProperty);
- }
-
- /**
- * Gets the property with the given property id from the item.
- *
- * @param propertyId
- * The id if the property to find
- * @return The property with the given id from the item
- * @throws BindException
- * If the property was not found in the item or no item has been
- * set
- */
- protected Property<?> getItemProperty(Object propertyId)
- throws BindException {
- Item item = getItemDataSource();
- if (item == null) {
- throw new BindException("Could not lookup property with id "
- + propertyId + " as no item has been set");
- }
- Property<?> p = item.getItemProperty(propertyId);
- if (p == null) {
- throw new BindException("A property with id " + propertyId
- + " was not found in the item");
- }
- return p;
- }
-
- /**
- * Detaches the field from its property id and removes it from this
- * FieldBinder.
- * <p>
- * Note that the field is not detached from its property data source if it
- * is no longer connected to the same property id it was bound to using this
- * FieldBinder.
- *
- * @param field
- * The field to detach
- * @throws BindException
- * If the field is not bound by this field binder or not bound
- * to the correct property id
- */
- public void unbind(Field<?> field) throws BindException {
- Object propertyId = fieldToPropertyId.get(field);
- if (propertyId == null) {
- throw new BindException(
- "The given field is not part of this FieldBinder");
- }
-
- Property fieldDataSource = field.getPropertyDataSource();
- if (fieldDataSource instanceof TransactionalPropertyWrapper) {
- fieldDataSource = ((TransactionalPropertyWrapper) fieldDataSource)
- .getWrappedProperty();
- }
- if (fieldDataSource == getItemProperty(propertyId)) {
- field.setPropertyDataSource(null);
- }
- fieldToPropertyId.remove(field);
- propertyIdToField.remove(propertyId);
- }
-
- /**
- * Configures a field with the settings set for this FieldBinder.
- * <p>
- * By default this updates the buffered, read only and enabled state of the
- * field. Also adds validators when applicable.
- *
- * @param field
- * The field to update
- */
- protected void configureField(Field<?> field) {
- field.setBuffered(isBuffered());
-
- field.setEnabled(isEnabled());
- field.setReadOnly(isReadOnly());
- }
-
- /**
- * Gets the type of the property with the given property id.
- *
- * @param propertyId
- * The propertyId. Must be find
- * @return The type of the property
- */
- protected Class<?> getPropertyType(Object propertyId) throws BindException {
- if (getItemDataSource() == null) {
- throw new BindException(
- "Property type for '"
- + propertyId
- + "' could not be determined. No item data source has been set.");
- }
- Property<?> p = getItemDataSource().getItemProperty(propertyId);
- if (p == null) {
- throw new BindException(
- "Property type for '"
- + propertyId
- + "' could not be determined. No property with that id was found.");
- }
-
- return p.getType();
- }
-
- /**
- * Returns a collection of all property ids that have been bound to fields.
- * <p>
- * Note that this will return property ids even before the item has been
- * set. In that case it returns the property ids that will be bound once the
- * item is set.
- * </p>
- * <p>
- * No guarantee is given for the order of the property ids
- * </p>
- *
- * @return A collection of bound property ids
- */
- public Collection<Object> getBoundPropertyIds() {
- return Collections.unmodifiableCollection(propertyIdToField.keySet());
- }
-
- /**
- * Returns a collection of all property ids that exist in the item set using
- * {@link #setItemDataSource(Item)} but have not been bound to fields.
- * <p>
- * Will always return an empty collection before an item has been set using
- * {@link #setItemDataSource(Item)}.
- * </p>
- * <p>
- * No guarantee is given for the order of the property ids
- * </p>
- *
- * @return A collection of property ids that have not been bound to fields
- */
- public Collection<Object> getUnboundPropertyIds() {
- if (getItemDataSource() == null) {
- return new ArrayList<Object>();
- }
- List<Object> unboundPropertyIds = new ArrayList<Object>();
- unboundPropertyIds.addAll(getItemDataSource().getItemPropertyIds());
- unboundPropertyIds.removeAll(propertyIdToField.keySet());
- return unboundPropertyIds;
- }
-
- /**
- * Commits all changes done to the bound fields.
- * <p>
- * Calls all {@link CommitHandler}s before and after committing the field
- * changes to the item data source. The whole commit is aborted and state is
- * restored to what it was before commit was called if any
- * {@link CommitHandler} throws a CommitException or there is a problem
- * committing the fields
- *
- * @throws CommitException
- * If the commit was aborted
- */
- public void commit() throws CommitException {
- if (!isBuffered()) {
- // Not using buffered mode, nothing to do
- return;
- }
- for (Field<?> f : fieldToPropertyId.keySet()) {
- ((Property.Transactional<?>) f.getPropertyDataSource())
- .startTransaction();
- }
- try {
- firePreCommitEvent();
- // Commit the field values to the properties
- for (Field<?> f : fieldToPropertyId.keySet()) {
- f.commit();
- }
- firePostCommitEvent();
-
- // Commit the properties
- for (Field<?> f : fieldToPropertyId.keySet()) {
- ((Property.Transactional<?>) f.getPropertyDataSource())
- .commit();
- }
-
- } catch (Exception e) {
- for (Field<?> f : fieldToPropertyId.keySet()) {
- try {
- ((Property.Transactional<?>) f.getPropertyDataSource())
- .rollback();
- } catch (Exception rollbackException) {
- // FIXME: What to do ?
- }
- }
-
- throw new CommitException("Commit failed", e);
- }
-
- }
-
- /**
- * Sends a preCommit event to all registered commit handlers
- *
- * @throws CommitException
- * If the commit should be aborted
- */
- private void firePreCommitEvent() throws CommitException {
- CommitHandler[] handlers = commitHandlers
- .toArray(new CommitHandler[commitHandlers.size()]);
-
- for (CommitHandler handler : handlers) {
- handler.preCommit(new CommitEvent(this));
- }
- }
-
- /**
- * Sends a postCommit event to all registered commit handlers
- *
- * @throws CommitException
- * If the commit should be aborted
- */
- private void firePostCommitEvent() throws CommitException {
- CommitHandler[] handlers = commitHandlers
- .toArray(new CommitHandler[commitHandlers.size()]);
-
- for (CommitHandler handler : handlers) {
- handler.postCommit(new CommitEvent(this));
- }
- }
-
- /**
- * Discards all changes done to the bound fields.
- * <p>
- * Only has effect if buffered mode is used.
- *
- */
- public void discard() {
- for (Field<?> f : fieldToPropertyId.keySet()) {
- try {
- f.discard();
- } catch (Exception e) {
- // TODO: handle exception
- // What can we do if discard fails other than try to discard all
- // other fields?
- }
- }
- }
-
- /**
- * Returns the field that is bound to the given property id
- *
- * @param propertyId
- * The property id to use to lookup the field
- * @return The field that is bound to the property id or null if no field is
- * bound to that property id
- */
- public Field<?> getField(Object propertyId) {
- return propertyIdToField.get(propertyId);
- }
-
- /**
- * Returns the property id that is bound to the given field
- *
- * @param field
- * The field to use to lookup the property id
- * @return The property id that is bound to the field or null if the field
- * is not bound to any property id by this FieldBinder
- */
- public Object getPropertyId(Field<?> field) {
- return fieldToPropertyId.get(field);
- }
-
- /**
- * Adds a commit handler.
- * <p>
- * The commit handler is called before the field values are committed to the
- * item ( {@link CommitHandler#preCommit(CommitEvent)}) and after the item
- * has been updated ({@link CommitHandler#postCommit(CommitEvent)}). If a
- * {@link CommitHandler} throws a CommitException the whole commit is
- * aborted and the fields retain their old values.
- *
- * @param commitHandler
- * The commit handler to add
- */
- public void addCommitHandler(CommitHandler commitHandler) {
- commitHandlers.add(commitHandler);
- }
-
- /**
- * Removes the given commit handler.
- *
- * @see #addCommitHandler(CommitHandler)
- *
- * @param commitHandler
- * The commit handler to remove
- */
- public void removeCommitHandler(CommitHandler commitHandler) {
- commitHandlers.remove(commitHandler);
- }
-
- /**
- * Returns a list of all commit handlers for this {@link FieldGroup}.
- * <p>
- * Use {@link #addCommitHandler(CommitHandler)} and
- * {@link #removeCommitHandler(CommitHandler)} to register or unregister a
- * commit handler.
- *
- * @return A collection of commit handlers
- */
- protected Collection<CommitHandler> getCommitHandlers() {
- return Collections.unmodifiableCollection(commitHandlers);
- }
-
- /**
- * CommitHandlers are used by {@link FieldGroup#commit()} as part of the
- * commit transactions. CommitHandlers can perform custom operations as part
- * of the commit and cause the commit to be aborted by throwing a
- * {@link CommitException}.
- */
- public interface CommitHandler extends Serializable {
- /**
- * Called before changes are committed to the field and the item is
- * updated.
- * <p>
- * Throw a {@link CommitException} to abort the commit.
- *
- * @param commitEvent
- * An event containing information regarding the commit
- * @throws CommitException
- * if the commit should be aborted
- */
- public void preCommit(CommitEvent commitEvent) throws CommitException;
-
- /**
- * Called after changes are committed to the fields and the item is
- * updated..
- * <p>
- * Throw a {@link CommitException} to abort the commit.
- *
- * @param commitEvent
- * An event containing information regarding the commit
- * @throws CommitException
- * if the commit should be aborted
- */
- public void postCommit(CommitEvent commitEvent) throws CommitException;
- }
-
- /**
- * FIXME javadoc
- *
- */
- public static class CommitEvent implements Serializable {
- private FieldGroup fieldBinder;
-
- private CommitEvent(FieldGroup fieldBinder) {
- this.fieldBinder = fieldBinder;
- }
-
- /**
- * Returns the field binder that this commit relates to
- *
- * @return The FieldBinder that is being committed.
- */
- public FieldGroup getFieldBinder() {
- return fieldBinder;
- }
-
- }
-
- /**
- * Checks the validity of the bound fields.
- * <p>
- * Call the {@link Field#validate()} for the fields to get the individual
- * error messages.
- *
- * @return true if all bound fields are valid, false otherwise.
- */
- public boolean isValid() {
- try {
- for (Field<?> field : getFields()) {
- field.validate();
- }
- return true;
- } catch (InvalidValueException e) {
- return false;
- }
- }
-
- /**
- * Checks if any bound field has been modified.
- *
- * @return true if at least on field has been modified, false otherwise
- */
- public boolean isModified() {
- for (Field<?> field : getFields()) {
- if (field.isModified()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Gets the field factory for the {@link FieldGroup}. The field factory is
- * only used when {@link FieldGroup} creates a new field.
- *
- * @return The field factory in use
- *
- */
- public FieldGroupFieldFactory getFieldFactory() {
- return fieldFactory;
- }
-
- /**
- * Sets the field factory for the {@link FieldGroup}. The field factory is
- * only used when {@link FieldGroup} creates a new field.
- *
- * @param fieldFactory
- * The field factory to use
- */
- public void setFieldFactory(FieldGroupFieldFactory fieldFactory) {
- this.fieldFactory = fieldFactory;
- }
-
- /**
- * Binds member fields found in the given object.
- * <p>
- * This method processes all (Java) member fields whose type extends
- * {@link Field} and that can be mapped to a property id. Property id
- * mapping is done based on the field name or on a @{@link PropertyId}
- * annotation on the field. All non-null fields for which a property id can
- * be determined are bound to the property id.
- * </p>
- * <p>
- * For example:
- *
- * <pre>
- * public class MyForm extends VerticalLayout {
- * private TextField firstName = new TextField("First name");
- * @PropertyId("last")
- * private TextField lastName = new TextField("Last name");
- * private TextField age = new TextField("Age"); ... }
- *
- * MyForm myForm = new MyForm();
- * ...
- * fieldGroup.bindMemberFields(myForm);
- * </pre>
- *
- * </p>
- * This binds the firstName TextField to a "firstName" property in the item,
- * lastName TextField to a "last" property and the age TextField to a "age"
- * property.
- *
- * @param objectWithMemberFields
- * The object that contains (Java) member fields to bind
- * @throws BindException
- * If there is a problem binding a field
- */
- public void bindMemberFields(Object objectWithMemberFields)
- throws BindException {
- buildAndBindMemberFields(objectWithMemberFields, false);
- }
-
- /**
- * Binds member fields found in the given object and builds member fields
- * that have not been initialized.
- * <p>
- * This method processes all (Java) member fields whose type extends
- * {@link Field} and that can be mapped to a property id. Property id
- * mapping is done based on the field name or on a @{@link PropertyId}
- * annotation on the field. Fields that are not initialized (null) are built
- * using the field factory. All non-null fields for which a property id can
- * be determined are bound to the property id.
- * </p>
- * <p>
- * For example:
- *
- * <pre>
- * public class MyForm extends VerticalLayout {
- * private TextField firstName = new TextField("First name");
- * @PropertyId("last")
- * private TextField lastName = new TextField("Last name");
- * private TextField age;
- *
- * MyForm myForm = new MyForm();
- * ...
- * fieldGroup.buildAndBindMemberFields(myForm);
- * </pre>
- *
- * </p>
- * <p>
- * This binds the firstName TextField to a "firstName" property in the item,
- * lastName TextField to a "last" property and builds an age TextField using
- * the field factory and then binds it to the "age" property.
- * </p>
- *
- * @param objectWithMemberFields
- * The object that contains (Java) member fields to build and
- * bind
- * @throws BindException
- * If there is a problem binding or building a field
- */
- public void buildAndBindMemberFields(Object objectWithMemberFields)
- throws BindException {
- buildAndBindMemberFields(objectWithMemberFields, true);
- }
-
- /**
- * Binds member fields found in the given object and optionally builds
- * member fields that have not been initialized.
- * <p>
- * This method processes all (Java) member fields whose type extends
- * {@link Field} and that can be mapped to a property id. Property id
- * mapping is done based on the field name or on a @{@link PropertyId}
- * annotation on the field. Fields that are not initialized (null) are built
- * using the field factory is buildFields is true. All non-null fields for
- * which a property id can be determined are bound to the property id.
- * </p>
- *
- * @param objectWithMemberFields
- * The object that contains (Java) member fields to build and
- * bind
- * @throws BindException
- * If there is a problem binding or building a field
- */
- protected void buildAndBindMemberFields(Object objectWithMemberFields,
- boolean buildFields) throws BindException {
- Class<?> objectClass = objectWithMemberFields.getClass();
-
- for (java.lang.reflect.Field memberField : objectClass
- .getDeclaredFields()) {
-
- if (!Field.class.isAssignableFrom(memberField.getType())) {
- // Process next field
- continue;
- }
-
- PropertyId propertyIdAnnotation = memberField
- .getAnnotation(PropertyId.class);
-
- Class<? extends Field> fieldType = (Class<? extends Field>) memberField
- .getType();
-
- Object propertyId = null;
- if (propertyIdAnnotation != null) {
- // @PropertyId(propertyId) always overrides property id
- propertyId = propertyIdAnnotation.value();
- } else {
- propertyId = memberField.getName();
- }
-
- // Ensure that the property id exists
- Class<?> propertyType;
-
- try {
- propertyType = getPropertyType(propertyId);
- } catch (BindException e) {
- // Property id was not found, skip this field
- continue;
- }
-
- Field<?> field;
- try {
- // Get the field from the object
- field = (Field<?>) ReflectTools.getJavaFieldValue(
- objectWithMemberFields, memberField);
- } catch (Exception e) {
- // If we cannot determine the value, just skip the field and try
- // the next one
- continue;
- }
-
- if (field == null && buildFields) {
- Caption captionAnnotation = memberField
- .getAnnotation(Caption.class);
- String caption;
- if (captionAnnotation != null) {
- caption = captionAnnotation.value();
- } else {
- caption = DefaultFieldFactory
- .createCaptionByPropertyId(propertyId);
- }
-
- // Create the component (Field)
- field = build(caption, propertyType, fieldType);
-
- // Store it in the field
- try {
- ReflectTools.setJavaFieldValue(objectWithMemberFields,
- memberField, field);
- } catch (IllegalArgumentException e) {
- throw new BindException("Could not assign value to field '"
- + memberField.getName() + "'", e);
- } catch (IllegalAccessException e) {
- throw new BindException("Could not assign value to field '"
- + memberField.getName() + "'", e);
- } catch (InvocationTargetException e) {
- throw new BindException("Could not assign value to field '"
- + memberField.getName() + "'", e);
- }
- }
-
- if (field != null) {
- // Bind it to the property id
- bind(field, propertyId);
- }
- }
- }
-
- public static class CommitException extends Exception {
-
- public CommitException() {
- super();
- // TODO Auto-generated constructor stub
- }
-
- public CommitException(String message, Throwable cause) {
- super(message, cause);
- // TODO Auto-generated constructor stub
- }
-
- public CommitException(String message) {
- super(message);
- // TODO Auto-generated constructor stub
- }
-
- public CommitException(Throwable cause) {
- super(cause);
- // TODO Auto-generated constructor stub
- }
-
- }
-
- public static class BindException extends RuntimeException {
-
- public BindException(String message) {
- super(message);
- }
-
- public BindException(String message, Throwable t) {
- super(message, t);
- }
-
- }
-
- /**
- * Builds a field and binds it to the given property id using the field
- * binder.
- *
- * @param propertyId
- * The property id to bind to. Must be present in the field
- * finder.
- * @throws BindException
- * If there is a problem while building or binding
- * @return The created and bound field
- */
- public Field<?> buildAndBind(Object propertyId) throws BindException {
- String caption = DefaultFieldFactory
- .createCaptionByPropertyId(propertyId);
- return buildAndBind(caption, propertyId);
- }
-
- /**
- * Builds a field using the given caption and binds it to the given property
- * id using the field binder.
- *
- * @param caption
- * The caption for the field
- * @param propertyId
- * The property id to bind to. Must be present in the field
- * finder.
- * @throws BindException
- * If there is a problem while building or binding
- * @return The created and bound field. Can be any type of {@link Field}.
- */
- public Field<?> buildAndBind(String caption, Object propertyId)
- throws BindException {
- Class<?> type = getPropertyType(propertyId);
- return buildAndBind(caption, propertyId, Field.class);
-
- }
-
- /**
- * Builds a field using the given caption and binds it to the given property
- * id using the field binder. Ensures the new field is of the given type.
- *
- * @param caption
- * The caption for the field
- * @param propertyId
- * The property id to bind to. Must be present in the field
- * finder.
- * @throws BindException
- * If the field could not be created
- * @return The created and bound field. Can be any type of {@link Field}.
- */
-
- public <T extends Field> T buildAndBind(String caption, Object propertyId,
- Class<T> fieldType) throws BindException {
- Class<?> type = getPropertyType(propertyId);
-
- T field = build(caption, type, fieldType);
- bind(field, propertyId);
-
- return field;
- }
-
- /**
- * Creates a field based on the given data type.
- * <p>
- * The data type is the type that we want to edit using the field. The field
- * type is the type of field we want to create, can be {@link Field} if any
- * Field is good.
- * </p>
- *
- * @param caption
- * The caption for the new field
- * @param dataType
- * The data model type that we want to edit using the field
- * @param fieldType
- * The type of field that we want to create
- * @return A Field capable of editing the given type
- * @throws BindException
- * If the field could not be created
- */
- protected <T extends Field> T build(String caption, Class<?> dataType,
- Class<T> fieldType) throws BindException {
- T field = getFieldFactory().createField(dataType, fieldType);
- if (field == null) {
- throw new BindException("Unable to build a field of type "
- + fieldType.getName() + " for editing "
- + dataType.getName());
- }
-
- field.setCaption(caption);
- return field;
- }
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.data.fieldgroup; + +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.logging.Logger; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.Validator.InvalidValueException; +import com.vaadin.data.util.TransactionalPropertyWrapper; +import com.vaadin.tools.ReflectTools; +import com.vaadin.ui.DefaultFieldFactory; +import com.vaadin.ui.Field; +import com.vaadin.ui.Form; + +/** + * FieldGroup provides an easy way of binding fields to data and handling + * commits of these fields. + * <p> + * The functionality of FieldGroup is similar to {@link Form} but + * {@link FieldGroup} does not handle layouts in any way. The typical use case + * is to create a layout outside the FieldGroup and then use FieldGroup to bind + * the fields to a data source. + * </p> + * <p> + * {@link FieldGroup} is not a UI component so it cannot be added to a layout. + * Using the buildAndBind methods {@link FieldGroup} can create fields for you + * using a FieldGroupFieldFactory but you still have to add them to the correct + * position in your layout. + * </p> + * + * @author Vaadin Ltd + * @version @version@ + * @since 7.0 + */ +public class FieldGroup implements Serializable { + + private static final Logger logger = Logger.getLogger(FieldGroup.class + .getName()); + + private Item itemDataSource; + private boolean buffered = true; + + private boolean enabled = true; + private boolean readOnly = false; + + private HashMap<Object, Field<?>> propertyIdToField = new HashMap<Object, Field<?>>(); + private LinkedHashMap<Field<?>, Object> fieldToPropertyId = new LinkedHashMap<Field<?>, Object>(); + private List<CommitHandler> commitHandlers = new ArrayList<CommitHandler>(); + + /** + * The field factory used by builder methods. + */ + private FieldGroupFieldFactory fieldFactory = new DefaultFieldGroupFieldFactory(); + + /** + * Constructs a field binder. Use {@link #setItemDataSource(Item)} to set a + * data source for the field binder. + * + */ + public FieldGroup() { + + } + + /** + * Constructs a field binder that uses the given data source. + * + * @param itemDataSource + * The data source to bind the fields to + */ + public FieldGroup(Item itemDataSource) { + setItemDataSource(itemDataSource); + } + + /** + * Updates the item that is used by this FieldBinder. Rebinds all fields to + * the properties in the new item. + * + * @param itemDataSource + * The new item to use + */ + public void setItemDataSource(Item itemDataSource) { + this.itemDataSource = itemDataSource; + + for (Field<?> f : fieldToPropertyId.keySet()) { + bind(f, fieldToPropertyId.get(f)); + } + } + + /** + * Gets the item used by this FieldBinder. Note that you must call + * {@link #commit()} for the item to be updated unless buffered mode has + * been switched off. + * + * @see #setBuffered(boolean) + * @see #commit() + * + * @return The item used by this FieldBinder + */ + public Item getItemDataSource() { + return itemDataSource; + } + + /** + * Checks the buffered mode for the bound fields. + * <p> + * + * @see #setBuffered(boolean) for more details on buffered mode + * + * @see Field#isBuffered() + * @return true if buffered mode is on, false otherwise + * + */ + public boolean isBuffered() { + return buffered; + } + + /** + * Sets the buffered mode for the bound fields. + * <p> + * When buffered mode is on the item will not be updated until + * {@link #commit()} is called. If buffered mode is off the item will be + * updated once the fields are updated. + * </p> + * <p> + * The default is to use buffered mode. + * </p> + * + * @see Field#setBuffered(boolean) + * @param buffered + * true to turn on buffered mode, false otherwise + */ + public void setBuffered(boolean buffered) { + if (buffered == this.buffered) { + return; + } + + this.buffered = buffered; + for (Field<?> field : getFields()) { + field.setBuffered(buffered); + } + } + + /** + * Returns the enabled status for the fields. + * <p> + * Note that this will not accurately represent the enabled status of all + * fields if you change the enabled status of the fields through some other + * method than {@link #setEnabled(boolean)}. + * + * @return true if the fields are enabled, false otherwise + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Updates the enabled state of all bound fields. + * + * @param fieldsEnabled + * true to enable all bound fields, false to disable them + */ + public void setEnabled(boolean fieldsEnabled) { + enabled = fieldsEnabled; + for (Field<?> field : getFields()) { + field.setEnabled(fieldsEnabled); + } + } + + /** + * Returns the read only status for the fields. + * <p> + * Note that this will not accurately represent the read only status of all + * fields if you change the read only status of the fields through some + * other method than {@link #setReadOnly(boolean)}. + * + * @return true if the fields are set to read only, false otherwise + */ + public boolean isReadOnly() { + return readOnly; + } + + /** + * Updates the read only state of all bound fields. + * + * @param fieldsReadOnly + * true to set all bound fields to read only, false to set them + * to read write + */ + public void setReadOnly(boolean fieldsReadOnly) { + readOnly = fieldsReadOnly; + } + + /** + * Returns a collection of all fields that have been bound. + * <p> + * The fields are not returned in any specific order. + * </p> + * + * @return A collection with all bound Fields + */ + public Collection<Field<?>> getFields() { + return fieldToPropertyId.keySet(); + } + + /** + * Binds the field with the given propertyId from the current item. If an + * item has not been set then the binding is postponed until the item is set + * using {@link #setItemDataSource(Item)}. + * <p> + * This method also adds validators when applicable. + * </p> + * + * @param field + * The field to bind + * @param propertyId + * The propertyId to bind to the field + * @throws BindException + * If the property id is already bound to another field by this + * field binder + */ + public void bind(Field<?> field, Object propertyId) throws BindException { + if (propertyIdToField.containsKey(propertyId) + && propertyIdToField.get(propertyId) != field) { + throw new BindException("Property id " + propertyId + + " is already bound to another field"); + } + fieldToPropertyId.put(field, propertyId); + propertyIdToField.put(propertyId, field); + if (itemDataSource == null) { + // Will be bound when data source is set + return; + } + + field.setPropertyDataSource(wrapInTransactionalProperty(getItemProperty(propertyId))); + configureField(field); + } + + private <T> Property.Transactional<T> wrapInTransactionalProperty( + Property<T> itemProperty) { + return new TransactionalPropertyWrapper<T>(itemProperty); + } + + /** + * Gets the property with the given property id from the item. + * + * @param propertyId + * The id if the property to find + * @return The property with the given id from the item + * @throws BindException + * If the property was not found in the item or no item has been + * set + */ + protected Property<?> getItemProperty(Object propertyId) + throws BindException { + Item item = getItemDataSource(); + if (item == null) { + throw new BindException("Could not lookup property with id " + + propertyId + " as no item has been set"); + } + Property<?> p = item.getItemProperty(propertyId); + if (p == null) { + throw new BindException("A property with id " + propertyId + + " was not found in the item"); + } + return p; + } + + /** + * Detaches the field from its property id and removes it from this + * FieldBinder. + * <p> + * Note that the field is not detached from its property data source if it + * is no longer connected to the same property id it was bound to using this + * FieldBinder. + * + * @param field + * The field to detach + * @throws BindException + * If the field is not bound by this field binder or not bound + * to the correct property id + */ + public void unbind(Field<?> field) throws BindException { + Object propertyId = fieldToPropertyId.get(field); + if (propertyId == null) { + throw new BindException( + "The given field is not part of this FieldBinder"); + } + + Property fieldDataSource = field.getPropertyDataSource(); + if (fieldDataSource instanceof TransactionalPropertyWrapper) { + fieldDataSource = ((TransactionalPropertyWrapper) fieldDataSource) + .getWrappedProperty(); + } + if (fieldDataSource == getItemProperty(propertyId)) { + field.setPropertyDataSource(null); + } + fieldToPropertyId.remove(field); + propertyIdToField.remove(propertyId); + } + + /** + * Configures a field with the settings set for this FieldBinder. + * <p> + * By default this updates the buffered, read only and enabled state of the + * field. Also adds validators when applicable. + * + * @param field + * The field to update + */ + protected void configureField(Field<?> field) { + field.setBuffered(isBuffered()); + + field.setEnabled(isEnabled()); + field.setReadOnly(isReadOnly()); + } + + /** + * Gets the type of the property with the given property id. + * + * @param propertyId + * The propertyId. Must be find + * @return The type of the property + */ + protected Class<?> getPropertyType(Object propertyId) throws BindException { + if (getItemDataSource() == null) { + throw new BindException( + "Property type for '" + + propertyId + + "' could not be determined. No item data source has been set."); + } + Property<?> p = getItemDataSource().getItemProperty(propertyId); + if (p == null) { + throw new BindException( + "Property type for '" + + propertyId + + "' could not be determined. No property with that id was found."); + } + + return p.getType(); + } + + /** + * Returns a collection of all property ids that have been bound to fields. + * <p> + * Note that this will return property ids even before the item has been + * set. In that case it returns the property ids that will be bound once the + * item is set. + * </p> + * <p> + * No guarantee is given for the order of the property ids + * </p> + * + * @return A collection of bound property ids + */ + public Collection<Object> getBoundPropertyIds() { + return Collections.unmodifiableCollection(propertyIdToField.keySet()); + } + + /** + * Returns a collection of all property ids that exist in the item set using + * {@link #setItemDataSource(Item)} but have not been bound to fields. + * <p> + * Will always return an empty collection before an item has been set using + * {@link #setItemDataSource(Item)}. + * </p> + * <p> + * No guarantee is given for the order of the property ids + * </p> + * + * @return A collection of property ids that have not been bound to fields + */ + public Collection<Object> getUnboundPropertyIds() { + if (getItemDataSource() == null) { + return new ArrayList<Object>(); + } + List<Object> unboundPropertyIds = new ArrayList<Object>(); + unboundPropertyIds.addAll(getItemDataSource().getItemPropertyIds()); + unboundPropertyIds.removeAll(propertyIdToField.keySet()); + return unboundPropertyIds; + } + + /** + * Commits all changes done to the bound fields. + * <p> + * Calls all {@link CommitHandler}s before and after committing the field + * changes to the item data source. The whole commit is aborted and state is + * restored to what it was before commit was called if any + * {@link CommitHandler} throws a CommitException or there is a problem + * committing the fields + * + * @throws CommitException + * If the commit was aborted + */ + public void commit() throws CommitException { + if (!isBuffered()) { + // Not using buffered mode, nothing to do + return; + } + for (Field<?> f : fieldToPropertyId.keySet()) { + ((Property.Transactional<?>) f.getPropertyDataSource()) + .startTransaction(); + } + try { + firePreCommitEvent(); + // Commit the field values to the properties + for (Field<?> f : fieldToPropertyId.keySet()) { + f.commit(); + } + firePostCommitEvent(); + + // Commit the properties + for (Field<?> f : fieldToPropertyId.keySet()) { + ((Property.Transactional<?>) f.getPropertyDataSource()) + .commit(); + } + + } catch (Exception e) { + for (Field<?> f : fieldToPropertyId.keySet()) { + try { + ((Property.Transactional<?>) f.getPropertyDataSource()) + .rollback(); + } catch (Exception rollbackException) { + // FIXME: What to do ? + } + } + + throw new CommitException("Commit failed", e); + } + + } + + /** + * Sends a preCommit event to all registered commit handlers + * + * @throws CommitException + * If the commit should be aborted + */ + private void firePreCommitEvent() throws CommitException { + CommitHandler[] handlers = commitHandlers + .toArray(new CommitHandler[commitHandlers.size()]); + + for (CommitHandler handler : handlers) { + handler.preCommit(new CommitEvent(this)); + } + } + + /** + * Sends a postCommit event to all registered commit handlers + * + * @throws CommitException + * If the commit should be aborted + */ + private void firePostCommitEvent() throws CommitException { + CommitHandler[] handlers = commitHandlers + .toArray(new CommitHandler[commitHandlers.size()]); + + for (CommitHandler handler : handlers) { + handler.postCommit(new CommitEvent(this)); + } + } + + /** + * Discards all changes done to the bound fields. + * <p> + * Only has effect if buffered mode is used. + * + */ + public void discard() { + for (Field<?> f : fieldToPropertyId.keySet()) { + try { + f.discard(); + } catch (Exception e) { + // TODO: handle exception + // What can we do if discard fails other than try to discard all + // other fields? + } + } + } + + /** + * Returns the field that is bound to the given property id + * + * @param propertyId + * The property id to use to lookup the field + * @return The field that is bound to the property id or null if no field is + * bound to that property id + */ + public Field<?> getField(Object propertyId) { + return propertyIdToField.get(propertyId); + } + + /** + * Returns the property id that is bound to the given field + * + * @param field + * The field to use to lookup the property id + * @return The property id that is bound to the field or null if the field + * is not bound to any property id by this FieldBinder + */ + public Object getPropertyId(Field<?> field) { + return fieldToPropertyId.get(field); + } + + /** + * Adds a commit handler. + * <p> + * The commit handler is called before the field values are committed to the + * item ( {@link CommitHandler#preCommit(CommitEvent)}) and after the item + * has been updated ({@link CommitHandler#postCommit(CommitEvent)}). If a + * {@link CommitHandler} throws a CommitException the whole commit is + * aborted and the fields retain their old values. + * + * @param commitHandler + * The commit handler to add + */ + public void addCommitHandler(CommitHandler commitHandler) { + commitHandlers.add(commitHandler); + } + + /** + * Removes the given commit handler. + * + * @see #addCommitHandler(CommitHandler) + * + * @param commitHandler + * The commit handler to remove + */ + public void removeCommitHandler(CommitHandler commitHandler) { + commitHandlers.remove(commitHandler); + } + + /** + * Returns a list of all commit handlers for this {@link FieldGroup}. + * <p> + * Use {@link #addCommitHandler(CommitHandler)} and + * {@link #removeCommitHandler(CommitHandler)} to register or unregister a + * commit handler. + * + * @return A collection of commit handlers + */ + protected Collection<CommitHandler> getCommitHandlers() { + return Collections.unmodifiableCollection(commitHandlers); + } + + /** + * CommitHandlers are used by {@link FieldGroup#commit()} as part of the + * commit transactions. CommitHandlers can perform custom operations as part + * of the commit and cause the commit to be aborted by throwing a + * {@link CommitException}. + */ + public interface CommitHandler extends Serializable { + /** + * Called before changes are committed to the field and the item is + * updated. + * <p> + * Throw a {@link CommitException} to abort the commit. + * + * @param commitEvent + * An event containing information regarding the commit + * @throws CommitException + * if the commit should be aborted + */ + public void preCommit(CommitEvent commitEvent) throws CommitException; + + /** + * Called after changes are committed to the fields and the item is + * updated.. + * <p> + * Throw a {@link CommitException} to abort the commit. + * + * @param commitEvent + * An event containing information regarding the commit + * @throws CommitException + * if the commit should be aborted + */ + public void postCommit(CommitEvent commitEvent) throws CommitException; + } + + /** + * FIXME javadoc + * + */ + public static class CommitEvent implements Serializable { + private FieldGroup fieldBinder; + + private CommitEvent(FieldGroup fieldBinder) { + this.fieldBinder = fieldBinder; + } + + /** + * Returns the field binder that this commit relates to + * + * @return The FieldBinder that is being committed. + */ + public FieldGroup getFieldBinder() { + return fieldBinder; + } + + } + + /** + * Checks the validity of the bound fields. + * <p> + * Call the {@link Field#validate()} for the fields to get the individual + * error messages. + * + * @return true if all bound fields are valid, false otherwise. + */ + public boolean isValid() { + try { + for (Field<?> field : getFields()) { + field.validate(); + } + return true; + } catch (InvalidValueException e) { + return false; + } + } + + /** + * Checks if any bound field has been modified. + * + * @return true if at least on field has been modified, false otherwise + */ + public boolean isModified() { + for (Field<?> field : getFields()) { + if (field.isModified()) { + return true; + } + } + return false; + } + + /** + * Gets the field factory for the {@link FieldGroup}. The field factory is + * only used when {@link FieldGroup} creates a new field. + * + * @return The field factory in use + * + */ + public FieldGroupFieldFactory getFieldFactory() { + return fieldFactory; + } + + /** + * Sets the field factory for the {@link FieldGroup}. The field factory is + * only used when {@link FieldGroup} creates a new field. + * + * @param fieldFactory + * The field factory to use + */ + public void setFieldFactory(FieldGroupFieldFactory fieldFactory) { + this.fieldFactory = fieldFactory; + } + + /** + * Binds member fields found in the given object. + * <p> + * This method processes all (Java) member fields whose type extends + * {@link Field} and that can be mapped to a property id. Property id + * mapping is done based on the field name or on a @{@link PropertyId} + * annotation on the field. All non-null fields for which a property id can + * be determined are bound to the property id. + * </p> + * <p> + * For example: + * + * <pre> + * public class MyForm extends VerticalLayout { + * private TextField firstName = new TextField("First name"); + * @PropertyId("last") + * private TextField lastName = new TextField("Last name"); + * private TextField age = new TextField("Age"); ... } + * + * MyForm myForm = new MyForm(); + * ... + * fieldGroup.bindMemberFields(myForm); + * </pre> + * + * </p> + * This binds the firstName TextField to a "firstName" property in the item, + * lastName TextField to a "last" property and the age TextField to a "age" + * property. + * + * @param objectWithMemberFields + * The object that contains (Java) member fields to bind + * @throws BindException + * If there is a problem binding a field + */ + public void bindMemberFields(Object objectWithMemberFields) + throws BindException { + buildAndBindMemberFields(objectWithMemberFields, false); + } + + /** + * Binds member fields found in the given object and builds member fields + * that have not been initialized. + * <p> + * This method processes all (Java) member fields whose type extends + * {@link Field} and that can be mapped to a property id. Property id + * mapping is done based on the field name or on a @{@link PropertyId} + * annotation on the field. Fields that are not initialized (null) are built + * using the field factory. All non-null fields for which a property id can + * be determined are bound to the property id. + * </p> + * <p> + * For example: + * + * <pre> + * public class MyForm extends VerticalLayout { + * private TextField firstName = new TextField("First name"); + * @PropertyId("last") + * private TextField lastName = new TextField("Last name"); + * private TextField age; + * + * MyForm myForm = new MyForm(); + * ... + * fieldGroup.buildAndBindMemberFields(myForm); + * </pre> + * + * </p> + * <p> + * This binds the firstName TextField to a "firstName" property in the item, + * lastName TextField to a "last" property and builds an age TextField using + * the field factory and then binds it to the "age" property. + * </p> + * + * @param objectWithMemberFields + * The object that contains (Java) member fields to build and + * bind + * @throws BindException + * If there is a problem binding or building a field + */ + public void buildAndBindMemberFields(Object objectWithMemberFields) + throws BindException { + buildAndBindMemberFields(objectWithMemberFields, true); + } + + /** + * Binds member fields found in the given object and optionally builds + * member fields that have not been initialized. + * <p> + * This method processes all (Java) member fields whose type extends + * {@link Field} and that can be mapped to a property id. Property id + * mapping is done based on the field name or on a @{@link PropertyId} + * annotation on the field. Fields that are not initialized (null) are built + * using the field factory is buildFields is true. All non-null fields for + * which a property id can be determined are bound to the property id. + * </p> + * + * @param objectWithMemberFields + * The object that contains (Java) member fields to build and + * bind + * @throws BindException + * If there is a problem binding or building a field + */ + protected void buildAndBindMemberFields(Object objectWithMemberFields, + boolean buildFields) throws BindException { + Class<?> objectClass = objectWithMemberFields.getClass(); + + for (java.lang.reflect.Field memberField : objectClass + .getDeclaredFields()) { + + if (!Field.class.isAssignableFrom(memberField.getType())) { + // Process next field + continue; + } + + PropertyId propertyIdAnnotation = memberField + .getAnnotation(PropertyId.class); + + Class<? extends Field> fieldType = (Class<? extends Field>) memberField + .getType(); + + Object propertyId = null; + if (propertyIdAnnotation != null) { + // @PropertyId(propertyId) always overrides property id + propertyId = propertyIdAnnotation.value(); + } else { + propertyId = memberField.getName(); + } + + // Ensure that the property id exists + Class<?> propertyType; + + try { + propertyType = getPropertyType(propertyId); + } catch (BindException e) { + // Property id was not found, skip this field + continue; + } + + Field<?> field; + try { + // Get the field from the object + field = (Field<?>) ReflectTools.getJavaFieldValue( + objectWithMemberFields, memberField); + } catch (Exception e) { + // If we cannot determine the value, just skip the field and try + // the next one + continue; + } + + if (field == null && buildFields) { + Caption captionAnnotation = memberField + .getAnnotation(Caption.class); + String caption; + if (captionAnnotation != null) { + caption = captionAnnotation.value(); + } else { + caption = DefaultFieldFactory + .createCaptionByPropertyId(propertyId); + } + + // Create the component (Field) + field = build(caption, propertyType, fieldType); + + // Store it in the field + try { + ReflectTools.setJavaFieldValue(objectWithMemberFields, + memberField, field); + } catch (IllegalArgumentException e) { + throw new BindException("Could not assign value to field '" + + memberField.getName() + "'", e); + } catch (IllegalAccessException e) { + throw new BindException("Could not assign value to field '" + + memberField.getName() + "'", e); + } catch (InvocationTargetException e) { + throw new BindException("Could not assign value to field '" + + memberField.getName() + "'", e); + } + } + + if (field != null) { + // Bind it to the property id + bind(field, propertyId); + } + } + } + + public static class CommitException extends Exception { + + public CommitException() { + super(); + // TODO Auto-generated constructor stub + } + + public CommitException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + + public CommitException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + public CommitException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + + } + + public static class BindException extends RuntimeException { + + public BindException(String message) { + super(message); + } + + public BindException(String message, Throwable t) { + super(message, t); + } + + } + + /** + * Builds a field and binds it to the given property id using the field + * binder. + * + * @param propertyId + * The property id to bind to. Must be present in the field + * finder. + * @throws BindException + * If there is a problem while building or binding + * @return The created and bound field + */ + public Field<?> buildAndBind(Object propertyId) throws BindException { + String caption = DefaultFieldFactory + .createCaptionByPropertyId(propertyId); + return buildAndBind(caption, propertyId); + } + + /** + * Builds a field using the given caption and binds it to the given property + * id using the field binder. + * + * @param caption + * The caption for the field + * @param propertyId + * The property id to bind to. Must be present in the field + * finder. + * @throws BindException + * If there is a problem while building or binding + * @return The created and bound field. Can be any type of {@link Field}. + */ + public Field<?> buildAndBind(String caption, Object propertyId) + throws BindException { + Class<?> type = getPropertyType(propertyId); + return buildAndBind(caption, propertyId, Field.class); + + } + + /** + * Builds a field using the given caption and binds it to the given property + * id using the field binder. Ensures the new field is of the given type. + * + * @param caption + * The caption for the field + * @param propertyId + * The property id to bind to. Must be present in the field + * finder. + * @throws BindException + * If the field could not be created + * @return The created and bound field. Can be any type of {@link Field}. + */ + + public <T extends Field> T buildAndBind(String caption, Object propertyId, + Class<T> fieldType) throws BindException { + Class<?> type = getPropertyType(propertyId); + + T field = build(caption, type, fieldType); + bind(field, propertyId); + + return field; + } + + /** + * Creates a field based on the given data type. + * <p> + * The data type is the type that we want to edit using the field. The field + * type is the type of field we want to create, can be {@link Field} if any + * Field is good. + * </p> + * + * @param caption + * The caption for the new field + * @param dataType + * The data model type that we want to edit using the field + * @param fieldType + * The type of field that we want to create + * @return A Field capable of editing the given type + * @throws BindException + * If the field could not be created + */ + protected <T extends Field> T build(String caption, Class<?> dataType, + Class<T> fieldType) throws BindException { + T field = getFieldFactory().createField(dataType, fieldType); + if (field == null) { + throw new BindException("Unable to build a field of type " + + fieldType.getName() + " for editing " + + dataType.getName()); + } + + field.setCaption(caption); + return field; + } }
\ No newline at end of file diff --git a/src/com/vaadin/data/fieldgroup/FieldGroupFieldFactory.java b/src/com/vaadin/data/fieldgroup/FieldGroupFieldFactory.java index 6945a492bd..80c012cbdc 100644 --- a/src/com/vaadin/data/fieldgroup/FieldGroupFieldFactory.java +++ b/src/com/vaadin/data/fieldgroup/FieldGroupFieldFactory.java @@ -1,31 +1,31 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.fieldgroup;
-
-import java.io.Serializable;
-
-import com.vaadin.ui.Field;
-
-/**
- * Factory interface for creating new Field-instances based on the data type
- * that should be edited.
- *
- * @author Vaadin Ltd.
- * @version @version@
- * @since 7.0
- */
-public interface FieldGroupFieldFactory extends Serializable {
- /**
- * Creates a field based on the data type that we want to edit
- *
- * @param dataType
- * The type that we want to edit using the field
- * @param fieldType
- * The type of field we want to create. If set to {@link Field}
- * then any type of field is accepted
- * @return A field that can be assigned to the given fieldType and that is
- * capable of editing the given type of data
- */
- <T extends Field> T createField(Class<?> dataType, Class<T> fieldType);
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.data.fieldgroup; + +import java.io.Serializable; + +import com.vaadin.ui.Field; + +/** + * Factory interface for creating new Field-instances based on the data type + * that should be edited. + * + * @author Vaadin Ltd. + * @version @version@ + * @since 7.0 + */ +public interface FieldGroupFieldFactory extends Serializable { + /** + * Creates a field based on the data type that we want to edit + * + * @param dataType + * The type that we want to edit using the field + * @param fieldType + * The type of field we want to create. If set to {@link Field} + * then any type of field is accepted + * @return A field that can be assigned to the given fieldType and that is + * capable of editing the given type of data + */ + <T extends Field> T createField(Class<?> dataType, Class<T> fieldType); +} diff --git a/src/com/vaadin/data/fieldgroup/PropertyId.java b/src/com/vaadin/data/fieldgroup/PropertyId.java index 588fdc3020..268047401d 100644 --- a/src/com/vaadin/data/fieldgroup/PropertyId.java +++ b/src/com/vaadin/data/fieldgroup/PropertyId.java @@ -1,15 +1,15 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.fieldgroup;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Target({ ElementType.FIELD })
-@Retention(RetentionPolicy.RUNTIME)
-public @interface PropertyId {
- String value();
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.data.fieldgroup; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface PropertyId { + String value(); +} diff --git a/src/com/vaadin/data/util/TextFileProperty.java b/src/com/vaadin/data/util/TextFileProperty.java index 77325e141d..5ebba98062 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<String> {
-
- 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<String> getType() {
- return String.class;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Property#getValue()
- */
- public String 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<String> { + + 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<String> getType() { + return String.class; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.Property#getValue() + */ + public String 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/TransactionalPropertyWrapper.java b/src/com/vaadin/data/util/TransactionalPropertyWrapper.java index de44dbe544..06ec0935c3 100644 --- a/src/com/vaadin/data/util/TransactionalPropertyWrapper.java +++ b/src/com/vaadin/data/util/TransactionalPropertyWrapper.java @@ -1,107 +1,107 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.util;
-
-import com.vaadin.data.Property;
-import com.vaadin.data.Property.ValueChangeEvent;
-import com.vaadin.data.Property.ValueChangeNotifier;
-
-/**
- * Wrapper class that helps implement two-phase commit for a non-transactional
- * property.
- *
- * When accessing the property through the wrapper, getting and setting the
- * property value take place immediately. However, the wrapper keeps track of
- * the old value of the property so that it can be set for the property in case
- * of a roll-back. This can result in the underlying property value changing
- * multiple times (first based on modifications made by the application, then
- * back upon roll-back).
- *
- * Value change events on the {@link TransactionalPropertyWrapper} are only
- * fired at the end of a successful transaction, whereas listeners attached to
- * the underlying property may receive multiple value change events.
- *
- * @see com.vaadin.data.Property.Transactional
- *
- * @author Vaadin Ltd
- * @version @version@
- * @since 7.0
- *
- * @param <T>
- */
-public class TransactionalPropertyWrapper<T> extends AbstractProperty<T>
- implements ValueChangeNotifier, Property.Transactional<T> {
-
- private Property<T> wrappedProperty;
- private boolean inTransaction = false;
- private boolean valueChangePending;
- private T valueBeforeTransaction;
-
- public TransactionalPropertyWrapper(Property<T> wrappedProperty) {
- this.wrappedProperty = wrappedProperty;
- if (wrappedProperty instanceof ValueChangeNotifier) {
- ((ValueChangeNotifier) wrappedProperty)
- .addListener(new ValueChangeListener() {
-
- public void valueChange(ValueChangeEvent event) {
- fireValueChange();
- }
- });
- }
- }
-
- public Class getType() {
- return wrappedProperty.getType();
- }
-
- public T getValue() {
- return wrappedProperty.getValue();
- }
-
- public void setValue(Object newValue) throws ReadOnlyException {
- // Causes a value change to be sent to this listener which in turn fires
- // a new value change event for this property
- wrappedProperty.setValue(newValue);
- }
-
- public void startTransaction() {
- inTransaction = true;
- valueBeforeTransaction = getValue();
- }
-
- public void commit() {
- endTransaction();
- }
-
- public void rollback() {
- try {
- wrappedProperty.setValue(valueBeforeTransaction);
- } finally {
- valueChangePending = false;
- endTransaction();
- }
- }
-
- protected void endTransaction() {
- inTransaction = false;
- valueBeforeTransaction = null;
- if (valueChangePending) {
- fireValueChange();
- }
- }
-
- @Override
- protected void fireValueChange() {
- if (inTransaction) {
- valueChangePending = true;
- } else {
- super.fireValueChange();
- }
- }
-
- public Property<T> getWrappedProperty() {
- return wrappedProperty;
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.data.util; + +import com.vaadin.data.Property; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeNotifier; + +/** + * Wrapper class that helps implement two-phase commit for a non-transactional + * property. + * + * When accessing the property through the wrapper, getting and setting the + * property value take place immediately. However, the wrapper keeps track of + * the old value of the property so that it can be set for the property in case + * of a roll-back. This can result in the underlying property value changing + * multiple times (first based on modifications made by the application, then + * back upon roll-back). + * + * Value change events on the {@link TransactionalPropertyWrapper} are only + * fired at the end of a successful transaction, whereas listeners attached to + * the underlying property may receive multiple value change events. + * + * @see com.vaadin.data.Property.Transactional + * + * @author Vaadin Ltd + * @version @version@ + * @since 7.0 + * + * @param <T> + */ +public class TransactionalPropertyWrapper<T> extends AbstractProperty<T> + implements ValueChangeNotifier, Property.Transactional<T> { + + private Property<T> wrappedProperty; + private boolean inTransaction = false; + private boolean valueChangePending; + private T valueBeforeTransaction; + + public TransactionalPropertyWrapper(Property<T> wrappedProperty) { + this.wrappedProperty = wrappedProperty; + if (wrappedProperty instanceof ValueChangeNotifier) { + ((ValueChangeNotifier) wrappedProperty) + .addListener(new ValueChangeListener() { + + public void valueChange(ValueChangeEvent event) { + fireValueChange(); + } + }); + } + } + + public Class getType() { + return wrappedProperty.getType(); + } + + public T getValue() { + return wrappedProperty.getValue(); + } + + public void setValue(Object newValue) throws ReadOnlyException { + // Causes a value change to be sent to this listener which in turn fires + // a new value change event for this property + wrappedProperty.setValue(newValue); + } + + public void startTransaction() { + inTransaction = true; + valueBeforeTransaction = getValue(); + } + + public void commit() { + endTransaction(); + } + + public void rollback() { + try { + wrappedProperty.setValue(valueBeforeTransaction); + } finally { + valueChangePending = false; + endTransaction(); + } + } + + protected void endTransaction() { + inTransaction = false; + valueBeforeTransaction = null; + if (valueChangePending) { + fireValueChange(); + } + } + + @Override + protected void fireValueChange() { + if (inTransaction) { + valueChangePending = true; + } else { + super.fireValueChange(); + } + } + + public Property<T> getWrappedProperty() { + return wrappedProperty; + } + +} diff --git a/src/com/vaadin/data/util/converter/Converter.java b/src/com/vaadin/data/util/converter/Converter.java index 065d06b071..b8c15e8cdc 100644 --- a/src/com/vaadin/data/util/converter/Converter.java +++ b/src/com/vaadin/data/util/converter/Converter.java @@ -1,159 +1,159 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.io.Serializable;
-import java.util.Locale;
-
-/**
- * Interface that implements conversion between a model and a presentation type.
- * <p>
- * Typically {@link #convertToPresentation(Object, Locale)} and
- * {@link #convertToModel(Object, Locale)} should be symmetric so that chaining
- * these together returns the original result for all input but this is not a
- * requirement.
- * </p>
- * <p>
- * Converters must not have any side effects (never update UI from inside a
- * converter).
- * </p>
- * <p>
- * All Converters must be stateless and thread safe.
- * </p>
- * <p>
- * If conversion of a value fails, a {@link ConversionException} is thrown.
- * </p>
- *
- * @param <MODEL>
- * The model type. Must be compatible with what
- * {@link #getModelType()} returns.
- * @param <PRESENTATION>
- * The presentation type. Must be compatible with what
- * {@link #getPresentationType()} returns.
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 7.0
- */
-public interface Converter<PRESENTATION, MODEL> extends Serializable {
-
- /**
- * Converts the given value from target type to source type.
- * <p>
- * A converter can optionally use locale to do the conversion.
- * </p>
- * A converter should in most cases be symmetric so chaining
- * {@link #convertToPresentation(Object, Locale)} and
- * {@link #convertToModel(Object, Locale)} should return the original value.
- *
- * @param value
- * The value to convert, compatible with the target type. Can be
- * null
- * @param locale
- * The locale to use for conversion. Can be null.
- * @return The converted value compatible with the source type
- * @throws ConversionException
- * If the value could not be converted
- */
- public MODEL convertToModel(PRESENTATION value, Locale locale)
- throws ConversionException;
-
- /**
- * Converts the given value from source type to target type.
- * <p>
- * A converter can optionally use locale to do the conversion.
- * </p>
- * A converter should in most cases be symmetric so chaining
- * {@link #convertToPresentation(Object, Locale)} and
- * {@link #convertToModel(Object, Locale)} should return the original value.
- *
- * @param value
- * The value to convert, compatible with the target type. Can be
- * null
- * @param locale
- * The locale to use for conversion. Can be null.
- * @return The converted value compatible with the source type
- * @throws ConversionException
- * If the value could not be converted
- */
- public PRESENTATION convertToPresentation(MODEL value, Locale locale)
- throws ConversionException;
-
- /**
- * The source type of the converter.
- *
- * Values of this type can be passed to
- * {@link #convertToPresentation(Object, Locale)}.
- *
- * @return The source type
- */
- public Class<MODEL> getModelType();
-
- /**
- * The target type of the converter.
- *
- * Values of this type can be passed to
- * {@link #convertToModel(Object, Locale)}.
- *
- * @return The target type
- */
- public Class<PRESENTATION> getPresentationType();
-
- /**
- * An exception that signals that the value passed to
- * {@link Converter#convertToPresentation(Object, Locale)} or
- * {@link Converter#convertToModel(Object, Locale)} could not be converted.
- *
- * @author Vaadin Ltd
- * @version
- * @VERSION@
- * @since 7.0
- */
- public static class ConversionException extends RuntimeException {
-
- /**
- * Constructs a new <code>ConversionException</code> without a detail
- * message.
- */
- public ConversionException() {
- }
-
- /**
- * Constructs a new <code>ConversionException</code> with the specified
- * detail message.
- *
- * @param msg
- * the detail message
- */
- public ConversionException(String msg) {
- super(msg);
- }
-
- /**
- * Constructs a new {@code ConversionException} with the specified
- * cause.
- *
- * @param cause
- * The cause of the the exception
- */
- public ConversionException(Throwable cause) {
- super(cause);
- }
-
- /**
- * Constructs a new <code>ConversionException</code> with the specified
- * detail message and cause.
- *
- * @param message
- * the detail message
- * @param cause
- * The cause of the the exception
- */
- public ConversionException(String message, Throwable cause) {
- super(message, cause);
- }
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.io.Serializable; +import java.util.Locale; + +/** + * Interface that implements conversion between a model and a presentation type. + * <p> + * Typically {@link #convertToPresentation(Object, Locale)} and + * {@link #convertToModel(Object, Locale)} should be symmetric so that chaining + * these together returns the original result for all input but this is not a + * requirement. + * </p> + * <p> + * Converters must not have any side effects (never update UI from inside a + * converter). + * </p> + * <p> + * All Converters must be stateless and thread safe. + * </p> + * <p> + * If conversion of a value fails, a {@link ConversionException} is thrown. + * </p> + * + * @param <MODEL> + * The model type. Must be compatible with what + * {@link #getModelType()} returns. + * @param <PRESENTATION> + * The presentation type. Must be compatible with what + * {@link #getPresentationType()} returns. + * @author Vaadin Ltd. + * @version + * @VERSION@ + * @since 7.0 + */ +public interface Converter<PRESENTATION, MODEL> extends Serializable { + + /** + * Converts the given value from target type to source type. + * <p> + * A converter can optionally use locale to do the conversion. + * </p> + * A converter should in most cases be symmetric so chaining + * {@link #convertToPresentation(Object, Locale)} and + * {@link #convertToModel(Object, Locale)} should return the original value. + * + * @param value + * The value to convert, compatible with the target type. Can be + * null + * @param locale + * The locale to use for conversion. Can be null. + * @return The converted value compatible with the source type + * @throws ConversionException + * If the value could not be converted + */ + public MODEL convertToModel(PRESENTATION value, Locale locale) + throws ConversionException; + + /** + * Converts the given value from source type to target type. + * <p> + * A converter can optionally use locale to do the conversion. + * </p> + * A converter should in most cases be symmetric so chaining + * {@link #convertToPresentation(Object, Locale)} and + * {@link #convertToModel(Object, Locale)} should return the original value. + * + * @param value + * The value to convert, compatible with the target type. Can be + * null + * @param locale + * The locale to use for conversion. Can be null. + * @return The converted value compatible with the source type + * @throws ConversionException + * If the value could not be converted + */ + public PRESENTATION convertToPresentation(MODEL value, Locale locale) + throws ConversionException; + + /** + * The source type of the converter. + * + * Values of this type can be passed to + * {@link #convertToPresentation(Object, Locale)}. + * + * @return The source type + */ + public Class<MODEL> getModelType(); + + /** + * The target type of the converter. + * + * Values of this type can be passed to + * {@link #convertToModel(Object, Locale)}. + * + * @return The target type + */ + public Class<PRESENTATION> getPresentationType(); + + /** + * An exception that signals that the value passed to + * {@link Converter#convertToPresentation(Object, Locale)} or + * {@link Converter#convertToModel(Object, Locale)} could not be converted. + * + * @author Vaadin Ltd + * @version + * @VERSION@ + * @since 7.0 + */ + public static class ConversionException extends RuntimeException { + + /** + * Constructs a new <code>ConversionException</code> without a detail + * message. + */ + public ConversionException() { + } + + /** + * Constructs a new <code>ConversionException</code> with the specified + * detail message. + * + * @param msg + * the detail message + */ + public ConversionException(String msg) { + super(msg); + } + + /** + * Constructs a new {@code ConversionException} with the specified + * cause. + * + * @param cause + * The cause of the the exception + */ + public ConversionException(Throwable cause) { + super(cause); + } + + /** + * Constructs a new <code>ConversionException</code> with the specified + * detail message and cause. + * + * @param message + * the detail message + * @param cause + * The cause of the the exception + */ + public ConversionException(String message, Throwable cause) { + super(message, cause); + } + } + +} diff --git a/src/com/vaadin/data/util/converter/ConverterFactory.java b/src/com/vaadin/data/util/converter/ConverterFactory.java index 451f84185d..ed4ab41ac0 100644 --- a/src/com/vaadin/data/util/converter/ConverterFactory.java +++ b/src/com/vaadin/data/util/converter/ConverterFactory.java @@ -1,23 +1,23 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.io.Serializable;
-
-/**
- * Factory interface for providing Converters based on a presentation type and a
- * model type.
- *
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 7.0
- *
- */
-public interface ConverterFactory extends Serializable {
- public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> createConverter(
- Class<PRESENTATION> presentationType, Class<MODEL> modelType);
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.io.Serializable; + +/** + * Factory interface for providing Converters based on a presentation type and a + * model type. + * + * @author Vaadin Ltd. + * @version + * @VERSION@ + * @since 7.0 + * + */ +public interface ConverterFactory extends Serializable { + public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> createConverter( + Class<PRESENTATION> presentationType, Class<MODEL> modelType); + +} diff --git a/src/com/vaadin/data/util/converter/DateToLongConverter.java b/src/com/vaadin/data/util/converter/DateToLongConverter.java index d66adece06..537800f617 100644 --- a/src/com/vaadin/data/util/converter/DateToLongConverter.java +++ b/src/com/vaadin/data/util/converter/DateToLongConverter.java @@ -1,68 +1,68 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.util.Date;
-import java.util.Locale;
-
-/**
- * A converter that converts from {@link Long} to {@link Date} and back.
- *
- * @author Vaadin Ltd
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class DateToLongConverter implements Converter<Date, Long> {
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object,
- * java.util.Locale)
- */
- public Long convertToModel(Date value, Locale locale) {
- if (value == null) {
- return null;
- }
-
- return value.getTime();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang
- * .Object, java.util.Locale)
- */
- public Date convertToPresentation(Long value, Locale locale) {
- if (value == null) {
- return null;
- }
-
- return new Date(value);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getModelType()
- */
- public Class<Long> getModelType() {
- return Long.class;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getPresentationType()
- */
- public Class<Date> getPresentationType() {
- return Date.class;
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.util.Date; +import java.util.Locale; + +/** + * A converter that converts from {@link Long} to {@link Date} and back. + * + * @author Vaadin Ltd + * @version + * @VERSION@ + * @since 7.0 + */ +public class DateToLongConverter implements Converter<Date, Long> { + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object, + * java.util.Locale) + */ + public Long convertToModel(Date value, Locale locale) { + if (value == null) { + return null; + } + + return value.getTime(); + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang + * .Object, java.util.Locale) + */ + public Date convertToPresentation(Long value, Locale locale) { + if (value == null) { + return null; + } + + return new Date(value); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getModelType() + */ + public Class<Long> getModelType() { + return Long.class; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getPresentationType() + */ + public Class<Date> getPresentationType() { + return Date.class; + } + +} diff --git a/src/com/vaadin/data/util/converter/DefaultConverterFactory.java b/src/com/vaadin/data/util/converter/DefaultConverterFactory.java index 9233624819..3ad7b6a85b 100644 --- a/src/com/vaadin/data/util/converter/DefaultConverterFactory.java +++ b/src/com/vaadin/data/util/converter/DefaultConverterFactory.java @@ -1,100 +1,100 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.util.Date;
-import java.util.logging.Logger;
-
-import com.vaadin.Application;
-
-/**
- * Default implementation of {@link ConverterFactory}. Provides converters for
- * standard types like {@link String}, {@link Double} and {@link Date}. </p>
- * <p>
- * Custom converters can be provided by extending this class and using
- * {@link Application#setConverterFactory(ConverterFactory)}.
- * </p>
- *
- * @author Vaadin Ltd
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class DefaultConverterFactory implements ConverterFactory {
-
- private final static Logger log = Logger
- .getLogger(DefaultConverterFactory.class.getName());
-
- public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> createConverter(
- Class<PRESENTATION> presentationType, Class<MODEL> modelType) {
- Converter<PRESENTATION, MODEL> converter = findConverter(
- presentationType, modelType);
- if (converter != null) {
- log.finest(getClass().getName() + " created a "
- + converter.getClass());
- return converter;
- }
-
- // Try to find a reverse converter
- Converter<MODEL, PRESENTATION> reverseConverter = findConverter(
- modelType, presentationType);
- if (reverseConverter != null) {
- log.finest(getClass().getName() + " created a reverse "
- + reverseConverter.getClass());
- return new ReverseConverter<PRESENTATION, MODEL>(reverseConverter);
- }
-
- log.finest(getClass().getName() + " could not find a converter for "
- + presentationType.getName() + " to " + modelType.getName()
- + " conversion");
- return null;
-
- }
-
- protected <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> findConverter(
- Class<PRESENTATION> presentationType, Class<MODEL> modelType) {
- if (presentationType == String.class) {
- // TextField converters and more
- Converter<PRESENTATION, MODEL> converter = (Converter<PRESENTATION, MODEL>) createStringConverter(modelType);
- if (converter != null) {
- return converter;
- }
- } else if (presentationType == Date.class) {
- // DateField converters and more
- Converter<PRESENTATION, MODEL> converter = (Converter<PRESENTATION, MODEL>) createDateConverter(modelType);
- if (converter != null) {
- return converter;
- }
- }
-
- return null;
-
- }
-
- protected Converter<Date, ?> createDateConverter(Class<?> sourceType) {
- if (Long.class.isAssignableFrom(sourceType)) {
- return new DateToLongConverter();
- } else {
- return null;
- }
- }
-
- protected Converter<String, ?> createStringConverter(Class<?> sourceType) {
- if (Double.class.isAssignableFrom(sourceType)) {
- return new StringToDoubleConverter();
- } else if (Integer.class.isAssignableFrom(sourceType)) {
- return new StringToIntegerConverter();
- } else if (Boolean.class.isAssignableFrom(sourceType)) {
- return new StringToBooleanConverter();
- } else if (Number.class.isAssignableFrom(sourceType)) {
- return new StringToNumberConverter();
- } else if (Date.class.isAssignableFrom(sourceType)) {
- return new StringToDateConverter();
- } else {
- return null;
- }
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.util.Date; +import java.util.logging.Logger; + +import com.vaadin.Application; + +/** + * Default implementation of {@link ConverterFactory}. Provides converters for + * standard types like {@link String}, {@link Double} and {@link Date}. </p> + * <p> + * Custom converters can be provided by extending this class and using + * {@link Application#setConverterFactory(ConverterFactory)}. + * </p> + * + * @author Vaadin Ltd + * @version + * @VERSION@ + * @since 7.0 + */ +public class DefaultConverterFactory implements ConverterFactory { + + private final static Logger log = Logger + .getLogger(DefaultConverterFactory.class.getName()); + + public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> createConverter( + Class<PRESENTATION> presentationType, Class<MODEL> modelType) { + Converter<PRESENTATION, MODEL> converter = findConverter( + presentationType, modelType); + if (converter != null) { + log.finest(getClass().getName() + " created a " + + converter.getClass()); + return converter; + } + + // Try to find a reverse converter + Converter<MODEL, PRESENTATION> reverseConverter = findConverter( + modelType, presentationType); + if (reverseConverter != null) { + log.finest(getClass().getName() + " created a reverse " + + reverseConverter.getClass()); + return new ReverseConverter<PRESENTATION, MODEL>(reverseConverter); + } + + log.finest(getClass().getName() + " could not find a converter for " + + presentationType.getName() + " to " + modelType.getName() + + " conversion"); + return null; + + } + + protected <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> findConverter( + Class<PRESENTATION> presentationType, Class<MODEL> modelType) { + if (presentationType == String.class) { + // TextField converters and more + Converter<PRESENTATION, MODEL> converter = (Converter<PRESENTATION, MODEL>) createStringConverter(modelType); + if (converter != null) { + return converter; + } + } else if (presentationType == Date.class) { + // DateField converters and more + Converter<PRESENTATION, MODEL> converter = (Converter<PRESENTATION, MODEL>) createDateConverter(modelType); + if (converter != null) { + return converter; + } + } + + return null; + + } + + protected Converter<Date, ?> createDateConverter(Class<?> sourceType) { + if (Long.class.isAssignableFrom(sourceType)) { + return new DateToLongConverter(); + } else { + return null; + } + } + + protected Converter<String, ?> createStringConverter(Class<?> sourceType) { + if (Double.class.isAssignableFrom(sourceType)) { + return new StringToDoubleConverter(); + } else if (Integer.class.isAssignableFrom(sourceType)) { + return new StringToIntegerConverter(); + } else if (Boolean.class.isAssignableFrom(sourceType)) { + return new StringToBooleanConverter(); + } else if (Number.class.isAssignableFrom(sourceType)) { + return new StringToNumberConverter(); + } else if (Date.class.isAssignableFrom(sourceType)) { + return new StringToDateConverter(); + } else { + return null; + } + } + +} diff --git a/src/com/vaadin/data/util/converter/ReverseConverter.java b/src/com/vaadin/data/util/converter/ReverseConverter.java index b191d1ca0b..1c561f29e8 100644 --- a/src/com/vaadin/data/util/converter/ReverseConverter.java +++ b/src/com/vaadin/data/util/converter/ReverseConverter.java @@ -1,80 +1,80 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.util.Locale;
-
-/**
- * A converter that wraps another {@link Converter} and reverses source and
- * target types.
- *
- * @param <MODEL>
- * The source type
- * @param <PRESENTATION>
- * The target type
- *
- * @author Vaadin Ltd
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class ReverseConverter<PRESENTATION, MODEL> implements
- Converter<PRESENTATION, MODEL> {
-
- private Converter<MODEL, PRESENTATION> realConverter;
-
- /**
- * Creates a converter from source to target based on a converter that
- * converts from target to source.
- *
- * @param converter
- * The converter to use in a reverse fashion
- */
- public ReverseConverter(Converter<MODEL, PRESENTATION> converter) {
- this.realConverter = converter;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#convertToModel(java
- * .lang.Object, java.util.Locale)
- */
- public MODEL convertToModel(PRESENTATION value, Locale locale)
- throws com.vaadin.data.util.converter.Converter.ConversionException {
- return realConverter.convertToPresentation(value, locale);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang
- * .Object, java.util.Locale)
- */
- public PRESENTATION convertToPresentation(MODEL value, Locale locale)
- throws com.vaadin.data.util.converter.Converter.ConversionException {
- return realConverter.convertToModel(value, locale);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getSourceType()
- */
- public Class<MODEL> getModelType() {
- return realConverter.getPresentationType();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getTargetType()
- */
- public Class<PRESENTATION> getPresentationType() {
- return realConverter.getModelType();
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.util.Locale; + +/** + * A converter that wraps another {@link Converter} and reverses source and + * target types. + * + * @param <MODEL> + * The source type + * @param <PRESENTATION> + * The target type + * + * @author Vaadin Ltd + * @version + * @VERSION@ + * @since 7.0 + */ +public class ReverseConverter<PRESENTATION, MODEL> implements + Converter<PRESENTATION, MODEL> { + + private Converter<MODEL, PRESENTATION> realConverter; + + /** + * Creates a converter from source to target based on a converter that + * converts from target to source. + * + * @param converter + * The converter to use in a reverse fashion + */ + public ReverseConverter(Converter<MODEL, PRESENTATION> converter) { + this.realConverter = converter; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#convertToModel(java + * .lang.Object, java.util.Locale) + */ + public MODEL convertToModel(PRESENTATION value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + return realConverter.convertToPresentation(value, locale); + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang + * .Object, java.util.Locale) + */ + public PRESENTATION convertToPresentation(MODEL value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + return realConverter.convertToModel(value, locale); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getSourceType() + */ + public Class<MODEL> getModelType() { + return realConverter.getPresentationType(); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getTargetType() + */ + public Class<PRESENTATION> getPresentationType() { + return realConverter.getModelType(); + } + +} diff --git a/src/com/vaadin/data/util/converter/StringToBooleanConverter.java b/src/com/vaadin/data/util/converter/StringToBooleanConverter.java index 3b2034a361..96a3a3d071 100644 --- a/src/com/vaadin/data/util/converter/StringToBooleanConverter.java +++ b/src/com/vaadin/data/util/converter/StringToBooleanConverter.java @@ -1,104 +1,104 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.util.Locale;
-
-/**
- * A converter that converts from {@link String} to {@link Boolean} and back.
- * The String representation is given by Boolean.toString().
- * <p>
- * Leading and trailing white spaces are ignored when converting from a String.
- * </p>
- *
- * @author Vaadin Ltd
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class StringToBooleanConverter implements Converter<String, Boolean> {
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object,
- * java.util.Locale)
- */
- public Boolean convertToModel(String value, Locale locale)
- throws ConversionException {
- if (value == null) {
- return null;
- }
-
- // Remove leading and trailing white space
- value = value.trim();
-
- if (getTrueString().equals(value)) {
- return true;
- } else if (getFalseString().equals(value)) {
- return false;
- } else {
- throw new ConversionException("Cannot convert " + value + " to "
- + getModelType().getName());
- }
- }
-
- /**
- * Gets the string representation for true. Default is "true".
- *
- * @return the string representation for true
- */
- protected String getTrueString() {
- return Boolean.TRUE.toString();
- }
-
- /**
- * Gets the string representation for false. Default is "false".
- *
- * @return the string representation for false
- */
- protected String getFalseString() {
- return Boolean.FALSE.toString();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang
- * .Object, java.util.Locale)
- */
- public String convertToPresentation(Boolean value, Locale locale)
- throws ConversionException {
- if (value == null) {
- return null;
- }
- if (value) {
- return getTrueString();
- } else {
- return getFalseString();
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getModelType()
- */
- public Class<Boolean> getModelType() {
- return Boolean.class;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getPresentationType()
- */
- public Class<String> getPresentationType() {
- return String.class;
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.util.Locale; + +/** + * A converter that converts from {@link String} to {@link Boolean} and back. + * The String representation is given by Boolean.toString(). + * <p> + * Leading and trailing white spaces are ignored when converting from a String. + * </p> + * + * @author Vaadin Ltd + * @version + * @VERSION@ + * @since 7.0 + */ +public class StringToBooleanConverter implements Converter<String, Boolean> { + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object, + * java.util.Locale) + */ + public Boolean convertToModel(String value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + // Remove leading and trailing white space + value = value.trim(); + + if (getTrueString().equals(value)) { + return true; + } else if (getFalseString().equals(value)) { + return false; + } else { + throw new ConversionException("Cannot convert " + value + " to " + + getModelType().getName()); + } + } + + /** + * Gets the string representation for true. Default is "true". + * + * @return the string representation for true + */ + protected String getTrueString() { + return Boolean.TRUE.toString(); + } + + /** + * Gets the string representation for false. Default is "false". + * + * @return the string representation for false + */ + protected String getFalseString() { + return Boolean.FALSE.toString(); + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang + * .Object, java.util.Locale) + */ + public String convertToPresentation(Boolean value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + if (value) { + return getTrueString(); + } else { + return getFalseString(); + } + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getModelType() + */ + public Class<Boolean> getModelType() { + return Boolean.class; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getPresentationType() + */ + public Class<String> getPresentationType() { + return String.class; + } + +} diff --git a/src/com/vaadin/data/util/converter/StringToDateConverter.java b/src/com/vaadin/data/util/converter/StringToDateConverter.java index 2aa9395532..6f3c2e47f6 100644 --- a/src/com/vaadin/data/util/converter/StringToDateConverter.java +++ b/src/com/vaadin/data/util/converter/StringToDateConverter.java @@ -1,108 +1,108 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.text.DateFormat;
-import java.text.ParsePosition;
-import java.util.Date;
-import java.util.Locale;
-
-/**
- * A converter that converts from {@link Date} to {@link String} and back. Uses
- * the given locale and {@link DateFormat} for formatting and parsing.
- * <p>
- * Leading and trailing white spaces are ignored when converting from a String.
- * </p>
- * <p>
- * Override and overwrite {@link #getFormat(Locale)} to use a different format.
- * </p>
- *
- * @author Vaadin Ltd
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class StringToDateConverter implements Converter<String, Date> {
-
- /**
- * Returns the format used by {@link #convertToPresentation(Date, Locale)}
- * and {@link #convertToModel(String, Locale)}.
- *
- * @param locale
- * The locale to use
- * @return A DateFormat instance
- */
- protected DateFormat getFormat(Locale locale) {
- if (locale == null) {
- locale = Locale.getDefault();
- }
-
- DateFormat f = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
- DateFormat.MEDIUM, locale);
- f.setLenient(false);
- return f;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object,
- * java.util.Locale)
- */
- public Date convertToModel(String value, Locale locale)
- throws com.vaadin.data.util.converter.Converter.ConversionException {
- if (value == null) {
- return null;
- }
-
- // Remove leading and trailing white space
- value = value.trim();
-
- ParsePosition parsePosition = new ParsePosition(0);
- Date parsedValue = getFormat(locale).parse(value, parsePosition);
- if (parsePosition.getIndex() != value.length()) {
- throw new ConversionException("Could not convert '" + value
- + "' to " + getModelType().getName());
- }
-
- return parsedValue;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang
- * .Object, java.util.Locale)
- */
- public String convertToPresentation(Date value, Locale locale)
- throws com.vaadin.data.util.converter.Converter.ConversionException {
- if (value == null) {
- return null;
- }
-
- return getFormat(locale).format(value);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getModelType()
- */
- public Class<Date> getModelType() {
- return Date.class;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getPresentationType()
- */
- public Class<String> getPresentationType() {
- return String.class;
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.text.DateFormat; +import java.text.ParsePosition; +import java.util.Date; +import java.util.Locale; + +/** + * A converter that converts from {@link Date} to {@link String} and back. Uses + * the given locale and {@link DateFormat} for formatting and parsing. + * <p> + * Leading and trailing white spaces are ignored when converting from a String. + * </p> + * <p> + * Override and overwrite {@link #getFormat(Locale)} to use a different format. + * </p> + * + * @author Vaadin Ltd + * @version + * @VERSION@ + * @since 7.0 + */ +public class StringToDateConverter implements Converter<String, Date> { + + /** + * Returns the format used by {@link #convertToPresentation(Date, Locale)} + * and {@link #convertToModel(String, Locale)}. + * + * @param locale + * The locale to use + * @return A DateFormat instance + */ + protected DateFormat getFormat(Locale locale) { + if (locale == null) { + locale = Locale.getDefault(); + } + + DateFormat f = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, + DateFormat.MEDIUM, locale); + f.setLenient(false); + return f; + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object, + * java.util.Locale) + */ + public Date convertToModel(String value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + if (value == null) { + return null; + } + + // Remove leading and trailing white space + value = value.trim(); + + ParsePosition parsePosition = new ParsePosition(0); + Date parsedValue = getFormat(locale).parse(value, parsePosition); + if (parsePosition.getIndex() != value.length()) { + throw new ConversionException("Could not convert '" + value + + "' to " + getModelType().getName()); + } + + return parsedValue; + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang + * .Object, java.util.Locale) + */ + public String convertToPresentation(Date value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + if (value == null) { + return null; + } + + return getFormat(locale).format(value); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getModelType() + */ + public Class<Date> getModelType() { + return Date.class; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getPresentationType() + */ + public Class<String> getPresentationType() { + return String.class; + } + +} diff --git a/src/com/vaadin/data/util/converter/StringToDoubleConverter.java b/src/com/vaadin/data/util/converter/StringToDoubleConverter.java index 29c6329451..60a38f4127 100644 --- a/src/com/vaadin/data/util/converter/StringToDoubleConverter.java +++ b/src/com/vaadin/data/util/converter/StringToDoubleConverter.java @@ -1,103 +1,103 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.text.NumberFormat;
-import java.text.ParsePosition;
-import java.util.Locale;
-
-/**
- * A converter that converts from {@link String} to {@link Double} and back.
- * Uses the given locale and a {@link NumberFormat} instance for formatting and
- * parsing.
- * <p>
- * Leading and trailing white spaces are ignored when converting from a String.
- * </p>
- * <p>
- * Override and overwrite {@link #getFormat(Locale)} to use a different format.
- * </p>
- *
- * @author Vaadin Ltd
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class StringToDoubleConverter implements Converter<String, Double> {
-
- /**
- * Returns the format used by {@link #convertToPresentation(Double, Locale)}
- * and {@link #convertToModel(String, Locale)}.
- *
- * @param locale
- * The locale to use
- * @return A NumberFormat instance
- */
- protected NumberFormat getFormat(Locale locale) {
- if (locale == null) {
- locale = Locale.getDefault();
- }
-
- return NumberFormat.getNumberInstance(locale);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object,
- * java.util.Locale)
- */
- public Double convertToModel(String value, Locale locale)
- throws ConversionException {
- if (value == null) {
- return null;
- }
-
- // Remove leading and trailing white space
- value = value.trim();
-
- ParsePosition parsePosition = new ParsePosition(0);
- Number parsedValue = getFormat(locale).parse(value, parsePosition);
- if (parsePosition.getIndex() != value.length()) {
- throw new ConversionException("Could not convert '" + value
- + "' to " + getModelType().getName());
- }
- return parsedValue.doubleValue();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang
- * .Object, java.util.Locale)
- */
- public String convertToPresentation(Double value, Locale locale)
- throws ConversionException {
- if (value == null) {
- return null;
- }
-
- return getFormat(locale).format(value);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getModelType()
- */
- public Class<Double> getModelType() {
- return Double.class;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getPresentationType()
- */
- public Class<String> getPresentationType() {
- return String.class;
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.util.Locale; + +/** + * A converter that converts from {@link String} to {@link Double} and back. + * Uses the given locale and a {@link NumberFormat} instance for formatting and + * parsing. + * <p> + * Leading and trailing white spaces are ignored when converting from a String. + * </p> + * <p> + * Override and overwrite {@link #getFormat(Locale)} to use a different format. + * </p> + * + * @author Vaadin Ltd + * @version + * @VERSION@ + * @since 7.0 + */ +public class StringToDoubleConverter implements Converter<String, Double> { + + /** + * Returns the format used by {@link #convertToPresentation(Double, Locale)} + * and {@link #convertToModel(String, Locale)}. + * + * @param locale + * The locale to use + * @return A NumberFormat instance + */ + protected NumberFormat getFormat(Locale locale) { + if (locale == null) { + locale = Locale.getDefault(); + } + + return NumberFormat.getNumberInstance(locale); + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object, + * java.util.Locale) + */ + public Double convertToModel(String value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + // Remove leading and trailing white space + value = value.trim(); + + ParsePosition parsePosition = new ParsePosition(0); + Number parsedValue = getFormat(locale).parse(value, parsePosition); + if (parsePosition.getIndex() != value.length()) { + throw new ConversionException("Could not convert '" + value + + "' to " + getModelType().getName()); + } + return parsedValue.doubleValue(); + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang + * .Object, java.util.Locale) + */ + public String convertToPresentation(Double value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + return getFormat(locale).format(value); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getModelType() + */ + public Class<Double> getModelType() { + return Double.class; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getPresentationType() + */ + public Class<String> getPresentationType() { + return String.class; + } +} diff --git a/src/com/vaadin/data/util/converter/StringToIntegerConverter.java b/src/com/vaadin/data/util/converter/StringToIntegerConverter.java index 7fa4458c51..e55feec3b6 100644 --- a/src/com/vaadin/data/util/converter/StringToIntegerConverter.java +++ b/src/com/vaadin/data/util/converter/StringToIntegerConverter.java @@ -1,84 +1,84 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.text.NumberFormat;
-import java.text.ParsePosition;
-import java.util.Locale;
-
-/**
- * A converter that converts from {@link String} to {@link Integer} and back.
- * Uses the given locale and a {@link NumberFormat} instance for formatting and
- * parsing.
- * <p>
- * Override and overwrite {@link #getFormat(Locale)} to use a different format.
- * </p>
- *
- * @author Vaadin Ltd
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class StringToIntegerConverter implements Converter<String, Integer> {
-
- /**
- * Returns the format used by
- * {@link #convertToPresentation(Integer, Locale)} and
- * {@link #convertToModel(String, Locale)}.
- *
- * @param locale
- * The locale to use
- * @return A NumberFormat instance
- */
- protected NumberFormat getFormat(Locale locale) {
- if (locale == null) {
- locale = Locale.getDefault();
- }
- return NumberFormat.getIntegerInstance(locale);
- }
-
- public Integer convertToModel(String value, Locale locale)
- throws ConversionException {
- if (value == null) {
- return null;
- }
-
- // Remove leading and trailing white space
- value = value.trim();
-
- // Parse and detect errors. If the full string was not used, it is
- // an error.
- ParsePosition parsePosition = new ParsePosition(0);
- Number parsedValue = getFormat(locale).parse(value, parsePosition);
- if (parsePosition.getIndex() != value.length()) {
- throw new ConversionException("Could not convert '" + value
- + "' to " + getModelType().getName());
- }
-
- if (parsedValue == null) {
- // Convert "" to null
- return null;
- }
- return parsedValue.intValue();
- }
-
- public String convertToPresentation(Integer value, Locale locale)
- throws ConversionException {
- if (value == null) {
- return null;
- }
-
- return getFormat(locale).format(value);
- }
-
- public Class<Integer> getModelType() {
- return Integer.class;
- }
-
- public Class<String> getPresentationType() {
- return String.class;
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.util.Locale; + +/** + * A converter that converts from {@link String} to {@link Integer} and back. + * Uses the given locale and a {@link NumberFormat} instance for formatting and + * parsing. + * <p> + * Override and overwrite {@link #getFormat(Locale)} to use a different format. + * </p> + * + * @author Vaadin Ltd + * @version + * @VERSION@ + * @since 7.0 + */ +public class StringToIntegerConverter implements Converter<String, Integer> { + + /** + * Returns the format used by + * {@link #convertToPresentation(Integer, Locale)} and + * {@link #convertToModel(String, Locale)}. + * + * @param locale + * The locale to use + * @return A NumberFormat instance + */ + protected NumberFormat getFormat(Locale locale) { + if (locale == null) { + locale = Locale.getDefault(); + } + return NumberFormat.getIntegerInstance(locale); + } + + public Integer convertToModel(String value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + // Remove leading and trailing white space + value = value.trim(); + + // Parse and detect errors. If the full string was not used, it is + // an error. + ParsePosition parsePosition = new ParsePosition(0); + Number parsedValue = getFormat(locale).parse(value, parsePosition); + if (parsePosition.getIndex() != value.length()) { + throw new ConversionException("Could not convert '" + value + + "' to " + getModelType().getName()); + } + + if (parsedValue == null) { + // Convert "" to null + return null; + } + return parsedValue.intValue(); + } + + public String convertToPresentation(Integer value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + return getFormat(locale).format(value); + } + + public Class<Integer> getModelType() { + return Integer.class; + } + + public Class<String> getPresentationType() { + return String.class; + } + +} diff --git a/src/com/vaadin/data/util/converter/StringToNumberConverter.java b/src/com/vaadin/data/util/converter/StringToNumberConverter.java index 64944a434c..d1816007e7 100644 --- a/src/com/vaadin/data/util/converter/StringToNumberConverter.java +++ b/src/com/vaadin/data/util/converter/StringToNumberConverter.java @@ -1,107 +1,107 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.util.converter;
-
-import java.text.NumberFormat;
-import java.text.ParsePosition;
-import java.util.Locale;
-
-/**
- * A converter that converts from {@link Number} to {@link String} and back.
- * Uses the given locale and {@link NumberFormat} for formatting and parsing.
- * <p>
- * Override and overwrite {@link #getFormat(Locale)} to use a different format.
- * </p>
- *
- * @author Vaadin Ltd
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class StringToNumberConverter implements Converter<String, Number> {
-
- /**
- * Returns the format used by {@link #convertToPresentation(Number, Locale)}
- * and {@link #convertToModel(String, Locale)}.
- *
- * @param locale
- * The locale to use
- * @return A NumberFormat instance
- */
- protected NumberFormat getFormat(Locale locale) {
- if (locale == null) {
- locale = Locale.getDefault();
- }
-
- return NumberFormat.getNumberInstance(locale);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object,
- * java.util.Locale)
- */
- public Number convertToModel(String value, Locale locale)
- throws ConversionException {
- if (value == null) {
- return null;
- }
-
- // Remove leading and trailing white space
- value = value.trim();
-
- // Parse and detect errors. If the full string was not used, it is
- // an error.
- ParsePosition parsePosition = new ParsePosition(0);
- Number parsedValue = getFormat(locale).parse(value, parsePosition);
- if (parsePosition.getIndex() != value.length()) {
- throw new ConversionException("Could not convert '" + value
- + "' to " + getModelType().getName());
- }
-
- if (parsedValue == null) {
- // Convert "" to null
- return null;
- }
- return parsedValue;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang
- * .Object, java.util.Locale)
- */
- public String convertToPresentation(Number value, Locale locale)
- throws ConversionException {
- if (value == null) {
- return null;
- }
-
- return getFormat(locale).format(value);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getModelType()
- */
- public Class<Number> getModelType() {
- return Number.class;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.util.converter.Converter#getPresentationType()
- */
- public Class<String> getPresentationType() {
- return String.class;
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.util.converter; + +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.util.Locale; + +/** + * A converter that converts from {@link Number} to {@link String} and back. + * Uses the given locale and {@link NumberFormat} for formatting and parsing. + * <p> + * Override and overwrite {@link #getFormat(Locale)} to use a different format. + * </p> + * + * @author Vaadin Ltd + * @version + * @VERSION@ + * @since 7.0 + */ +public class StringToNumberConverter implements Converter<String, Number> { + + /** + * Returns the format used by {@link #convertToPresentation(Number, Locale)} + * and {@link #convertToModel(String, Locale)}. + * + * @param locale + * The locale to use + * @return A NumberFormat instance + */ + protected NumberFormat getFormat(Locale locale) { + if (locale == null) { + locale = Locale.getDefault(); + } + + return NumberFormat.getNumberInstance(locale); + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object, + * java.util.Locale) + */ + public Number convertToModel(String value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + // Remove leading and trailing white space + value = value.trim(); + + // Parse and detect errors. If the full string was not used, it is + // an error. + ParsePosition parsePosition = new ParsePosition(0); + Number parsedValue = getFormat(locale).parse(value, parsePosition); + if (parsePosition.getIndex() != value.length()) { + throw new ConversionException("Could not convert '" + value + + "' to " + getModelType().getName()); + } + + if (parsedValue == null) { + // Convert "" to null + return null; + } + return parsedValue; + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang + * .Object, java.util.Locale) + */ + public String convertToPresentation(Number value, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + + return getFormat(locale).format(value); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getModelType() + */ + public Class<Number> getModelType() { + return Number.class; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.util.converter.Converter#getPresentationType() + */ + public Class<String> getPresentationType() { + return String.class; + } + +} 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/data/validator/BeanValidator.java b/src/com/vaadin/data/validator/BeanValidator.java index 939fd2e9c4..817df85248 100644 --- a/src/com/vaadin/data/validator/BeanValidator.java +++ b/src/com/vaadin/data/validator/BeanValidator.java @@ -1,173 +1,173 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.data.validator;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-
-import javax.validation.ConstraintViolation;
-import javax.validation.MessageInterpolator.Context;
-import javax.validation.Validation;
-import javax.validation.ValidatorFactory;
-import javax.validation.metadata.ConstraintDescriptor;
-
-import com.vaadin.data.Validator;
-
-/**
- * Vaadin {@link Validator} using the JSR-303 (javax.validation)
- * annotation-based bean validation.
- *
- * The annotations of the fields of the beans are used to determine the
- * validation to perform.
- *
- * Note that a JSR-303 implementation (e.g. Hibernate Validator or Apache Bean
- * Validation - formerly agimatec validation) must be present on the project
- * classpath when using bean validation.
- *
- * @since 7.0
- *
- * @author Petri Hakala
- * @author Henri Sara
- */
-public class BeanValidator implements Validator {
-
- private static final long serialVersionUID = 1L;
- private static ValidatorFactory factory;
-
- private transient javax.validation.Validator javaxBeanValidator;
- private String propertyName;
- private Class<?> beanClass;
- private Locale locale;
-
- /**
- * Simple implementation of a message interpolator context that returns
- * fixed values.
- */
- protected static class SimpleContext implements Context, Serializable {
-
- private final Object value;
- private final ConstraintDescriptor<?> descriptor;
-
- /**
- * Create a simple immutable message interpolator context.
- *
- * @param value
- * value being validated
- * @param descriptor
- * ConstraintDescriptor corresponding to the constraint being
- * validated
- */
- public SimpleContext(Object value, ConstraintDescriptor<?> descriptor) {
- this.value = value;
- this.descriptor = descriptor;
- }
-
- public ConstraintDescriptor<?> getConstraintDescriptor() {
- return descriptor;
- }
-
- public Object getValidatedValue() {
- return value;
- }
-
- }
-
- /**
- * Creates a Vaadin {@link Validator} utilizing JSR-303 bean validation.
- *
- * @param beanClass
- * bean class based on which the validation should be performed
- * @param propertyName
- * property to validate
- */
- public BeanValidator(Class<?> beanClass, String propertyName) {
- this.beanClass = beanClass;
- this.propertyName = propertyName;
- locale = Locale.getDefault();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.Validator#validate(java.lang.Object)
- */
- public void validate(final Object value) throws InvalidValueException {
- Set<?> violations = getJavaxBeanValidator().validateValue(beanClass,
- propertyName, value);
- if (violations.size() > 0) {
- List<String> exceptions = new ArrayList<String>();
- for (Object v : violations) {
- final ConstraintViolation<?> violation = (ConstraintViolation<?>) v;
- String msg = getJavaxBeanValidatorFactory()
- .getMessageInterpolator().interpolate(
- violation.getMessageTemplate(),
- new SimpleContext(value, violation
- .getConstraintDescriptor()), locale);
- exceptions.add(msg);
- }
- StringBuilder b = new StringBuilder();
- for (int i = 0; i < exceptions.size(); i++) {
- if (i != 0) {
- b.append("<br/>");
- }
- b.append(exceptions.get(i));
- }
- throw new InvalidValueException(b.toString());
- }
- }
-
- /**
- * Sets the locale used for validation error messages.
- *
- * Revalidation is not automatically triggered by setting the locale.
- *
- * @param locale
- */
- public void setLocale(Locale locale) {
- this.locale = locale;
- }
-
- /**
- * Gets the locale used for validation error messages.
- *
- * @return locale used for validation
- */
- public Locale getLocale() {
- return locale;
- }
-
- /**
- * Returns the underlying JSR-303 bean validator factory used. A factory is
- * created using {@link Validation} if necessary.
- *
- * @return {@link ValidatorFactory} to use
- */
- protected static ValidatorFactory getJavaxBeanValidatorFactory() {
- if (factory == null) {
- factory = Validation.buildDefaultValidatorFactory();
- }
-
- return factory;
- }
-
- /**
- * Returns a shared Validator instance to use. An instance is created using
- * the validator factory if necessary and thereafter reused by the
- * {@link BeanValidator} instance.
- *
- * @return the JSR-303 {@link javax.validation.Validator} to use
- */
- protected javax.validation.Validator getJavaxBeanValidator() {
- if (javaxBeanValidator == null) {
- javaxBeanValidator = getJavaxBeanValidatorFactory().getValidator();
- }
-
- return javaxBeanValidator;
- }
-
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.data.validator; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.MessageInterpolator.Context; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; +import javax.validation.metadata.ConstraintDescriptor; + +import com.vaadin.data.Validator; + +/** + * Vaadin {@link Validator} using the JSR-303 (javax.validation) + * annotation-based bean validation. + * + * The annotations of the fields of the beans are used to determine the + * validation to perform. + * + * Note that a JSR-303 implementation (e.g. Hibernate Validator or Apache Bean + * Validation - formerly agimatec validation) must be present on the project + * classpath when using bean validation. + * + * @since 7.0 + * + * @author Petri Hakala + * @author Henri Sara + */ +public class BeanValidator implements Validator { + + private static final long serialVersionUID = 1L; + private static ValidatorFactory factory; + + private transient javax.validation.Validator javaxBeanValidator; + private String propertyName; + private Class<?> beanClass; + private Locale locale; + + /** + * Simple implementation of a message interpolator context that returns + * fixed values. + */ + protected static class SimpleContext implements Context, Serializable { + + private final Object value; + private final ConstraintDescriptor<?> descriptor; + + /** + * Create a simple immutable message interpolator context. + * + * @param value + * value being validated + * @param descriptor + * ConstraintDescriptor corresponding to the constraint being + * validated + */ + public SimpleContext(Object value, ConstraintDescriptor<?> descriptor) { + this.value = value; + this.descriptor = descriptor; + } + + public ConstraintDescriptor<?> getConstraintDescriptor() { + return descriptor; + } + + public Object getValidatedValue() { + return value; + } + + } + + /** + * Creates a Vaadin {@link Validator} utilizing JSR-303 bean validation. + * + * @param beanClass + * bean class based on which the validation should be performed + * @param propertyName + * property to validate + */ + public BeanValidator(Class<?> beanClass, String propertyName) { + this.beanClass = beanClass; + this.propertyName = propertyName; + locale = Locale.getDefault(); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.Validator#validate(java.lang.Object) + */ + public void validate(final Object value) throws InvalidValueException { + Set<?> violations = getJavaxBeanValidator().validateValue(beanClass, + propertyName, value); + if (violations.size() > 0) { + List<String> exceptions = new ArrayList<String>(); + for (Object v : violations) { + final ConstraintViolation<?> violation = (ConstraintViolation<?>) v; + String msg = getJavaxBeanValidatorFactory() + .getMessageInterpolator().interpolate( + violation.getMessageTemplate(), + new SimpleContext(value, violation + .getConstraintDescriptor()), locale); + exceptions.add(msg); + } + StringBuilder b = new StringBuilder(); + for (int i = 0; i < exceptions.size(); i++) { + if (i != 0) { + b.append("<br/>"); + } + b.append(exceptions.get(i)); + } + throw new InvalidValueException(b.toString()); + } + } + + /** + * Sets the locale used for validation error messages. + * + * Revalidation is not automatically triggered by setting the locale. + * + * @param locale + */ + public void setLocale(Locale locale) { + this.locale = locale; + } + + /** + * Gets the locale used for validation error messages. + * + * @return locale used for validation + */ + public Locale getLocale() { + return locale; + } + + /** + * Returns the underlying JSR-303 bean validator factory used. A factory is + * created using {@link Validation} if necessary. + * + * @return {@link ValidatorFactory} to use + */ + protected static ValidatorFactory getJavaxBeanValidatorFactory() { + if (factory == null) { + factory = Validation.buildDefaultValidatorFactory(); + } + + return factory; + } + + /** + * Returns a shared Validator instance to use. An instance is created using + * the validator factory if necessary and thereafter reused by the + * {@link BeanValidator} instance. + * + * @return the JSR-303 {@link javax.validation.Validator} to use + */ + protected javax.validation.Validator getJavaxBeanValidator() { + if (javaxBeanValidator == null) { + javaxBeanValidator = getJavaxBeanValidatorFactory().getValidator(); + } + + return javaxBeanValidator; + } + }
\ No newline at end of file diff --git a/src/com/vaadin/data/validator/DateRangeValidator.java b/src/com/vaadin/data/validator/DateRangeValidator.java index 42f5a224ed..24f3d3ce10 100644 --- a/src/com/vaadin/data/validator/DateRangeValidator.java +++ b/src/com/vaadin/data/validator/DateRangeValidator.java @@ -1,51 +1,51 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.validator;
-
-import java.util.Date;
-
-import com.vaadin.ui.DateField.Resolution;
-
-/**
- * Validator for validating that a Date is inside a given range.
- *
- * <p>
- * Note that the comparison is done directly on the Date object so take care
- * that the hours/minutes/seconds/milliseconds of the min/max values are
- * properly set.
- * </p>
- *
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class DateRangeValidator extends RangeValidator<Date> {
-
- /**
- * Creates a validator for checking that an Date is within a given range.
- * <p>
- * By default the range is inclusive i.e. both minValue and maxValue are
- * valid values. Use {@link #setMinValueIncluded(boolean)} or
- * {@link #setMaxValueIncluded(boolean)} to change it.
- * </p>
- * <p>
- * Note that the comparison is done directly on the Date object so take care
- * that the hours/minutes/seconds/milliseconds of the min/max values are
- * properly set.
- * </p>
- *
- * @param errorMessage
- * the message to display in case the value does not validate.
- * @param minValue
- * The minimum value to accept or null for no limit
- * @param maxValue
- * The maximum value to accept or null for no limit
- */
- public DateRangeValidator(String errorMessage, Date minValue,
- Date maxValue, Resolution resolution) {
- super(errorMessage, Date.class, minValue, maxValue);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.data.validator; + +import java.util.Date; + +import com.vaadin.ui.DateField.Resolution; + +/** + * Validator for validating that a Date is inside a given range. + * + * <p> + * Note that the comparison is done directly on the Date object so take care + * that the hours/minutes/seconds/milliseconds of the min/max values are + * properly set. + * </p> + * + * @author Vaadin Ltd. + * @version + * @VERSION@ + * @since 7.0 + */ +public class DateRangeValidator extends RangeValidator<Date> { + + /** + * Creates a validator for checking that an Date is within a given range. + * <p> + * By default the range is inclusive i.e. both minValue and maxValue are + * valid values. Use {@link #setMinValueIncluded(boolean)} or + * {@link #setMaxValueIncluded(boolean)} to change it. + * </p> + * <p> + * Note that the comparison is done directly on the Date object so take care + * that the hours/minutes/seconds/milliseconds of the min/max values are + * properly set. + * </p> + * + * @param errorMessage + * the message to display in case the value does not validate. + * @param minValue + * The minimum value to accept or null for no limit + * @param maxValue + * The maximum value to accept or null for no limit + */ + public DateRangeValidator(String errorMessage, Date minValue, + Date maxValue, Resolution resolution) { + super(errorMessage, Date.class, minValue, maxValue); + } + +} diff --git a/src/com/vaadin/data/validator/RangeValidator.java b/src/com/vaadin/data/validator/RangeValidator.java index 457f046360..433271274f 100644 --- a/src/com/vaadin/data/validator/RangeValidator.java +++ b/src/com/vaadin/data/validator/RangeValidator.java @@ -1,186 +1,186 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.data.validator;
-
-/**
- * An base implementation for validating any objects that implement
- * {@link Comparable}.
- *
- * Verifies that the value is of the given type and within the (optionally)
- * given limits. Typically you want to use a sub class of this like
- * {@link IntegerRangeValidator}, {@link DoubleRangeValidator} or
- * {@link DateRangeValidator} in applications.
- * <p>
- * Note that {@link RangeValidator} always accept null values. Make a field
- * required to ensure that no empty values are accepted or override
- * {@link #isValidValue(Comparable)}.
- * </p>
- *
- * @param <T>
- * The type of Number to validate. Must implement Comparable so that
- * minimum and maximum checks work.
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 7.0
- */
-public class RangeValidator<T extends Comparable> extends AbstractValidator<T> {
-
- private T minValue = null;
- private boolean minValueIncluded = true;
- private T maxValue = null;
- private boolean maxValueIncluded = true;
- private Class<T> type;
-
- /**
- * Creates a new range validator of the given type.
- *
- * @param errorMessage
- * The error message to use if validation fails
- * @param type
- * The type of object the validator can validate.
- * @param minValue
- * The minimum value that should be accepted or null for no limit
- * @param maxValue
- * The maximum value that should be accepted or null for no limit
- */
- public RangeValidator(String errorMessage, Class<T> type, T minValue,
- T maxValue) {
- super(errorMessage);
- this.type = type;
- this.minValue = minValue;
- this.maxValue = maxValue;
- }
-
- /**
- * Checks if the minimum value is part of the accepted range
- *
- * @return true if the minimum value is part of the range, false otherwise
- */
- public boolean isMinValueIncluded() {
- return minValueIncluded;
- }
-
- /**
- * Sets if the minimum value is part of the accepted range
- *
- * @param minValueIncluded
- * true if the minimum value should be part of the range, false
- * otherwise
- */
- public void setMinValueIncluded(boolean minValueIncluded) {
- this.minValueIncluded = minValueIncluded;
- }
-
- /**
- * Checks if the maximum value is part of the accepted range
- *
- * @return true if the maximum value is part of the range, false otherwise
- */
- public boolean isMaxValueIncluded() {
- return maxValueIncluded;
- }
-
- /**
- * Sets if the maximum value is part of the accepted range
- *
- * @param maxValueIncluded
- * true if the maximum value should be part of the range, false
- * otherwise
- */
- public void setMaxValueIncluded(boolean maxValueIncluded) {
- this.maxValueIncluded = maxValueIncluded;
- }
-
- /**
- * Gets the minimum value of the range
- *
- * @return the minimum value
- */
- public T getMinValue() {
- return minValue;
- }
-
- /**
- * Sets the minimum value of the range. Use
- * {@link #setMinValueIncluded(boolean)} to control whether this value is
- * part of the range or not.
- *
- * @param minValue
- * the minimum value
- */
- public void setMinValue(T minValue) {
- this.minValue = minValue;
- }
-
- /**
- * Gets the maximum value of the range
- *
- * @return the maximum value
- */
- public T getMaxValue() {
- return maxValue;
- }
-
- /**
- * Sets the maximum value of the range. Use
- * {@link #setMaxValueIncluded(boolean)} to control whether this value is
- * part of the range or not.
- *
- * @param maxValue
- * the maximum value
- */
- public void setMaxValue(T maxValue) {
- this.maxValue = maxValue;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.data.validator.AbstractValidator#isValidValue(java.lang.Object
- * )
- */
- @Override
- protected boolean isValidValue(T value) {
- if (value == null) {
- return true;
- }
-
- if (getMinValue() != null) {
- // Ensure that the min limit is ok
- int result = value.compareTo(getMinValue());
- if (result < 0) {
- // value less than min value
- return false;
- } else if (result == 0 && !isMinValueIncluded()) {
- // values equal and min value not included
- return false;
- }
- }
- if (getMaxValue() != null) {
- // Ensure that the Max limit is ok
- int result = value.compareTo(getMaxValue());
- if (result > 0) {
- // value greater than max value
- return false;
- } else if (result == 0 && !isMaxValueIncluded()) {
- // values equal and max value not included
- return false;
- }
- }
- return true;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.data.validator.AbstractValidator#getType()
- */
- @Override
- public Class<T> getType() {
- return type;
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.data.validator; + +/** + * An base implementation for validating any objects that implement + * {@link Comparable}. + * + * Verifies that the value is of the given type and within the (optionally) + * given limits. Typically you want to use a sub class of this like + * {@link IntegerRangeValidator}, {@link DoubleRangeValidator} or + * {@link DateRangeValidator} in applications. + * <p> + * Note that {@link RangeValidator} always accept null values. Make a field + * required to ensure that no empty values are accepted or override + * {@link #isValidValue(Comparable)}. + * </p> + * + * @param <T> + * The type of Number to validate. Must implement Comparable so that + * minimum and maximum checks work. + * @author Vaadin Ltd. + * @version + * @VERSION@ + * @since 7.0 + */ +public class RangeValidator<T extends Comparable> extends AbstractValidator<T> { + + private T minValue = null; + private boolean minValueIncluded = true; + private T maxValue = null; + private boolean maxValueIncluded = true; + private Class<T> type; + + /** + * Creates a new range validator of the given type. + * + * @param errorMessage + * The error message to use if validation fails + * @param type + * The type of object the validator can validate. + * @param minValue + * The minimum value that should be accepted or null for no limit + * @param maxValue + * The maximum value that should be accepted or null for no limit + */ + public RangeValidator(String errorMessage, Class<T> type, T minValue, + T maxValue) { + super(errorMessage); + this.type = type; + this.minValue = minValue; + this.maxValue = maxValue; + } + + /** + * Checks if the minimum value is part of the accepted range + * + * @return true if the minimum value is part of the range, false otherwise + */ + public boolean isMinValueIncluded() { + return minValueIncluded; + } + + /** + * Sets if the minimum value is part of the accepted range + * + * @param minValueIncluded + * true if the minimum value should be part of the range, false + * otherwise + */ + public void setMinValueIncluded(boolean minValueIncluded) { + this.minValueIncluded = minValueIncluded; + } + + /** + * Checks if the maximum value is part of the accepted range + * + * @return true if the maximum value is part of the range, false otherwise + */ + public boolean isMaxValueIncluded() { + return maxValueIncluded; + } + + /** + * Sets if the maximum value is part of the accepted range + * + * @param maxValueIncluded + * true if the maximum value should be part of the range, false + * otherwise + */ + public void setMaxValueIncluded(boolean maxValueIncluded) { + this.maxValueIncluded = maxValueIncluded; + } + + /** + * Gets the minimum value of the range + * + * @return the minimum value + */ + public T getMinValue() { + return minValue; + } + + /** + * Sets the minimum value of the range. Use + * {@link #setMinValueIncluded(boolean)} to control whether this value is + * part of the range or not. + * + * @param minValue + * the minimum value + */ + public void setMinValue(T minValue) { + this.minValue = minValue; + } + + /** + * Gets the maximum value of the range + * + * @return the maximum value + */ + public T getMaxValue() { + return maxValue; + } + + /** + * Sets the maximum value of the range. Use + * {@link #setMaxValueIncluded(boolean)} to control whether this value is + * part of the range or not. + * + * @param maxValue + * the maximum value + */ + public void setMaxValue(T maxValue) { + this.maxValue = maxValue; + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.data.validator.AbstractValidator#isValidValue(java.lang.Object + * ) + */ + @Override + protected boolean isValidValue(T value) { + if (value == null) { + return true; + } + + if (getMinValue() != null) { + // Ensure that the min limit is ok + int result = value.compareTo(getMinValue()); + if (result < 0) { + // value less than min value + return false; + } else if (result == 0 && !isMinValueIncluded()) { + // values equal and min value not included + return false; + } + } + if (getMaxValue() != null) { + // Ensure that the Max limit is ok + int result = value.compareTo(getMaxValue()); + if (result > 0) { + // value greater than max value + return false; + } else if (result == 0 && !isMaxValueIncluded()) { + // values equal and max value not included + return false; + } + } + return true; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.data.validator.AbstractValidator#getType() + */ + @Override + public Class<T> getType() { + return type; + } + +} 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/external/json/JSONException.java b/src/com/vaadin/external/json/JSONException.java index 9d97a32d7d..d799021506 100644 --- a/src/com/vaadin/external/json/JSONException.java +++ b/src/com/vaadin/external/json/JSONException.java @@ -1,28 +1,28 @@ -package com.vaadin.external.json;
-
-/**
- * The JSONException is thrown by the JSON.org classes when things are amiss.
- * @author JSON.org
- * @version 2010-12-24
- */
-public class JSONException extends Exception {
- private static final long serialVersionUID = 0;
- private Throwable cause;
-
- /**
- * Constructs a JSONException with an explanatory message.
- * @param message Detail about the reason for the exception.
- */
- public JSONException(String message) {
- super(message);
- }
-
- public JSONException(Throwable cause) {
- super(cause.getMessage());
- this.cause = cause;
- }
-
- public Throwable getCause() {
- return this.cause;
- }
-}
+package com.vaadin.external.json; + +/** + * The JSONException is thrown by the JSON.org classes when things are amiss. + * @author JSON.org + * @version 2010-12-24 + */ +public class JSONException extends Exception { + private static final long serialVersionUID = 0; + private Throwable cause; + + /** + * Constructs a JSONException with an explanatory message. + * @param message Detail about the reason for the exception. + */ + public JSONException(String message) { + super(message); + } + + public JSONException(Throwable cause) { + super(cause.getMessage()); + this.cause = cause; + } + + public Throwable getCause() { + return this.cause; + } +} diff --git a/src/com/vaadin/external/json/JSONString.java b/src/com/vaadin/external/json/JSONString.java index 7b574d1915..cc7e4d8c07 100644 --- a/src/com/vaadin/external/json/JSONString.java +++ b/src/com/vaadin/external/json/JSONString.java @@ -1,21 +1,21 @@ -package com.vaadin.external.json;
-
-import java.io.Serializable;
-
-/**
- * The <code>JSONString</code> interface allows a <code>toJSONString()</code>
- * method so that a class can change the behavior of
- * <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>, and
- * <code>JSONWriter.value(</code>Object<code>)</code>. The
- * <code>toJSONString</code> method will be used instead of the default behavior
- * of using the Object's <code>toString()</code> method and quoting the result.
- */
-public interface JSONString extends Serializable {
- /**
- * The <code>toJSONString</code> method allows a class to produce its own
- * JSON serialization.
- *
- * @return A strictly syntactically correct JSON text.
- */
- public String toJSONString();
-}
+package com.vaadin.external.json; + +import java.io.Serializable; + +/** + * The <code>JSONString</code> interface allows a <code>toJSONString()</code> + * method so that a class can change the behavior of + * <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>, and + * <code>JSONWriter.value(</code>Object<code>)</code>. The + * <code>toJSONString</code> method will be used instead of the default behavior + * of using the Object's <code>toString()</code> method and quoting the result. + */ +public interface JSONString extends Serializable { + /** + * The <code>toJSONString</code> method allows a class to produce its own + * JSON serialization. + * + * @return A strictly syntactically correct JSON text. + */ + public String toJSONString(); +} diff --git a/src/com/vaadin/external/json/JSONStringer.java b/src/com/vaadin/external/json/JSONStringer.java index c4a1af600a..465f27aaab 100644 --- a/src/com/vaadin/external/json/JSONStringer.java +++ b/src/com/vaadin/external/json/JSONStringer.java @@ -1,78 +1,78 @@ -package com.vaadin.external.json;
-
-/*
-Copyright (c) 2006 JSON.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-The Software shall be used for Good, not Evil.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-import java.io.StringWriter;
-
-/**
- * JSONStringer provides a quick and convenient way of producing JSON text.
- * The texts produced strictly conform to JSON syntax rules. No whitespace is
- * added, so the results are ready for transmission or storage. Each instance of
- * JSONStringer can produce one JSON text.
- * <p>
- * A JSONStringer instance provides a <code>value</code> method for appending
- * values to the
- * text, and a <code>key</code>
- * method for adding keys before values in objects. There are <code>array</code>
- * and <code>endArray</code> methods that make and bound array values, and
- * <code>object</code> and <code>endObject</code> methods which make and bound
- * object values. All of these methods return the JSONWriter instance,
- * permitting cascade style. For example, <pre>
- * myString = new JSONStringer()
- * .object()
- * .key("JSON")
- * .value("Hello, World!")
- * .endObject()
- * .toString();</pre> which produces the string <pre>
- * {"JSON":"Hello, World!"}</pre>
- * <p>
- * The first method called must be <code>array</code> or <code>object</code>.
- * There are no methods for adding commas or colons. JSONStringer adds them for
- * you. Objects and arrays can be nested up to 20 levels deep.
- * <p>
- * This can sometimes be easier than using a JSONObject to build a string.
- * @author JSON.org
- * @version 2008-09-18
- */
-public class JSONStringer extends JSONWriter {
- /**
- * Make a fresh JSONStringer. It can be used to build one JSON text.
- */
- public JSONStringer() {
- super(new StringWriter());
- }
-
- /**
- * Return the JSON text. This method is used to obtain the product of the
- * JSONStringer instance. It will return <code>null</code> if there was a
- * problem in the construction of the JSON text (such as the calls to
- * <code>array</code> were not properly balanced with calls to
- * <code>endArray</code>).
- * @return The JSON text.
- */
- public String toString() {
- return this.mode == 'd' ? this.writer.toString() : null;
- }
-}
+package com.vaadin.external.json; + +/* +Copyright (c) 2006 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.StringWriter; + +/** + * JSONStringer provides a quick and convenient way of producing JSON text. + * The texts produced strictly conform to JSON syntax rules. No whitespace is + * added, so the results are ready for transmission or storage. Each instance of + * JSONStringer can produce one JSON text. + * <p> + * A JSONStringer instance provides a <code>value</code> method for appending + * values to the + * text, and a <code>key</code> + * method for adding keys before values in objects. There are <code>array</code> + * and <code>endArray</code> methods that make and bound array values, and + * <code>object</code> and <code>endObject</code> methods which make and bound + * object values. All of these methods return the JSONWriter instance, + * permitting cascade style. For example, <pre> + * myString = new JSONStringer() + * .object() + * .key("JSON") + * .value("Hello, World!") + * .endObject() + * .toString();</pre> which produces the string <pre> + * {"JSON":"Hello, World!"}</pre> + * <p> + * The first method called must be <code>array</code> or <code>object</code>. + * There are no methods for adding commas or colons. JSONStringer adds them for + * you. Objects and arrays can be nested up to 20 levels deep. + * <p> + * This can sometimes be easier than using a JSONObject to build a string. + * @author JSON.org + * @version 2008-09-18 + */ +public class JSONStringer extends JSONWriter { + /** + * Make a fresh JSONStringer. It can be used to build one JSON text. + */ + public JSONStringer() { + super(new StringWriter()); + } + + /** + * Return the JSON text. This method is used to obtain the product of the + * JSONStringer instance. It will return <code>null</code> if there was a + * problem in the construction of the JSON text (such as the calls to + * <code>array</code> were not properly balanced with calls to + * <code>endArray</code>). + * @return The JSON text. + */ + public String toString() { + return this.mode == 'd' ? this.writer.toString() : null; + } +} diff --git a/src/com/vaadin/external/json/JSONWriter.java b/src/com/vaadin/external/json/JSONWriter.java index 438721b7b2..5f9ddeeae2 100644 --- a/src/com/vaadin/external/json/JSONWriter.java +++ b/src/com/vaadin/external/json/JSONWriter.java @@ -1,355 +1,355 @@ -package com.vaadin.external.json;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.io.Writer;
-
-/*
- Copyright (c) 2006 JSON.org
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- The Software shall be used for Good, not Evil.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
-
-/**
- * JSONWriter provides a quick and convenient way of producing JSON text. The
- * texts produced strictly conform to JSON syntax rules. No whitespace is added,
- * so the results are ready for transmission or storage. Each instance of
- * JSONWriter can produce one JSON text.
- * <p>
- * A JSONWriter instance provides a <code>value</code> method for appending
- * values to the text, and a <code>key</code> method for adding keys before
- * values in objects. There are <code>array</code> and <code>endArray</code>
- * methods that make and bound array values, and <code>object</code> and
- * <code>endObject</code> methods which make and bound object values. All of
- * these methods return the JSONWriter instance, permitting a cascade style. For
- * example,
- *
- * <pre>
- * new JSONWriter(myWriter).object().key("JSON").value("Hello, World!")
- * .endObject();
- * </pre>
- *
- * which writes
- *
- * <pre>
- * {"JSON":"Hello, World!"}
- * </pre>
- * <p>
- * The first method called must be <code>array</code> or <code>object</code>.
- * There are no methods for adding commas or colons. JSONWriter adds them for
- * you. Objects and arrays can be nested up to 20 levels deep.
- * <p>
- * This can sometimes be easier than using a JSONObject to build a string.
- *
- * @author JSON.org
- * @version 2011-11-14
- */
-public class JSONWriter implements Serializable {
- private static final int maxdepth = 200;
-
- /**
- * The comma flag determines if a comma should be output before the next
- * value.
- */
- private boolean comma;
-
- /**
- * The current mode. Values: 'a' (array), 'd' (done), 'i' (initial), 'k'
- * (key), 'o' (object).
- */
- protected char mode;
-
- /**
- * The object/array stack.
- */
- private final JSONObject stack[];
-
- /**
- * The stack top index. A value of 0 indicates that the stack is empty.
- */
- private int top;
-
- /**
- * The writer that will receive the output.
- */
- protected Writer writer;
-
- /**
- * Make a fresh JSONWriter. It can be used to build one JSON text.
- */
- public JSONWriter(Writer w) {
- comma = false;
- mode = 'i';
- stack = new JSONObject[maxdepth];
- top = 0;
- writer = w;
- }
-
- /**
- * Append a value.
- *
- * @param string
- * A string value.
- * @return this
- * @throws JSONException
- * If the value is out of sequence.
- */
- private JSONWriter append(String string) throws JSONException {
- if (string == null) {
- throw new JSONException("Null pointer");
- }
- if (mode == 'o' || mode == 'a') {
- try {
- if (comma && mode == 'a') {
- writer.write(',');
- }
- writer.write(string);
- } catch (IOException e) {
- throw new JSONException(e);
- }
- if (mode == 'o') {
- mode = 'k';
- }
- comma = true;
- return this;
- }
- throw new JSONException("Value out of sequence.");
- }
-
- /**
- * Begin appending a new array. All values until the balancing
- * <code>endArray</code> will be appended to this array. The
- * <code>endArray</code> method must be called to mark the array's end.
- *
- * @return this
- * @throws JSONException
- * If the nesting is too deep, or if the object is started in
- * the wrong place (for example as a key or after the end of the
- * outermost array or object).
- */
- public JSONWriter array() throws JSONException {
- if (mode == 'i' || mode == 'o' || mode == 'a') {
- push(null);
- append("[");
- comma = false;
- return this;
- }
- throw new JSONException("Misplaced array.");
- }
-
- /**
- * End something.
- *
- * @param mode
- * Mode
- * @param c
- * Closing character
- * @return this
- * @throws JSONException
- * If unbalanced.
- */
- private JSONWriter end(char mode, char c) throws JSONException {
- if (this.mode != mode) {
- throw new JSONException(mode == 'a' ? "Misplaced endArray."
- : "Misplaced endObject.");
- }
- pop(mode);
- try {
- writer.write(c);
- } catch (IOException e) {
- throw new JSONException(e);
- }
- comma = true;
- return this;
- }
-
- /**
- * End an array. This method most be called to balance calls to
- * <code>array</code>.
- *
- * @return this
- * @throws JSONException
- * If incorrectly nested.
- */
- public JSONWriter endArray() throws JSONException {
- return end('a', ']');
- }
-
- /**
- * End an object. This method most be called to balance calls to
- * <code>object</code>.
- *
- * @return this
- * @throws JSONException
- * If incorrectly nested.
- */
- public JSONWriter endObject() throws JSONException {
- return end('k', '}');
- }
-
- /**
- * Append a key. The key will be associated with the next value. In an
- * object, every value must be preceded by a key.
- *
- * @param string
- * A key string.
- * @return this
- * @throws JSONException
- * If the key is out of place. For example, keys do not belong
- * in arrays or if the key is null.
- */
- public JSONWriter key(String string) throws JSONException {
- if (string == null) {
- throw new JSONException("Null key.");
- }
- if (mode == 'k') {
- try {
- stack[top - 1].putOnce(string, Boolean.TRUE);
- if (comma) {
- writer.write(',');
- }
- writer.write(JSONObject.quote(string));
- writer.write(':');
- comma = false;
- mode = 'o';
- return this;
- } catch (IOException e) {
- throw new JSONException(e);
- }
- }
- throw new JSONException("Misplaced key.");
- }
-
- /**
- * Begin appending a new object. All keys and values until the balancing
- * <code>endObject</code> will be appended to this object. The
- * <code>endObject</code> method must be called to mark the object's end.
- *
- * @return this
- * @throws JSONException
- * If the nesting is too deep, or if the object is started in
- * the wrong place (for example as a key or after the end of the
- * outermost array or object).
- */
- public JSONWriter object() throws JSONException {
- if (mode == 'i') {
- mode = 'o';
- }
- if (mode == 'o' || mode == 'a') {
- append("{");
- push(new JSONObject());
- comma = false;
- return this;
- }
- throw new JSONException("Misplaced object.");
-
- }
-
- /**
- * Pop an array or object scope.
- *
- * @param c
- * The scope to close.
- * @throws JSONException
- * If nesting is wrong.
- */
- private void pop(char c) throws JSONException {
- if (top <= 0) {
- throw new JSONException("Nesting error.");
- }
- char m = stack[top - 1] == null ? 'a' : 'k';
- if (m != c) {
- throw new JSONException("Nesting error.");
- }
- top -= 1;
- mode = top == 0 ? 'd' : stack[top - 1] == null ? 'a' : 'k';
- }
-
- /**
- * Push an array or object scope.
- *
- * @param c
- * The scope to open.
- * @throws JSONException
- * If nesting is too deep.
- */
- private void push(JSONObject jo) throws JSONException {
- if (top >= maxdepth) {
- throw new JSONException("Nesting too deep.");
- }
- stack[top] = jo;
- mode = jo == null ? 'a' : 'k';
- top += 1;
- }
-
- /**
- * Append either the value <code>true</code> or the value <code>false</code>
- * .
- *
- * @param b
- * A boolean.
- * @return this
- * @throws JSONException
- */
- public JSONWriter value(boolean b) throws JSONException {
- return append(b ? "true" : "false");
- }
-
- /**
- * Append a double value.
- *
- * @param d
- * A double.
- * @return this
- * @throws JSONException
- * If the number is not finite.
- */
- public JSONWriter value(double d) throws JSONException {
- return this.value(new Double(d));
- }
-
- /**
- * Append a long value.
- *
- * @param l
- * A long.
- * @return this
- * @throws JSONException
- */
- public JSONWriter value(long l) throws JSONException {
- return append(Long.toString(l));
- }
-
- /**
- * Append an object value.
- *
- * @param object
- * The object to append. It can be null, or a Boolean, Number,
- * String, JSONObject, or JSONArray, or an object that implements
- * JSONString.
- * @return this
- * @throws JSONException
- * If the value is out of sequence.
- */
- public JSONWriter value(Object object) throws JSONException {
- return append(JSONObject.valueToString(object));
- }
-}
+package com.vaadin.external.json; + +import java.io.IOException; +import java.io.Serializable; +import java.io.Writer; + +/* + Copyright (c) 2006 JSON.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + The Software shall be used for Good, not Evil. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +/** + * JSONWriter provides a quick and convenient way of producing JSON text. The + * texts produced strictly conform to JSON syntax rules. No whitespace is added, + * so the results are ready for transmission or storage. Each instance of + * JSONWriter can produce one JSON text. + * <p> + * A JSONWriter instance provides a <code>value</code> method for appending + * values to the text, and a <code>key</code> method for adding keys before + * values in objects. There are <code>array</code> and <code>endArray</code> + * methods that make and bound array values, and <code>object</code> and + * <code>endObject</code> methods which make and bound object values. All of + * these methods return the JSONWriter instance, permitting a cascade style. For + * example, + * + * <pre> + * new JSONWriter(myWriter).object().key("JSON").value("Hello, World!") + * .endObject(); + * </pre> + * + * which writes + * + * <pre> + * {"JSON":"Hello, World!"} + * </pre> + * <p> + * The first method called must be <code>array</code> or <code>object</code>. + * There are no methods for adding commas or colons. JSONWriter adds them for + * you. Objects and arrays can be nested up to 20 levels deep. + * <p> + * This can sometimes be easier than using a JSONObject to build a string. + * + * @author JSON.org + * @version 2011-11-14 + */ +public class JSONWriter implements Serializable { + private static final int maxdepth = 200; + + /** + * The comma flag determines if a comma should be output before the next + * value. + */ + private boolean comma; + + /** + * The current mode. Values: 'a' (array), 'd' (done), 'i' (initial), 'k' + * (key), 'o' (object). + */ + protected char mode; + + /** + * The object/array stack. + */ + private final JSONObject stack[]; + + /** + * The stack top index. A value of 0 indicates that the stack is empty. + */ + private int top; + + /** + * The writer that will receive the output. + */ + protected Writer writer; + + /** + * Make a fresh JSONWriter. It can be used to build one JSON text. + */ + public JSONWriter(Writer w) { + comma = false; + mode = 'i'; + stack = new JSONObject[maxdepth]; + top = 0; + writer = w; + } + + /** + * Append a value. + * + * @param string + * A string value. + * @return this + * @throws JSONException + * If the value is out of sequence. + */ + private JSONWriter append(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null pointer"); + } + if (mode == 'o' || mode == 'a') { + try { + if (comma && mode == 'a') { + writer.write(','); + } + writer.write(string); + } catch (IOException e) { + throw new JSONException(e); + } + if (mode == 'o') { + mode = 'k'; + } + comma = true; + return this; + } + throw new JSONException("Value out of sequence."); + } + + /** + * Begin appending a new array. All values until the balancing + * <code>endArray</code> will be appended to this array. The + * <code>endArray</code> method must be called to mark the array's end. + * + * @return this + * @throws JSONException + * If the nesting is too deep, or if the object is started in + * the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter array() throws JSONException { + if (mode == 'i' || mode == 'o' || mode == 'a') { + push(null); + append("["); + comma = false; + return this; + } + throw new JSONException("Misplaced array."); + } + + /** + * End something. + * + * @param mode + * Mode + * @param c + * Closing character + * @return this + * @throws JSONException + * If unbalanced. + */ + private JSONWriter end(char mode, char c) throws JSONException { + if (this.mode != mode) { + throw new JSONException(mode == 'a' ? "Misplaced endArray." + : "Misplaced endObject."); + } + pop(mode); + try { + writer.write(c); + } catch (IOException e) { + throw new JSONException(e); + } + comma = true; + return this; + } + + /** + * End an array. This method most be called to balance calls to + * <code>array</code>. + * + * @return this + * @throws JSONException + * If incorrectly nested. + */ + public JSONWriter endArray() throws JSONException { + return end('a', ']'); + } + + /** + * End an object. This method most be called to balance calls to + * <code>object</code>. + * + * @return this + * @throws JSONException + * If incorrectly nested. + */ + public JSONWriter endObject() throws JSONException { + return end('k', '}'); + } + + /** + * Append a key. The key will be associated with the next value. In an + * object, every value must be preceded by a key. + * + * @param string + * A key string. + * @return this + * @throws JSONException + * If the key is out of place. For example, keys do not belong + * in arrays or if the key is null. + */ + public JSONWriter key(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null key."); + } + if (mode == 'k') { + try { + stack[top - 1].putOnce(string, Boolean.TRUE); + if (comma) { + writer.write(','); + } + writer.write(JSONObject.quote(string)); + writer.write(':'); + comma = false; + mode = 'o'; + return this; + } catch (IOException e) { + throw new JSONException(e); + } + } + throw new JSONException("Misplaced key."); + } + + /** + * Begin appending a new object. All keys and values until the balancing + * <code>endObject</code> will be appended to this object. The + * <code>endObject</code> method must be called to mark the object's end. + * + * @return this + * @throws JSONException + * If the nesting is too deep, or if the object is started in + * the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter object() throws JSONException { + if (mode == 'i') { + mode = 'o'; + } + if (mode == 'o' || mode == 'a') { + append("{"); + push(new JSONObject()); + comma = false; + return this; + } + throw new JSONException("Misplaced object."); + + } + + /** + * Pop an array or object scope. + * + * @param c + * The scope to close. + * @throws JSONException + * If nesting is wrong. + */ + private void pop(char c) throws JSONException { + if (top <= 0) { + throw new JSONException("Nesting error."); + } + char m = stack[top - 1] == null ? 'a' : 'k'; + if (m != c) { + throw new JSONException("Nesting error."); + } + top -= 1; + mode = top == 0 ? 'd' : stack[top - 1] == null ? 'a' : 'k'; + } + + /** + * Push an array or object scope. + * + * @param c + * The scope to open. + * @throws JSONException + * If nesting is too deep. + */ + private void push(JSONObject jo) throws JSONException { + if (top >= maxdepth) { + throw new JSONException("Nesting too deep."); + } + stack[top] = jo; + mode = jo == null ? 'a' : 'k'; + top += 1; + } + + /** + * Append either the value <code>true</code> or the value <code>false</code> + * . + * + * @param b + * A boolean. + * @return this + * @throws JSONException + */ + public JSONWriter value(boolean b) throws JSONException { + return append(b ? "true" : "false"); + } + + /** + * Append a double value. + * + * @param d + * A double. + * @return this + * @throws JSONException + * If the number is not finite. + */ + public JSONWriter value(double d) throws JSONException { + return this.value(new Double(d)); + } + + /** + * Append a long value. + * + * @param l + * A long. + * @return this + * @throws JSONException + */ + public JSONWriter value(long l) throws JSONException { + return append(Long.toString(l)); + } + + /** + * Append an object value. + * + * @param object + * The object to append. It can be null, or a Boolean, Number, + * String, JSONObject, or JSONArray, or an object that implements + * JSONString. + * @return this + * @throws JSONException + * If the value is out of sequence. + */ + public JSONWriter value(Object object) throws JSONException { + return append(JSONObject.valueToString(object)); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 630f9bf99b..88d6009a29 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -45,11 +45,9 @@ import com.vaadin.terminal.gwt.client.communication.JsonEncoder; import com.vaadin.terminal.gwt.client.communication.MethodInvocation; import com.vaadin.terminal.gwt.client.communication.SharedState; import com.vaadin.terminal.gwt.client.ui.Field; -import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget; import com.vaadin.terminal.gwt.client.ui.VContextMenu; import com.vaadin.terminal.gwt.client.ui.VNotification; import com.vaadin.terminal.gwt.client.ui.VNotification.HideEvent; -import com.vaadin.terminal.gwt.client.ui.VView; import com.vaadin.terminal.gwt.client.ui.VViewPaintable; import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager; import com.vaadin.terminal.gwt.server.AbstractCommunicationManager; @@ -177,7 +175,8 @@ public class ApplicationConnection { private Set<VPaintableWidget> zeroHeightComponents = null; public ApplicationConnection() { - view = GWT.create(VView.class); + view = GWT.create(VViewPaintable.class); + view.setConnection(this); } public void init(WidgetSet widgetSet, ApplicationConfiguration cnf) { @@ -2079,10 +2078,9 @@ public class ApplicationConnection { if (!paintableMap.hasPaintable(pid)) { // Create and register a new paintable if no old was found VPaintableWidget p = widgetSet.createWidget(uidl, configuration); - if (p instanceof VAbstractPaintableWidget) { - ((VAbstractPaintableWidget) p).setConnection(this); - ((VAbstractPaintableWidget) p).init(); - } + p.setConnection(this); + p.setId(pid); + p.init(); paintableMap.registerPaintable(pid, p); } return (VPaintableWidget) paintableMap.getPaintable(pid); 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/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index a3b1074fc4..6a3e663103 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -1221,4 +1221,18 @@ public class Util { cur = cur.parentNode; } }-*/; + + /** + * Checks if the given event is either a touch event or caused by the left + * mouse button + * + * @param event + * @return true if the event is a touch event or caused by the left mouse + * button, false otherwise + */ + public static boolean isTouchEventOrLeftMouseButton(Event event) { + int eventType = event.getTypeInt(); + boolean touchEvent = Util.isTouchEvent(event); + return touchEvent || event.getButton() == Event.BUTTON_LEFT; + } } diff --git a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java index d9ca56be05..89e106f063 100644 --- a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java +++ b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java @@ -1,356 +1,356 @@ -/*
-@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 isChromeFrameCapable = false;
- private boolean isChromeFrame = 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;
-
- // chromeframe
- isChromeFrameCapable = userAgent.indexOf("chromeframe") != -1;
- isChromeFrame = isChromeFrameCapable && !isChrome;
-
- // 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 capable of running ChromeFrame.
- *
- * @return true if it has ChromeFrame, false otherwise
- */
- public boolean isChromeFrameCapable() {
- return isChromeFrameCapable;
- }
-
- /**
- * Tests if the browser is running ChromeFrame.
- *
- * @return true if it is ChromeFrame, false otherwise
- */
- public boolean isChromeFrame() {
- return isChromeFrame;
- }
-
- /**
- * 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;
- }
-
- /**
- * Checks if the browser is so old that it simply won't work with a Vaadin
- * application. NOTE that the browser might still be capable of running
- * Crome Frame, so you might still want to check
- * {@link #isChromeFrameCapable()} if this returns true.
- *
- * @return true if the browser won't work, false if not the browser is
- * supported or might work
- */
- public boolean isTooOldToFunctionProperly() {
- if (isIE() && getBrowserMajorVersion() < 8) {
- return true;
- }
- if (isSafari() && getBrowserMajorVersion() < 5) {
- return true;
- }
- if (isFirefox() && getBrowserMajorVersion() < 4) {
- return true;
- }
- if (isOpera() && getBrowserMajorVersion() < 11) {
- return true;
- }
-
- return false;
- }
-
-}
+/* +@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 isChromeFrameCapable = false; + private boolean isChromeFrame = 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; + + // chromeframe + isChromeFrameCapable = userAgent.indexOf("chromeframe") != -1; + isChromeFrame = isChromeFrameCapable && !isChrome; + + // 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 capable of running ChromeFrame. + * + * @return true if it has ChromeFrame, false otherwise + */ + public boolean isChromeFrameCapable() { + return isChromeFrameCapable; + } + + /** + * Tests if the browser is running ChromeFrame. + * + * @return true if it is ChromeFrame, false otherwise + */ + public boolean isChromeFrame() { + return isChromeFrame; + } + + /** + * 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; + } + + /** + * Checks if the browser is so old that it simply won't work with a Vaadin + * application. NOTE that the browser might still be capable of running + * Crome Frame, so you might still want to check + * {@link #isChromeFrameCapable()} if this returns true. + * + * @return true if the browser won't work, false if not the browser is + * supported or might work + */ + public boolean isTooOldToFunctionProperly() { + if (isIE() && getBrowserMajorVersion() < 8) { + return true; + } + if (isSafari() && getBrowserMajorVersion() < 5) { + return true; + } + if (isFirefox() && getBrowserMajorVersion() < 4) { + return true; + } + if (isOpera() && getBrowserMajorVersion() < 11) { + return true; + } + + return false; + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/VPaintable.java b/src/com/vaadin/terminal/gwt/client/VPaintable.java index d85c6d33e2..032058b8d5 100644 --- a/src/com/vaadin/terminal/gwt/client/VPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/VPaintable.java @@ -1,74 +1,80 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client;
-
-/**
- * Interface implemented by all client side classes that can be communicate with
- * the server. Classes implementing this interface are initialized by the
- * framework when needed and have the ability to communicate with the server.
- *
- * @author Vaadin Ltd
- * @version @VERSION@
- * @since 7.0.0
- */
-public interface VPaintable {
- /**
- * TODO
- *
- * @param uidl
- * @param client
- */
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client);
-
- // /**
- // * Returns the id for this VPaintable. This must always be what has been
- // set
- // * using {@link #setId(String)}.
- // *
- // * @return The id for the VPaintable.
- // */
- // public String getId();
- //
- // /**
- // * Sets the id for the VPaintable. This method is called once by the
- // * framework when the VPaintable is initialized and should never be called
- // * otherwise.
- // * <p>
- // * The VPaintable id is used to map the server and the client paintables
- // * together. It is unique in this root and assigned by the framework.
- // * </p>
- // *
- // * @param id
- // * The id of the paintable.
- // */
- // public void setId(String id);
-
- /**
- * Gets ApplicationConnection instance that created this VPaintable.
- *
- * @return The ApplicationConnection as set by
- * {@link #setConnection(ApplicationConnection)}
- */
- // public ApplicationConnection getConnection();
-
- /**
- * Sets the reference to ApplicationConnection. This method is called by the
- * framework when the VPaintable is created and should never be called
- * otherwise.
- *
- * @param connection
- * The ApplicationConnection that created this VPaintable
- */
- // public void setConnection(ApplicationConnection connection);
-
- /**
- * Tests whether the component is enabled or not. A user can not interact
- * with disabled components. Disabled components are rendered in a style
- * that indicates the status, usually in gray color. Children of a disabled
- * component are also disabled.
- *
- * @return true if the component is enabled, false otherwise
- */
- // public boolean isEnabled();
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client; + +/** + * Interface implemented by all client side classes that can be communicate with + * the server. Classes implementing this interface are initialized by the + * framework when needed and have the ability to communicate with the server. + * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0.0 + */ +public interface VPaintable { + /** + * TODO + * + * @param uidl + * @param client + */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client); + + /** + * Returns the id for this VPaintable. This must always be what has been set + * using {@link #setId(String)}. + * + * @return The id for the VPaintable. + */ + public String getId(); + + /** + * Sets the id for the VPaintable. This method is called once by the + * framework when the VPaintable is initialized and should never be called + * otherwise. + * <p> + * The VPaintable id is used to map the server and the client paintables + * together. It is unique in this root and assigned by the framework. + * </p> + * + * @param id + * The id of the paintable. + */ + public void setId(String id); + + /** + * Gets ApplicationConnection instance that created this VPaintable. + * + * @return The ApplicationConnection as set by + * {@link #setConnection(ApplicationConnection)} + */ + public ApplicationConnection getConnection(); + + /** + * Sets the reference to ApplicationConnection. This method is called by the + * framework when the VPaintable is created and should never be called + * otherwise. + * + * @param connection + * The ApplicationConnection that created this VPaintable + */ + public void setConnection(ApplicationConnection connection); + + /** + * Tests whether the component is enabled or not. A user can not interact + * with disabled components. Disabled components are rendered in a style + * that indicates the status, usually in gray color. Children of a disabled + * component are also disabled. + * + * @return true if the component is enabled, false otherwise + */ + // public boolean isEnabled(); + + /** + * + * Called once when the connection and id has been set + */ + public void init(); + +} diff --git a/src/com/vaadin/terminal/gwt/client/VPaintableMap.java b/src/com/vaadin/terminal/gwt/client/VPaintableMap.java index f9d05e592d..e36d02bb2b 100644 --- a/src/com/vaadin/terminal/gwt/client/VPaintableMap.java +++ b/src/com/vaadin/terminal/gwt/client/VPaintableMap.java @@ -1,404 +1,404 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.HasWidgets;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.Paintable;
-import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize;
-import com.vaadin.terminal.gwt.client.RenderInformation.Size;
-
-public class VPaintableMap {
-
- private Map<String, VPaintable> idToPaintable = new HashMap<String, VPaintable>();
- private Map<VPaintable, String> paintableToId = new HashMap<VPaintable, String>();
-
- public static VPaintableMap get(ApplicationConnection applicationConnection) {
- return applicationConnection.getPaintableMap();
- }
-
- @Deprecated
- private final ComponentDetailMap idToComponentDetail = ComponentDetailMap
- .create();
-
- private Set<String> unregistryBag = new HashSet<String>();
-
- /**
- * Returns a Paintable by its paintable id
- *
- * @param id
- * The Paintable id
- */
- public VPaintable getPaintable(String pid) {
- return idToPaintable.get(pid);
- }
-
- /**
- * Returns a Paintable element by its root element
- *
- * @param element
- * Root element of the paintable
- */
- public VPaintableWidget getPaintable(Element element) {
- return (VPaintableWidget) getPaintable(getPid(element));
- }
-
- /**
- * FIXME: What does this even do and why?
- *
- * @param pid
- * @return
- */
- public boolean isDragAndDropPaintable(String pid) {
- return (pid.startsWith("DD"));
- }
-
- /**
- * Checks if a paintable with the given paintable id has been registered.
- *
- * @param pid
- * The paintable id to check for
- * @return true if a paintable has been registered with the given paintable
- * id, false otherwise
- */
- public boolean hasPaintable(String pid) {
- return idToPaintable.containsKey(pid);
- }
-
- /**
- * Removes all registered paintable ids
- */
- public void clear() {
- idToPaintable.clear();
- paintableToId.clear();
- idToComponentDetail.clear();
- }
-
- @Deprecated
- public Widget getWidget(VPaintableWidget paintable) {
- return paintable.getWidgetForPaintable();
- }
-
- @Deprecated
- public VPaintableWidget getPaintable(Widget widget) {
- return getPaintable(widget.getElement());
- }
-
- public void registerPaintable(String pid, VPaintable paintable) {
- ComponentDetail componentDetail = GWT.create(ComponentDetail.class);
- idToComponentDetail.put(pid, componentDetail);
- idToPaintable.put(pid, paintable);
- paintableToId.put(paintable, pid);
- if (paintable instanceof VPaintableWidget) {
- VPaintableWidget pw = (VPaintableWidget) paintable;
- setPid(pw.getWidgetForPaintable().getElement(), pid);
- }
- }
-
- private native void setPid(Element el, String pid)
- /*-{
- el.tkPid = pid;
- }-*/;
-
- /**
- * Gets the paintableId for a specific paintable.
- * <p>
- * The paintableId is used in the UIDL to identify a specific widget
- * instance, effectively linking the widget with it's server side Component.
- * </p>
- *
- * @param paintable
- * the paintable who's id is needed
- * @return the id for the given paintable or null if the paintable could not
- * be found
- */
- public String getPid(VPaintable paintable) {
- if (paintable == null) {
- return null;
- }
- return paintableToId.get(paintable);
- }
-
- @Deprecated
- public String getPid(Widget widget) {
- return getPid(widget.getElement());
- }
-
- /**
- * Gets the paintableId using a DOM element - the element should be the main
- * element for a paintable otherwise no id will be found. Use
- * {@link #getPid(Paintable)} instead whenever possible.
- *
- * @see #getPid(Paintable)
- * @param el
- * element of the paintable whose pid is desired
- * @return the pid of the element's paintable, if it's a paintable
- */
- native String getPid(Element el)
- /*-{
- return el.tkPid;
- }-*/;
-
- /**
- * Gets the main element for the paintable with the given id. The revers of
- * {@link #getPid(Element)}.
- *
- * @param pid
- * the pid of the widget whose element is desired
- * @return the element for the paintable corresponding to the pid
- */
- public Element getElement(String pid) {
- VPaintable p = getPaintable(pid);
- if (p instanceof VPaintableWidget) {
- return ((VPaintableWidget) p).getWidgetForPaintable().getElement();
- }
-
- return null;
- }
-
- /**
- * Unregisters the given paintable; always use after removing a paintable.
- * This method does not remove the paintable from the DOM, but marks the
- * paintable so that ApplicationConnection may clean up its references to
- * it. Removing the widget from DOM is component containers responsibility.
- *
- * @param p
- * the paintable to remove
- */
- public void unregisterPaintable(VPaintable p) {
-
- // add to unregistry que
-
- if (p == null) {
- VConsole.error("WARN: Trying to unregister null paintable");
- return;
- }
- String id = getPid(p);
- Widget widget = null;
- if (p instanceof VPaintableWidget) {
- widget = ((VPaintableWidget) p).getWidgetForPaintable();
- }
-
- if (id == null) {
- /*
- * Uncomment the following to debug unregistring components. No
- * paintables with null id should end here. At least one exception
- * is our VScrollTableRow, that is hacked to fake it self as a
- * Paintable to build support for sizing easier.
- */
- // if (!(p instanceof VScrollTableRow)) {
- // VConsole.log("Trying to unregister Paintable not created by Application Connection.");
- // }
- } else {
- unregistryBag.add(id);
- }
- if (widget != null && widget instanceof HasWidgets) {
- unregisterChildPaintables((HasWidgets) widget);
- }
-
- }
-
- void purgeUnregistryBag(boolean unregisterPaintables) {
- if (unregisterPaintables) {
- for (String pid : unregistryBag) {
- VPaintable paintable = getPaintable(pid);
- if (paintable == null) {
- /*
- * this should never happen, but it does :-( See e.g.
- * com.vaadin.tests.components.accordion.RemoveTabs (with
- * test script)
- */
- VConsole.error("Tried to unregister component (id="
- + pid
- + ") that is never registered (or already unregistered)");
- continue;
- }
- Widget widget = null;
- if (paintable instanceof VPaintableWidget) {
- widget = ((VPaintableWidget) paintable)
- .getWidgetForPaintable();
- }
-
- // check if can be cleaned
- if (widget == null || !widget.isAttached()) {
- // clean reference to paintable
- idToComponentDetail.remove(pid);
- idToPaintable.remove(pid);
- paintableToId.remove(paintable);
- // TODO purge shared state for pid
- }
- /*
- * else NOP : same component has been reattached to another
- * parent or replaced by another component implementation.
- */
- }
- }
-
- unregistryBag.clear();
- }
-
- /**
- * Unregisters a paintable and all it's child paintables recursively. Use
- * when after removing a paintable that contains other paintables. Does not
- * unregister the given container itself. Does not actually remove the
- * paintable from the DOM.
- *
- * @see #unregisterPaintable(Paintable)
- * @param container
- */
- public void unregisterChildPaintables(HasWidgets container) {
- // FIXME: This should be based on the paintable hierarchy
- final Iterator<Widget> it = container.iterator();
- while (it.hasNext()) {
- final Widget w = it.next();
- VPaintableWidget p = getPaintable(w);
- if (p != null) {
- // This will unregister the paintable and all its children
- unregisterPaintable(p);
- } else if (w instanceof HasWidgets) {
- // For normal widget containers, unregister the children
- unregisterChildPaintables((HasWidgets) w);
- }
- }
- }
-
- /**
- * FIXME: Should not be here
- *
- * @param pid
- * @param uidl
- */
- @Deprecated
- public void registerEventListenersFromUIDL(String pid, UIDL uidl) {
- ComponentDetail cd = idToComponentDetail.get(pid);
- if (cd == null) {
- throw new IllegalArgumentException("Pid must not be null");
- }
-
- cd.registerEventListenersFromUIDL(uidl);
-
- }
-
- /**
- * FIXME: Should not be here
- *
- * @param paintable
- * @return
- */
- @Deprecated
- public Size getOffsetSize(VPaintableWidget paintable) {
- return getComponentDetail(paintable).getOffsetSize();
- }
-
- /**
- * FIXME: Should not be here
- *
- * @param paintable
- * @return
- */
- @Deprecated
- public FloatSize getRelativeSize(VPaintableWidget paintable) {
- return getComponentDetail(paintable).getRelativeSize();
- }
-
- /**
- * FIXME: Should not be here
- *
- * @param paintable
- * @return
- */
- @Deprecated
- public void setOffsetSize(VPaintableWidget paintable, Size newSize) {
- getComponentDetail(paintable).setOffsetSize(newSize);
- }
-
- /**
- * FIXME: Should not be here
- *
- * @param paintable
- * @return
- */
- @Deprecated
- public void setRelativeSize(VPaintableWidget paintable,
- FloatSize relativeSize) {
- getComponentDetail(paintable).setRelativeSize(relativeSize);
-
- }
-
- private ComponentDetail getComponentDetail(VPaintableWidget paintable) {
- return idToComponentDetail.get(getPid(paintable));
- }
-
- public int size() {
- return idToPaintable.size();
- }
-
- /**
- * FIXME: Should be moved to VAbstractPaintableWidget
- *
- * @param paintable
- * @return
- */
- @Deprecated
- public TooltipInfo getTooltipInfo(VPaintableWidget paintable, Object key) {
- return getComponentDetail(paintable).getTooltipInfo(key);
- }
-
- @Deprecated
- public TooltipInfo getWidgetTooltipInfo(Widget widget, Object key) {
- return getTooltipInfo(getPaintable(widget), key);
- }
-
- public Collection<? extends VPaintable> getPaintables() {
- return Collections.unmodifiableCollection(paintableToId.keySet());
- }
-
- /**
- * FIXME: Should not be here
- *
- * @param paintable
- * @return
- */
- @Deprecated
- public void registerTooltip(VPaintableWidget paintable, Object key,
- TooltipInfo tooltip) {
- getComponentDetail(paintable).putAdditionalTooltip(key, tooltip);
-
- }
-
- /**
- * FIXME: Should not be here
- *
- * @param paintable
- * @return
- */
- @Deprecated
- public boolean hasEventListeners(VPaintableWidget paintable,
- String eventIdentifier) {
- return getComponentDetail(paintable).hasEventListeners(eventIdentifier);
- }
-
- /**
- * Tests if the widget is the root widget of a VPaintableWidget.
- *
- * @param widget
- * The widget to test
- * @return true if the widget is the root widget of a VPaintableWidget,
- * false otherwise
- */
- public boolean isPaintable(Widget w) {
- return getPid(w) != null;
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.HasWidgets; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.Paintable; +import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; +import com.vaadin.terminal.gwt.client.RenderInformation.Size; + +public class VPaintableMap { + + private Map<String, VPaintable> idToPaintable = new HashMap<String, VPaintable>(); + private Map<VPaintable, String> paintableToId = new HashMap<VPaintable, String>(); + + public static VPaintableMap get(ApplicationConnection applicationConnection) { + return applicationConnection.getPaintableMap(); + } + + @Deprecated + private final ComponentDetailMap idToComponentDetail = ComponentDetailMap + .create(); + + private Set<String> unregistryBag = new HashSet<String>(); + + /** + * Returns a Paintable by its paintable id + * + * @param id + * The Paintable id + */ + public VPaintable getPaintable(String pid) { + return idToPaintable.get(pid); + } + + /** + * Returns a Paintable element by its root element + * + * @param element + * Root element of the paintable + */ + public VPaintableWidget getPaintable(Element element) { + return (VPaintableWidget) getPaintable(getPid(element)); + } + + /** + * FIXME: What does this even do and why? + * + * @param pid + * @return + */ + public boolean isDragAndDropPaintable(String pid) { + return (pid.startsWith("DD")); + } + + /** + * Checks if a paintable with the given paintable id has been registered. + * + * @param pid + * The paintable id to check for + * @return true if a paintable has been registered with the given paintable + * id, false otherwise + */ + public boolean hasPaintable(String pid) { + return idToPaintable.containsKey(pid); + } + + /** + * Removes all registered paintable ids + */ + public void clear() { + idToPaintable.clear(); + paintableToId.clear(); + idToComponentDetail.clear(); + } + + @Deprecated + public Widget getWidget(VPaintableWidget paintable) { + return paintable.getWidgetForPaintable(); + } + + @Deprecated + public VPaintableWidget getPaintable(Widget widget) { + return getPaintable(widget.getElement()); + } + + public void registerPaintable(String pid, VPaintable paintable) { + ComponentDetail componentDetail = GWT.create(ComponentDetail.class); + idToComponentDetail.put(pid, componentDetail); + idToPaintable.put(pid, paintable); + paintableToId.put(paintable, pid); + if (paintable instanceof VPaintableWidget) { + VPaintableWidget pw = (VPaintableWidget) paintable; + setPid(pw.getWidgetForPaintable().getElement(), pid); + } + } + + private native void setPid(Element el, String pid) + /*-{ + el.tkPid = pid; + }-*/; + + /** + * Gets the paintableId for a specific paintable. + * <p> + * The paintableId is used in the UIDL to identify a specific widget + * instance, effectively linking the widget with it's server side Component. + * </p> + * + * @param paintable + * the paintable who's id is needed + * @return the id for the given paintable or null if the paintable could not + * be found + */ + public String getPid(VPaintable paintable) { + if (paintable == null) { + return null; + } + return paintableToId.get(paintable); + } + + @Deprecated + public String getPid(Widget widget) { + return getPid(widget.getElement()); + } + + /** + * Gets the paintableId using a DOM element - the element should be the main + * element for a paintable otherwise no id will be found. Use + * {@link #getPid(Paintable)} instead whenever possible. + * + * @see #getPid(Paintable) + * @param el + * element of the paintable whose pid is desired + * @return the pid of the element's paintable, if it's a paintable + */ + native String getPid(Element el) + /*-{ + return el.tkPid; + }-*/; + + /** + * Gets the main element for the paintable with the given id. The revers of + * {@link #getPid(Element)}. + * + * @param pid + * the pid of the widget whose element is desired + * @return the element for the paintable corresponding to the pid + */ + public Element getElement(String pid) { + VPaintable p = getPaintable(pid); + if (p instanceof VPaintableWidget) { + return ((VPaintableWidget) p).getWidgetForPaintable().getElement(); + } + + return null; + } + + /** + * Unregisters the given paintable; always use after removing a paintable. + * This method does not remove the paintable from the DOM, but marks the + * paintable so that ApplicationConnection may clean up its references to + * it. Removing the widget from DOM is component containers responsibility. + * + * @param p + * the paintable to remove + */ + public void unregisterPaintable(VPaintable p) { + + // add to unregistry que + + if (p == null) { + VConsole.error("WARN: Trying to unregister null paintable"); + return; + } + String id = getPid(p); + Widget widget = null; + if (p instanceof VPaintableWidget) { + widget = ((VPaintableWidget) p).getWidgetForPaintable(); + } + + if (id == null) { + /* + * Uncomment the following to debug unregistring components. No + * paintables with null id should end here. At least one exception + * is our VScrollTableRow, that is hacked to fake it self as a + * Paintable to build support for sizing easier. + */ + // if (!(p instanceof VScrollTableRow)) { + // VConsole.log("Trying to unregister Paintable not created by Application Connection."); + // } + } else { + unregistryBag.add(id); + } + if (widget != null && widget instanceof HasWidgets) { + unregisterChildPaintables((HasWidgets) widget); + } + + } + + void purgeUnregistryBag(boolean unregisterPaintables) { + if (unregisterPaintables) { + for (String pid : unregistryBag) { + // TODO purge shared state for pid + VPaintable paintable = getPaintable(pid); + if (paintable == null) { + /* + * this should never happen, but it does :-( See e.g. + * com.vaadin.tests.components.accordion.RemoveTabs (with + * test script) + */ + VConsole.error("Tried to unregister component (id=" + + pid + + ") that is never registered (or already unregistered)"); + continue; + } + Widget widget = null; + if (paintable instanceof VPaintableWidget) { + widget = ((VPaintableWidget) paintable) + .getWidgetForPaintable(); + } + + // check if can be cleaned + if (widget == null || !widget.isAttached()) { + // clean reference to paintable + idToComponentDetail.remove(pid); + idToPaintable.remove(pid); + paintableToId.remove(paintable); + } + /* + * else NOP : same component has been reattached to another + * parent or replaced by another component implementation. + */ + } + } + + unregistryBag.clear(); + } + + /** + * Unregisters a paintable and all it's child paintables recursively. Use + * when after removing a paintable that contains other paintables. Does not + * unregister the given container itself. Does not actually remove the + * paintable from the DOM. + * + * @see #unregisterPaintable(Paintable) + * @param container + */ + public void unregisterChildPaintables(HasWidgets container) { + // FIXME: This should be based on the paintable hierarchy + final Iterator<Widget> it = container.iterator(); + while (it.hasNext()) { + final Widget w = it.next(); + VPaintableWidget p = getPaintable(w); + if (p != null) { + // This will unregister the paintable and all its children + unregisterPaintable(p); + } else if (w instanceof HasWidgets) { + // For normal widget containers, unregister the children + unregisterChildPaintables((HasWidgets) w); + } + } + } + + /** + * FIXME: Should not be here + * + * @param pid + * @param uidl + */ + @Deprecated + public void registerEventListenersFromUIDL(String pid, UIDL uidl) { + ComponentDetail cd = idToComponentDetail.get(pid); + if (cd == null) { + throw new IllegalArgumentException("Pid must not be null"); + } + + cd.registerEventListenersFromUIDL(uidl); + + } + + /** + * FIXME: Should not be here + * + * @param paintable + * @return + */ + @Deprecated + public Size getOffsetSize(VPaintableWidget paintable) { + return getComponentDetail(paintable).getOffsetSize(); + } + + /** + * FIXME: Should not be here + * + * @param paintable + * @return + */ + @Deprecated + public FloatSize getRelativeSize(VPaintableWidget paintable) { + return getComponentDetail(paintable).getRelativeSize(); + } + + /** + * FIXME: Should not be here + * + * @param paintable + * @return + */ + @Deprecated + public void setOffsetSize(VPaintableWidget paintable, Size newSize) { + getComponentDetail(paintable).setOffsetSize(newSize); + } + + /** + * FIXME: Should not be here + * + * @param paintable + * @return + */ + @Deprecated + public void setRelativeSize(VPaintableWidget paintable, + FloatSize relativeSize) { + getComponentDetail(paintable).setRelativeSize(relativeSize); + + } + + private ComponentDetail getComponentDetail(VPaintableWidget paintable) { + return idToComponentDetail.get(getPid(paintable)); + } + + public int size() { + return idToPaintable.size(); + } + + /** + * FIXME: Should be moved to VAbstractPaintableWidget + * + * @param paintable + * @return + */ + @Deprecated + public TooltipInfo getTooltipInfo(VPaintableWidget paintable, Object key) { + return getComponentDetail(paintable).getTooltipInfo(key); + } + + @Deprecated + public TooltipInfo getWidgetTooltipInfo(Widget widget, Object key) { + return getTooltipInfo(getPaintable(widget), key); + } + + public Collection<? extends VPaintable> getPaintables() { + return Collections.unmodifiableCollection(paintableToId.keySet()); + } + + /** + * FIXME: Should not be here + * + * @param paintable + * @return + */ + @Deprecated + public void registerTooltip(VPaintableWidget paintable, Object key, + TooltipInfo tooltip) { + getComponentDetail(paintable).putAdditionalTooltip(key, tooltip); + + } + + /** + * FIXME: Should not be here + * + * @param paintable + * @return + */ + @Deprecated + public boolean hasEventListeners(VPaintableWidget paintable, + String eventIdentifier) { + return getComponentDetail(paintable).hasEventListeners(eventIdentifier); + } + + /** + * Tests if the widget is the root widget of a VPaintableWidget. + * + * @param widget + * The widget to test + * @return true if the widget is the root widget of a VPaintableWidget, + * false otherwise + */ + public boolean isPaintable(Widget w) { + return getPid(w) != null; + } + +} 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/VAbsoluteLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java index f95acfc43c..7ac44bc4b7 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java @@ -309,8 +309,4 @@ public class VAbsoluteLayout extends ComplexPanel implements Container { return Util.getPaintableForElement(client, this, element); } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayoutPaintable.java index 27535806c1..9d73e75b09 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayoutPaintable.java @@ -1,84 +1,87 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.HashSet;
-import java.util.Iterator;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.DomEvent.Type;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.EventId;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.ui.VAbsoluteLayout.AbsoluteWrapper;
-
-public class VAbsoluteLayoutPaintable extends VAbstractPaintableWidgetContainer {
-
- private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
- this, EventId.LAYOUT_CLICK) {
-
- @Override
- protected VPaintableWidget getChildComponent(Element element) {
- return getWidgetForPaintable().getComponent(element);
- }
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- return getWidgetForPaintable().addDomHandler(handler, type);
- }
- };
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
- getWidgetForPaintable().client = client;
- // TODO margin handling
- if (client.updateComponent(this, uidl, true)) {
- getWidgetForPaintable().rendering = false;
- return;
- }
-
- clickEventHandler.handleEventHandlerRegistration(client);
-
- HashSet<String> unrenderedPids = new HashSet<String>(
- getWidgetForPaintable().pidToComponentWrappper.keySet());
-
- for (Iterator<Object> childIterator = uidl.getChildIterator(); childIterator
- .hasNext();) {
- UIDL cc = (UIDL) childIterator.next();
- if (cc.getTag().equals("cc")) {
- UIDL componentUIDL = cc.getChildUIDL(0);
- unrenderedPids.remove(componentUIDL.getId());
- getWidgetForPaintable().getWrapper(client, componentUIDL)
- .updateFromUIDL(cc);
- }
- }
-
- for (String pid : unrenderedPids) {
- AbsoluteWrapper absoluteWrapper = getWidgetForPaintable().pidToComponentWrappper
- .get(pid);
- getWidgetForPaintable().pidToComponentWrappper.remove(pid);
- absoluteWrapper.destroy();
- }
- getWidgetForPaintable().rendering = false;
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- AbsoluteWrapper parent2 = (AbsoluteWrapper) (component
- .getWidgetForPaintable()).getParent();
- parent2.updateCaption(uidl);
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VAbsoluteLayout.class);
- }
-
- @Override
- public VAbsoluteLayout getWidgetForPaintable() {
- return (VAbsoluteLayout) super.getWidgetForPaintable();
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.HashSet; +import java.util.Iterator; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.DomEvent.Type; +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.EventId; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableWidget; +import com.vaadin.terminal.gwt.client.ui.VAbsoluteLayout.AbsoluteWrapper; + +public class VAbsoluteLayoutPaintable extends VAbstractPaintableWidgetContainer { + + private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( + this, EventId.LAYOUT_CLICK) { + + @Override + protected VPaintableWidget getChildComponent(Element element) { + return getWidgetForPaintable().getComponent(element); + } + + @Override + protected <H extends EventHandler> HandlerRegistration registerHandler( + H handler, Type<H> type) { + return getWidgetForPaintable().addDomHandler(handler, type); + } + }; + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + getWidgetForPaintable().client = client; + // TODO margin handling + if (client.updateComponent(this, uidl, true)) { + getWidgetForPaintable().rendering = false; + return; + } + + clickEventHandler.handleEventHandlerRegistration(client); + + HashSet<String> unrenderedPids = new HashSet<String>( + getWidgetForPaintable().pidToComponentWrappper.keySet()); + + for (Iterator<Object> childIterator = uidl.getChildIterator(); childIterator + .hasNext();) { + UIDL cc = (UIDL) childIterator.next(); + if (cc.getTag().equals("cc")) { + UIDL componentUIDL = cc.getChildUIDL(0); + unrenderedPids.remove(componentUIDL.getId()); + getWidgetForPaintable().getWrapper(client, componentUIDL) + .updateFromUIDL(cc); + } + } + + for (String pid : unrenderedPids) { + AbsoluteWrapper absoluteWrapper = getWidgetForPaintable().pidToComponentWrappper + .get(pid); + getWidgetForPaintable().pidToComponentWrappper.remove(pid); + absoluteWrapper.destroy(); + } + getWidgetForPaintable().rendering = false; + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + AbsoluteWrapper parent2 = (AbsoluteWrapper) (component + .getWidgetForPaintable()).getParent(); + parent2.updateCaption(uidl); + } + + @Override + protected Widget createWidget() { + return GWT.create(VAbsoluteLayout.class); + } + + @Override + public VAbsoluteLayout getWidgetForPaintable() { + return (VAbsoluteLayout) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java index 90da0ef4ac..09bf02ec43 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java @@ -1,103 +1,103 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.VPaintableMap;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.VPaintableWidgetContainer;
-
-public abstract class VAbstractPaintableWidget implements VPaintableWidget {
-
- private Widget widget;
- private ApplicationConnection connection;
- private String id;
-
- /* State variables */
- private boolean enabled = true;
-
- /**
- * Default constructor
- */
- public VAbstractPaintableWidget() {
- }
-
- /**
- * Called after the application connection reference has been set up
- */
- public void init() {
- }
-
- /**
- * Creates and returns the widget for this VPaintableWidget. This method
- * should only be called once when initializing the paintable.
- *
- * @return
- */
- protected abstract Widget createWidget();
-
- /**
- * Returns the widget associated with this paintable. The widget returned by
- * this method must not changed during the life time of the paintable.
- *
- * @return The widget associated with this paintable
- */
- public Widget getWidgetForPaintable() {
- if (widget == null) {
- widget = createWidget();
- }
-
- return widget;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.VPaintable#getConnection()
- */
- public final ApplicationConnection getConnection() {
- return connection;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.VPaintable#setConnection(com.vaadin.terminal
- * .gwt.client.ApplicationConnection)
- */
- public final void setConnection(ApplicationConnection connection) {
- this.connection = connection;
- }
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public VPaintableWidgetContainer getParentPaintable() {
- // FIXME: Return VPaintableWidgetContainer
- // FIXME: Store hierarchy instead of doing lookup every time
-
- VPaintableMap paintableMap = VPaintableMap.get(getConnection());
-
- Widget w = getWidgetForPaintable();
- while (w != null) {
- w = w.getParent();
- if (paintableMap.isPaintable(w)) {
- return (VPaintableWidgetContainer) paintableMap.getPaintable(w);
- }
- }
-
- return null;
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.VPaintableWidget; +import com.vaadin.terminal.gwt.client.VPaintableWidgetContainer; + +public abstract class VAbstractPaintableWidget implements VPaintableWidget { + + private Widget widget; + private ApplicationConnection connection; + private String id; + + /* State variables */ + private boolean enabled = true; + + /** + * Default constructor + */ + public VAbstractPaintableWidget() { + } + + /** + * Called after the application connection reference has been set up + */ + public void init() { + } + + /** + * Creates and returns the widget for this VPaintableWidget. This method + * should only be called once when initializing the paintable. + * + * @return + */ + protected abstract Widget createWidget(); + + /** + * Returns the widget associated with this paintable. The widget returned by + * this method must not changed during the life time of the paintable. + * + * @return The widget associated with this paintable + */ + public Widget getWidgetForPaintable() { + if (widget == null) { + widget = createWidget(); + } + + return widget; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.terminal.gwt.client.VPaintable#getConnection() + */ + public final ApplicationConnection getConnection() { + return connection; + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.terminal.gwt.client.VPaintable#setConnection(com.vaadin.terminal + * .gwt.client.ApplicationConnection) + */ + public final void setConnection(ApplicationConnection connection) { + this.connection = connection; + } + + public boolean isEnabled() { + return enabled; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public VPaintableWidgetContainer getParentPaintable() { + // FIXME: Return VPaintableWidgetContainer + // FIXME: Store hierarchy instead of doing lookup every time + + VPaintableMap paintableMap = VPaintableMap.get(getConnection()); + + Widget w = getWidgetForPaintable(); + while (w != null) { + w = w.getParent(); + if (paintableMap.isPaintable(w)) { + return (VPaintableWidgetContainer) paintableMap.getPaintable(w); + } + } + + return null; + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidgetContainer.java b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidgetContainer.java index b3e19f037a..1f78c02f58 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidgetContainer.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidgetContainer.java @@ -1,17 +1,17 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.vaadin.terminal.gwt.client.VPaintableWidgetContainer;
-
-public abstract class VAbstractPaintableWidgetContainer extends
- VAbstractPaintableWidget implements VPaintableWidgetContainer {
-
- /**
- * Default constructor
- */
- public VAbstractPaintableWidgetContainer() {
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.vaadin.terminal.gwt.client.VPaintableWidgetContainer; + +public abstract class VAbstractPaintableWidgetContainer extends + VAbstractPaintableWidget implements VPaintableWidgetContainer { + + /** + * Default constructor + */ + public VAbstractPaintableWidgetContainer() { + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanel.java index 1aa9d92770..f1a932b3a3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanel.java @@ -730,7 +730,4 @@ public class VAbstractSplitPanel extends ComplexPanel implements Container, return enabled; } - public Widget getWidgetForPaintable() { - return this; - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanelPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanelPaintable.java index 1ff066d004..9c7e5f04f9 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanelPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanelPaintable.java @@ -1,140 +1,143 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.event.dom.client.DomEvent.Type;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableMap;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public abstract class VAbstractSplitPanelPaintable extends
- VAbstractPaintableWidgetContainer {
-
- public static final String SPLITTER_CLICK_EVENT_IDENTIFIER = "sp_click";
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- // TODO Implement caption handling
- }
-
- ClickEventHandler clickEventHandler = new ClickEventHandler(this,
- SPLITTER_CLICK_EVENT_IDENTIFIER) {
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- if ((Event.getEventsSunk(getWidgetForPaintable().splitter) & Event
- .getTypeInt(type.getName())) != 0) {
- // If we are already sinking the event for the splitter we do
- // not want to additionally sink it for the root element
- return getWidgetForPaintable().addHandler(handler, type);
- } else {
- return getWidgetForPaintable().addDomHandler(handler, type);
- }
- }
-
- @Override
- public void onContextMenu(
- com.google.gwt.event.dom.client.ContextMenuEvent event) {
- Element target = event.getNativeEvent().getEventTarget().cast();
- if (getWidgetForPaintable().splitter.isOrHasChild(target)) {
- super.onContextMenu(event);
- }
- };
-
- @Override
- protected void fireClick(NativeEvent event) {
- Element target = event.getEventTarget().cast();
- if (getWidgetForPaintable().splitter.isOrHasChild(target)) {
- super.fireClick(event);
- }
- }
-
- @Override
- protected Element getRelativeToElement() {
- return null;
- }
-
- };
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().client = client;
- getWidgetForPaintable().id = uidl.getId();
- getWidgetForPaintable().rendering = true;
-
- getWidgetForPaintable().immediate = uidl.hasAttribute("immediate");
-
- if (client.updateComponent(this, uidl, true)) {
- getWidgetForPaintable().rendering = false;
- return;
- }
- getWidgetForPaintable().setEnabled(
- !uidl.getBooleanAttribute("disabled"));
-
- clickEventHandler.handleEventHandlerRegistration(client);
- if (uidl.hasAttribute("style")) {
- getWidgetForPaintable().componentStyleNames = uidl
- .getStringAttribute("style").split(" ");
- } else {
- getWidgetForPaintable().componentStyleNames = new String[0];
- }
-
- getWidgetForPaintable().setLocked(uidl.getBooleanAttribute("locked"));
-
- getWidgetForPaintable().setPositionReversed(
- uidl.getBooleanAttribute("reversed"));
-
- getWidgetForPaintable().setStylenames();
-
- getWidgetForPaintable().position = uidl.getStringAttribute("position");
- getWidgetForPaintable().setSplitPosition(
- getWidgetForPaintable().position);
-
- final VPaintableWidget newFirstChildPaintable = client
- .getPaintable(uidl.getChildUIDL(0));
- final VPaintableWidget newSecondChildPaintable = client
- .getPaintable(uidl.getChildUIDL(1));
- Widget newFirstChild = newFirstChildPaintable.getWidgetForPaintable();
- Widget newSecondChild = newSecondChildPaintable.getWidgetForPaintable();
-
- if (getWidgetForPaintable().firstChild != newFirstChild) {
- if (getWidgetForPaintable().firstChild != null) {
- client.unregisterPaintable(VPaintableMap.get(client)
- .getPaintable(getWidgetForPaintable().firstChild));
- }
- getWidgetForPaintable().setFirstWidget(newFirstChild);
- }
- if (getWidgetForPaintable().secondChild != newSecondChild) {
- if (getWidgetForPaintable().secondChild != null) {
- client.unregisterPaintable(VPaintableMap.get(client)
- .getPaintable(getWidgetForPaintable().secondChild));
- }
- getWidgetForPaintable().setSecondWidget(newSecondChild);
- }
- newFirstChildPaintable.updateFromUIDL(uidl.getChildUIDL(0), client);
- newSecondChildPaintable.updateFromUIDL(uidl.getChildUIDL(1), client);
-
- getWidgetForPaintable().renderInformation
- .updateSize(getWidgetForPaintable().getElement());
-
- // This is needed at least for cases like #3458 to take
- // appearing/disappearing scrollbars into account.
- client.runDescendentsLayout(getWidgetForPaintable());
-
- getWidgetForPaintable().rendering = false;
-
- }
-
- @Override
- public VAbstractSplitPanel getWidgetForPaintable() {
- return (VAbstractSplitPanel) super.getWidgetForPaintable();
- }
-
- @Override
- protected abstract VAbstractSplitPanel createWidget();
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.event.dom.client.DomEvent.Type; +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public abstract class VAbstractSplitPanelPaintable extends + VAbstractPaintableWidgetContainer { + + public static final String SPLITTER_CLICK_EVENT_IDENTIFIER = "sp_click"; + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + // TODO Implement caption handling + } + + ClickEventHandler clickEventHandler = new ClickEventHandler(this, + SPLITTER_CLICK_EVENT_IDENTIFIER) { + + @Override + protected <H extends EventHandler> HandlerRegistration registerHandler( + H handler, Type<H> type) { + if ((Event.getEventsSunk(getWidgetForPaintable().splitter) & Event + .getTypeInt(type.getName())) != 0) { + // If we are already sinking the event for the splitter we do + // not want to additionally sink it for the root element + return getWidgetForPaintable().addHandler(handler, type); + } else { + return getWidgetForPaintable().addDomHandler(handler, type); + } + } + + @Override + public void onContextMenu( + com.google.gwt.event.dom.client.ContextMenuEvent event) { + Element target = event.getNativeEvent().getEventTarget().cast(); + if (getWidgetForPaintable().splitter.isOrHasChild(target)) { + super.onContextMenu(event); + } + }; + + @Override + protected void fireClick(NativeEvent event) { + Element target = event.getEventTarget().cast(); + if (getWidgetForPaintable().splitter.isOrHasChild(target)) { + super.fireClick(event); + } + } + + @Override + protected Element getRelativeToElement() { + return null; + } + + }; + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().client = client; + getWidgetForPaintable().id = uidl.getId(); + getWidgetForPaintable().rendering = true; + + getWidgetForPaintable().immediate = uidl.hasAttribute("immediate"); + + if (client.updateComponent(this, uidl, true)) { + getWidgetForPaintable().rendering = false; + return; + } + getWidgetForPaintable().setEnabled( + !uidl.getBooleanAttribute("disabled")); + + clickEventHandler.handleEventHandlerRegistration(client); + if (uidl.hasAttribute("style")) { + getWidgetForPaintable().componentStyleNames = uidl + .getStringAttribute("style").split(" "); + } else { + getWidgetForPaintable().componentStyleNames = new String[0]; + } + + getWidgetForPaintable().setLocked(uidl.getBooleanAttribute("locked")); + + getWidgetForPaintable().setPositionReversed( + uidl.getBooleanAttribute("reversed")); + + getWidgetForPaintable().setStylenames(); + + getWidgetForPaintable().position = uidl.getStringAttribute("position"); + getWidgetForPaintable().setSplitPosition( + getWidgetForPaintable().position); + + final VPaintableWidget newFirstChildPaintable = client + .getPaintable(uidl.getChildUIDL(0)); + final VPaintableWidget newSecondChildPaintable = client + .getPaintable(uidl.getChildUIDL(1)); + Widget newFirstChild = newFirstChildPaintable.getWidgetForPaintable(); + Widget newSecondChild = newSecondChildPaintable.getWidgetForPaintable(); + + if (getWidgetForPaintable().firstChild != newFirstChild) { + if (getWidgetForPaintable().firstChild != null) { + client.unregisterPaintable(VPaintableMap.get(client) + .getPaintable(getWidgetForPaintable().firstChild)); + } + getWidgetForPaintable().setFirstWidget(newFirstChild); + } + if (getWidgetForPaintable().secondChild != newSecondChild) { + if (getWidgetForPaintable().secondChild != null) { + client.unregisterPaintable(VPaintableMap.get(client) + .getPaintable(getWidgetForPaintable().secondChild)); + } + getWidgetForPaintable().setSecondWidget(newSecondChild); + } + newFirstChildPaintable.updateFromUIDL(uidl.getChildUIDL(0), client); + newSecondChildPaintable.updateFromUIDL(uidl.getChildUIDL(1), client); + + getWidgetForPaintable().renderInformation + .updateSize(getWidgetForPaintable().getElement()); + + // This is needed at least for cases like #3458 to take + // appearing/disappearing scrollbars into account. + client.runDescendentsLayout(getWidgetForPaintable()); + + getWidgetForPaintable().rendering = false; + + } + + @Override + public VAbstractSplitPanel getWidgetForPaintable() { + return (VAbstractSplitPanel) super.getWidgetForPaintable(); + } + + @Override + protected abstract VAbstractSplitPanel createWidget(); + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAccordionPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VAccordionPaintable.java index 3f28818073..6b03300a09 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAccordionPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAccordionPaintable.java @@ -1,68 +1,71 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Iterator;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.ui.VAccordion.StackItem;
-
-public class VAccordionPaintable extends VTabsheetBasePaintable {
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
- getWidgetForPaintable().selectedUIDLItemIndex = -1;
- super.updateFromUIDL(uidl, client);
- /*
- * Render content after all tabs have been created and we know how large
- * the content area is
- */
- if (getWidgetForPaintable().selectedUIDLItemIndex >= 0) {
- StackItem selectedItem = getWidgetForPaintable().getStackItem(
- getWidgetForPaintable().selectedUIDLItemIndex);
- UIDL selectedTabUIDL = getWidgetForPaintable().lazyUpdateMap
- .remove(selectedItem);
- getWidgetForPaintable().open(
- getWidgetForPaintable().selectedUIDLItemIndex);
-
- selectedItem.setContent(selectedTabUIDL);
- } else if (!uidl.getBooleanAttribute("cached")
- && getWidgetForPaintable().openTab != null) {
- getWidgetForPaintable().close(getWidgetForPaintable().openTab);
- }
-
- getWidgetForPaintable().iLayout();
- // finally render possible hidden tabs
- if (getWidgetForPaintable().lazyUpdateMap.size() > 0) {
- for (Iterator iterator = getWidgetForPaintable().lazyUpdateMap
- .keySet().iterator(); iterator.hasNext();) {
- StackItem item = (StackItem) iterator.next();
- item.setContent(getWidgetForPaintable().lazyUpdateMap.get(item));
- }
- getWidgetForPaintable().lazyUpdateMap.clear();
- }
-
- getWidgetForPaintable().renderInformation
- .updateSize(getWidgetForPaintable().getElement());
-
- getWidgetForPaintable().rendering = false;
- }
-
- @Override
- public VAccordion getWidgetForPaintable() {
- return (VAccordion) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VAccordion.class);
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- /* Accordion does not render its children's captions */
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Iterator; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableWidget; +import com.vaadin.terminal.gwt.client.ui.VAccordion.StackItem; + +public class VAccordionPaintable extends VTabsheetBasePaintable { + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + getWidgetForPaintable().selectedUIDLItemIndex = -1; + super.updateFromUIDL(uidl, client); + /* + * Render content after all tabs have been created and we know how large + * the content area is + */ + if (getWidgetForPaintable().selectedUIDLItemIndex >= 0) { + StackItem selectedItem = getWidgetForPaintable().getStackItem( + getWidgetForPaintable().selectedUIDLItemIndex); + UIDL selectedTabUIDL = getWidgetForPaintable().lazyUpdateMap + .remove(selectedItem); + getWidgetForPaintable().open( + getWidgetForPaintable().selectedUIDLItemIndex); + + selectedItem.setContent(selectedTabUIDL); + } else if (!uidl.getBooleanAttribute("cached") + && getWidgetForPaintable().openTab != null) { + getWidgetForPaintable().close(getWidgetForPaintable().openTab); + } + + getWidgetForPaintable().iLayout(); + // finally render possible hidden tabs + if (getWidgetForPaintable().lazyUpdateMap.size() > 0) { + for (Iterator iterator = getWidgetForPaintable().lazyUpdateMap + .keySet().iterator(); iterator.hasNext();) { + StackItem item = (StackItem) iterator.next(); + item.setContent(getWidgetForPaintable().lazyUpdateMap.get(item)); + } + getWidgetForPaintable().lazyUpdateMap.clear(); + } + + getWidgetForPaintable().renderInformation + .updateSize(getWidgetForPaintable().getElement()); + + getWidgetForPaintable().rendering = false; + } + + @Override + public VAccordion getWidgetForPaintable() { + return (VAccordion) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VAccordion.class); + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + /* Accordion does not render its children's captions */ + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAudioPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VAudioPaintable.java index e949d95104..a10c81861b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAudioPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAudioPaintable.java @@ -1,37 +1,40 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Unit;
-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;
-
-public class VAudioPaintable extends VMediaBasePaintable {
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
- super.updateFromUIDL(uidl, client);
- Style style = getWidgetForPaintable().getElement().getStyle();
-
- // Make sure that the controls are not clipped if visible.
- if (shouldShowControls(uidl)
- && (style.getHeight() == null || "".equals(style.getHeight()))) {
- if (BrowserInfo.get().isChrome()) {
- style.setHeight(32, Unit.PX);
- } else {
- style.setHeight(25, Unit.PX);
- }
- }
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VAudio.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Style; +import com.google.gwt.dom.client.Style.Unit; +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; + +public class VAudioPaintable extends VMediaBasePaintable { + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, true)) { + return; + } + super.updateFromUIDL(uidl, client); + Style style = getWidgetForPaintable().getElement().getStyle(); + + // Make sure that the controls are not clipped if visible. + if (shouldShowControls(uidl) + && (style.getHeight() == null || "".equals(style.getHeight()))) { + if (BrowserInfo.get().isChrome()) { + style.setHeight(32, Unit.PX); + } else { + style.setHeight(25, Unit.PX); + } + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VAudio.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java index b318fe0af3..2968e132c6 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCalendarPanel.java @@ -1,1730 +1,1737 @@ -/*
-@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;
-import com.vaadin.terminal.gwt.client.ui.label.VLabel;
-
-@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";
-
- 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 day of current time. Used when moving in the
- * calender with the keyboard.
- *
- * @param date
- * The day number from by Date.getDate()
- */
- private void focusDay(Date day) {
- // Only used when calender body is present
- if (resolution > VDateField.RESOLUTION_MONTH) {
- if (focusedDay != null) {
- focusedDay.removeStyleDependentName(CN_FOCUSED);
- }
-
- if (day != null && focusedDate != null) {
- focusedDate.setTime(day.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(day)) {
- curday.addStyleDependentName(CN_FOCUSED);
- focusedDay = curday;
- focusedRow = i;
- return;
- }
- }
- }
- }
- }
- }
- }
-
- /**
- * Sets the selection hightlight to a given date of current time
- *
- * @param date
- */
- 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, " ");
- }
- }
- } 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("‹");
- prevMonth.setStyleName("v-button-prevmonth");
- prevMonth.setTabIndex(-1);
- nextMonth = new VEventButton();
- nextMonth.setHTML("›");
- 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("«");
- prevYear.setStyleName("v-button-prevyear");
- prevYear.setTabIndex(-1);
- nextYear = new VEventButton();
- nextYear.setHTML("»");
- 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 VEventButton sender = (VEventButton) 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 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);
- }
-
- 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_HOUR) {
- add(new VLabel(delimiter + "00")); // o'clock
- }
- if (getDateTimeService().isTwelveHourClock()) {
- add(new VLabel(" "));
- 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 (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 (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() == 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 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();
- 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.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_AMPM_SELECT.equals(subPart)) {
- return time.ampm.getElement();
- }
- if (subPart.startsWith(SUBPART_DAY)) {
- // can be less than 1 or greater than the number of days in the current month
- // these map to the "off-month" days
- int dayOfMonth = Integer.parseInt(subPart.substring(SUBPART_DAY
- .length()));
- Date date = new Date(displayedMonth.getYear(),
- displayedMonth.getMonth(), dayOfMonth);
- Iterator<Widget> iter = days.iterator();
- while (iter.hasNext()) {
- Widget w = iter.next();
- if (w instanceof Day) {
- Day day = (Day) w;
- if (day.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; +import com.vaadin.terminal.gwt.client.ui.label.VLabel; + +@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, " "); + } + } + } 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("‹"); + prevMonth.setStyleName("v-button-prevmonth"); + prevMonth.setTabIndex(-1); + nextMonth = new VEventButton(); + nextMonth.setHTML("›"); + 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("«"); + prevYear.setStyleName("v-button-prevyear"); + prevYear.setTabIndex(-1); + nextYear = new VEventButton(); + nextYear.setHTML("»"); + 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, ""); + } + } + + // Zero out hours, minutes, seconds, and milliseconds to compare dates + // without time part + final Date tmp = new Date(); + final Date today = new Date(tmp.getYear(), tmp.getMonth(), + tmp.getDate()); + + final Date selectedDate = value == null ? null : new Date( + value.getYear(), value.getMonth(), value.getDate()); + + final int startWeekDay = getDateTimeService().getStartWeekDay( + displayedMonth); + final Date curr = (Date) displayedMonth.clone(); + // Start from the first day of the week that at least partially belongs + // to the current month + curr.setDate(1 - 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(selectedDate)) { + 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() != displayedMonth.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) { + Date now = new Date(); + // focusedDate must have zero hours, mins, secs, millisecs + focusedDate = new Date(now.getYear(), now.getMonth(), now.getDate()); + displayedMonth = new Date(now.getYear(), now.getMonth(), 1); + } + + 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); + } + } + + /** + * Moves the focus forward the given number of days. + */ + private void focusNextDay(int days) { + int oldMonth = focusedDate.getMonth(); + focusedDate.setDate(focusedDate.getDate() + days); + + if (focusedDate.getMonth() == oldMonth) { + // Month did not change, only move the selection + focusDay(focusedDate); + } else { + // If the month changed we need to re-render the calendar + displayedMonth.setMonth(focusedDate.getMonth()); + renderCalendar(); + } + } + + /** + * Moves the focus backward the given number of days. + */ + private void focusPreviousDay(int days) { + focusNextDay(-days); + } + + /** + * 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) { + int currentMonth = focusedDate.getMonth(); + focusedDate.setYear(focusedDate.getYear() - years); + displayedMonth.setYear(displayedMonth.getYear() - years); + /* + * If the focused date was a leap day (Feb 29), the new date becomes Mar + * 1 if the new year is not also a leap year. Set it to Feb 28 instead. + */ + if (focusedDate.getMonth() != currentMonth) { + focusedDate.setDate(0); + } + renderCalendar(); + } + + /** + * Selects the next year + */ + private void focusNextYear(int years) { + int currentMonth = focusedDate.getMonth(); + focusedDate.setYear(focusedDate.getYear() + years); + displayedMonth.setYear(displayedMonth.getYear() + years); + /* + * If the focused date was a leap day (Feb 29), the new date becomes Mar + * 1 if the new year is not also a leap year. Set it to Feb 28 instead. + */ + if (focusedDate.getMonth() != currentMonth) { + focusedDate.setDate(0); + } + 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) { + focusNextDay(1); + return true; + + /* + * Jumps to the previous day + */ + } else if (keycode == getBackwardKey() && !shift) { + focusPreviousDay(1); + return true; + + /* + * Jumps one week forward in the calendar + */ + } else if (keycode == getNextKey() && !shift) { + focusNextDay(7); + return true; + + /* + * Jumps one week back in the calendar + */ + } else if (keycode == getPreviousKey() && !shift) { + focusPreviousDay(7); + 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 = new Date(value.getYear(), value.getMonth(), + value.getDate()); + displayedMonth = new Date(value.getYear(), value.getMonth(), 1); + 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 VEventButton sender = (VEventButton) 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 = new Date(value.getYear(), value.getMonth(), + value.getDate()); + displayedMonth = new Date(value.getYear(), value.getMonth(), 1); + } + + // 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(focusedDate); + selectFocused(); + } + + if (!hasFocus) { + focusDay(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 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); + } + + 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_HOUR) { + add(new VLabel(delimiter + "00")); // o'clock + } + if (getDateTimeService().isTwelveHourClock()) { + add(new VLabel(" ")); + 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 (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 (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() == 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.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_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(); + } + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCheckBox.java b/src/com/vaadin/terminal/gwt/client/ui/VCheckBox.java index d92d7e37ed..320520cb39 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCheckBox.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCheckBox.java @@ -14,7 +14,6 @@ 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.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.EventId; import com.vaadin.terminal.gwt.client.MouseEventDetails; @@ -101,8 +100,4 @@ public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox implements client.updateVariable(id, EventId.BLUR, "", true); } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCheckBoxPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VCheckBoxPaintable.java index 03233c6e27..9fee6a8ba6 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCheckBoxPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCheckBoxPaintable.java @@ -1,96 +1,99 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.EventHelper;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VTooltip;
-
-public class VCheckBoxPaintable extends VAbstractPaintableWidget {
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- // Save details
- getWidgetForPaintable().client = client;
- getWidgetForPaintable().id = uidl.getId();
-
- // Ensure correct implementation
- if (client.updateComponent(this, uidl, false)) {
- return;
- }
-
- getWidgetForPaintable().focusHandlerRegistration = EventHelper
- .updateFocusHandler(this, client,
- getWidgetForPaintable().focusHandlerRegistration);
- getWidgetForPaintable().blurHandlerRegistration = EventHelper
- .updateBlurHandler(this, client,
- getWidgetForPaintable().blurHandlerRegistration);
-
- if (uidl.hasAttribute("error")) {
- if (getWidgetForPaintable().errorIndicatorElement == null) {
- getWidgetForPaintable().errorIndicatorElement = DOM
- .createSpan();
- getWidgetForPaintable().errorIndicatorElement
- .setInnerHTML(" ");
- DOM.setElementProperty(
- getWidgetForPaintable().errorIndicatorElement,
- "className", "v-errorindicator");
- DOM.appendChild(getWidgetForPaintable().getElement(),
- getWidgetForPaintable().errorIndicatorElement);
- DOM.sinkEvents(getWidgetForPaintable().errorIndicatorElement,
- VTooltip.TOOLTIP_EVENTS | Event.ONCLICK);
- } else {
- DOM.setStyleAttribute(
- getWidgetForPaintable().errorIndicatorElement,
- "display", "");
- }
- } else if (getWidgetForPaintable().errorIndicatorElement != null) {
- DOM.setStyleAttribute(
- getWidgetForPaintable().errorIndicatorElement, "display",
- "none");
- }
-
- if (uidl.hasAttribute("readonly")) {
- getWidgetForPaintable().setEnabled(false);
- }
-
- if (uidl.hasAttribute("icon")) {
- if (getWidgetForPaintable().icon == null) {
- getWidgetForPaintable().icon = new Icon(client);
- DOM.insertChild(getWidgetForPaintable().getElement(),
- getWidgetForPaintable().icon.getElement(), 1);
- getWidgetForPaintable().icon
- .sinkEvents(VTooltip.TOOLTIP_EVENTS);
- getWidgetForPaintable().icon.sinkEvents(Event.ONCLICK);
- }
- getWidgetForPaintable().icon
- .setUri(uidl.getStringAttribute("icon"));
- } else if (getWidgetForPaintable().icon != null) {
- // detach icon
- DOM.removeChild(getWidgetForPaintable().getElement(),
- getWidgetForPaintable().icon.getElement());
- getWidgetForPaintable().icon = null;
- }
-
- // Set text
- getWidgetForPaintable().setText(uidl.getStringAttribute("caption"));
- getWidgetForPaintable()
- .setValue(
- uidl.getBooleanVariable(getWidgetForPaintable().VARIABLE_STATE));
- getWidgetForPaintable().immediate = uidl
- .getBooleanAttribute("immediate");
- }
-
- @Override
- public VCheckBox getWidgetForPaintable() {
- return (VCheckBox) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VCheckBox.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.EventHelper; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VTooltip; + +public class VCheckBoxPaintable extends VAbstractPaintableWidget { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Save details + getWidgetForPaintable().client = client; + getWidgetForPaintable().id = uidl.getId(); + + // Ensure correct implementation + if (client.updateComponent(this, uidl, false)) { + return; + } + + getWidgetForPaintable().focusHandlerRegistration = EventHelper + .updateFocusHandler(this, client, + getWidgetForPaintable().focusHandlerRegistration); + getWidgetForPaintable().blurHandlerRegistration = EventHelper + .updateBlurHandler(this, client, + getWidgetForPaintable().blurHandlerRegistration); + + if (uidl.hasAttribute("error")) { + if (getWidgetForPaintable().errorIndicatorElement == null) { + getWidgetForPaintable().errorIndicatorElement = DOM + .createSpan(); + getWidgetForPaintable().errorIndicatorElement + .setInnerHTML(" "); + DOM.setElementProperty( + getWidgetForPaintable().errorIndicatorElement, + "className", "v-errorindicator"); + DOM.appendChild(getWidgetForPaintable().getElement(), + getWidgetForPaintable().errorIndicatorElement); + DOM.sinkEvents(getWidgetForPaintable().errorIndicatorElement, + VTooltip.TOOLTIP_EVENTS | Event.ONCLICK); + } else { + DOM.setStyleAttribute( + getWidgetForPaintable().errorIndicatorElement, + "display", ""); + } + } else if (getWidgetForPaintable().errorIndicatorElement != null) { + DOM.setStyleAttribute( + getWidgetForPaintable().errorIndicatorElement, "display", + "none"); + } + + if (uidl.hasAttribute("readonly")) { + getWidgetForPaintable().setEnabled(false); + } + + if (uidl.hasAttribute("icon")) { + if (getWidgetForPaintable().icon == null) { + getWidgetForPaintable().icon = new Icon(client); + DOM.insertChild(getWidgetForPaintable().getElement(), + getWidgetForPaintable().icon.getElement(), 1); + getWidgetForPaintable().icon + .sinkEvents(VTooltip.TOOLTIP_EVENTS); + getWidgetForPaintable().icon.sinkEvents(Event.ONCLICK); + } + getWidgetForPaintable().icon + .setUri(uidl.getStringAttribute("icon")); + } else if (getWidgetForPaintable().icon != null) { + // detach icon + DOM.removeChild(getWidgetForPaintable().getElement(), + getWidgetForPaintable().icon.getElement()); + getWidgetForPaintable().icon = null; + } + + // Set text + getWidgetForPaintable().setText(uidl.getStringAttribute("caption")); + getWidgetForPaintable() + .setValue( + uidl.getBooleanVariable(getWidgetForPaintable().VARIABLE_STATE)); + getWidgetForPaintable().immediate = uidl + .getBooleanAttribute("immediate"); + } + + @Override + public VCheckBox getWidgetForPaintable() { + return (VCheckBox) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VCheckBox.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCssLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VCssLayout.java index e56d333dad..839b84061c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCssLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCssLayout.java @@ -294,10 +294,6 @@ public class VCssLayout extends SimplePanel implements Container { return cssProperty; } - public Widget getWidgetForPaintable() { - return this; - } - /** * Sets CSS classes for margin and spacing based on the given parameters. * diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCssLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VCssLayoutPaintable.java index d8640e3fe5..4d551fa5e8 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCssLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCssLayoutPaintable.java @@ -1,61 +1,64 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.DomEvent.Type;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.EventId;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VCssLayoutPaintable extends VAbstractPaintableWidgetContainer {
-
- private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
- this, EventId.LAYOUT_CLICK) {
-
- @Override
- protected VPaintableWidget getChildComponent(Element element) {
- return getWidgetForPaintable().panel.getComponent(element);
- }
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- return getWidgetForPaintable().addDomHandler(handler, type);
- }
- };
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
-
- if (client.updateComponent(this, uidl, true)) {
- getWidgetForPaintable().rendering = false;
- return;
- }
- clickEventHandler.handleEventHandlerRegistration(client);
-
- getWidgetForPaintable().setMarginAndSpacingStyles(
- new VMarginInfo(uidl.getIntAttribute("margins")),
- uidl.hasAttribute("spacing"));
- getWidgetForPaintable().panel.updateFromUIDL(uidl, client);
- getWidgetForPaintable().rendering = false;
- }
-
- @Override
- public VCssLayout getWidgetForPaintable() {
- return (VCssLayout) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VCssLayout.class);
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- getWidgetForPaintable().panel.updateCaption(component, uidl);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.DomEvent.Type; +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.EventId; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VCssLayoutPaintable extends VAbstractPaintableWidgetContainer { + + private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( + this, EventId.LAYOUT_CLICK) { + + @Override + protected VPaintableWidget getChildComponent(Element element) { + return getWidgetForPaintable().panel.getComponent(element); + } + + @Override + protected <H extends EventHandler> HandlerRegistration registerHandler( + H handler, Type<H> type) { + return getWidgetForPaintable().addDomHandler(handler, type); + } + }; + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + + if (client.updateComponent(this, uidl, true)) { + getWidgetForPaintable().rendering = false; + return; + } + clickEventHandler.handleEventHandlerRegistration(client); + + getWidgetForPaintable().setMarginAndSpacingStyles( + new VMarginInfo(uidl.getIntAttribute("margins")), + uidl.hasAttribute("spacing")); + getWidgetForPaintable().panel.updateFromUIDL(uidl, client); + getWidgetForPaintable().rendering = false; + } + + @Override + public VCssLayout getWidgetForPaintable() { + return (VCssLayout) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VCssLayout.class); + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + getWidgetForPaintable().panel.updateCaption(component, uidl); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCustomComponent.java b/src/com/vaadin/terminal/gwt/client/ui/VCustomComponent.java index ca18104c86..d8181cf00c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCustomComponent.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCustomComponent.java @@ -111,8 +111,4 @@ public class VCustomComponent extends SimplePanel implements Container { } } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCustomComponentPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VCustomComponentPaintable.java index 3abcd9cd75..585466f4f7 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCustomComponentPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCustomComponentPaintable.java @@ -1,79 +1,82 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableMap;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VCustomComponentPaintable extends
- VAbstractPaintableWidgetContainer {
-
- public void updateFromUIDL(UIDL uidl, final ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
- if (client.updateComponent(this, uidl, true)) {
- getWidgetForPaintable().rendering = false;
- return;
- }
- getWidgetForPaintable().client = client;
-
- final UIDL child = uidl.getChildUIDL(0);
- if (child != null) {
- final VPaintableWidget paintable = client.getPaintable(child);
- Widget widget = paintable.getWidgetForPaintable();
- if (widget != getWidgetForPaintable().getWidget()) {
- if (getWidgetForPaintable().getWidget() != null) {
- client.unregisterPaintable(VPaintableMap.get(client)
- .getPaintable(getWidgetForPaintable().getWidget()));
- getWidgetForPaintable().clear();
- }
- getWidgetForPaintable().setWidget(widget);
- }
- paintable.updateFromUIDL(child, client);
- }
-
- boolean updateDynamicSize = getWidgetForPaintable().updateDynamicSize();
- if (updateDynamicSize) {
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- // FIXME deferred relative size update needed to fix some
- // scrollbar issues in sampler. This must be the wrong way
- // to do it. Might be that some other component is broken.
- client.handleComponentRelativeSize(getWidgetForPaintable());
-
- }
- });
- }
-
- getWidgetForPaintable().renderSpace.setWidth(getWidgetForPaintable()
- .getElement().getOffsetWidth());
- getWidgetForPaintable().renderSpace.setHeight(getWidgetForPaintable()
- .getElement().getOffsetHeight());
-
- /*
- * Needed to update client size if the size of this component has
- * changed and the child uses relative size(s).
- */
- client.runDescendentsLayout(getWidgetForPaintable());
-
- getWidgetForPaintable().rendering = false;
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VCustomComponent.class);
- }
-
- @Override
- public VCustomComponent getWidgetForPaintable() {
- return (VCustomComponent) super.getWidgetForPaintable();
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- // NOP, custom component dont render composition roots caption
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VCustomComponentPaintable extends + VAbstractPaintableWidgetContainer { + + public void updateFromUIDL(UIDL uidl, final ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + if (client.updateComponent(this, uidl, true)) { + getWidgetForPaintable().rendering = false; + return; + } + getWidgetForPaintable().client = client; + + final UIDL child = uidl.getChildUIDL(0); + if (child != null) { + final VPaintableWidget paintable = client.getPaintable(child); + Widget widget = paintable.getWidgetForPaintable(); + if (widget != getWidgetForPaintable().getWidget()) { + if (getWidgetForPaintable().getWidget() != null) { + client.unregisterPaintable(VPaintableMap.get(client) + .getPaintable(getWidgetForPaintable().getWidget())); + getWidgetForPaintable().clear(); + } + getWidgetForPaintable().setWidget(widget); + } + paintable.updateFromUIDL(child, client); + } + + boolean updateDynamicSize = getWidgetForPaintable().updateDynamicSize(); + if (updateDynamicSize) { + Scheduler.get().scheduleDeferred(new Command() { + public void execute() { + // FIXME deferred relative size update needed to fix some + // scrollbar issues in sampler. This must be the wrong way + // to do it. Might be that some other component is broken. + client.handleComponentRelativeSize(getWidgetForPaintable()); + + } + }); + } + + getWidgetForPaintable().renderSpace.setWidth(getWidgetForPaintable() + .getElement().getOffsetWidth()); + getWidgetForPaintable().renderSpace.setHeight(getWidgetForPaintable() + .getElement().getOffsetHeight()); + + /* + * Needed to update client size if the size of this component has + * changed and the child uses relative size(s). + */ + client.runDescendentsLayout(getWidgetForPaintable()); + + getWidgetForPaintable().rendering = false; + } + + @Override + protected Widget createWidget() { + return GWT.create(VCustomComponent.class); + } + + @Override + public VCustomComponent getWidgetForPaintable() { + return (VCustomComponent) super.getWidgetForPaintable(); + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + // NOP, custom component dont render composition roots caption + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCustomLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VCustomLayout.java index 7a5f630587..4aa838b660 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCustomLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCustomLayout.java @@ -590,8 +590,4 @@ public class VCustomLayout extends ComplexPanel implements Container, return larger; } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCustomLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VCustomLayoutPaintable.java index 7997355136..9cf877f446 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCustomLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCustomLayoutPaintable.java @@ -1,87 +1,90 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VCustomLayoutPaintable extends VAbstractPaintableWidgetContainer {
-
- /** Update the layout from UIDL */
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().client = client;
- // ApplicationConnection manages generic component features
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- getWidgetForPaintable().pid = uidl.getId();
- if (!getWidgetForPaintable().hasTemplate()) {
- // Update HTML template only once
- getWidgetForPaintable().initializeHTML(uidl, client);
- }
-
- // Evaluate scripts
- VCustomLayout.eval(getWidgetForPaintable().scripts);
- getWidgetForPaintable().scripts = null;
-
- getWidgetForPaintable().iLayout();
- // TODO Check if this is needed
- client.runDescendentsLayout(getWidgetForPaintable());
-
- Set<Widget> oldWidgets = new HashSet<Widget>();
- oldWidgets.addAll(getWidgetForPaintable().locationToWidget.values());
-
- // For all contained widgets
- for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
- final UIDL uidlForChild = (UIDL) i.next();
- if (uidlForChild.getTag().equals("location")) {
- final String location = uidlForChild.getStringAttribute("name");
- UIDL childUIDL = uidlForChild.getChildUIDL(0);
- final VPaintableWidget childPaintable = client
- .getPaintable(childUIDL);
- Widget childWidget = childPaintable.getWidgetForPaintable();
- try {
- getWidgetForPaintable().setWidget(childWidget, location);
- childPaintable.updateFromUIDL(childUIDL, client);
- } catch (final IllegalArgumentException e) {
- // If no location is found, this component is not visible
- }
- oldWidgets.remove(childWidget);
- }
- }
- for (Iterator<Widget> iterator = oldWidgets.iterator(); iterator
- .hasNext();) {
- Widget oldWidget = iterator.next();
- if (oldWidget.isAttached()) {
- // slot of this widget is emptied, remove it
- getWidgetForPaintable().remove(oldWidget);
- }
- }
-
- getWidgetForPaintable().iLayout();
- // TODO Check if this is needed
- client.runDescendentsLayout(getWidgetForPaintable());
-
- }
-
- @Override
- public VCustomLayout getWidgetForPaintable() {
- return (VCustomLayout) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VCustomLayout.class);
- }
-
- public void updateCaption(VPaintableWidget paintable, UIDL uidl) {
- getWidgetForPaintable().updateCaption(paintable, uidl);
-
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VCustomLayoutPaintable extends VAbstractPaintableWidgetContainer { + + /** Update the layout from UIDL */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().client = client; + // ApplicationConnection manages generic component features + if (client.updateComponent(this, uidl, true)) { + return; + } + + getWidgetForPaintable().pid = uidl.getId(); + if (!getWidgetForPaintable().hasTemplate()) { + // Update HTML template only once + getWidgetForPaintable().initializeHTML(uidl, client); + } + + // Evaluate scripts + VCustomLayout.eval(getWidgetForPaintable().scripts); + getWidgetForPaintable().scripts = null; + + getWidgetForPaintable().iLayout(); + // TODO Check if this is needed + client.runDescendentsLayout(getWidgetForPaintable()); + + Set<Widget> oldWidgets = new HashSet<Widget>(); + oldWidgets.addAll(getWidgetForPaintable().locationToWidget.values()); + + // For all contained widgets + for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) { + final UIDL uidlForChild = (UIDL) i.next(); + if (uidlForChild.getTag().equals("location")) { + final String location = uidlForChild.getStringAttribute("name"); + UIDL childUIDL = uidlForChild.getChildUIDL(0); + final VPaintableWidget childPaintable = client + .getPaintable(childUIDL); + Widget childWidget = childPaintable.getWidgetForPaintable(); + try { + getWidgetForPaintable().setWidget(childWidget, location); + childPaintable.updateFromUIDL(childUIDL, client); + } catch (final IllegalArgumentException e) { + // If no location is found, this component is not visible + } + oldWidgets.remove(childWidget); + } + } + for (Iterator<Widget> iterator = oldWidgets.iterator(); iterator + .hasNext();) { + Widget oldWidget = iterator.next(); + if (oldWidget.isAttached()) { + // slot of this widget is emptied, remove it + getWidgetForPaintable().remove(oldWidget); + } + } + + getWidgetForPaintable().iLayout(); + // TODO Check if this is needed + client.runDescendentsLayout(getWidgetForPaintable()); + + } + + @Override + public VCustomLayout getWidgetForPaintable() { + return (VCustomLayout) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VCustomLayout.class); + } + + public void updateCaption(VPaintableWidget paintable, UIDL uidl) { + getWidgetForPaintable().updateCaption(paintable, uidl); + + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java index 6fb8456258..6bf1d4a3a7 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java @@ -1,87 +1,87 @@ -/*
-@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.DateTimeService;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusOutListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.SubmitListener;
-
-/**
- * A client side implementation for InlineDateField
- */
-public class VDateFieldCalendar extends VDateField {
-
- protected 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;
- }
- });
- }
-
- /**
- * TODO refactor: almost same method as in VPopupCalendar.updateValue
- */
- @SuppressWarnings("deprecation")
- protected 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.DateTimeService; +import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusOutListener; +import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.SubmitListener; + +/** + * A client side implementation for InlineDateField + */ +public class VDateFieldCalendar extends VDateField { + + protected 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; + } + }); + } + + /** + * TODO refactor: almost same method as in VPopupCalendar.updateValue + */ + @SuppressWarnings("deprecation") + protected 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/VDateFieldPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldPaintable.java index 4aaf1c2dd3..a4bbe64a30 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VDateFieldPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldPaintable.java @@ -1,3 +1,6 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ package com.vaadin.terminal.gwt.client.ui; import java.util.Date; diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperPaintable.java index 1deb155001..2d2f0fcad3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperPaintable.java @@ -1,71 +1,74 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.HashMap;
-import java.util.Set;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-
-public class VDragAndDropWrapperPaintable extends VCustomComponentPaintable {
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().client = client;
- super.updateFromUIDL(uidl, client);
- if (!uidl.hasAttribute("cached") && !uidl.hasAttribute("hidden")) {
- UIDL acceptCrit = uidl.getChildByTagName("-ac");
- if (acceptCrit == null) {
- getWidgetForPaintable().dropHandler = null;
- } else {
- if (getWidgetForPaintable().dropHandler == null) {
- getWidgetForPaintable().dropHandler = getWidgetForPaintable().new CustomDropHandler();
- }
- getWidgetForPaintable().dropHandler
- .updateAcceptRules(acceptCrit);
- }
-
- Set<String> variableNames = uidl.getVariableNames();
- for (String fileId : variableNames) {
- if (fileId.startsWith("rec-")) {
- String receiverUrl = uidl.getStringVariable(fileId);
- fileId = fileId.substring(4);
- if (getWidgetForPaintable().fileIdToReceiver == null) {
- getWidgetForPaintable().fileIdToReceiver = new HashMap<String, String>();
- }
- if ("".equals(receiverUrl)) {
- Integer id = Integer.parseInt(fileId);
- int indexOf = getWidgetForPaintable().fileIds
- .indexOf(id);
- if (indexOf != -1) {
- getWidgetForPaintable().files.remove(indexOf);
- getWidgetForPaintable().fileIds.remove(indexOf);
- }
- } else {
- getWidgetForPaintable().fileIdToReceiver.put(fileId,
- receiverUrl);
- }
- }
- }
- getWidgetForPaintable().startNextUpload();
-
- getWidgetForPaintable().dragStartMode = uidl
- .getIntAttribute(VDragAndDropWrapper.DRAG_START_MODE);
- getWidgetForPaintable().initDragStartMode();
- getWidgetForPaintable().html5DataFlavors = uidl
- .getMapAttribute(VDragAndDropWrapper.HTML5_DATA_FLAVORS);
- }
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VDragAndDropWrapper.class);
- }
-
- @Override
- public VDragAndDropWrapper getWidgetForPaintable() {
- return (VDragAndDropWrapper) super.getWidgetForPaintable();
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.HashMap; +import java.util.Set; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; + +public class VDragAndDropWrapperPaintable extends VCustomComponentPaintable { + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().client = client; + super.updateFromUIDL(uidl, client); + if (!uidl.hasAttribute("cached") && !uidl.hasAttribute("hidden")) { + UIDL acceptCrit = uidl.getChildByTagName("-ac"); + if (acceptCrit == null) { + getWidgetForPaintable().dropHandler = null; + } else { + if (getWidgetForPaintable().dropHandler == null) { + getWidgetForPaintable().dropHandler = getWidgetForPaintable().new CustomDropHandler(); + } + getWidgetForPaintable().dropHandler + .updateAcceptRules(acceptCrit); + } + + Set<String> variableNames = uidl.getVariableNames(); + for (String fileId : variableNames) { + if (fileId.startsWith("rec-")) { + String receiverUrl = uidl.getStringVariable(fileId); + fileId = fileId.substring(4); + if (getWidgetForPaintable().fileIdToReceiver == null) { + getWidgetForPaintable().fileIdToReceiver = new HashMap<String, String>(); + } + if ("".equals(receiverUrl)) { + Integer id = Integer.parseInt(fileId); + int indexOf = getWidgetForPaintable().fileIds + .indexOf(id); + if (indexOf != -1) { + getWidgetForPaintable().files.remove(indexOf); + getWidgetForPaintable().fileIds.remove(indexOf); + } + } else { + getWidgetForPaintable().fileIdToReceiver.put(fileId, + receiverUrl); + } + } + } + getWidgetForPaintable().startNextUpload(); + + getWidgetForPaintable().dragStartMode = uidl + .getIntAttribute(VDragAndDropWrapper.DRAG_START_MODE); + getWidgetForPaintable().initDragStartMode(); + getWidgetForPaintable().html5DataFlavors = uidl + .getMapAttribute(VDragAndDropWrapper.HTML5_DATA_FLAVORS); + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VDragAndDropWrapper.class); + } + + @Override + public VDragAndDropWrapper getWidgetForPaintable() { + return (VDragAndDropWrapper) super.getWidgetForPaintable(); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java index 7006a82fd1..b54c3dd943 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java @@ -1003,6 +1003,20 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * The filter to apply to the components */ public void filterOptions(int page, String filter) { + filterOptions(page, filter, true); + } + + /** + * Filters the options at certain page using the given filter + * + * @param page + * The page to filter + * @param filter + * The filter to apply to the options + * @param immediate + * Whether to send the options request immediately + */ + private void filterOptions(int page, String filter, boolean immediate) { if (filter.equals(lastFilter) && currentPage == page) { if (!suggestionPopup.isAttached()) { suggestionPopup.showSuggestions(currentSuggestions, @@ -1022,7 +1036,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, waitingForFilteringResponse = true; client.updateVariable(paintableId, "filter", filter, false); - client.updateVariable(paintableId, "page", page, true); + client.updateVariable(paintableId, "page", page, immediate); lastFilter = filter; currentPage = page; } @@ -1404,7 +1418,12 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, // ask suggestionPopup if it was just closed, we are using GWT // Popup's auto close feature if (!suggestionPopup.isJustClosed()) { - filterOptions(-1, ""); + // If a focus event is not going to be sent, send the options + // request immediately; otherwise queue in the same burst as the + // focus event. Fixes #8321. + boolean immediate = focused + || !client.hasWidgetEventListeners(this, EventId.FOCUS); + filterOptions(-1, "", immediate); popupOpenerClicked = true; lastFilter = ""; } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VForm.java b/src/com/vaadin/terminal/gwt/client/ui/VForm.java index d70d7ed0d8..f3276db008 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VForm.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VForm.java @@ -195,10 +195,6 @@ public class VForm extends ComplexPanel implements Container, KeyDownHandler { shortcutHandler.handleKeyboardEvent(Event.as(event.getNativeEvent())); } - public Widget getWidgetForPaintable() { - return this; - } - @Override protected void add(Widget child, Element container) { // Overridden to allow VFormPaintable to call this. Should be removed diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java index b2357f11e1..6d3072f407 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java @@ -526,8 +526,4 @@ public class VFormLayout extends SimplePanel implements Container { } } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFormLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VFormLayoutPaintable.java index c4590a71c9..3be2a028c5 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFormLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFormLayoutPaintable.java @@ -1,39 +1,42 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VFormLayoutPaintable extends VAbstractPaintableWidgetContainer {
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
-
- getWidgetForPaintable().client = client;
-
- if (client.updateComponent(this, uidl, true)) {
- getWidgetForPaintable().rendering = false;
- return;
- }
-
- getWidgetForPaintable().table.updateFromUIDL(uidl, client);
-
- getWidgetForPaintable().rendering = false;
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- getWidgetForPaintable().table.updateCaption(component, uidl);
- }
-
- @Override
- public VFormLayout getWidgetForPaintable() {
- return (VFormLayout) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VFormLayout.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VFormLayoutPaintable extends VAbstractPaintableWidgetContainer { + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + + getWidgetForPaintable().client = client; + + if (client.updateComponent(this, uidl, true)) { + getWidgetForPaintable().rendering = false; + return; + } + + getWidgetForPaintable().table.updateFromUIDL(uidl, client); + + getWidgetForPaintable().rendering = false; + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + getWidgetForPaintable().table.updateCaption(component, uidl); + } + + @Override + public VFormLayout getWidgetForPaintable() { + return (VFormLayout) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VFormLayout.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFormPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VFormPaintable.java index 5f519c09d4..e2533591ea 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFormPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFormPaintable.java @@ -1,173 +1,176 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableMap;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VFormPaintable extends VAbstractPaintableWidgetContainer {
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
- getWidgetForPaintable().client = client;
- getWidgetForPaintable().id = uidl.getId();
-
- if (client.updateComponent(this, uidl, false)) {
- getWidgetForPaintable().rendering = false;
- return;
- }
-
- boolean legendEmpty = true;
- if (uidl.hasAttribute("caption")) {
- getWidgetForPaintable().caption.setInnerText(uidl
- .getStringAttribute("caption"));
- legendEmpty = false;
- } else {
- getWidgetForPaintable().caption.setInnerText("");
- }
- if (uidl.hasAttribute("icon")) {
- if (getWidgetForPaintable().icon == null) {
- getWidgetForPaintable().icon = new Icon(client);
- getWidgetForPaintable().legend
- .insertFirst(getWidgetForPaintable().icon.getElement());
- }
- getWidgetForPaintable().icon
- .setUri(uidl.getStringAttribute("icon"));
- legendEmpty = false;
- } else {
- if (getWidgetForPaintable().icon != null) {
- getWidgetForPaintable().legend
- .removeChild(getWidgetForPaintable().icon.getElement());
- }
- }
- if (legendEmpty) {
- getWidgetForPaintable().addStyleDependentName("nocaption");
- } else {
- getWidgetForPaintable().removeStyleDependentName("nocaption");
- }
-
- if (uidl.hasAttribute("error")) {
- final UIDL errorUidl = uidl.getErrors();
- getWidgetForPaintable().errorMessage.updateFromUIDL(errorUidl);
- getWidgetForPaintable().errorMessage.setVisible(true);
- } else {
- getWidgetForPaintable().errorMessage.setVisible(false);
- }
-
- if (uidl.hasAttribute("description")) {
- getWidgetForPaintable().desc.setInnerHTML(uidl
- .getStringAttribute("description"));
- if (getWidgetForPaintable().desc.getParentElement() == null) {
- getWidgetForPaintable().fieldSet.insertAfter(
- getWidgetForPaintable().desc,
- getWidgetForPaintable().legend);
- }
- } else {
- getWidgetForPaintable().desc.setInnerHTML("");
- if (getWidgetForPaintable().desc.getParentElement() != null) {
- getWidgetForPaintable().fieldSet
- .removeChild(getWidgetForPaintable().desc);
- }
- }
-
- getWidgetForPaintable().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
- VPaintableWidget newFooter = client.getPaintable(uidl
- .getChildUIDL(1));
- Widget newFooterWidget = newFooter.getWidgetForPaintable();
- if (getWidgetForPaintable().footer == null) {
- getWidgetForPaintable().add(newFooter.getWidgetForPaintable(),
- getWidgetForPaintable().footerContainer);
- getWidgetForPaintable().footer = newFooterWidget;
- } else if (newFooter != getWidgetForPaintable().footer) {
- getWidgetForPaintable().remove(getWidgetForPaintable().footer);
- client.unregisterPaintable(VPaintableMap.get(getConnection())
- .getPaintable(getWidgetForPaintable().footer));
- getWidgetForPaintable().add(newFooter.getWidgetForPaintable(),
- getWidgetForPaintable().footerContainer);
- }
- getWidgetForPaintable().footer = newFooterWidget;
- newFooter.updateFromUIDL(uidl.getChildUIDL(1), client);
- // needed for the main layout to know the space it has available
- getWidgetForPaintable().updateSize();
- } else {
- if (getWidgetForPaintable().footer != null) {
- getWidgetForPaintable().remove(getWidgetForPaintable().footer);
- client.unregisterPaintable(VPaintableMap.get(getConnection())
- .getPaintable(getWidgetForPaintable().footer));
- // needed for the main layout to know the space it has available
- getWidgetForPaintable().updateSize();
- }
- }
-
- final UIDL layoutUidl = uidl.getChildUIDL(0);
- VPaintableWidget newLayout = client.getPaintable(layoutUidl);
- Widget newLayoutWidget = newLayout.getWidgetForPaintable();
- if (getWidgetForPaintable().lo == null) {
- // Layout not rendered before
- getWidgetForPaintable().lo = newLayoutWidget;
- getWidgetForPaintable().add(newLayoutWidget,
- getWidgetForPaintable().fieldContainer);
- } else if (getWidgetForPaintable().lo != newLayoutWidget) {
- // Layout has changed
- client.unregisterPaintable(VPaintableMap.get(getConnection())
- .getPaintable(getWidgetForPaintable().lo));
- getWidgetForPaintable().remove(getWidgetForPaintable().lo);
- getWidgetForPaintable().lo = newLayoutWidget;
- getWidgetForPaintable().add(newLayoutWidget,
- getWidgetForPaintable().fieldContainer);
- }
- newLayout.updateFromUIDL(layoutUidl, client);
-
- // also recalculates size of the footer if undefined size form - see
- // #3710
- getWidgetForPaintable().updateSize();
- client.runDescendentsLayout(getWidgetForPaintable());
-
- // We may have actions attached
- if (uidl.getChildCount() > 1) {
- UIDL childUidl = uidl.getChildByTagName("actions");
- if (childUidl != null) {
- if (getWidgetForPaintable().shortcutHandler == null) {
- getWidgetForPaintable().shortcutHandler = new ShortcutActionHandler(
- getId(), client);
- getWidgetForPaintable().keyDownRegistration = getWidgetForPaintable()
- .addDomHandler(getWidgetForPaintable(),
- KeyDownEvent.getType());
- }
- getWidgetForPaintable().shortcutHandler
- .updateActionMap(childUidl);
- }
- } else if (getWidgetForPaintable().shortcutHandler != null) {
- getWidgetForPaintable().keyDownRegistration.removeHandler();
- getWidgetForPaintable().shortcutHandler = null;
- getWidgetForPaintable().keyDownRegistration = null;
- }
-
- getWidgetForPaintable().rendering = false;
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- // NOP form don't render caption for neither field layout nor footer
- // layout
- }
-
- @Override
- public VForm getWidgetForPaintable() {
- return (VForm) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VForm.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.KeyDownEvent; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VFormPaintable extends VAbstractPaintableWidgetContainer { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + getWidgetForPaintable().client = client; + getWidgetForPaintable().id = uidl.getId(); + + if (client.updateComponent(this, uidl, false)) { + getWidgetForPaintable().rendering = false; + return; + } + + boolean legendEmpty = true; + if (uidl.hasAttribute("caption")) { + getWidgetForPaintable().caption.setInnerText(uidl + .getStringAttribute("caption")); + legendEmpty = false; + } else { + getWidgetForPaintable().caption.setInnerText(""); + } + if (uidl.hasAttribute("icon")) { + if (getWidgetForPaintable().icon == null) { + getWidgetForPaintable().icon = new Icon(client); + getWidgetForPaintable().legend + .insertFirst(getWidgetForPaintable().icon.getElement()); + } + getWidgetForPaintable().icon + .setUri(uidl.getStringAttribute("icon")); + legendEmpty = false; + } else { + if (getWidgetForPaintable().icon != null) { + getWidgetForPaintable().legend + .removeChild(getWidgetForPaintable().icon.getElement()); + } + } + if (legendEmpty) { + getWidgetForPaintable().addStyleDependentName("nocaption"); + } else { + getWidgetForPaintable().removeStyleDependentName("nocaption"); + } + + if (uidl.hasAttribute("error")) { + final UIDL errorUidl = uidl.getErrors(); + getWidgetForPaintable().errorMessage.updateFromUIDL(errorUidl); + getWidgetForPaintable().errorMessage.setVisible(true); + } else { + getWidgetForPaintable().errorMessage.setVisible(false); + } + + if (uidl.hasAttribute("description")) { + getWidgetForPaintable().desc.setInnerHTML(uidl + .getStringAttribute("description")); + if (getWidgetForPaintable().desc.getParentElement() == null) { + getWidgetForPaintable().fieldSet.insertAfter( + getWidgetForPaintable().desc, + getWidgetForPaintable().legend); + } + } else { + getWidgetForPaintable().desc.setInnerHTML(""); + if (getWidgetForPaintable().desc.getParentElement() != null) { + getWidgetForPaintable().fieldSet + .removeChild(getWidgetForPaintable().desc); + } + } + + getWidgetForPaintable().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 + VPaintableWidget newFooter = client.getPaintable(uidl + .getChildUIDL(1)); + Widget newFooterWidget = newFooter.getWidgetForPaintable(); + if (getWidgetForPaintable().footer == null) { + getWidgetForPaintable().add(newFooter.getWidgetForPaintable(), + getWidgetForPaintable().footerContainer); + getWidgetForPaintable().footer = newFooterWidget; + } else if (newFooter != getWidgetForPaintable().footer) { + getWidgetForPaintable().remove(getWidgetForPaintable().footer); + client.unregisterPaintable(VPaintableMap.get(getConnection()) + .getPaintable(getWidgetForPaintable().footer)); + getWidgetForPaintable().add(newFooter.getWidgetForPaintable(), + getWidgetForPaintable().footerContainer); + } + getWidgetForPaintable().footer = newFooterWidget; + newFooter.updateFromUIDL(uidl.getChildUIDL(1), client); + // needed for the main layout to know the space it has available + getWidgetForPaintable().updateSize(); + } else { + if (getWidgetForPaintable().footer != null) { + getWidgetForPaintable().remove(getWidgetForPaintable().footer); + client.unregisterPaintable(VPaintableMap.get(getConnection()) + .getPaintable(getWidgetForPaintable().footer)); + // needed for the main layout to know the space it has available + getWidgetForPaintable().updateSize(); + } + } + + final UIDL layoutUidl = uidl.getChildUIDL(0); + VPaintableWidget newLayout = client.getPaintable(layoutUidl); + Widget newLayoutWidget = newLayout.getWidgetForPaintable(); + if (getWidgetForPaintable().lo == null) { + // Layout not rendered before + getWidgetForPaintable().lo = newLayoutWidget; + getWidgetForPaintable().add(newLayoutWidget, + getWidgetForPaintable().fieldContainer); + } else if (getWidgetForPaintable().lo != newLayoutWidget) { + // Layout has changed + client.unregisterPaintable(VPaintableMap.get(getConnection()) + .getPaintable(getWidgetForPaintable().lo)); + getWidgetForPaintable().remove(getWidgetForPaintable().lo); + getWidgetForPaintable().lo = newLayoutWidget; + getWidgetForPaintable().add(newLayoutWidget, + getWidgetForPaintable().fieldContainer); + } + newLayout.updateFromUIDL(layoutUidl, client); + + // also recalculates size of the footer if undefined size form - see + // #3710 + getWidgetForPaintable().updateSize(); + client.runDescendentsLayout(getWidgetForPaintable()); + + // We may have actions attached + if (uidl.getChildCount() > 1) { + UIDL childUidl = uidl.getChildByTagName("actions"); + if (childUidl != null) { + if (getWidgetForPaintable().shortcutHandler == null) { + getWidgetForPaintable().shortcutHandler = new ShortcutActionHandler( + getId(), client); + getWidgetForPaintable().keyDownRegistration = getWidgetForPaintable() + .addDomHandler(getWidgetForPaintable(), + KeyDownEvent.getType()); + } + getWidgetForPaintable().shortcutHandler + .updateActionMap(childUidl); + } + } else if (getWidgetForPaintable().shortcutHandler != null) { + getWidgetForPaintable().keyDownRegistration.removeHandler(); + getWidgetForPaintable().shortcutHandler = null; + getWidgetForPaintable().keyDownRegistration = null; + } + + getWidgetForPaintable().rendering = false; + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + // NOP form don't render caption for neither field layout nor footer + // layout + } + + @Override + public VForm getWidgetForPaintable() { + return (VForm) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VForm.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java index e6e167f077..5302fa6f67 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java @@ -980,8 +980,4 @@ public class VGridLayout extends SimplePanel implements Container { return Util.getPaintableForElement(client, this, element); } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java index 1ef958183b..8f84f27297 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java @@ -1,193 +1,196 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.DomEvent.Type;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.EventId;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableMap;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.ui.VGridLayout.Cell;
-import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer;
-
-public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer {
- private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
- this, EventId.LAYOUT_CLICK) {
-
- @Override
- protected VPaintableWidget getChildComponent(Element element) {
- return getWidgetForPaintable().getComponent(element);
- }
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- return getWidgetForPaintable().addDomHandler(handler, type);
- }
- };
-
- @SuppressWarnings("unchecked")
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
- getWidgetForPaintable().client = client;
-
- if (client.updateComponent(this, uidl, true)) {
- getWidgetForPaintable().rendering = false;
- return;
- }
- clickEventHandler.handleEventHandlerRegistration(client);
-
- getWidgetForPaintable().canvas.setWidth("0px");
-
- getWidgetForPaintable().handleMargins(uidl);
- getWidgetForPaintable().detectSpacing(uidl);
-
- int cols = uidl.getIntAttribute("w");
- int rows = uidl.getIntAttribute("h");
-
- getWidgetForPaintable().columnWidths = new int[cols];
- getWidgetForPaintable().rowHeights = new int[rows];
-
- if (getWidgetForPaintable().cells == null) {
- getWidgetForPaintable().cells = new Cell[cols][rows];
- } else if (getWidgetForPaintable().cells.length != cols
- || getWidgetForPaintable().cells[0].length != rows) {
- Cell[][] newCells = new Cell[cols][rows];
- for (int i = 0; i < getWidgetForPaintable().cells.length; i++) {
- for (int j = 0; j < getWidgetForPaintable().cells[i].length; j++) {
- if (i < cols && j < rows) {
- newCells[i][j] = getWidgetForPaintable().cells[i][j];
- }
- }
- }
- getWidgetForPaintable().cells = newCells;
- }
-
- getWidgetForPaintable().nonRenderedWidgets = (HashMap<Widget, ChildComponentContainer>) getWidgetForPaintable().widgetToComponentContainer
- .clone();
-
- final int[] alignments = uidl.getIntArrayAttribute("alignments");
- int alignmentIndex = 0;
-
- LinkedList<Cell> pendingCells = new LinkedList<Cell>();
-
- LinkedList<Cell> relativeHeighted = new LinkedList<Cell>();
-
- for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
- final UIDL r = (UIDL) i.next();
- if ("gr".equals(r.getTag())) {
- for (final Iterator<?> j = r.getChildIterator(); j.hasNext();) {
- final UIDL c = (UIDL) j.next();
- if ("gc".equals(c.getTag())) {
- Cell cell = getWidgetForPaintable().getCell(c);
- if (cell.hasContent()) {
- boolean rendered = cell.renderIfNoRelativeWidth();
- cell.alignment = alignments[alignmentIndex++];
- if (!rendered) {
- pendingCells.add(cell);
- }
-
- if (cell.colspan > 1) {
- getWidgetForPaintable().storeColSpannedCell(
- cell);
- } else if (rendered) {
- // strore non-colspanned widths to columnWidth
- // array
- if (getWidgetForPaintable().columnWidths[cell.col] < cell
- .getWidth()) {
- getWidgetForPaintable().columnWidths[cell.col] = cell
- .getWidth();
- }
- }
- if (cell.hasRelativeHeight()) {
- relativeHeighted.add(cell);
- }
- }
- }
- }
- }
- }
-
- getWidgetForPaintable().colExpandRatioArray = uidl
- .getIntArrayAttribute("colExpand");
- getWidgetForPaintable().rowExpandRatioArray = uidl
- .getIntArrayAttribute("rowExpand");
- getWidgetForPaintable().distributeColSpanWidths();
-
- getWidgetForPaintable().minColumnWidths = VGridLayout
- .cloneArray(getWidgetForPaintable().columnWidths);
- getWidgetForPaintable().expandColumns();
-
- getWidgetForPaintable().renderRemainingComponentsWithNoRelativeHeight(
- pendingCells);
-
- getWidgetForPaintable().detectRowHeights();
-
- getWidgetForPaintable().expandRows();
-
- getWidgetForPaintable().renderRemainingComponents(pendingCells);
-
- for (Cell cell : relativeHeighted) {
- // rendering done above so cell.cc should not be null
- Widget widget2 = cell.cc.getWidget();
- client.handleComponentRelativeSize(widget2);
- cell.cc.updateWidgetSize();
- }
-
- getWidgetForPaintable().layoutCells();
-
- // clean non rendered components
- for (Widget w : getWidgetForPaintable().nonRenderedWidgets.keySet()) {
- ChildComponentContainer childComponentContainer = getWidgetForPaintable().widgetToComponentContainer
- .get(w);
- getWidgetForPaintable().widgetToCell.remove(w);
- getWidgetForPaintable().widgetToComponentContainer.remove(w);
- childComponentContainer.removeFromParent();
- VPaintableMap paintableMap = VPaintableMap.get(client);
- paintableMap.unregisterPaintable(paintableMap.getPaintable(w));
- }
- getWidgetForPaintable().nonRenderedWidgets = null;
-
- getWidgetForPaintable().rendering = false;
- getWidgetForPaintable().sizeChangedDuringRendering = false;
-
- }
-
- public void updateCaption(VPaintableWidget paintable, UIDL uidl) {
- Widget widget = paintable.getWidgetForPaintable();
- ChildComponentContainer cc = getWidgetForPaintable().widgetToComponentContainer
- .get(widget);
- if (cc != null) {
- cc.updateCaption(uidl, getConnection());
- }
- if (!getWidgetForPaintable().rendering) {
- // ensure rel size details are updated
- getWidgetForPaintable().widgetToCell.get(widget)
- .updateRelSizeStatus(uidl);
- /*
- * This was a component-only update and the possible size change
- * must be propagated to the layout
- */
- getConnection().captionSizeUpdated(widget);
- }
- }
-
- @Override
- public VGridLayout getWidgetForPaintable() {
- return (VGridLayout) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VGridLayout.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.DomEvent.Type; +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.EventId; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.VPaintableWidget; +import com.vaadin.terminal.gwt.client.ui.VGridLayout.Cell; +import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer; + +public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer { + private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( + this, EventId.LAYOUT_CLICK) { + + @Override + protected VPaintableWidget getChildComponent(Element element) { + return getWidgetForPaintable().getComponent(element); + } + + @Override + protected <H extends EventHandler> HandlerRegistration registerHandler( + H handler, Type<H> type) { + return getWidgetForPaintable().addDomHandler(handler, type); + } + }; + + @SuppressWarnings("unchecked") + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + getWidgetForPaintable().client = client; + + if (client.updateComponent(this, uidl, true)) { + getWidgetForPaintable().rendering = false; + return; + } + clickEventHandler.handleEventHandlerRegistration(client); + + getWidgetForPaintable().canvas.setWidth("0px"); + + getWidgetForPaintable().handleMargins(uidl); + getWidgetForPaintable().detectSpacing(uidl); + + int cols = uidl.getIntAttribute("w"); + int rows = uidl.getIntAttribute("h"); + + getWidgetForPaintable().columnWidths = new int[cols]; + getWidgetForPaintable().rowHeights = new int[rows]; + + if (getWidgetForPaintable().cells == null) { + getWidgetForPaintable().cells = new Cell[cols][rows]; + } else if (getWidgetForPaintable().cells.length != cols + || getWidgetForPaintable().cells[0].length != rows) { + Cell[][] newCells = new Cell[cols][rows]; + for (int i = 0; i < getWidgetForPaintable().cells.length; i++) { + for (int j = 0; j < getWidgetForPaintable().cells[i].length; j++) { + if (i < cols && j < rows) { + newCells[i][j] = getWidgetForPaintable().cells[i][j]; + } + } + } + getWidgetForPaintable().cells = newCells; + } + + getWidgetForPaintable().nonRenderedWidgets = (HashMap<Widget, ChildComponentContainer>) getWidgetForPaintable().widgetToComponentContainer + .clone(); + + final int[] alignments = uidl.getIntArrayAttribute("alignments"); + int alignmentIndex = 0; + + LinkedList<Cell> pendingCells = new LinkedList<Cell>(); + + LinkedList<Cell> relativeHeighted = new LinkedList<Cell>(); + + for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) { + final UIDL r = (UIDL) i.next(); + if ("gr".equals(r.getTag())) { + for (final Iterator<?> j = r.getChildIterator(); j.hasNext();) { + final UIDL c = (UIDL) j.next(); + if ("gc".equals(c.getTag())) { + Cell cell = getWidgetForPaintable().getCell(c); + if (cell.hasContent()) { + boolean rendered = cell.renderIfNoRelativeWidth(); + cell.alignment = alignments[alignmentIndex++]; + if (!rendered) { + pendingCells.add(cell); + } + + if (cell.colspan > 1) { + getWidgetForPaintable().storeColSpannedCell( + cell); + } else if (rendered) { + // strore non-colspanned widths to columnWidth + // array + if (getWidgetForPaintable().columnWidths[cell.col] < cell + .getWidth()) { + getWidgetForPaintable().columnWidths[cell.col] = cell + .getWidth(); + } + } + if (cell.hasRelativeHeight()) { + relativeHeighted.add(cell); + } + } + } + } + } + } + + getWidgetForPaintable().colExpandRatioArray = uidl + .getIntArrayAttribute("colExpand"); + getWidgetForPaintable().rowExpandRatioArray = uidl + .getIntArrayAttribute("rowExpand"); + getWidgetForPaintable().distributeColSpanWidths(); + + getWidgetForPaintable().minColumnWidths = VGridLayout + .cloneArray(getWidgetForPaintable().columnWidths); + getWidgetForPaintable().expandColumns(); + + getWidgetForPaintable().renderRemainingComponentsWithNoRelativeHeight( + pendingCells); + + getWidgetForPaintable().detectRowHeights(); + + getWidgetForPaintable().expandRows(); + + getWidgetForPaintable().renderRemainingComponents(pendingCells); + + for (Cell cell : relativeHeighted) { + // rendering done above so cell.cc should not be null + Widget widget2 = cell.cc.getWidget(); + client.handleComponentRelativeSize(widget2); + cell.cc.updateWidgetSize(); + } + + getWidgetForPaintable().layoutCells(); + + // clean non rendered components + for (Widget w : getWidgetForPaintable().nonRenderedWidgets.keySet()) { + ChildComponentContainer childComponentContainer = getWidgetForPaintable().widgetToComponentContainer + .get(w); + getWidgetForPaintable().widgetToCell.remove(w); + getWidgetForPaintable().widgetToComponentContainer.remove(w); + childComponentContainer.removeFromParent(); + VPaintableMap paintableMap = VPaintableMap.get(client); + paintableMap.unregisterPaintable(paintableMap.getPaintable(w)); + } + getWidgetForPaintable().nonRenderedWidgets = null; + + getWidgetForPaintable().rendering = false; + getWidgetForPaintable().sizeChangedDuringRendering = false; + + } + + public void updateCaption(VPaintableWidget paintable, UIDL uidl) { + Widget widget = paintable.getWidgetForPaintable(); + ChildComponentContainer cc = getWidgetForPaintable().widgetToComponentContainer + .get(widget); + if (cc != null) { + cc.updateCaption(uidl, getConnection()); + } + if (!getWidgetForPaintable().rendering) { + // ensure rel size details are updated + getWidgetForPaintable().widgetToCell.get(widget) + .updateRelSizeStatus(uidl); + /* + * This was a component-only update and the possible size change + * must be propagated to the layout + */ + getConnection().captionSizeUpdated(widget); + } + } + + @Override + public VGridLayout getWidgetForPaintable() { + return (VGridLayout) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VGridLayout.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayoutPaintable.java index b72f5222cc..acc49ece18 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayoutPaintable.java @@ -1,17 +1,20 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-
-public class VHorizontalLayoutPaintable extends VOrderedLayoutPaintable {
-
- @Override
- public VHorizontalLayout getWidgetForPaintable() {
- return (VHorizontalLayout) super.getWidgetForPaintable();
- }
-
- @Override
- protected VHorizontalLayout createWidget() {
- return GWT.create(VHorizontalLayout.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; + +public class VHorizontalLayoutPaintable extends VOrderedLayoutPaintable { + + @Override + public VHorizontalLayout getWidgetForPaintable() { + return (VHorizontalLayout) super.getWidgetForPaintable(); + } + + @Override + protected VHorizontalLayout createWidget() { + return GWT.create(VHorizontalLayout.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VHorizontalSplitPanelPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VHorizontalSplitPanelPaintable.java index 2340ceb0b6..44141107aa 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VHorizontalSplitPanelPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VHorizontalSplitPanelPaintable.java @@ -1,13 +1,16 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-
-public class VHorizontalSplitPanelPaintable extends
- VAbstractSplitPanelPaintable {
-
- @Override
- protected VAbstractSplitPanel createWidget() {
- return GWT.create(VSplitPanelHorizontal.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; + +public class VHorizontalSplitPanelPaintable extends + VAbstractSplitPanelPaintable { + + @Override + protected VAbstractSplitPanel createWidget() { + return GWT.create(VSplitPanelHorizontal.class); + } + +} 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/VMediaBasePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VMediaBasePaintable.java index fc709d56b3..1f6bbe6a0a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VMediaBasePaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VMediaBasePaintable.java @@ -1,109 +1,112 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-
-public abstract class VMediaBasePaintable extends VAbstractPaintableWidget {
-
- public static final String TAG_SOURCE = "src";
-
- public static final String ATTR_PAUSE = "pause";
- public static final String ATTR_PLAY = "play";
- public static final String ATTR_MUTED = "muted";
- public static final String ATTR_CONTROLS = "ctrl";
- public static final String ATTR_AUTOPLAY = "auto";
- public static final String ATTR_RESOURCE = "res";
- public static final String ATTR_RESOURCE_TYPE = "type";
- public static final String ATTR_HTML = "html";
- public static final String ATTR_ALT_TEXT = "alt";
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- getWidgetForPaintable().setControls(shouldShowControls(uidl));
- getWidgetForPaintable().setAutoplay(shouldAutoplay(uidl));
- getWidgetForPaintable().setMuted(isMediaMuted(uidl));
-
- // Add all sources
- for (int ix = 0; ix < uidl.getChildCount(); ix++) {
- UIDL child = uidl.getChildUIDL(ix);
- if (TAG_SOURCE.equals(child.getTag())) {
- getWidgetForPaintable().addSource(getSourceUrl(child),
- getSourceType(child));
- }
- }
- setAltText(uidl);
-
- evalPauseCommand(uidl);
- evalPlayCommand(uidl);
- }
-
- protected boolean shouldShowControls(UIDL uidl) {
- return uidl.getBooleanAttribute(ATTR_CONTROLS);
- }
-
- private boolean shouldAutoplay(UIDL uidl) {
- return uidl.getBooleanAttribute(ATTR_AUTOPLAY);
- }
-
- private boolean isMediaMuted(UIDL uidl) {
- return uidl.getBooleanAttribute(ATTR_MUTED);
- }
-
- private boolean allowHtmlContent(UIDL uidl) {
- return uidl.getBooleanAttribute(ATTR_HTML);
- }
-
- private void evalPlayCommand(UIDL uidl) {
- if (uidl.hasAttribute(ATTR_PLAY)) {
- getWidgetForPaintable().play();
- }
- }
-
- private void evalPauseCommand(UIDL uidl) {
- if (uidl.hasAttribute(ATTR_PAUSE)) {
- getWidgetForPaintable().pause();
- }
- }
-
- @Override
- public VMediaBase getWidgetForPaintable() {
- return (VMediaBase) super.getWidgetForPaintable();
- }
-
- /**
- * @param uidl
- * @return the URL of a resource to be used as a source for the media
- */
- private String getSourceUrl(UIDL uidl) {
- String url = getConnection().translateVaadinUri(
- uidl.getStringAttribute(VMediaBasePaintable.ATTR_RESOURCE));
- if (url == null) {
- return "";
- }
- return url;
- }
-
- /**
- * @param uidl
- * @return the mime type of the media
- */
- private String getSourceType(UIDL uidl) {
- return uidl.getStringAttribute(VMediaBasePaintable.ATTR_RESOURCE_TYPE);
- }
-
- private void setAltText(UIDL uidl) {
- String alt = uidl.getStringAttribute(VMediaBasePaintable.ATTR_ALT_TEXT);
-
- if (alt == null || "".equals(alt)) {
- alt = getWidgetForPaintable().getDefaultAltHtml();
- } else if (!allowHtmlContent(uidl)) {
- alt = Util.escapeHTML(alt);
- }
- getWidgetForPaintable().setAltText(alt);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.Util; + +public abstract class VMediaBasePaintable extends VAbstractPaintableWidget { + + public static final String TAG_SOURCE = "src"; + + public static final String ATTR_PAUSE = "pause"; + public static final String ATTR_PLAY = "play"; + public static final String ATTR_MUTED = "muted"; + public static final String ATTR_CONTROLS = "ctrl"; + public static final String ATTR_AUTOPLAY = "auto"; + public static final String ATTR_RESOURCE = "res"; + public static final String ATTR_RESOURCE_TYPE = "type"; + public static final String ATTR_HTML = "html"; + public static final String ATTR_ALT_TEXT = "alt"; + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, true)) { + return; + } + + getWidgetForPaintable().setControls(shouldShowControls(uidl)); + getWidgetForPaintable().setAutoplay(shouldAutoplay(uidl)); + getWidgetForPaintable().setMuted(isMediaMuted(uidl)); + + // Add all sources + for (int ix = 0; ix < uidl.getChildCount(); ix++) { + UIDL child = uidl.getChildUIDL(ix); + if (TAG_SOURCE.equals(child.getTag())) { + getWidgetForPaintable().addSource(getSourceUrl(child), + getSourceType(child)); + } + } + setAltText(uidl); + + evalPauseCommand(uidl); + evalPlayCommand(uidl); + } + + protected boolean shouldShowControls(UIDL uidl) { + return uidl.getBooleanAttribute(ATTR_CONTROLS); + } + + private boolean shouldAutoplay(UIDL uidl) { + return uidl.getBooleanAttribute(ATTR_AUTOPLAY); + } + + private boolean isMediaMuted(UIDL uidl) { + return uidl.getBooleanAttribute(ATTR_MUTED); + } + + private boolean allowHtmlContent(UIDL uidl) { + return uidl.getBooleanAttribute(ATTR_HTML); + } + + private void evalPlayCommand(UIDL uidl) { + if (uidl.hasAttribute(ATTR_PLAY)) { + getWidgetForPaintable().play(); + } + } + + private void evalPauseCommand(UIDL uidl) { + if (uidl.hasAttribute(ATTR_PAUSE)) { + getWidgetForPaintable().pause(); + } + } + + @Override + public VMediaBase getWidgetForPaintable() { + return (VMediaBase) super.getWidgetForPaintable(); + } + + /** + * @param uidl + * @return the URL of a resource to be used as a source for the media + */ + private String getSourceUrl(UIDL uidl) { + String url = getConnection().translateVaadinUri( + uidl.getStringAttribute(VMediaBasePaintable.ATTR_RESOURCE)); + if (url == null) { + return ""; + } + return url; + } + + /** + * @param uidl + * @return the mime type of the media + */ + private String getSourceType(UIDL uidl) { + return uidl.getStringAttribute(VMediaBasePaintable.ATTR_RESOURCE_TYPE); + } + + private void setAltText(UIDL uidl) { + String alt = uidl.getStringAttribute(VMediaBasePaintable.ATTR_ALT_TEXT); + + if (alt == null || "".equals(alt)) { + alt = getWidgetForPaintable().getDefaultAltHtml(); + } else if (!allowHtmlContent(uidl)) { + alt = Util.escapeHTML(alt); + } + getWidgetForPaintable().setAltText(alt); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java index fabc77bced..ef2a49b9d0 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VMenuBarPaintable.java @@ -1,161 +1,161 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Iterator;
-import java.util.Stack;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.ui.VMenuBar.CustomMenuItem;
-
-public class VMenuBarPaintable extends VAbstractPaintableWidget {
- /**
- * This method must be implemented to update the client-side component from
- * UIDL data received from server.
- *
- * This method is called when the page is loaded for the first time, and
- * every time UI changes in the component are received from the server.
- */
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- // This call should be made first. Ensure correct implementation,
- // and let the containing layout manage caption, etc.
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- getWidgetForPaintable().htmlContentAllowed = uidl
- .hasAttribute(VMenuBar.HTML_CONTENT_ALLOWED);
-
- getWidgetForPaintable().openRootOnHover = uidl
- .getBooleanAttribute(VMenuBar.OPEN_ROOT_MENU_ON_HOWER);
-
- getWidgetForPaintable().enabled = !uidl.getBooleanAttribute("disabled");
-
- // For future connections
- getWidgetForPaintable().client = client;
- getWidgetForPaintable().uidlId = uidl.getId();
-
- // Empty the menu every time it receives new information
- if (!getWidgetForPaintable().getItems().isEmpty()) {
- getWidgetForPaintable().clearItems();
- }
-
- UIDL options = uidl.getChildUIDL(0);
-
- if (uidl.hasAttribute("width")) {
- UIDL moreItemUIDL = options.getChildUIDL(0);
- StringBuffer itemHTML = new StringBuffer();
-
- if (moreItemUIDL.hasAttribute("icon")) {
- itemHTML.append("<img src=\""
- + Util.escapeAttribute(client
- .translateVaadinUri(moreItemUIDL
- .getStringAttribute("icon")))
- + "\" class=\"" + Icon.CLASSNAME + "\" alt=\"\" />");
- }
-
- String moreItemText = moreItemUIDL.getStringAttribute("text");
- if ("".equals(moreItemText)) {
- moreItemText = "►";
- }
- itemHTML.append(moreItemText);
-
- getWidgetForPaintable().moreItem = GWT.create(CustomMenuItem.class);
- getWidgetForPaintable().moreItem.setHTML(itemHTML.toString());
- getWidgetForPaintable().moreItem.setCommand(VMenuBar.emptyCommand);
-
- getWidgetForPaintable().collapsedRootItems = new VMenuBar(true,
- getWidgetForPaintable());
- getWidgetForPaintable().moreItem
- .setSubMenu(getWidgetForPaintable().collapsedRootItems);
- getWidgetForPaintable().moreItem.addStyleName(VMenuBar.CLASSNAME
- + "-more-menuitem");
- }
-
- UIDL uidlItems = uidl.getChildUIDL(1);
- Iterator<Object> itr = uidlItems.getChildIterator();
- Stack<Iterator<Object>> iteratorStack = new Stack<Iterator<Object>>();
- Stack<VMenuBar> menuStack = new Stack<VMenuBar>();
- VMenuBar currentMenu = getWidgetForPaintable();
-
- while (itr.hasNext()) {
- UIDL item = (UIDL) itr.next();
- CustomMenuItem currentItem = null;
-
- final int itemId = item.getIntAttribute("id");
-
- boolean itemHasCommand = item.hasAttribute("command");
- boolean itemIsCheckable = item
- .hasAttribute(VMenuBar.ATTRIBUTE_CHECKED);
-
- String itemHTML = getWidgetForPaintable().buildItemHTML(item);
-
- Command cmd = null;
- if (!item.hasAttribute("separator")) {
- if (itemHasCommand || itemIsCheckable) {
- // Construct a command that fires onMenuClick(int) with the
- // item's id-number
- cmd = new Command() {
- public void execute() {
- getWidgetForPaintable().hostReference
- .onMenuClick(itemId);
- }
- };
- }
- }
-
- currentItem = currentMenu.addItem(itemHTML.toString(), cmd);
- currentItem.updateFromUIDL(item, client);
-
- if (item.getChildCount() > 0) {
- menuStack.push(currentMenu);
- iteratorStack.push(itr);
- itr = item.getChildIterator();
- currentMenu = new VMenuBar(true, currentMenu);
- if (uidl.hasAttribute("style")) {
- for (String style : uidl.getStringAttribute("style").split(
- " ")) {
- currentMenu.addStyleDependentName(style);
- }
- }
- currentItem.setSubMenu(currentMenu);
- }
-
- while (!itr.hasNext() && !iteratorStack.empty()) {
- boolean hasCheckableItem = false;
- for (CustomMenuItem menuItem : currentMenu.getItems()) {
- hasCheckableItem = hasCheckableItem
- || menuItem.isCheckable();
- }
- if (hasCheckableItem) {
- currentMenu.addStyleDependentName("check-column");
- } else {
- currentMenu.removeStyleDependentName("check-column");
- }
-
- itr = iteratorStack.pop();
- currentMenu = menuStack.pop();
- }
- }// while
-
- getWidgetForPaintable().iLayout(false);
-
- }// updateFromUIDL
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VMenuBar.class);
- }
-
- @Override
- public VMenuBar getWidgetForPaintable() {
- return (VMenuBar) super.getWidgetForPaintable();
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Iterator; +import java.util.Stack; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.ui.VMenuBar.CustomMenuItem; + +public class VMenuBarPaintable extends VAbstractPaintableWidget { + /** + * This method must be implemented to update the client-side component from + * UIDL data received from server. + * + * This method is called when the page is loaded for the first time, and + * every time UI changes in the component are received from the server. + */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // This call should be made first. Ensure correct implementation, + // and let the containing layout manage caption, etc. + if (client.updateComponent(this, uidl, true)) { + return; + } + + getWidgetForPaintable().htmlContentAllowed = uidl + .hasAttribute(VMenuBar.HTML_CONTENT_ALLOWED); + + getWidgetForPaintable().openRootOnHover = uidl + .getBooleanAttribute(VMenuBar.OPEN_ROOT_MENU_ON_HOWER); + + getWidgetForPaintable().enabled = !uidl.getBooleanAttribute("disabled"); + + // For future connections + getWidgetForPaintable().client = client; + getWidgetForPaintable().uidlId = uidl.getId(); + + // Empty the menu every time it receives new information + if (!getWidgetForPaintable().getItems().isEmpty()) { + getWidgetForPaintable().clearItems(); + } + + UIDL options = uidl.getChildUIDL(0); + + if (uidl.hasAttribute("width")) { + UIDL moreItemUIDL = options.getChildUIDL(0); + StringBuffer itemHTML = new StringBuffer(); + + if (moreItemUIDL.hasAttribute("icon")) { + itemHTML.append("<img src=\"" + + Util.escapeAttribute(client + .translateVaadinUri(moreItemUIDL + .getStringAttribute("icon"))) + + "\" class=\"" + Icon.CLASSNAME + "\" alt=\"\" />"); + } + + String moreItemText = moreItemUIDL.getStringAttribute("text"); + if ("".equals(moreItemText)) { + moreItemText = "►"; + } + itemHTML.append(moreItemText); + + getWidgetForPaintable().moreItem = GWT.create(CustomMenuItem.class); + getWidgetForPaintable().moreItem.setHTML(itemHTML.toString()); + getWidgetForPaintable().moreItem.setCommand(VMenuBar.emptyCommand); + + getWidgetForPaintable().collapsedRootItems = new VMenuBar(true, + getWidgetForPaintable()); + getWidgetForPaintable().moreItem + .setSubMenu(getWidgetForPaintable().collapsedRootItems); + getWidgetForPaintable().moreItem.addStyleName(VMenuBar.CLASSNAME + + "-more-menuitem"); + } + + UIDL uidlItems = uidl.getChildUIDL(1); + Iterator<Object> itr = uidlItems.getChildIterator(); + Stack<Iterator<Object>> iteratorStack = new Stack<Iterator<Object>>(); + Stack<VMenuBar> menuStack = new Stack<VMenuBar>(); + VMenuBar currentMenu = getWidgetForPaintable(); + + while (itr.hasNext()) { + UIDL item = (UIDL) itr.next(); + CustomMenuItem currentItem = null; + + final int itemId = item.getIntAttribute("id"); + + boolean itemHasCommand = item.hasAttribute("command"); + boolean itemIsCheckable = item + .hasAttribute(VMenuBar.ATTRIBUTE_CHECKED); + + String itemHTML = getWidgetForPaintable().buildItemHTML(item); + + Command cmd = null; + if (!item.hasAttribute("separator")) { + if (itemHasCommand || itemIsCheckable) { + // Construct a command that fires onMenuClick(int) with the + // item's id-number + cmd = new Command() { + public void execute() { + getWidgetForPaintable().hostReference + .onMenuClick(itemId); + } + }; + } + } + + currentItem = currentMenu.addItem(itemHTML.toString(), cmd); + currentItem.updateFromUIDL(item, client); + + if (item.getChildCount() > 0) { + menuStack.push(currentMenu); + iteratorStack.push(itr); + itr = item.getChildIterator(); + currentMenu = new VMenuBar(true, currentMenu); + if (uidl.hasAttribute("style")) { + for (String style : uidl.getStringAttribute("style").split( + " ")) { + currentMenu.addStyleDependentName(style); + } + } + currentItem.setSubMenu(currentMenu); + } + + while (!itr.hasNext() && !iteratorStack.empty()) { + boolean hasCheckableItem = false; + for (CustomMenuItem menuItem : currentMenu.getItems()) { + hasCheckableItem = hasCheckableItem + || menuItem.isCheckable(); + } + if (hasCheckableItem) { + currentMenu.addStyleDependentName("check-column"); + } else { + currentMenu.removeStyleDependentName("check-column"); + } + + itr = iteratorStack.pop(); + currentMenu = menuStack.pop(); + } + }// while + + getWidgetForPaintable().iLayout(false); + + }// updateFromUIDL + + @Override + protected Widget createWidget() { + return GWT.create(VMenuBar.class); + } + + @Override + public VMenuBar getWidgetForPaintable() { + return (VMenuBar) super.getWidgetForPaintable(); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/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/VOrderedLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java index 9f5576dfaf..413eadb314 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java @@ -725,8 +725,4 @@ public class VOrderedLayout extends CellBasedLayout { return Util.getPaintableForElement(client, this, element); } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayoutPaintable.java index 4720e07099..6ab1145798 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayoutPaintable.java @@ -1,254 +1,257 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-import com.google.gwt.event.dom.client.DomEvent.Type;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Element;
-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.RenderInformation.FloatSize;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.ui.layout.CellBasedLayoutPaintable;
-import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer;
-
-public abstract class VOrderedLayoutPaintable extends CellBasedLayoutPaintable {
-
- private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
- this, EventId.LAYOUT_CLICK) {
-
- @Override
- protected VPaintableWidget getChildComponent(Element element) {
- return getWidgetForPaintable().getComponent(element);
- }
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- return getWidgetForPaintable().addDomHandler(handler, type);
- }
- };
-
- public void updateCaption(VPaintableWidget paintable, UIDL uidl) {
- Widget widget = paintable.getWidgetForPaintable();
- ChildComponentContainer componentContainer = getWidgetForPaintable()
- .getComponentContainer(widget);
- componentContainer.updateCaption(uidl, getConnection());
- if (!getWidgetForPaintable().isRendering) {
- /*
- * This was a component-only update and the possible size change
- * must be propagated to the layout
- */
- getConnection().captionSizeUpdated(widget);
- }
- }
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().isRendering = true;
- super.updateFromUIDL(uidl, client);
-
- // Only non-cached, visible UIDL:s can introduce changes
- if (uidl.getBooleanAttribute("cached")
- || uidl.getBooleanAttribute("invisible")) {
- getWidgetForPaintable().isRendering = false;
- return;
- }
-
- clickEventHandler.handleEventHandlerRegistration(client);
-
- // IStopWatch w = new IStopWatch("OrderedLayout.updateFromUIDL");
-
- ArrayList<Widget> uidlWidgets = new ArrayList<Widget>(
- uidl.getChildCount());
- ArrayList<ChildComponentContainer> relativeSizeComponents = new ArrayList<ChildComponentContainer>();
- ArrayList<UIDL> relativeSizeComponentUIDL = new ArrayList<UIDL>();
-
- int pos = 0;
- for (final Iterator<Object> it = uidl.getChildIterator(); it.hasNext();) {
- final UIDL childUIDL = (UIDL) it.next();
- final VPaintableWidget childPaintable = client
- .getPaintable(childUIDL);
- Widget widget = childPaintable.getWidgetForPaintable();
-
- // Create container for component
- ChildComponentContainer childComponentContainer = getWidgetForPaintable()
- .getComponentContainer(widget);
-
- if (childComponentContainer == null) {
- // This is a new component
- childComponentContainer = getWidgetForPaintable()
- .createChildContainer(childPaintable);
- } else {
- /*
- * The widget may be null if the same paintable has been
- * rendered in a different component container while this has
- * been invisible. Ensure the childComponentContainer has the
- * widget attached. See e.g. #5372
- */
- childComponentContainer.setPaintable(childPaintable);
- }
-
- getWidgetForPaintable().addOrMoveChild(childComponentContainer,
- pos++);
-
- /*
- * Components which are to be expanded in the same orientation as
- * the layout are rendered later when it is clear how much space
- * they can use
- */
- if (!Util.isCached(childUIDL)) {
- FloatSize relativeSize = Util.parseRelativeSize(childUIDL);
- childComponentContainer.setRelativeSize(relativeSize);
- }
-
- if (childComponentContainer
- .isComponentRelativeSized(getWidgetForPaintable().orientation)) {
- relativeSizeComponents.add(childComponentContainer);
- relativeSizeComponentUIDL.add(childUIDL);
- } else {
- if (getWidgetForPaintable().isDynamicWidth()) {
- childComponentContainer.renderChild(childUIDL, client, -1);
- } else {
- childComponentContainer
- .renderChild(childUIDL, client,
- getWidgetForPaintable().activeLayoutSize
- .getWidth());
- }
- if (getWidgetForPaintable().sizeHasChangedDuringRendering
- && Util.isCached(childUIDL)) {
- // notify cached relative sized component about size
- // chance
- client.handleComponentRelativeSize(childComponentContainer
- .getWidget());
- }
- }
-
- uidlWidgets.add(widget);
-
- }
-
- // w.mark("Rendering of "
- // + (uidlWidgets.size() - relativeSizeComponents.size())
- // + " absolute size components done");
-
- /*
- * Remove any children after pos. These are the ones that previously
- * were in the layout but have now been removed
- */
- getWidgetForPaintable().removeChildrenAfter(pos);
-
- // w.mark("Old children removed");
-
- /* Fetch alignments and expand ratio from UIDL */
- getWidgetForPaintable().updateAlignmentsAndExpandRatios(uidl,
- uidlWidgets);
- // w.mark("Alignments and expand ratios updated");
-
- /* Fetch widget sizes from rendered components */
- getWidgetForPaintable().updateWidgetSizes();
- // w.mark("Widget sizes updated");
-
- getWidgetForPaintable().recalculateLayout();
- // w.mark("Layout size calculated (" + activeLayoutSize +
- // ") offsetSize: "
- // + getOffsetWidth() + "," + getOffsetHeight());
-
- /* Render relative size components */
- for (int i = 0; i < relativeSizeComponents.size(); i++) {
- ChildComponentContainer childComponentContainer = relativeSizeComponents
- .get(i);
- UIDL childUIDL = relativeSizeComponentUIDL.get(i);
-
- if (getWidgetForPaintable().isDynamicWidth()) {
- childComponentContainer.renderChild(childUIDL, client, -1);
- } else {
- childComponentContainer.renderChild(childUIDL, client,
- getWidgetForPaintable().activeLayoutSize.getWidth());
- }
-
- if (Util.isCached(childUIDL)) {
- /*
- * We must update the size of the relative sized component if
- * the expand ratio or something else in the layout changes
- * which affects the size of a relative sized component
- */
- client.handleComponentRelativeSize(childComponentContainer
- .getWidget());
- }
-
- // childComponentContainer.updateWidgetSize();
- }
-
- // w.mark("Rendering of " + (relativeSizeComponents.size())
- // + " relative size components done");
-
- /* Fetch widget sizes for relative size components */
- for (ChildComponentContainer childComponentContainer : getWidgetForPaintable()
- .getComponentContainers()) {
-
- /* Update widget size from DOM */
- childComponentContainer.updateWidgetSize();
- }
-
- // w.mark("Widget sizes updated");
-
- /*
- * Components with relative size in main direction may affect the layout
- * size in the other direction
- */
- if ((getWidgetForPaintable().isHorizontal() && getWidgetForPaintable()
- .isDynamicHeight())
- || (getWidgetForPaintable().isVertical() && getWidgetForPaintable()
- .isDynamicWidth())) {
- getWidgetForPaintable().layoutSizeMightHaveChanged();
- }
- // w.mark("Layout dimensions updated");
-
- /* Update component spacing */
- getWidgetForPaintable().updateContainerMargins();
-
- /*
- * Update component sizes for components with relative size in non-main
- * direction
- */
- if (getWidgetForPaintable().updateRelativeSizesInNonMainDirection()) {
- // Sizes updated - might affect the other dimension so we need to
- // recheck the widget sizes and recalculate layout dimensions
- getWidgetForPaintable().updateWidgetSizes();
- getWidgetForPaintable().layoutSizeMightHaveChanged();
- }
- getWidgetForPaintable().calculateAlignments();
- // w.mark("recalculateComponentSizesAndAlignments done");
-
- getWidgetForPaintable().setRootSize();
-
- if (BrowserInfo.get().isIE()) {
- /*
- * This should fix the issue with padding not always taken into
- * account for the containers leading to no spacing between
- * elements.
- */
- getWidgetForPaintable().root.getStyle().setProperty("zoom", "1");
- }
-
- // w.mark("runDescendentsLayout done");
- getWidgetForPaintable().isRendering = false;
- getWidgetForPaintable().sizeHasChangedDuringRendering = false;
- }
-
- @Override
- protected abstract VOrderedLayout createWidget();
-
- @Override
- public VOrderedLayout getWidgetForPaintable() {
- return (VOrderedLayout) super.getWidgetForPaintable();
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.ArrayList; +import java.util.Iterator; + +import com.google.gwt.event.dom.client.DomEvent.Type; +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Element; +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.RenderInformation.FloatSize; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VPaintableWidget; +import com.vaadin.terminal.gwt.client.ui.layout.CellBasedLayoutPaintable; +import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer; + +public abstract class VOrderedLayoutPaintable extends CellBasedLayoutPaintable { + + private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( + this, EventId.LAYOUT_CLICK) { + + @Override + protected VPaintableWidget getChildComponent(Element element) { + return getWidgetForPaintable().getComponent(element); + } + + @Override + protected <H extends EventHandler> HandlerRegistration registerHandler( + H handler, Type<H> type) { + return getWidgetForPaintable().addDomHandler(handler, type); + } + }; + + public void updateCaption(VPaintableWidget paintable, UIDL uidl) { + Widget widget = paintable.getWidgetForPaintable(); + ChildComponentContainer componentContainer = getWidgetForPaintable() + .getComponentContainer(widget); + componentContainer.updateCaption(uidl, getConnection()); + if (!getWidgetForPaintable().isRendering) { + /* + * This was a component-only update and the possible size change + * must be propagated to the layout + */ + getConnection().captionSizeUpdated(widget); + } + } + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().isRendering = true; + super.updateFromUIDL(uidl, client); + + // Only non-cached, visible UIDL:s can introduce changes + if (uidl.getBooleanAttribute("cached") + || uidl.getBooleanAttribute("invisible")) { + getWidgetForPaintable().isRendering = false; + return; + } + + clickEventHandler.handleEventHandlerRegistration(client); + + // IStopWatch w = new IStopWatch("OrderedLayout.updateFromUIDL"); + + ArrayList<Widget> uidlWidgets = new ArrayList<Widget>( + uidl.getChildCount()); + ArrayList<ChildComponentContainer> relativeSizeComponents = new ArrayList<ChildComponentContainer>(); + ArrayList<UIDL> relativeSizeComponentUIDL = new ArrayList<UIDL>(); + + int pos = 0; + for (final Iterator<Object> it = uidl.getChildIterator(); it.hasNext();) { + final UIDL childUIDL = (UIDL) it.next(); + final VPaintableWidget childPaintable = client + .getPaintable(childUIDL); + Widget widget = childPaintable.getWidgetForPaintable(); + + // Create container for component + ChildComponentContainer childComponentContainer = getWidgetForPaintable() + .getComponentContainer(widget); + + if (childComponentContainer == null) { + // This is a new component + childComponentContainer = getWidgetForPaintable() + .createChildContainer(childPaintable); + } else { + /* + * The widget may be null if the same paintable has been + * rendered in a different component container while this has + * been invisible. Ensure the childComponentContainer has the + * widget attached. See e.g. #5372 + */ + childComponentContainer.setPaintable(childPaintable); + } + + getWidgetForPaintable().addOrMoveChild(childComponentContainer, + pos++); + + /* + * Components which are to be expanded in the same orientation as + * the layout are rendered later when it is clear how much space + * they can use + */ + if (!Util.isCached(childUIDL)) { + FloatSize relativeSize = Util.parseRelativeSize(childUIDL); + childComponentContainer.setRelativeSize(relativeSize); + } + + if (childComponentContainer + .isComponentRelativeSized(getWidgetForPaintable().orientation)) { + relativeSizeComponents.add(childComponentContainer); + relativeSizeComponentUIDL.add(childUIDL); + } else { + if (getWidgetForPaintable().isDynamicWidth()) { + childComponentContainer.renderChild(childUIDL, client, -1); + } else { + childComponentContainer + .renderChild(childUIDL, client, + getWidgetForPaintable().activeLayoutSize + .getWidth()); + } + if (getWidgetForPaintable().sizeHasChangedDuringRendering + && Util.isCached(childUIDL)) { + // notify cached relative sized component about size + // chance + client.handleComponentRelativeSize(childComponentContainer + .getWidget()); + } + } + + uidlWidgets.add(widget); + + } + + // w.mark("Rendering of " + // + (uidlWidgets.size() - relativeSizeComponents.size()) + // + " absolute size components done"); + + /* + * Remove any children after pos. These are the ones that previously + * were in the layout but have now been removed + */ + getWidgetForPaintable().removeChildrenAfter(pos); + + // w.mark("Old children removed"); + + /* Fetch alignments and expand ratio from UIDL */ + getWidgetForPaintable().updateAlignmentsAndExpandRatios(uidl, + uidlWidgets); + // w.mark("Alignments and expand ratios updated"); + + /* Fetch widget sizes from rendered components */ + getWidgetForPaintable().updateWidgetSizes(); + // w.mark("Widget sizes updated"); + + getWidgetForPaintable().recalculateLayout(); + // w.mark("Layout size calculated (" + activeLayoutSize + + // ") offsetSize: " + // + getOffsetWidth() + "," + getOffsetHeight()); + + /* Render relative size components */ + for (int i = 0; i < relativeSizeComponents.size(); i++) { + ChildComponentContainer childComponentContainer = relativeSizeComponents + .get(i); + UIDL childUIDL = relativeSizeComponentUIDL.get(i); + + if (getWidgetForPaintable().isDynamicWidth()) { + childComponentContainer.renderChild(childUIDL, client, -1); + } else { + childComponentContainer.renderChild(childUIDL, client, + getWidgetForPaintable().activeLayoutSize.getWidth()); + } + + if (Util.isCached(childUIDL)) { + /* + * We must update the size of the relative sized component if + * the expand ratio or something else in the layout changes + * which affects the size of a relative sized component + */ + client.handleComponentRelativeSize(childComponentContainer + .getWidget()); + } + + // childComponentContainer.updateWidgetSize(); + } + + // w.mark("Rendering of " + (relativeSizeComponents.size()) + // + " relative size components done"); + + /* Fetch widget sizes for relative size components */ + for (ChildComponentContainer childComponentContainer : getWidgetForPaintable() + .getComponentContainers()) { + + /* Update widget size from DOM */ + childComponentContainer.updateWidgetSize(); + } + + // w.mark("Widget sizes updated"); + + /* + * Components with relative size in main direction may affect the layout + * size in the other direction + */ + if ((getWidgetForPaintable().isHorizontal() && getWidgetForPaintable() + .isDynamicHeight()) + || (getWidgetForPaintable().isVertical() && getWidgetForPaintable() + .isDynamicWidth())) { + getWidgetForPaintable().layoutSizeMightHaveChanged(); + } + // w.mark("Layout dimensions updated"); + + /* Update component spacing */ + getWidgetForPaintable().updateContainerMargins(); + + /* + * Update component sizes for components with relative size in non-main + * direction + */ + if (getWidgetForPaintable().updateRelativeSizesInNonMainDirection()) { + // Sizes updated - might affect the other dimension so we need to + // recheck the widget sizes and recalculate layout dimensions + getWidgetForPaintable().updateWidgetSizes(); + getWidgetForPaintable().layoutSizeMightHaveChanged(); + } + getWidgetForPaintable().calculateAlignments(); + // w.mark("recalculateComponentSizesAndAlignments done"); + + getWidgetForPaintable().setRootSize(); + + if (BrowserInfo.get().isIE()) { + /* + * This should fix the issue with padding not always taken into + * account for the containers leading to no spacing between + * elements. + */ + getWidgetForPaintable().root.getStyle().setProperty("zoom", "1"); + } + + // w.mark("runDescendentsLayout done"); + getWidgetForPaintable().isRendering = false; + getWidgetForPaintable().sizeHasChangedDuringRendering = false; + } + + @Override + protected abstract VOrderedLayout createWidget(); + + @Override + public VOrderedLayout getWidgetForPaintable() { + return (VOrderedLayout) super.getWidgetForPaintable(); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java index 354a42c4d5..82b362a385 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java @@ -432,8 +432,4 @@ public class VPanel extends SimplePanel implements Container, return shortcutHandler; } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPanelPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VPanelPaintable.java index 198d7f4020..df4554ea5e 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPanelPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPanelPaintable.java @@ -1,175 +1,178 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.DomEvent.Type;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VPanelPaintable extends VAbstractPaintableWidgetContainer {
-
- public static final String CLICK_EVENT_IDENTIFIER = "click";
-
- private ClickEventHandler clickEventHandler = new ClickEventHandler(this,
- CLICK_EVENT_IDENTIFIER) {
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- return getWidgetForPaintable().addDomHandler(handler, type);
- }
- };
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
- if (!uidl.hasAttribute("cached")) {
-
- // Handle caption displaying and style names, prior generics.
- // Affects size
- // calculations
-
- // Restore default stylenames
- getWidgetForPaintable().contentNode.setClassName(VPanel.CLASSNAME
- + "-content");
- getWidgetForPaintable().bottomDecoration
- .setClassName(VPanel.CLASSNAME + "-deco");
- getWidgetForPaintable().captionNode.setClassName(VPanel.CLASSNAME
- + "-caption");
- boolean hasCaption = false;
- if (uidl.hasAttribute("caption")
- && !uidl.getStringAttribute("caption").equals("")) {
- getWidgetForPaintable().setCaption(
- uidl.getStringAttribute("caption"));
- hasCaption = true;
- } else {
- getWidgetForPaintable().setCaption("");
- getWidgetForPaintable().captionNode
- .setClassName(VPanel.CLASSNAME + "-nocaption");
- }
-
- // Add proper stylenames for all elements. This way we can prevent
- // unwanted CSS selector inheritance.
- if (uidl.hasAttribute("style")) {
- final String[] styles = uidl.getStringAttribute("style").split(
- " ");
- final String captionBaseClass = VPanel.CLASSNAME
- + (hasCaption ? "-caption" : "-nocaption");
- final String contentBaseClass = VPanel.CLASSNAME + "-content";
- final String decoBaseClass = VPanel.CLASSNAME + "-deco";
- String captionClass = captionBaseClass;
- String contentClass = contentBaseClass;
- String decoClass = decoBaseClass;
- for (int i = 0; i < styles.length; i++) {
- captionClass += " " + captionBaseClass + "-" + styles[i];
- contentClass += " " + contentBaseClass + "-" + styles[i];
- decoClass += " " + decoBaseClass + "-" + styles[i];
- }
- getWidgetForPaintable().captionNode.setClassName(captionClass);
- getWidgetForPaintable().contentNode.setClassName(contentClass);
- getWidgetForPaintable().bottomDecoration
- .setClassName(decoClass);
-
- }
- }
- // Ensure correct implementation
- if (client.updateComponent(this, uidl, false)) {
- getWidgetForPaintable().rendering = false;
- return;
- }
-
- clickEventHandler.handleEventHandlerRegistration(client);
-
- getWidgetForPaintable().client = client;
- getWidgetForPaintable().id = uidl.getId();
-
- getWidgetForPaintable().setIconUri(uidl, client);
-
- getWidgetForPaintable().handleError(uidl);
-
- // Render content
- final UIDL layoutUidl = uidl.getChildUIDL(0);
- final VPaintableWidget newLayout = client.getPaintable(layoutUidl);
- if (newLayout != getWidgetForPaintable().layout) {
- if (getWidgetForPaintable().layout != null) {
- client.unregisterPaintable(getWidgetForPaintable().layout);
- }
- getWidgetForPaintable()
- .setWidget(newLayout.getWidgetForPaintable());
- getWidgetForPaintable().layout = newLayout;
- }
- getWidgetForPaintable().layout.updateFromUIDL(layoutUidl, client);
-
- // We may have actions attached to this panel
- if (uidl.getChildCount() > 1) {
- final int cnt = uidl.getChildCount();
- for (int i = 1; i < cnt; i++) {
- UIDL childUidl = uidl.getChildUIDL(i);
- if (childUidl.getTag().equals("actions")) {
- if (getWidgetForPaintable().shortcutHandler == null) {
- getWidgetForPaintable().shortcutHandler = new ShortcutActionHandler(
- getId(), client);
- }
- getWidgetForPaintable().shortcutHandler
- .updateActionMap(childUidl);
- }
- }
- }
-
- if (uidl.hasVariable("scrollTop")
- && uidl.getIntVariable("scrollTop") != getWidgetForPaintable().scrollTop) {
- getWidgetForPaintable().scrollTop = uidl
- .getIntVariable("scrollTop");
- getWidgetForPaintable().contentNode
- .setScrollTop(getWidgetForPaintable().scrollTop);
- // re-read the actual scrollTop in case invalid value was set
- // (scrollTop != 0 when no scrollbar exists, other values would be
- // caught by scroll listener), see #3784
- getWidgetForPaintable().scrollTop = getWidgetForPaintable().contentNode
- .getScrollTop();
- }
-
- if (uidl.hasVariable("scrollLeft")
- && uidl.getIntVariable("scrollLeft") != getWidgetForPaintable().scrollLeft) {
- getWidgetForPaintable().scrollLeft = uidl
- .getIntVariable("scrollLeft");
- getWidgetForPaintable().contentNode
- .setScrollLeft(getWidgetForPaintable().scrollLeft);
- // re-read the actual scrollTop in case invalid value was set
- // (scrollTop != 0 when no scrollbar exists, other values would be
- // caught by scroll listener), see #3784
- getWidgetForPaintable().scrollLeft = getWidgetForPaintable().contentNode
- .getScrollLeft();
- }
-
- // Must be run after scrollTop is set as Webkit overflow fix re-sets the
- // scrollTop
- getWidgetForPaintable().runHacks(false);
-
- // And apply tab index
- if (uidl.hasVariable("tabindex")) {
- getWidgetForPaintable().contentNode.setTabIndex(uidl
- .getIntVariable("tabindex"));
- }
-
- getWidgetForPaintable().rendering = false;
-
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- // NOP: layouts caption, errors etc not rendered in Panel
- }
-
- @Override
- public VPanel getWidgetForPaintable() {
- return (VPanel) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VPanel.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.DomEvent.Type; +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VPanelPaintable extends VAbstractPaintableWidgetContainer { + + public static final String CLICK_EVENT_IDENTIFIER = "click"; + + private ClickEventHandler clickEventHandler = new ClickEventHandler(this, + CLICK_EVENT_IDENTIFIER) { + + @Override + protected <H extends EventHandler> HandlerRegistration registerHandler( + H handler, Type<H> type) { + return getWidgetForPaintable().addDomHandler(handler, type); + } + }; + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + if (!uidl.hasAttribute("cached")) { + + // Handle caption displaying and style names, prior generics. + // Affects size + // calculations + + // Restore default stylenames + getWidgetForPaintable().contentNode.setClassName(VPanel.CLASSNAME + + "-content"); + getWidgetForPaintable().bottomDecoration + .setClassName(VPanel.CLASSNAME + "-deco"); + getWidgetForPaintable().captionNode.setClassName(VPanel.CLASSNAME + + "-caption"); + boolean hasCaption = false; + if (uidl.hasAttribute("caption") + && !uidl.getStringAttribute("caption").equals("")) { + getWidgetForPaintable().setCaption( + uidl.getStringAttribute("caption")); + hasCaption = true; + } else { + getWidgetForPaintable().setCaption(""); + getWidgetForPaintable().captionNode + .setClassName(VPanel.CLASSNAME + "-nocaption"); + } + + // Add proper stylenames for all elements. This way we can prevent + // unwanted CSS selector inheritance. + if (uidl.hasAttribute("style")) { + final String[] styles = uidl.getStringAttribute("style").split( + " "); + final String captionBaseClass = VPanel.CLASSNAME + + (hasCaption ? "-caption" : "-nocaption"); + final String contentBaseClass = VPanel.CLASSNAME + "-content"; + final String decoBaseClass = VPanel.CLASSNAME + "-deco"; + String captionClass = captionBaseClass; + String contentClass = contentBaseClass; + String decoClass = decoBaseClass; + for (int i = 0; i < styles.length; i++) { + captionClass += " " + captionBaseClass + "-" + styles[i]; + contentClass += " " + contentBaseClass + "-" + styles[i]; + decoClass += " " + decoBaseClass + "-" + styles[i]; + } + getWidgetForPaintable().captionNode.setClassName(captionClass); + getWidgetForPaintable().contentNode.setClassName(contentClass); + getWidgetForPaintable().bottomDecoration + .setClassName(decoClass); + + } + } + // Ensure correct implementation + if (client.updateComponent(this, uidl, false)) { + getWidgetForPaintable().rendering = false; + return; + } + + clickEventHandler.handleEventHandlerRegistration(client); + + getWidgetForPaintable().client = client; + getWidgetForPaintable().id = uidl.getId(); + + getWidgetForPaintable().setIconUri(uidl, client); + + getWidgetForPaintable().handleError(uidl); + + // Render content + final UIDL layoutUidl = uidl.getChildUIDL(0); + final VPaintableWidget newLayout = client.getPaintable(layoutUidl); + if (newLayout != getWidgetForPaintable().layout) { + if (getWidgetForPaintable().layout != null) { + client.unregisterPaintable(getWidgetForPaintable().layout); + } + getWidgetForPaintable() + .setWidget(newLayout.getWidgetForPaintable()); + getWidgetForPaintable().layout = newLayout; + } + getWidgetForPaintable().layout.updateFromUIDL(layoutUidl, client); + + // We may have actions attached to this panel + if (uidl.getChildCount() > 1) { + final int cnt = uidl.getChildCount(); + for (int i = 1; i < cnt; i++) { + UIDL childUidl = uidl.getChildUIDL(i); + if (childUidl.getTag().equals("actions")) { + if (getWidgetForPaintable().shortcutHandler == null) { + getWidgetForPaintable().shortcutHandler = new ShortcutActionHandler( + getId(), client); + } + getWidgetForPaintable().shortcutHandler + .updateActionMap(childUidl); + } + } + } + + if (uidl.hasVariable("scrollTop") + && uidl.getIntVariable("scrollTop") != getWidgetForPaintable().scrollTop) { + getWidgetForPaintable().scrollTop = uidl + .getIntVariable("scrollTop"); + getWidgetForPaintable().contentNode + .setScrollTop(getWidgetForPaintable().scrollTop); + // re-read the actual scrollTop in case invalid value was set + // (scrollTop != 0 when no scrollbar exists, other values would be + // caught by scroll listener), see #3784 + getWidgetForPaintable().scrollTop = getWidgetForPaintable().contentNode + .getScrollTop(); + } + + if (uidl.hasVariable("scrollLeft") + && uidl.getIntVariable("scrollLeft") != getWidgetForPaintable().scrollLeft) { + getWidgetForPaintable().scrollLeft = uidl + .getIntVariable("scrollLeft"); + getWidgetForPaintable().contentNode + .setScrollLeft(getWidgetForPaintable().scrollLeft); + // re-read the actual scrollTop in case invalid value was set + // (scrollTop != 0 when no scrollbar exists, other values would be + // caught by scroll listener), see #3784 + getWidgetForPaintable().scrollLeft = getWidgetForPaintable().contentNode + .getScrollLeft(); + } + + // Must be run after scrollTop is set as Webkit overflow fix re-sets the + // scrollTop + getWidgetForPaintable().runHacks(false); + + // And apply tab index + if (uidl.hasVariable("tabindex")) { + getWidgetForPaintable().contentNode.setTabIndex(uidl + .getIntVariable("tabindex")); + } + + getWidgetForPaintable().rendering = false; + + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + // NOP: layouts caption, errors etc not rendered in Panel + } + + @Override + public VPanel getWidgetForPaintable() { + return (VPanel) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VPanel.class); + } + +} 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 223e13c8d7..1c0b937e05 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java @@ -1,378 +1,378 @@ -/*
-@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.BrowserInfo;
-import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusOutListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.SubmitListener;
-
-/**
- * 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 Field,
- ClickHandler, CloseHandler<PopupPanel>, SubPartAware {
-
- protected static final String POPUP_PRIMARY_STYLE_NAME = VDateField.CLASSNAME
- + "-popup";
-
- protected final Button calendarToggle;
-
- protected VCalendarPanel calendar;
-
- protected final VOverlay popup;
- private boolean open = false;
- protected 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")
- protected void updateValue(Date newDate) {
- Date currentDate = getCurrentDate();
- if (currentDate == null || newDate.getTime() != currentDate.getTime()) {
- setCurrentDate((Date) newDate.clone());
- getClient().updateVariable(getId(), "year",
- newDate.getYear() + 1900, false);
- if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) {
- getClient().updateVariable(getId(), "month",
- newDate.getMonth() + 1, false);
- if (getCurrentResolution() > RESOLUTION_MONTH) {
- getClient().updateVariable(getId(), "day",
- newDate.getDate(), false);
- if (getCurrentResolution() > RESOLUTION_DAY) {
- getClient().updateVariable(getId(), "hour",
- newDate.getHours(), false);
- if (getCurrentResolution() > RESOLUTION_HOUR) {
- getClient().updateVariable(getId(), "min",
- newDate.getMinutes(), false);
- if (getCurrentResolution() > RESOLUTION_MIN) {
- getClient().updateVariable(getId(), "sec",
- newDate.getSeconds(), false);
- }
- }
- }
- }
- }
- if (isImmediate()) {
- getClient().sendPendingVariableChanges();
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.user.client.ui.UIObject#setStyleName(java.lang.String)
- */
- @Override
- public void setStyleName(String style) {
- // make sure the style is there before size calculation
- super.setStyleName(style + " " + CLASSNAME + "-popupcalendar");
- }
-
- /**
- * Opens the calendar panel popup
- */
- public void openCalendarPanel() {
-
- if (!open && !readonly) {
- open = true;
-
- if (getCurrentDate() != null) {
- calendar.setDate((Date) getCurrentDate().clone());
- } else {
- calendar.setDate(new Date());
- }
-
- // clear previous values
- popup.setWidth("");
- popup.setHeight("");
- popup.setPopupPositionAndShow(new PositionCallback() {
- public void setPosition(int offsetWidth, int offsetHeight) {
- final int w = offsetWidth;
- final int h = offsetHeight;
- final int browserWindowWidth = Window.getClientWidth()
- + Window.getScrollLeft();
- final int browserWindowHeight = Window.getClientHeight()
- + Window.getScrollTop();
- int t = calendarToggle.getAbsoluteTop();
- int l = calendarToggle.getAbsoluteLeft();
-
- // Add a little extra space to the right to avoid
- // problems with IE7 scrollbars and to make it look
- // nicer.
- int extraSpace = 30;
-
- boolean overflowRight = false;
- if (l + +w + extraSpace > browserWindowWidth) {
- overflowRight = true;
- // Part of the popup is outside the browser window
- // (to the right)
- l = browserWindowWidth - w - extraSpace;
- }
-
- if (t + h + calendarToggle.getOffsetHeight() + 30 > browserWindowHeight) {
- // Part of the popup is outside the browser window
- // (below)
- t = browserWindowHeight - h
- - calendarToggle.getOffsetHeight() - 30;
- if (!overflowRight) {
- // Show to the right of the popup button unless we
- // are in the lower right corner of the screen
- l += calendarToggle.getOffsetWidth();
- }
- }
-
- // fix size
- popup.setWidth(w + "px");
- popup.setHeight(h + "px");
-
- popup.setPopupPosition(l,
- t + calendarToggle.getOffsetHeight() + 2);
-
- /*
- * We have to wait a while before focusing since the popup
- * needs to be opened before we can focus
- */
- Timer focusTimer = new Timer() {
- @Override
- public void run() {
- setFocus(true);
- }
- };
-
- focusTimer.schedule(100);
- }
- });
- } else {
- VConsole.error("Cannot reopen popup, it is already open!");
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event
- * .dom.client.ClickEvent)
- */
- public void onClick(ClickEvent event) {
- if (event.getSource() == calendarToggle && isEnabled()) {
- openCalendarPanel();
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt
- * .event.logical.shared.CloseEvent)
- */
- public void onClose(CloseEvent<PopupPanel> event) {
- if (event.getSource() == popup) {
- buildDate();
- if (!BrowserInfo.get().isTouchDevice()) {
- /*
- * Move focus to textbox, unless on touch device (avoids opening
- * virtual keyboard).
- */
- focus();
- }
-
- // TODO resolve what the "Sigh." is all about and document it here
- // Sigh.
- Timer t = new Timer() {
- @Override
- public void run() {
- open = false;
- }
- };
- t.schedule(100);
- }
- }
-
- /**
- * Sets focus to Calendar panel.
- *
- * @param focus
- */
- public void setFocus(boolean focus) {
- calendar.setFocus(focus);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#getFieldExtraWidth()
- */
- @Override
- protected int getFieldExtraWidth() {
- if (fieldExtraWidth < 0) {
- fieldExtraWidth = super.getFieldExtraWidth();
- fieldExtraWidth += calendarToggle.getOffsetWidth();
- }
- return fieldExtraWidth;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#buildDate()
- */
- @Override
- protected void buildDate() {
- // Save previous value
- String previousValue = getText();
- super.buildDate();
-
- // Restore previous value if the input could not be parsed
- if (!parsable) {
- setText(previousValue);
- }
- }
-
- /**
- * Update the text field contents from the date. See {@link #buildDate()}.
- *
- * @param forceValid
- * true to force the text field to be updated, false to only
- * update if the parsable flag is true.
- */
- protected void buildDate(boolean forceValid) {
- if (forceValid) {
- parsable = true;
- }
- buildDate();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.ui.VDateField#onBrowserEvent(com.google
- * .gwt.user.client.Event)
- */
- @Override
- public void onBrowserEvent(com.google.gwt.user.client.Event event) {
- super.onBrowserEvent(event);
- if (DOM.eventGetType(event) == Event.ONKEYDOWN
- && event.getKeyCode() == getOpenCalenderPanelKey()) {
- openCalendarPanel();
- event.preventDefault();
- }
- }
-
- /**
- * Get the key code that opens the calendar panel. By default it is the down
- * key but you can override this to be whatever you like
- *
- * @return
- */
- protected int getOpenCalenderPanelKey() {
- return KeyCodes.KEY_DOWN;
- }
-
- /**
- * Closes the open popup panel
- */
- public void closeCalendarPanel() {
- if (open) {
- popup.hide(true);
- }
- }
-
- private final String CALENDAR_TOGGLE_ID = "popupButton";
-
- @Override
- public Element getSubPartElement(String subPart) {
- if (subPart.equals(CALENDAR_TOGGLE_ID)) {
- return calendarToggle.getElement();
- }
-
- return super.getSubPartElement(subPart);
- }
-
- @Override
- public String getSubPartName(Element subElement) {
- if (calendarToggle.getElement().isOrHasChild(subElement)) {
- return CALENDAR_TOGGLE_ID;
- }
-
- return super.getSubPartName(subElement);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Date; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.DomEvent; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.logical.shared.CloseEvent; +import com.google.gwt.event.logical.shared.CloseHandler; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.PopupPanel; +import com.google.gwt.user.client.ui.PopupPanel.PositionCallback; +import com.vaadin.terminal.gwt.client.BrowserInfo; +import com.vaadin.terminal.gwt.client.VConsole; +import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusOutListener; +import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.SubmitListener; + +/** + * 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 Field, + ClickHandler, CloseHandler<PopupPanel>, SubPartAware { + + protected static final String POPUP_PRIMARY_STYLE_NAME = VDateField.CLASSNAME + + "-popup"; + + protected final Button calendarToggle; + + protected VCalendarPanel calendar; + + protected final VOverlay popup; + private boolean open = false; + protected 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") + protected void updateValue(Date newDate) { + Date currentDate = getCurrentDate(); + if (currentDate == null || newDate.getTime() != currentDate.getTime()) { + setCurrentDate((Date) newDate.clone()); + getClient().updateVariable(getId(), "year", + newDate.getYear() + 1900, false); + if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) { + getClient().updateVariable(getId(), "month", + newDate.getMonth() + 1, false); + if (getCurrentResolution() > RESOLUTION_MONTH) { + getClient().updateVariable(getId(), "day", + newDate.getDate(), false); + if (getCurrentResolution() > RESOLUTION_DAY) { + getClient().updateVariable(getId(), "hour", + newDate.getHours(), false); + if (getCurrentResolution() > RESOLUTION_HOUR) { + getClient().updateVariable(getId(), "min", + newDate.getMinutes(), false); + if (getCurrentResolution() > RESOLUTION_MIN) { + getClient().updateVariable(getId(), "sec", + newDate.getSeconds(), false); + } + } + } + } + } + if (isImmediate()) { + getClient().sendPendingVariableChanges(); + } + } + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.user.client.ui.UIObject#setStyleName(java.lang.String) + */ + @Override + public void setStyleName(String style) { + // make sure the style is there before size calculation + super.setStyleName(style + " " + CLASSNAME + "-popupcalendar"); + } + + /** + * Opens the calendar panel popup + */ + public void openCalendarPanel() { + + if (!open && !readonly) { + open = true; + + if (getCurrentDate() != null) { + calendar.setDate((Date) getCurrentDate().clone()); + } else { + calendar.setDate(new Date()); + } + + // clear previous values + popup.setWidth(""); + popup.setHeight(""); + popup.setPopupPositionAndShow(new PositionCallback() { + public void setPosition(int offsetWidth, int offsetHeight) { + final int w = offsetWidth; + final int h = offsetHeight; + final int browserWindowWidth = Window.getClientWidth() + + Window.getScrollLeft(); + final int browserWindowHeight = Window.getClientHeight() + + Window.getScrollTop(); + int t = calendarToggle.getAbsoluteTop(); + int l = calendarToggle.getAbsoluteLeft(); + + // Add a little extra space to the right to avoid + // problems with IE7 scrollbars and to make it look + // nicer. + int extraSpace = 30; + + boolean overflowRight = false; + if (l + +w + extraSpace > browserWindowWidth) { + overflowRight = true; + // Part of the popup is outside the browser window + // (to the right) + l = browserWindowWidth - w - extraSpace; + } + + if (t + h + calendarToggle.getOffsetHeight() + 30 > browserWindowHeight) { + // Part of the popup is outside the browser window + // (below) + t = browserWindowHeight - h + - calendarToggle.getOffsetHeight() - 30; + if (!overflowRight) { + // Show to the right of the popup button unless we + // are in the lower right corner of the screen + l += calendarToggle.getOffsetWidth(); + } + } + + // fix size + popup.setWidth(w + "px"); + popup.setHeight(h + "px"); + + popup.setPopupPosition(l, + t + calendarToggle.getOffsetHeight() + 2); + + /* + * We have to wait a while before focusing since the popup + * needs to be opened before we can focus + */ + Timer focusTimer = new Timer() { + @Override + public void run() { + setFocus(true); + } + }; + + focusTimer.schedule(100); + } + }); + } else { + VConsole.error("Cannot reopen popup, it is already open!"); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event + * .dom.client.ClickEvent) + */ + public void onClick(ClickEvent event) { + if (event.getSource() == calendarToggle && isEnabled()) { + openCalendarPanel(); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt + * .event.logical.shared.CloseEvent) + */ + public void onClose(CloseEvent<PopupPanel> event) { + if (event.getSource() == popup) { + buildDate(); + if (!BrowserInfo.get().isTouchDevice()) { + /* + * Move focus to textbox, unless on touch device (avoids opening + * virtual keyboard). + */ + focus(); + } + + // TODO resolve what the "Sigh." is all about and document it here + // Sigh. + Timer t = new Timer() { + @Override + public void run() { + open = false; + } + }; + t.schedule(100); + } + } + + /** + * Sets focus to Calendar panel. + * + * @param focus + */ + public void setFocus(boolean focus) { + calendar.setFocus(focus); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#getFieldExtraWidth() + */ + @Override + protected int getFieldExtraWidth() { + if (fieldExtraWidth < 0) { + fieldExtraWidth = super.getFieldExtraWidth(); + fieldExtraWidth += calendarToggle.getOffsetWidth(); + } + return fieldExtraWidth; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#buildDate() + */ + @Override + protected void buildDate() { + // Save previous value + String previousValue = getText(); + super.buildDate(); + + // Restore previous value if the input could not be parsed + if (!parsable) { + setText(previousValue); + } + } + + /** + * Update the text field contents from the date. See {@link #buildDate()}. + * + * @param forceValid + * true to force the text field to be updated, false to only + * update if the parsable flag is true. + */ + protected void buildDate(boolean forceValid) { + if (forceValid) { + parsable = true; + } + buildDate(); + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.terminal.gwt.client.ui.VDateField#onBrowserEvent(com.google + * .gwt.user.client.Event) + */ + @Override + public void onBrowserEvent(com.google.gwt.user.client.Event event) { + super.onBrowserEvent(event); + if (DOM.eventGetType(event) == Event.ONKEYDOWN + && event.getKeyCode() == getOpenCalenderPanelKey()) { + openCalendarPanel(); + event.preventDefault(); + } + } + + /** + * Get the key code that opens the calendar panel. By default it is the down + * key but you can override this to be whatever you like + * + * @return + */ + protected int getOpenCalenderPanelKey() { + return KeyCodes.KEY_DOWN; + } + + /** + * Closes the open popup panel + */ + public void closeCalendarPanel() { + if (open) { + popup.hide(true); + } + } + + private final String CALENDAR_TOGGLE_ID = "popupButton"; + + @Override + public Element getSubPartElement(String subPart) { + if (subPart.equals(CALENDAR_TOGGLE_ID)) { + return calendarToggle.getElement(); + } + + return super.getSubPartElement(subPart); + } + + @Override + public String getSubPartName(Element subElement) { + if (calendarToggle.getElement().isOrHasChild(subElement)) { + return CALENDAR_TOGGLE_ID; + } + + return super.getSubPartName(subElement); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPopupView.java b/src/com/vaadin/terminal/gwt/client/ui/VPopupView.java index 34bf0ca619..b3acc9a9a7 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPopupView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupView.java @@ -424,8 +424,4 @@ public class VPopupView extends HTML implements Container, Iterable<Widget> { }; } - public Widget getWidgetForPaintable() { - return this; - } - }// class VPopupView diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPopupViewPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VPopupViewPaintable.java index 627f925d77..cd8965ffc6 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPopupViewPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupViewPaintable.java @@ -1,104 +1,107 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VCaption;
-import com.vaadin.terminal.gwt.client.VCaptionWrapper;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VPopupViewPaintable extends VAbstractPaintableWidgetContainer {
-
- /**
- *
- *
- * @see com.vaadin.terminal.gwt.client.VPaintableWidget#updateFromUIDL(com.vaadin.terminal.gwt.client.UIDL,
- * com.vaadin.terminal.gwt.client.ApplicationConnection)
- */
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- // This call should be made first. Ensure correct implementation,
- // and don't let the containing layout manage caption.
- if (client.updateComponent(this, uidl, false)) {
- return;
- }
- // These are for future server connections
- getWidgetForPaintable().client = client;
- getWidgetForPaintable().uidlId = uidl.getId();
-
- getWidgetForPaintable().hostPopupVisible = uidl
- .getBooleanVariable("popupVisibility");
-
- getWidgetForPaintable().setHTML(uidl.getStringAttribute("html"));
-
- if (uidl.hasAttribute("hideOnMouseOut")) {
- getWidgetForPaintable().popup.setHideOnMouseOut(uidl
- .getBooleanAttribute("hideOnMouseOut"));
- }
-
- // Render the popup if visible and show it.
- if (getWidgetForPaintable().hostPopupVisible) {
- UIDL popupUIDL = uidl.getChildUIDL(0);
-
- // showPopupOnTop(popup, hostReference);
- getWidgetForPaintable().preparePopup(getWidgetForPaintable().popup);
- getWidgetForPaintable().popup.updateFromUIDL(popupUIDL, client);
- if (uidl.hasAttribute("style")) {
- final String[] styles = uidl.getStringAttribute("style").split(
- " ");
- final StringBuffer styleBuf = new StringBuffer();
- final String primaryName = getWidgetForPaintable().popup
- .getStylePrimaryName();
- styleBuf.append(primaryName);
- for (int i = 0; i < styles.length; i++) {
- styleBuf.append(" ");
- styleBuf.append(primaryName);
- styleBuf.append("-");
- styleBuf.append(styles[i]);
- }
- getWidgetForPaintable().popup.setStyleName(styleBuf.toString());
- } else {
- getWidgetForPaintable().popup
- .setStyleName(getWidgetForPaintable().popup
- .getStylePrimaryName());
- }
- getWidgetForPaintable().showPopup(getWidgetForPaintable().popup);
-
- // The popup shouldn't be visible, try to hide it.
- } else {
- getWidgetForPaintable().popup.hide();
- }
- }// updateFromUIDL
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- if (VCaption.isNeeded(uidl)) {
- if (getWidgetForPaintable().popup.captionWrapper != null) {
- getWidgetForPaintable().popup.captionWrapper
- .updateCaption(uidl);
- } else {
- getWidgetForPaintable().popup.captionWrapper = new VCaptionWrapper(
- component, getConnection());
- getWidgetForPaintable().popup
- .setWidget(getWidgetForPaintable().popup.captionWrapper);
- getWidgetForPaintable().popup.captionWrapper
- .updateCaption(uidl);
- }
- } else {
- if (getWidgetForPaintable().popup.captionWrapper != null) {
- getWidgetForPaintable().popup
- .setWidget(getWidgetForPaintable().popup.popupComponentWidget);
- }
- }
- }
-
- @Override
- public VPopupView getWidgetForPaintable() {
- return (VPopupView) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VPopupView.class);
- }
-
-}
+/* + @VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VCaption; +import com.vaadin.terminal.gwt.client.VCaptionWrapper; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VPopupViewPaintable extends VAbstractPaintableWidgetContainer { + + /** + * + * + * @see com.vaadin.terminal.gwt.client.VPaintableWidget#updateFromUIDL(com.vaadin.terminal.gwt.client.UIDL, + * com.vaadin.terminal.gwt.client.ApplicationConnection) + */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // This call should be made first. Ensure correct implementation, + // and don't let the containing layout manage caption. + if (client.updateComponent(this, uidl, false)) { + return; + } + // These are for future server connections + getWidgetForPaintable().client = client; + getWidgetForPaintable().uidlId = uidl.getId(); + + getWidgetForPaintable().hostPopupVisible = uidl + .getBooleanVariable("popupVisibility"); + + getWidgetForPaintable().setHTML(uidl.getStringAttribute("html")); + + if (uidl.hasAttribute("hideOnMouseOut")) { + getWidgetForPaintable().popup.setHideOnMouseOut(uidl + .getBooleanAttribute("hideOnMouseOut")); + } + + // Render the popup if visible and show it. + if (getWidgetForPaintable().hostPopupVisible) { + UIDL popupUIDL = uidl.getChildUIDL(0); + + // showPopupOnTop(popup, hostReference); + getWidgetForPaintable().preparePopup(getWidgetForPaintable().popup); + getWidgetForPaintable().popup.updateFromUIDL(popupUIDL, client); + if (uidl.hasAttribute("style")) { + final String[] styles = uidl.getStringAttribute("style").split( + " "); + final StringBuffer styleBuf = new StringBuffer(); + final String primaryName = getWidgetForPaintable().popup + .getStylePrimaryName(); + styleBuf.append(primaryName); + for (int i = 0; i < styles.length; i++) { + styleBuf.append(" "); + styleBuf.append(primaryName); + styleBuf.append("-"); + styleBuf.append(styles[i]); + } + getWidgetForPaintable().popup.setStyleName(styleBuf.toString()); + } else { + getWidgetForPaintable().popup + .setStyleName(getWidgetForPaintable().popup + .getStylePrimaryName()); + } + getWidgetForPaintable().showPopup(getWidgetForPaintable().popup); + + // The popup shouldn't be visible, try to hide it. + } else { + getWidgetForPaintable().popup.hide(); + } + }// updateFromUIDL + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + if (VCaption.isNeeded(uidl)) { + if (getWidgetForPaintable().popup.captionWrapper != null) { + getWidgetForPaintable().popup.captionWrapper + .updateCaption(uidl); + } else { + getWidgetForPaintable().popup.captionWrapper = new VCaptionWrapper( + component, getConnection()); + getWidgetForPaintable().popup + .setWidget(getWidgetForPaintable().popup.captionWrapper); + getWidgetForPaintable().popup.captionWrapper + .updateCaption(uidl); + } + } else { + if (getWidgetForPaintable().popup.captionWrapper != null) { + getWidgetForPaintable().popup + .setWidget(getWidgetForPaintable().popup.popupComponentWidget); + } + } + } + + @Override + public VPopupView getWidgetForPaintable() { + return (VPopupView) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VPopupView.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index de68ae96a4..b84fc1312f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -106,7 +106,7 @@ import com.vaadin.terminal.gwt.client.ui.label.VLabel; */ public class VScrollTable extends FlowPanel implements HasWidgets, ScrollHandler, VHasDropHandler, FocusHandler, BlurHandler, Focusable, - ActionOwner { + ActionOwner, Container { public enum SelectMode { NONE(0), SINGLE(1), MULTI(2); @@ -2150,7 +2150,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, DOM.appendChild(td, captionContainer); - DOM.sinkEvents(td, Event.MOUSEEVENTS | Event.TOUCHEVENTS); + DOM.sinkEvents(td, Event.MOUSEEVENTS | Event.ONDBLCLICK + | Event.ONCONTEXTMENU | Event.TOUCHEVENTS); setElement(td); @@ -2267,8 +2268,18 @@ public class VScrollTable extends FlowPanel implements HasWidgets, scrollBodyPanel.setFocus(true); } handleCaptionEvent(event); - event.stopPropagation(); - event.preventDefault(); + boolean stopPropagation = true; + if (event.getTypeInt() == Event.ONCONTEXTMENU + && !client.hasWidgetEventListeners( + VScrollTable.this, HEADER_CLICK_EVENT_ID)) { + // Prevent showing the browser's context menu only when + // there is a header click listener. + stopPropagation = false; + } + if (stopPropagation) { + event.stopPropagation(); + event.preventDefault(); + } } } } @@ -2325,7 +2336,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, switch (DOM.eventGetType(event)) { case Event.ONTOUCHSTART: case Event.ONMOUSEDOWN: - if (columnReordering) { + if (columnReordering + && Util.isTouchEventOrLeftMouseButton(event)) { if (event.getTypeInt() == Event.ONTOUCHSTART) { /* * prevent using this event in e.g. scrolling @@ -2344,7 +2356,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, case Event.ONMOUSEUP: case Event.ONTOUCHEND: case Event.ONTOUCHCANCEL: - if (columnReordering) { + if (columnReordering + && Util.isTouchEventOrLeftMouseButton(event)) { dragging = false; DOM.releaseCapture(getElement()); if (moved) { @@ -2371,7 +2384,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (!moved) { // mouse event was a click to header -> sort column - if (sortable) { + if (sortable && Util.isTouchEventOrLeftMouseButton(event)) { if (sortColumn.equals(cid)) { // just toggle order client.updateVariable(paintableId, "sortascending", @@ -2404,9 +2417,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, break; } break; + case Event.ONDBLCLICK: + fireHeaderClickedEvent(event); + break; case Event.ONTOUCHMOVE: case Event.ONMOUSEMOVE: - if (dragging) { + if (dragging && Util.isTouchEventOrLeftMouseButton(event)) { if (event.getTypeInt() == Event.ONTOUCHMOVE) { /* * prevent using this event in e.g. scrolling @@ -2452,6 +2468,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private void onResizeEvent(Event event) { switch (DOM.eventGetType(event)) { case Event.ONMOUSEDOWN: + if (!Util.isTouchEventOrLeftMouseButton(event)) { + return; + } isResizing = true; DOM.setCapture(getElement()); dragStartX = DOM.eventGetClientX(event); @@ -2460,6 +2479,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets, DOM.eventPreventDefault(event); break; case Event.ONMOUSEUP: + if (!Util.isTouchEventOrLeftMouseButton(event)) { + return; + } isResizing = false; DOM.releaseCapture(getElement()); tHead.disableAutoColumnWidthCalculation(this); @@ -2474,6 +2496,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets, fireColumnResizeEvent(cid, originalWidth, getColWidth(cid)); break; case Event.ONMOUSEMOVE: + if (!Util.isTouchEventOrLeftMouseButton(event)) { + return; + } if (isResizing) { final int deltaX = DOM.eventGetClientX(event) - dragStartX; if (deltaX == 0) { @@ -3133,7 +3158,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, DOM.appendChild(td, captionContainer); - DOM.sinkEvents(td, Event.MOUSEEVENTS); + DOM.sinkEvents(td, Event.MOUSEEVENTS | Event.ONDBLCLICK + | Event.ONCONTEXTMENU); setElement(td); } @@ -3318,8 +3344,18 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (DOM.eventGetType(event) == Event.ONMOUSEUP) { scrollBodyPanel.setFocus(true); } - event.stopPropagation(); - event.preventDefault(); + boolean stopPropagation = true; + if (event.getTypeInt() == Event.ONCONTEXTMENU + && !client.hasWidgetEventListeners(VScrollTable.this, + FOOTER_CLICK_EVENT_ID)) { + // Show browser context menu if a footer click listener is + // not present + stopPropagation = false; + } + if (stopPropagation) { + event.stopPropagation(); + event.preventDefault(); + } } } @@ -3330,7 +3366,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, * The event to handle */ protected void handleCaptionEvent(Event event) { - if (DOM.eventGetType(event) == Event.ONMOUSEUP) { + if (event.getTypeInt() == Event.ONMOUSEUP + || event.getTypeInt() == Event.ONDBLCLICK) { fireFooterClickedEvent(event); } } @@ -4310,8 +4347,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } } - public class VScrollTableRow extends Panel implements ActionOwner, - Container { + public class VScrollTableRow extends Panel implements ActionOwner { private static final int TOUCHSCROLL_TIMEOUT = 70; private static final int DRAGMODE_MULTIROW = 2; @@ -4540,6 +4576,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, .get(client).getPaintable(uidl.getId()); paintable.updateFromUIDL(uidl, client); } + pendingComponentPaints.clear(); } } @@ -5267,29 +5304,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return paintableId; } - public RenderSpace getAllocatedSpace(Widget child) { - int w = 0; - int i = getColIndexOf(child); - HeaderCell headerCell = tHead.getHeaderCell(i); - if (headerCell != null) { - if (initializedAndAttached) { - w = headerCell.getWidth(); - } else { - // header offset width is not absolutely correct value, - // but a best guess (expecting similar content in all - // columns -> - // if one component is relative width so are others) - w = headerCell.getOffsetWidth() - getCellExtraWidth(); - } - } - return new RenderSpace(w, 0) { - @Override - public int getHeight() { - return (int) getRowHeight(); - } - }; - } - private int getColIndexOf(Widget child) { com.google.gwt.dom.client.Element widgetCell = child .getElement().getParentElement().getParentElement(); @@ -5319,16 +5333,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } - public boolean requestLayout(Set<Widget> children) { - // row size should never change and system wouldn't event - // survive as this is a kind of fake paitable - return true; - } - - public void updateCaption(VPaintableWidget component, UIDL uidl) { - // NOP, not rendered - } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { // Should never be called, // Component container interface faked here to get layouts @@ -6694,4 +6698,45 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return this; } + public void replaceChildComponent(Widget oldComponent, Widget newComponent) { + VScrollTableRow row = (VScrollTableRow) oldComponent.getParent(); + row.replaceChildComponent(oldComponent, newComponent); + + } + + public boolean hasChildComponent(Widget child) { + VScrollTableRow row = (VScrollTableRow) child.getParent(); + return row.hasChildComponent(child); + } + + public boolean requestLayout(Set<Widget> children) { + // row size should never change + return true; + } + + public RenderSpace getAllocatedSpace(Widget child) { + // Called by widgets attached to a row + VScrollTableRow row = (VScrollTableRow) child.getParent(); + int w = 0; + int i = row.getColIndexOf(child); + HeaderCell headerCell = tHead.getHeaderCell(i); + if (headerCell != null) { + if (initializedAndAttached) { + w = headerCell.getWidth(); + } else { + // header offset width is not absolutely correct value, + // but a best guess (expecting similar content in all + // columns -> + // if one component is relative width so are others) + w = headerCell.getOffsetWidth() + - scrollBody.getCellExtraWidth(); + } + } + return new RenderSpace(w, 0) { + @Override + public int getHeight() { + return (int) scrollBody.getRowHeight(); + } + }; + } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java index fa7cc3d4ec..058b8f15b3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTablePaintable.java @@ -1,254 +1,260 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.dom.client.Style.Position;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-
-public class VScrollTablePaintable extends VAbstractPaintableWidget {
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
- * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
- */
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
-
- if (uidl.hasAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST)) {
- getWidgetForPaintable().serverCacheFirst = uidl
- .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST);
- getWidgetForPaintable().serverCacheLast = uidl
- .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_LAST);
- } else {
- getWidgetForPaintable().serverCacheFirst = -1;
- getWidgetForPaintable().serverCacheLast = -1;
- }
- /*
- * We need to do this before updateComponent since updateComponent calls
- * this.setHeight() which will calculate a new body height depending on
- * the space available.
- */
- if (uidl.hasAttribute("colfooters")) {
- getWidgetForPaintable().showColFooters = uidl
- .getBooleanAttribute("colfooters");
- }
-
- getWidgetForPaintable().tFoot
- .setVisible(getWidgetForPaintable().showColFooters);
-
- if (client.updateComponent(this, uidl, true)) {
- getWidgetForPaintable().rendering = false;
- return;
- }
-
- getWidgetForPaintable().enabled = !uidl.hasAttribute("disabled");
-
- if (BrowserInfo.get().isIE8() && !getWidgetForPaintable().enabled) {
- /*
- * The disabled shim will not cover the table body if it is relative
- * in IE8. See #7324
- */
- getWidgetForPaintable().scrollBodyPanel.getElement().getStyle()
- .setPosition(Position.STATIC);
- } else if (BrowserInfo.get().isIE8()) {
- getWidgetForPaintable().scrollBodyPanel.getElement().getStyle()
- .setPosition(Position.RELATIVE);
- }
-
- getWidgetForPaintable().client = client;
- getWidgetForPaintable().paintableId = uidl.getStringAttribute("id");
- getWidgetForPaintable().immediate = uidl
- .getBooleanAttribute("immediate");
-
- int previousTotalRows = getWidgetForPaintable().totalRows;
- getWidgetForPaintable().updateTotalRows(uidl);
- boolean totalRowsChanged = (getWidgetForPaintable().totalRows != previousTotalRows);
-
- getWidgetForPaintable().updateDragMode(uidl);
-
- getWidgetForPaintable().updateSelectionProperties(uidl);
-
- if (uidl.hasAttribute("alb")) {
- getWidgetForPaintable().bodyActionKeys = uidl
- .getStringArrayAttribute("alb");
- } else {
- // Need to clear the actions if the action handlers have been
- // removed
- getWidgetForPaintable().bodyActionKeys = null;
- }
-
- getWidgetForPaintable().setCacheRateFromUIDL(uidl);
-
- getWidgetForPaintable().recalcWidths = uidl
- .hasAttribute("recalcWidths");
- if (getWidgetForPaintable().recalcWidths) {
- getWidgetForPaintable().tHead.clear();
- getWidgetForPaintable().tFoot.clear();
- }
-
- getWidgetForPaintable().updatePageLength(uidl);
-
- getWidgetForPaintable().updateFirstVisibleAndScrollIfNeeded(uidl);
-
- getWidgetForPaintable().showRowHeaders = uidl
- .getBooleanAttribute("rowheaders");
- getWidgetForPaintable().showColHeaders = uidl
- .getBooleanAttribute("colheaders");
-
- getWidgetForPaintable().updateSortingProperties(uidl);
-
- boolean keyboardSelectionOverRowFetchInProgress = getWidgetForPaintable()
- .selectSelectedRows(uidl);
-
- getWidgetForPaintable().updateActionMap(uidl);
-
- getWidgetForPaintable().updateColumnProperties(uidl);
-
- UIDL ac = uidl.getChildByTagName("-ac");
- if (ac == null) {
- if (getWidgetForPaintable().dropHandler != null) {
- // remove dropHandler if not present anymore
- getWidgetForPaintable().dropHandler = null;
- }
- } else {
- if (getWidgetForPaintable().dropHandler == null) {
- getWidgetForPaintable().dropHandler = getWidgetForPaintable().new VScrollTableDropHandler();
- }
- getWidgetForPaintable().dropHandler.updateAcceptRules(ac);
- }
-
- UIDL partialRowAdditions = uidl.getChildByTagName("prows");
- UIDL partialRowUpdates = uidl.getChildByTagName("urows");
- if (partialRowUpdates != null || partialRowAdditions != null) {
- // we may have pending cache row fetch, cancel it. See #2136
- getWidgetForPaintable().rowRequestHandler.cancel();
-
- getWidgetForPaintable().updateRowsInBody(partialRowUpdates);
- getWidgetForPaintable().addAndRemoveRows(partialRowAdditions);
- } else {
- UIDL rowData = uidl.getChildByTagName("rows");
- if (rowData != null) {
- // we may have pending cache row fetch, cancel it. See #2136
- getWidgetForPaintable().rowRequestHandler.cancel();
-
- if (!getWidgetForPaintable().recalcWidths
- && getWidgetForPaintable().initializedAndAttached) {
- getWidgetForPaintable().updateBody(rowData,
- uidl.getIntAttribute("firstrow"),
- uidl.getIntAttribute("rows"));
- if (getWidgetForPaintable().headerChangedDuringUpdate) {
- getWidgetForPaintable().triggerLazyColumnAdjustment(
- true);
- } else if (!getWidgetForPaintable()
- .isScrollPositionVisible()
- || totalRowsChanged
- || getWidgetForPaintable().lastRenderedHeight != getWidgetForPaintable().scrollBody
- .getOffsetHeight()) {
- // webkits may still bug with their disturbing scrollbar
- // bug, see #3457
- // Run overflow fix for the scrollable area
- // #6698 - If there's a scroll going on, don't abort it
- // by changing overflows as the length of the contents
- // *shouldn't* have changed (unless the number of rows
- // or the height of the widget has also changed)
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- Util.runWebkitOverflowAutoFix(getWidgetForPaintable().scrollBodyPanel
- .getElement());
- }
- });
- }
- } else {
- getWidgetForPaintable().initializeRows(uidl, rowData);
- }
- }
- }
-
- if (!getWidgetForPaintable().isSelectable()) {
- getWidgetForPaintable().scrollBody
- .addStyleName(VScrollTable.CLASSNAME + "-body-noselection");
- } else {
- getWidgetForPaintable().scrollBody
- .removeStyleName(VScrollTable.CLASSNAME
- + "-body-noselection");
- }
-
- getWidgetForPaintable().hideScrollPositionAnnotation();
- getWidgetForPaintable().purgeUnregistryBag();
-
- // selection is no in sync with server, avoid excessive server visits by
- // clearing to flag used during the normal operation
- if (!keyboardSelectionOverRowFetchInProgress) {
- getWidgetForPaintable().selectionChanged = false;
- }
-
- /*
- * This is called when the Home or page up button has been pressed in
- * selectable mode and the next selected row was not yet rendered in the
- * client
- */
- if (getWidgetForPaintable().selectFirstItemInNextRender
- || getWidgetForPaintable().focusFirstItemInNextRender) {
- getWidgetForPaintable().selectFirstRenderedRowInViewPort(
- getWidgetForPaintable().focusFirstItemInNextRender);
- getWidgetForPaintable().selectFirstItemInNextRender = getWidgetForPaintable().focusFirstItemInNextRender = false;
- }
-
- /*
- * This is called when the page down or end button has been pressed in
- * selectable mode and the next selected row was not yet rendered in the
- * client
- */
- if (getWidgetForPaintable().selectLastItemInNextRender
- || getWidgetForPaintable().focusLastItemInNextRender) {
- getWidgetForPaintable().selectLastRenderedRowInViewPort(
- getWidgetForPaintable().focusLastItemInNextRender);
- getWidgetForPaintable().selectLastItemInNextRender = getWidgetForPaintable().focusLastItemInNextRender = false;
- }
- getWidgetForPaintable().multiselectPending = false;
-
- if (getWidgetForPaintable().focusedRow != null) {
- if (!getWidgetForPaintable().focusedRow.isAttached()
- && !getWidgetForPaintable().rowRequestHandler.isRunning()) {
- // focused row has been orphaned, can't focus
- getWidgetForPaintable().focusRowFromBody();
- }
- }
-
- getWidgetForPaintable().tabIndex = uidl.hasAttribute("tabindex") ? uidl
- .getIntAttribute("tabindex") : 0;
- getWidgetForPaintable().setProperTabIndex();
-
- getWidgetForPaintable().resizeSortedColumnForSortIndicator();
-
- // Remember this to detect situations where overflow hack might be
- // needed during scrolling
- getWidgetForPaintable().lastRenderedHeight = getWidgetForPaintable().scrollBody
- .getOffsetHeight();
-
- getWidgetForPaintable().rendering = false;
- getWidgetForPaintable().headerChangedDuringUpdate = false;
-
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VScrollTable.class);
- }
-
- @Override
- public VScrollTable getWidgetForPaintable() {
- return (VScrollTable) super.getWidgetForPaintable();
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.dom.client.Style.Position; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.BrowserInfo; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VScrollTablePaintable extends VAbstractPaintableWidgetContainer { + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal + * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection) + */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + + if (uidl.hasAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST)) { + getWidgetForPaintable().serverCacheFirst = uidl + .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST); + getWidgetForPaintable().serverCacheLast = uidl + .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_LAST); + } else { + getWidgetForPaintable().serverCacheFirst = -1; + getWidgetForPaintable().serverCacheLast = -1; + } + /* + * We need to do this before updateComponent since updateComponent calls + * this.setHeight() which will calculate a new body height depending on + * the space available. + */ + if (uidl.hasAttribute("colfooters")) { + getWidgetForPaintable().showColFooters = uidl + .getBooleanAttribute("colfooters"); + } + + getWidgetForPaintable().tFoot + .setVisible(getWidgetForPaintable().showColFooters); + + if (client.updateComponent(this, uidl, true)) { + getWidgetForPaintable().rendering = false; + return; + } + + getWidgetForPaintable().enabled = !uidl.hasAttribute("disabled"); + + if (BrowserInfo.get().isIE8() && !getWidgetForPaintable().enabled) { + /* + * The disabled shim will not cover the table body if it is relative + * in IE8. See #7324 + */ + getWidgetForPaintable().scrollBodyPanel.getElement().getStyle() + .setPosition(Position.STATIC); + } else if (BrowserInfo.get().isIE8()) { + getWidgetForPaintable().scrollBodyPanel.getElement().getStyle() + .setPosition(Position.RELATIVE); + } + + getWidgetForPaintable().client = client; + getWidgetForPaintable().paintableId = uidl.getStringAttribute("id"); + getWidgetForPaintable().immediate = uidl + .getBooleanAttribute("immediate"); + + int previousTotalRows = getWidgetForPaintable().totalRows; + getWidgetForPaintable().updateTotalRows(uidl); + boolean totalRowsChanged = (getWidgetForPaintable().totalRows != previousTotalRows); + + getWidgetForPaintable().updateDragMode(uidl); + + getWidgetForPaintable().updateSelectionProperties(uidl); + + if (uidl.hasAttribute("alb")) { + getWidgetForPaintable().bodyActionKeys = uidl + .getStringArrayAttribute("alb"); + } else { + // Need to clear the actions if the action handlers have been + // removed + getWidgetForPaintable().bodyActionKeys = null; + } + + getWidgetForPaintable().setCacheRateFromUIDL(uidl); + + getWidgetForPaintable().recalcWidths = uidl + .hasAttribute("recalcWidths"); + if (getWidgetForPaintable().recalcWidths) { + getWidgetForPaintable().tHead.clear(); + getWidgetForPaintable().tFoot.clear(); + } + + getWidgetForPaintable().updatePageLength(uidl); + + getWidgetForPaintable().updateFirstVisibleAndScrollIfNeeded(uidl); + + getWidgetForPaintable().showRowHeaders = uidl + .getBooleanAttribute("rowheaders"); + getWidgetForPaintable().showColHeaders = uidl + .getBooleanAttribute("colheaders"); + + getWidgetForPaintable().updateSortingProperties(uidl); + + boolean keyboardSelectionOverRowFetchInProgress = getWidgetForPaintable() + .selectSelectedRows(uidl); + + getWidgetForPaintable().updateActionMap(uidl); + + getWidgetForPaintable().updateColumnProperties(uidl); + + UIDL ac = uidl.getChildByTagName("-ac"); + if (ac == null) { + if (getWidgetForPaintable().dropHandler != null) { + // remove dropHandler if not present anymore + getWidgetForPaintable().dropHandler = null; + } + } else { + if (getWidgetForPaintable().dropHandler == null) { + getWidgetForPaintable().dropHandler = getWidgetForPaintable().new VScrollTableDropHandler(); + } + getWidgetForPaintable().dropHandler.updateAcceptRules(ac); + } + + UIDL partialRowAdditions = uidl.getChildByTagName("prows"); + UIDL partialRowUpdates = uidl.getChildByTagName("urows"); + if (partialRowUpdates != null || partialRowAdditions != null) { + // we may have pending cache row fetch, cancel it. See #2136 + getWidgetForPaintable().rowRequestHandler.cancel(); + + getWidgetForPaintable().updateRowsInBody(partialRowUpdates); + getWidgetForPaintable().addAndRemoveRows(partialRowAdditions); + } else { + UIDL rowData = uidl.getChildByTagName("rows"); + if (rowData != null) { + // we may have pending cache row fetch, cancel it. See #2136 + getWidgetForPaintable().rowRequestHandler.cancel(); + + if (!getWidgetForPaintable().recalcWidths + && getWidgetForPaintable().initializedAndAttached) { + getWidgetForPaintable().updateBody(rowData, + uidl.getIntAttribute("firstrow"), + uidl.getIntAttribute("rows")); + if (getWidgetForPaintable().headerChangedDuringUpdate) { + getWidgetForPaintable().triggerLazyColumnAdjustment( + true); + } else if (!getWidgetForPaintable() + .isScrollPositionVisible() + || totalRowsChanged + || getWidgetForPaintable().lastRenderedHeight != getWidgetForPaintable().scrollBody + .getOffsetHeight()) { + // webkits may still bug with their disturbing scrollbar + // bug, see #3457 + // Run overflow fix for the scrollable area + // #6698 - If there's a scroll going on, don't abort it + // by changing overflows as the length of the contents + // *shouldn't* have changed (unless the number of rows + // or the height of the widget has also changed) + Scheduler.get().scheduleDeferred(new Command() { + public void execute() { + Util.runWebkitOverflowAutoFix(getWidgetForPaintable().scrollBodyPanel + .getElement()); + } + }); + } + } else { + getWidgetForPaintable().initializeRows(uidl, rowData); + } + } + } + + if (!getWidgetForPaintable().isSelectable()) { + getWidgetForPaintable().scrollBody + .addStyleName(VScrollTable.CLASSNAME + "-body-noselection"); + } else { + getWidgetForPaintable().scrollBody + .removeStyleName(VScrollTable.CLASSNAME + + "-body-noselection"); + } + + getWidgetForPaintable().hideScrollPositionAnnotation(); + getWidgetForPaintable().purgeUnregistryBag(); + + // selection is no in sync with server, avoid excessive server visits by + // clearing to flag used during the normal operation + if (!keyboardSelectionOverRowFetchInProgress) { + getWidgetForPaintable().selectionChanged = false; + } + + /* + * This is called when the Home or page up button has been pressed in + * selectable mode and the next selected row was not yet rendered in the + * client + */ + if (getWidgetForPaintable().selectFirstItemInNextRender + || getWidgetForPaintable().focusFirstItemInNextRender) { + getWidgetForPaintable().selectFirstRenderedRowInViewPort( + getWidgetForPaintable().focusFirstItemInNextRender); + getWidgetForPaintable().selectFirstItemInNextRender = getWidgetForPaintable().focusFirstItemInNextRender = false; + } + + /* + * This is called when the page down or end button has been pressed in + * selectable mode and the next selected row was not yet rendered in the + * client + */ + if (getWidgetForPaintable().selectLastItemInNextRender + || getWidgetForPaintable().focusLastItemInNextRender) { + getWidgetForPaintable().selectLastRenderedRowInViewPort( + getWidgetForPaintable().focusLastItemInNextRender); + getWidgetForPaintable().selectLastItemInNextRender = getWidgetForPaintable().focusLastItemInNextRender = false; + } + getWidgetForPaintable().multiselectPending = false; + + if (getWidgetForPaintable().focusedRow != null) { + if (!getWidgetForPaintable().focusedRow.isAttached() + && !getWidgetForPaintable().rowRequestHandler.isRunning()) { + // focused row has been orphaned, can't focus + getWidgetForPaintable().focusRowFromBody(); + } + } + + getWidgetForPaintable().tabIndex = uidl.hasAttribute("tabindex") ? uidl + .getIntAttribute("tabindex") : 0; + getWidgetForPaintable().setProperTabIndex(); + + getWidgetForPaintable().resizeSortedColumnForSortIndicator(); + + // Remember this to detect situations where overflow hack might be + // needed during scrolling + getWidgetForPaintable().lastRenderedHeight = getWidgetForPaintable().scrollBody + .getOffsetHeight(); + + getWidgetForPaintable().rendering = false; + getWidgetForPaintable().headerChangedDuringUpdate = false; + + } + + @Override + protected Widget createWidget() { + return GWT.create(VScrollTable.class); + } + + @Override + public VScrollTable getWidgetForPaintable() { + return (VScrollTable) super.getWidgetForPaintable(); + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + // NOP, not rendered + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java index 9fbbeb7181..d213a3826f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java @@ -1,517 +1,513 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-//
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.ContainerResizedListener;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VConsole;
-
-public class VSlider extends SimpleFocusablePanel implements 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;
-
- boolean immediate;
- boolean disabled;
- boolean readonly;
-
- private int acceleration = 1;
- double min;
- double max;
- int resolution;
- Double value;
- boolean vertical;
-
- private final HTML feedback = new HTML("", false);
- private final VOverlay feedbackPopup = new VOverlay(true, false, true) {
- @Override
- public void show() {
- super.show();
- updateFeedbackPosition();
- }
- };
-
- /* DOM element for slider's base */
- private final Element base;
- private final int BASE_BORDER_WIDTH = 1;
-
- /* DOM element for slider's handle */
- private final Element handle;
-
- /* DOM element for decrement arrow */
- private final Element smaller;
-
- /* DOM element for increment arrow */
- private final Element bigger;
-
- /* Temporary dragging/animation variables */
- private boolean dragging = false;
-
- private VLazyExecutor delayedValueUpdater = new VLazyExecutor(100,
- new ScheduledCommand() {
-
- public void execute() {
- updateValueToServer();
- acceleration = 1;
- }
- });
-
- public VSlider() {
- super();
-
- base = DOM.createDiv();
- handle = DOM.createDiv();
- smaller = DOM.createDiv();
- bigger = DOM.createDiv();
-
- setStyleName(CLASSNAME);
- DOM.setElementProperty(base, "className", CLASSNAME + "-base");
- DOM.setElementProperty(handle, "className", CLASSNAME + "-handle");
- DOM.setElementProperty(smaller, "className", CLASSNAME + "-smaller");
- DOM.setElementProperty(bigger, "className", CLASSNAME + "-bigger");
-
- DOM.appendChild(getElement(), bigger);
- DOM.appendChild(getElement(), smaller);
- DOM.appendChild(getElement(), base);
- DOM.appendChild(base, handle);
-
- // Hide initially
- DOM.setStyleAttribute(smaller, "display", "none");
- DOM.setStyleAttribute(bigger, "display", "none");
- DOM.setStyleAttribute(handle, "visibility", "hidden");
-
- sinkEvents(Event.MOUSEEVENTS | Event.ONMOUSEWHEEL | Event.KEYEVENTS
- | Event.FOCUSEVENTS | Event.TOUCHEVENTS);
-
- feedbackPopup.addStyleName(CLASSNAME + "-feedback");
- feedbackPopup.setWidget(feedback);
- }
-
- 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());
- }
- }
-
- 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
- }
-
- void buildHandle() {
- final String handleAttribute = vertical ? "marginTop" : "marginLeft";
-
- DOM.setStyleAttribute(handle, handleAttribute, "0");
-
- // Restore visibility
- DOM.setStyleAttribute(handle, "visibility", "visible");
-
- }
-
- void setValue(Double value, boolean updateToServer) {
- if (value == null) {
- return;
- }
-
- if (value < min) {
- value = min;
- } else if (value > max) {
- value = max;
- }
-
- // Update handle position
- final String styleAttribute = vertical ? "marginTop" : "marginLeft";
- final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
- final int handleSize = Integer.parseInt(DOM.getElementProperty(handle,
- domProperty));
- final int baseSize = Integer.parseInt(DOM.getElementProperty(base,
- domProperty)) - (2 * BASE_BORDER_WIDTH);
-
- final int range = baseSize - handleSize;
- double v = value.doubleValue();
-
- // Round value to resolution
- if (resolution > 0) {
- v = Math.round(v * Math.pow(10, resolution));
- v = v / Math.pow(10, resolution);
- } else {
- v = Math.round(v);
- }
- final double valueRange = max - min;
- double p = 0;
- if (valueRange > 0) {
- p = range * ((v - min) / valueRange);
- }
- if (p < 0) {
- p = 0;
- }
- if (vertical) {
- p = range - p;
- }
- final double pos = p;
-
- DOM.setStyleAttribute(handle, styleAttribute, (Math.round(pos)) + "px");
-
- // Update value
- this.value = new Double(v);
- setFeedbackValue(v);
-
- if (updateToServer) {
- updateValueToServer();
- }
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- if (disabled || readonly) {
- return;
- }
- final Element targ = DOM.eventGetTarget(event);
-
- if (DOM.eventGetType(event) == Event.ONMOUSEWHEEL) {
- processMouseWheelEvent(event);
- } else if (dragging || targ == handle) {
- processHandleEvent(event);
- } else if (targ == smaller) {
- decreaseValue(true);
- } else if (targ == bigger) {
- increaseValue(true);
- } else if (DOM.eventGetType(event) == Event.MOUSEEVENTS) {
- processBaseEvent(event);
- } else if ((BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYPRESS)
- || (!BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYDOWN)) {
-
- if (handleNavigation(event.getKeyCode(), event.getCtrlKey(),
- event.getShiftKey())) {
-
- feedbackPopup.show();
-
- delayedValueUpdater.trigger();
-
- DOM.eventPreventDefault(event);
- DOM.eventCancelBubble(event, true);
- }
- } else if (targ.equals(getElement())
- && DOM.eventGetType(event) == Event.ONFOCUS) {
- feedbackPopup.show();
- } else if (targ.equals(getElement())
- && DOM.eventGetType(event) == Event.ONBLUR) {
- feedbackPopup.hide();
- } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
- feedbackPopup.show();
- }
- if (Util.isTouchEvent(event)) {
- event.preventDefault(); // avoid simulated events
- event.stopPropagation();
- }
- }
-
- private void processMouseWheelEvent(final Event event) {
- final int dir = DOM.eventGetMouseWheelVelocityY(event);
-
- if (dir < 0) {
- increaseValue(false);
- } else {
- decreaseValue(false);
- }
-
- delayedValueUpdater.trigger();
-
- DOM.eventPreventDefault(event);
- DOM.eventCancelBubble(event, true);
- }
-
- private void processHandleEvent(Event event) {
- switch (DOM.eventGetType(event)) {
- case Event.ONMOUSEDOWN:
- case Event.ONTOUCHSTART:
- if (!disabled && !readonly) {
- focus();
- feedbackPopup.show();
- dragging = true;
- DOM.setElementProperty(handle, "className", CLASSNAME
- + "-handle " + CLASSNAME + "-handle-active");
- DOM.setCapture(getElement());
- DOM.eventPreventDefault(event); // prevent selecting text
- DOM.eventCancelBubble(event, true);
- event.stopPropagation();
- VConsole.log("Slider move start");
- }
- break;
- case Event.ONMOUSEMOVE:
- case Event.ONTOUCHMOVE:
- if (dragging) {
- VConsole.log("Slider move");
- setValueByEvent(event, false);
- updateFeedbackPosition();
- event.stopPropagation();
- }
- break;
- case Event.ONTOUCHEND:
- feedbackPopup.hide();
- case Event.ONMOUSEUP:
- // feedbackPopup.hide();
- VConsole.log("Slider move end");
- dragging = false;
- DOM.setElementProperty(handle, "className", CLASSNAME + "-handle");
- DOM.releaseCapture(getElement());
- setValueByEvent(event, true);
- event.stopPropagation();
- break;
- default:
- break;
- }
- }
-
- private void processBaseEvent(Event event) {
- if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
- if (!disabled && !readonly && !dragging) {
- setValueByEvent(event, true);
- DOM.eventCancelBubble(event, true);
- }
- }
- }
-
- private void decreaseValue(boolean updateToServer) {
- setValue(new Double(value.doubleValue() - Math.pow(10, -resolution)),
- updateToServer);
- }
-
- private void increaseValue(boolean updateToServer) {
- setValue(new Double(value.doubleValue() + Math.pow(10, -resolution)),
- updateToServer);
- }
-
- private void setValueByEvent(Event event, boolean updateToServer) {
- double v = min; // Fallback to min
-
- final int coord = getEventPosition(event);
-
- final int handleSize, baseSize, baseOffset;
- if (vertical) {
- handleSize = handle.getOffsetHeight();
- baseSize = base.getOffsetHeight();
- baseOffset = base.getAbsoluteTop() - Window.getScrollTop()
- - handleSize / 2;
- } else {
- handleSize = handle.getOffsetWidth();
- baseSize = base.getOffsetWidth();
- baseOffset = base.getAbsoluteLeft() - Window.getScrollLeft()
- + handleSize / 2;
- }
-
- if (vertical) {
- v = ((baseSize - (coord - baseOffset)) / (double) (baseSize - handleSize))
- * (max - min) + min;
- } else {
- v = ((coord - baseOffset) / (double) (baseSize - handleSize))
- * (max - min) + min;
- }
-
- if (v < min) {
- v = min;
- } else if (v > max) {
- v = max;
- }
-
- setValue(v, updateToServer);
- }
-
- /**
- * TODO consider extracting touches support to an impl class specific for
- * webkit (only browser that really supports touches).
- *
- * @param event
- * @return
- */
- protected int getEventPosition(Event event) {
- if (vertical) {
- return Util.getTouchOrMouseClientY(event);
- } else {
- return Util.getTouchOrMouseClientX(event);
- }
- }
-
- public void iLayout() {
- if (vertical) {
- setHeight();
- }
- // Update handle position
- setValue(value, false);
- }
-
- private void setHeight() {
- // Calculate decoration size
- DOM.setStyleAttribute(base, "height", "0");
- DOM.setStyleAttribute(base, "overflow", "hidden");
- int h = DOM.getElementPropertyInt(getElement(), "offsetHeight");
- if (h < MIN_SIZE) {
- h = MIN_SIZE;
- }
- DOM.setStyleAttribute(base, "height", h + "px");
- DOM.setStyleAttribute(base, "overflow", "");
- }
-
- private void updateValueToServer() {
- client.updateVariable(id, "value", value.doubleValue(), immediate);
- }
-
- /**
- * Handles the keyboard events handled by the Slider
- *
- * @param event
- * The keyboard event received
- * @return true iff the navigation event was handled
- */
- public boolean handleNavigation(int keycode, boolean ctrl, boolean shift) {
-
- // No support for ctrl moving
- if (ctrl) {
- return false;
- }
-
- if ((keycode == getNavigationUpKey() && vertical)
- || (keycode == getNavigationRightKey() && !vertical)) {
- if (shift) {
- for (int a = 0; a < acceleration; a++) {
- increaseValue(false);
- }
- acceleration++;
- } else {
- increaseValue(false);
- }
- return true;
- } else if (keycode == getNavigationDownKey() && vertical
- || (keycode == getNavigationLeftKey() && !vertical)) {
- if (shift) {
- for (int a = 0; a < acceleration; a++) {
- decreaseValue(false);
- }
- acceleration++;
- } else {
- decreaseValue(false);
- }
- return true;
- }
-
- return false;
- }
-
- /**
- * Get the key that increases the vertical slider. By default it is the up
- * arrow key but by overriding this you can change the key to whatever you
- * want.
- *
- * @return The keycode of the key
- */
- protected int getNavigationUpKey() {
- return KeyCodes.KEY_UP;
- }
-
- /**
- * Get the key that decreases the vertical slider. By default it is the down
- * arrow key but by overriding this you can change the key to whatever you
- * want.
- *
- * @return The keycode of the key
- */
- protected int getNavigationDownKey() {
- return KeyCodes.KEY_DOWN;
- }
-
- /**
- * Get the key that decreases the horizontal slider. By default it is the
- * left arrow key but by overriding this you can change the key to whatever
- * you want.
- *
- * @return The keycode of the key
- */
- protected int getNavigationLeftKey() {
- return KeyCodes.KEY_LEFT;
- }
-
- /**
- * Get the key that increases the horizontal slider. By default it is the
- * right arrow key but by overriding this you can change the key to whatever
- * you want.
- *
- * @return The keycode of the key
- */
- protected int getNavigationRightKey() {
- return KeyCodes.KEY_RIGHT;
- }
-
- public Widget getWidgetForPaintable() {
- return this;
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +// +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.BrowserInfo; +import com.vaadin.terminal.gwt.client.ContainerResizedListener; +import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VConsole; + +public class VSlider extends SimpleFocusablePanel implements 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; + + boolean immediate; + boolean disabled; + boolean readonly; + + private int acceleration = 1; + double min; + double max; + int resolution; + Double value; + boolean vertical; + + private final HTML feedback = new HTML("", false); + private final VOverlay feedbackPopup = new VOverlay(true, false, true) { + @Override + public void show() { + super.show(); + updateFeedbackPosition(); + } + }; + + /* DOM element for slider's base */ + private final Element base; + private final int BASE_BORDER_WIDTH = 1; + + /* DOM element for slider's handle */ + private final Element handle; + + /* DOM element for decrement arrow */ + private final Element smaller; + + /* DOM element for increment arrow */ + private final Element bigger; + + /* Temporary dragging/animation variables */ + private boolean dragging = false; + + private VLazyExecutor delayedValueUpdater = new VLazyExecutor(100, + new ScheduledCommand() { + + public void execute() { + updateValueToServer(); + acceleration = 1; + } + }); + + public VSlider() { + super(); + + base = DOM.createDiv(); + handle = DOM.createDiv(); + smaller = DOM.createDiv(); + bigger = DOM.createDiv(); + + setStyleName(CLASSNAME); + DOM.setElementProperty(base, "className", CLASSNAME + "-base"); + DOM.setElementProperty(handle, "className", CLASSNAME + "-handle"); + DOM.setElementProperty(smaller, "className", CLASSNAME + "-smaller"); + DOM.setElementProperty(bigger, "className", CLASSNAME + "-bigger"); + + DOM.appendChild(getElement(), bigger); + DOM.appendChild(getElement(), smaller); + DOM.appendChild(getElement(), base); + DOM.appendChild(base, handle); + + // Hide initially + DOM.setStyleAttribute(smaller, "display", "none"); + DOM.setStyleAttribute(bigger, "display", "none"); + DOM.setStyleAttribute(handle, "visibility", "hidden"); + + sinkEvents(Event.MOUSEEVENTS | Event.ONMOUSEWHEEL | Event.KEYEVENTS + | Event.FOCUSEVENTS | Event.TOUCHEVENTS); + + feedbackPopup.addStyleName(CLASSNAME + "-feedback"); + feedbackPopup.setWidget(feedback); + } + + 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()); + } + } + + 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 + } + + void buildHandle() { + final String handleAttribute = vertical ? "marginTop" : "marginLeft"; + + DOM.setStyleAttribute(handle, handleAttribute, "0"); + + // Restore visibility + DOM.setStyleAttribute(handle, "visibility", "visible"); + + } + + void setValue(Double value, boolean updateToServer) { + if (value == null) { + return; + } + + if (value < min) { + value = min; + } else if (value > max) { + value = max; + } + + // Update handle position + final String styleAttribute = vertical ? "marginTop" : "marginLeft"; + final String domProperty = vertical ? "offsetHeight" : "offsetWidth"; + final int handleSize = Integer.parseInt(DOM.getElementProperty(handle, + domProperty)); + final int baseSize = Integer.parseInt(DOM.getElementProperty(base, + domProperty)) - (2 * BASE_BORDER_WIDTH); + + final int range = baseSize - handleSize; + double v = value.doubleValue(); + + // Round value to resolution + if (resolution > 0) { + v = Math.round(v * Math.pow(10, resolution)); + v = v / Math.pow(10, resolution); + } else { + v = Math.round(v); + } + final double valueRange = max - min; + double p = 0; + if (valueRange > 0) { + p = range * ((v - min) / valueRange); + } + if (p < 0) { + p = 0; + } + if (vertical) { + p = range - p; + } + final double pos = p; + + DOM.setStyleAttribute(handle, styleAttribute, (Math.round(pos)) + "px"); + + // Update value + this.value = new Double(v); + setFeedbackValue(v); + + if (updateToServer) { + updateValueToServer(); + } + } + + @Override + public void onBrowserEvent(Event event) { + if (disabled || readonly) { + return; + } + final Element targ = DOM.eventGetTarget(event); + + if (DOM.eventGetType(event) == Event.ONMOUSEWHEEL) { + processMouseWheelEvent(event); + } else if (dragging || targ == handle) { + processHandleEvent(event); + } else if (targ == smaller) { + decreaseValue(true); + } else if (targ == bigger) { + increaseValue(true); + } else if (DOM.eventGetType(event) == Event.MOUSEEVENTS) { + processBaseEvent(event); + } else if ((BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYPRESS) + || (!BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYDOWN)) { + + if (handleNavigation(event.getKeyCode(), event.getCtrlKey(), + event.getShiftKey())) { + + feedbackPopup.show(); + + delayedValueUpdater.trigger(); + + DOM.eventPreventDefault(event); + DOM.eventCancelBubble(event, true); + } + } else if (targ.equals(getElement()) + && DOM.eventGetType(event) == Event.ONFOCUS) { + feedbackPopup.show(); + } else if (targ.equals(getElement()) + && DOM.eventGetType(event) == Event.ONBLUR) { + feedbackPopup.hide(); + } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) { + feedbackPopup.show(); + } + if (Util.isTouchEvent(event)) { + event.preventDefault(); // avoid simulated events + event.stopPropagation(); + } + } + + private void processMouseWheelEvent(final Event event) { + final int dir = DOM.eventGetMouseWheelVelocityY(event); + + if (dir < 0) { + increaseValue(false); + } else { + decreaseValue(false); + } + + delayedValueUpdater.trigger(); + + DOM.eventPreventDefault(event); + DOM.eventCancelBubble(event, true); + } + + private void processHandleEvent(Event event) { + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEDOWN: + case Event.ONTOUCHSTART: + if (!disabled && !readonly) { + focus(); + feedbackPopup.show(); + dragging = true; + DOM.setElementProperty(handle, "className", CLASSNAME + + "-handle " + CLASSNAME + "-handle-active"); + DOM.setCapture(getElement()); + DOM.eventPreventDefault(event); // prevent selecting text + DOM.eventCancelBubble(event, true); + event.stopPropagation(); + VConsole.log("Slider move start"); + } + break; + case Event.ONMOUSEMOVE: + case Event.ONTOUCHMOVE: + if (dragging) { + VConsole.log("Slider move"); + setValueByEvent(event, false); + updateFeedbackPosition(); + event.stopPropagation(); + } + break; + case Event.ONTOUCHEND: + feedbackPopup.hide(); + case Event.ONMOUSEUP: + // feedbackPopup.hide(); + VConsole.log("Slider move end"); + dragging = false; + DOM.setElementProperty(handle, "className", CLASSNAME + "-handle"); + DOM.releaseCapture(getElement()); + setValueByEvent(event, true); + event.stopPropagation(); + break; + default: + break; + } + } + + private void processBaseEvent(Event event) { + if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) { + if (!disabled && !readonly && !dragging) { + setValueByEvent(event, true); + DOM.eventCancelBubble(event, true); + } + } + } + + private void decreaseValue(boolean updateToServer) { + setValue(new Double(value.doubleValue() - Math.pow(10, -resolution)), + updateToServer); + } + + private void increaseValue(boolean updateToServer) { + setValue(new Double(value.doubleValue() + Math.pow(10, -resolution)), + updateToServer); + } + + private void setValueByEvent(Event event, boolean updateToServer) { + double v = min; // Fallback to min + + final int coord = getEventPosition(event); + + final int handleSize, baseSize, baseOffset; + if (vertical) { + handleSize = handle.getOffsetHeight(); + baseSize = base.getOffsetHeight(); + baseOffset = base.getAbsoluteTop() - Window.getScrollTop() + - handleSize / 2; + } else { + handleSize = handle.getOffsetWidth(); + baseSize = base.getOffsetWidth(); + baseOffset = base.getAbsoluteLeft() - Window.getScrollLeft() + + handleSize / 2; + } + + if (vertical) { + v = ((baseSize - (coord - baseOffset)) / (double) (baseSize - handleSize)) + * (max - min) + min; + } else { + v = ((coord - baseOffset) / (double) (baseSize - handleSize)) + * (max - min) + min; + } + + if (v < min) { + v = min; + } else if (v > max) { + v = max; + } + + setValue(v, updateToServer); + } + + /** + * TODO consider extracting touches support to an impl class specific for + * webkit (only browser that really supports touches). + * + * @param event + * @return + */ + protected int getEventPosition(Event event) { + if (vertical) { + return Util.getTouchOrMouseClientY(event); + } else { + return Util.getTouchOrMouseClientX(event); + } + } + + public void iLayout() { + if (vertical) { + setHeight(); + } + // Update handle position + setValue(value, false); + } + + private void setHeight() { + // Calculate decoration size + DOM.setStyleAttribute(base, "height", "0"); + DOM.setStyleAttribute(base, "overflow", "hidden"); + int h = DOM.getElementPropertyInt(getElement(), "offsetHeight"); + if (h < MIN_SIZE) { + h = MIN_SIZE; + } + DOM.setStyleAttribute(base, "height", h + "px"); + DOM.setStyleAttribute(base, "overflow", ""); + } + + private void updateValueToServer() { + client.updateVariable(id, "value", value.doubleValue(), immediate); + } + + /** + * Handles the keyboard events handled by the Slider + * + * @param event + * The keyboard event received + * @return true iff the navigation event was handled + */ + public boolean handleNavigation(int keycode, boolean ctrl, boolean shift) { + + // No support for ctrl moving + if (ctrl) { + return false; + } + + if ((keycode == getNavigationUpKey() && vertical) + || (keycode == getNavigationRightKey() && !vertical)) { + if (shift) { + for (int a = 0; a < acceleration; a++) { + increaseValue(false); + } + acceleration++; + } else { + increaseValue(false); + } + return true; + } else if (keycode == getNavigationDownKey() && vertical + || (keycode == getNavigationLeftKey() && !vertical)) { + if (shift) { + for (int a = 0; a < acceleration; a++) { + decreaseValue(false); + } + acceleration++; + } else { + decreaseValue(false); + } + return true; + } + + return false; + } + + /** + * Get the key that increases the vertical slider. By default it is the up + * arrow key but by overriding this you can change the key to whatever you + * want. + * + * @return The keycode of the key + */ + protected int getNavigationUpKey() { + return KeyCodes.KEY_UP; + } + + /** + * Get the key that decreases the vertical slider. By default it is the down + * arrow key but by overriding this you can change the key to whatever you + * want. + * + * @return The keycode of the key + */ + protected int getNavigationDownKey() { + return KeyCodes.KEY_DOWN; + } + + /** + * Get the key that decreases the horizontal slider. By default it is the + * left arrow key but by overriding this you can change the key to whatever + * you want. + * + * @return The keycode of the key + */ + protected int getNavigationLeftKey() { + return KeyCodes.KEY_LEFT; + } + + /** + * Get the key that increases the horizontal slider. By default it is the + * right arrow key but by overriding this you can change the key to whatever + * you want. + * + * @return The keycode of the key + */ + protected int getNavigationRightKey() { + return KeyCodes.KEY_RIGHT; + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSliderPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VSliderPaintable.java index f5b8c8a45e..6c0dc74412 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSliderPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSliderPaintable.java @@ -1,78 +1,81 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-
-public class VSliderPaintable extends VAbstractPaintableWidget {
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
-
- getWidgetForPaintable().client = client;
- getWidgetForPaintable().id = uidl.getId();
-
- // Ensure correct implementation
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- getWidgetForPaintable().immediate = uidl
- .getBooleanAttribute("immediate");
- getWidgetForPaintable().disabled = uidl.getBooleanAttribute("disabled");
- getWidgetForPaintable().readonly = uidl.getBooleanAttribute("readonly");
-
- getWidgetForPaintable().vertical = uidl.hasAttribute("vertical");
-
- String style = "";
- if (uidl.hasAttribute("style")) {
- style = uidl.getStringAttribute("style");
- }
-
- if (getWidgetForPaintable().vertical) {
- getWidgetForPaintable().addStyleName(
- VSlider.CLASSNAME + "-vertical");
- } else {
- getWidgetForPaintable().removeStyleName(
- VSlider.CLASSNAME + "-vertical");
- }
-
- getWidgetForPaintable().min = uidl.getDoubleAttribute("min");
- getWidgetForPaintable().max = uidl.getDoubleAttribute("max");
- getWidgetForPaintable().resolution = uidl.getIntAttribute("resolution");
- getWidgetForPaintable().value = new Double(
- uidl.getDoubleVariable("value"));
-
- getWidgetForPaintable().setFeedbackValue(getWidgetForPaintable().value);
-
- getWidgetForPaintable().buildBase();
-
- if (!getWidgetForPaintable().vertical) {
- // Draw handle with a delay to allow base to gain maximum width
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- getWidgetForPaintable().buildHandle();
- getWidgetForPaintable().setValue(
- getWidgetForPaintable().value, false);
- }
- });
- } else {
- getWidgetForPaintable().buildHandle();
- getWidgetForPaintable().setValue(getWidgetForPaintable().value,
- false);
- }
- }
-
- @Override
- public VSlider getWidgetForPaintable() {
- return (VSlider) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VSlider.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; + +public class VSliderPaintable extends VAbstractPaintableWidget { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + getWidgetForPaintable().client = client; + getWidgetForPaintable().id = uidl.getId(); + + // Ensure correct implementation + if (client.updateComponent(this, uidl, true)) { + return; + } + + getWidgetForPaintable().immediate = uidl + .getBooleanAttribute("immediate"); + getWidgetForPaintable().disabled = uidl.getBooleanAttribute("disabled"); + getWidgetForPaintable().readonly = uidl.getBooleanAttribute("readonly"); + + getWidgetForPaintable().vertical = uidl.hasAttribute("vertical"); + + String style = ""; + if (uidl.hasAttribute("style")) { + style = uidl.getStringAttribute("style"); + } + + if (getWidgetForPaintable().vertical) { + getWidgetForPaintable().addStyleName( + VSlider.CLASSNAME + "-vertical"); + } else { + getWidgetForPaintable().removeStyleName( + VSlider.CLASSNAME + "-vertical"); + } + + getWidgetForPaintable().min = uidl.getDoubleAttribute("min"); + getWidgetForPaintable().max = uidl.getDoubleAttribute("max"); + getWidgetForPaintable().resolution = uidl.getIntAttribute("resolution"); + getWidgetForPaintable().value = new Double( + uidl.getDoubleVariable("value")); + + getWidgetForPaintable().setFeedbackValue(getWidgetForPaintable().value); + + getWidgetForPaintable().buildBase(); + + if (!getWidgetForPaintable().vertical) { + // Draw handle with a delay to allow base to gain maximum width + Scheduler.get().scheduleDeferred(new Command() { + public void execute() { + getWidgetForPaintable().buildHandle(); + getWidgetForPaintable().setValue( + getWidgetForPaintable().value, false); + } + }); + } else { + getWidgetForPaintable().buildHandle(); + getWidgetForPaintable().setValue(getWidgetForPaintable().value, + false); + } + } + + @Override + public VSlider getWidgetForPaintable() { + return (VSlider) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VSlider.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java index 553a4d673e..809c1a0380 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java @@ -1137,8 +1137,4 @@ public class VTabsheet extends VTabsheetBase { tp.remove(index); } } - - public Widget getWidgetForPaintable() { - return this; - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBasePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBasePaintable.java index 3fbc52c2ca..79f6012ed1 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBasePaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBasePaintable.java @@ -1,96 +1,99 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableMap;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public abstract class VTabsheetBasePaintable extends
- VAbstractPaintableWidgetContainer {
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().client = client;
-
- // Ensure correct implementation
- getWidgetForPaintable().cachedUpdate = client.updateComponent(this,
- uidl, true);
- if (getWidgetForPaintable().cachedUpdate) {
- return;
- }
-
- // Update member references
- getWidgetForPaintable().id = uidl.getId();
- getWidgetForPaintable().disabled = uidl.hasAttribute("disabled");
-
- // Render content
- final UIDL tabs = uidl.getChildUIDL(0);
-
- // Paintables in the TabSheet before update
- ArrayList<Widget> oldWidgets = new ArrayList<Widget>();
- for (Iterator<Widget> iterator = getWidgetForPaintable()
- .getWidgetIterator(); iterator.hasNext();) {
- oldWidgets.add(iterator.next());
- }
-
- // Clear previous values
- getWidgetForPaintable().tabKeys.clear();
- getWidgetForPaintable().disabledTabKeys.clear();
-
- int index = 0;
- for (final Iterator<Object> it = tabs.getChildIterator(); it.hasNext();) {
- final UIDL tab = (UIDL) it.next();
- final String key = tab.getStringAttribute("key");
- final boolean selected = tab.getBooleanAttribute("selected");
- final boolean hidden = tab.getBooleanAttribute("hidden");
-
- if (tab.getBooleanAttribute("disabled")) {
- getWidgetForPaintable().disabledTabKeys.add(key);
- }
-
- getWidgetForPaintable().tabKeys.add(key);
-
- if (selected) {
- getWidgetForPaintable().activeTabIndex = index;
- }
- getWidgetForPaintable().renderTab(tab, index, selected, hidden);
- index++;
- }
-
- int tabCount = getWidgetForPaintable().getTabCount();
- while (tabCount-- > index) {
- getWidgetForPaintable().removeTab(index);
- }
-
- for (int i = 0; i < getWidgetForPaintable().getTabCount(); i++) {
- VPaintableWidget p = getWidgetForPaintable().getTab(i);
- // During the initial rendering the paintable might be null (this is
- // weird...)
- if (p != null) {
- oldWidgets.remove(p.getWidgetForPaintable());
- }
- }
-
- // Perform unregister for any paintables removed during update
- for (Iterator<Widget> iterator = oldWidgets.iterator(); iterator
- .hasNext();) {
- Widget oldWidget = iterator.next();
- VPaintableWidget oldPaintable = VPaintableMap.get(client)
- .getPaintable(oldWidget);
- if (oldWidget.isAttached()) {
- oldWidget.removeFromParent();
- }
- VPaintableMap.get(client).unregisterPaintable(oldPaintable);
- }
-
- }
-
- @Override
- public VTabsheetBase getWidgetForPaintable() {
- return (VTabsheetBase) super.getWidgetForPaintable();
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.ArrayList; +import java.util.Iterator; + +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public abstract class VTabsheetBasePaintable extends + VAbstractPaintableWidgetContainer { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().client = client; + + // Ensure correct implementation + getWidgetForPaintable().cachedUpdate = client.updateComponent(this, + uidl, true); + if (getWidgetForPaintable().cachedUpdate) { + return; + } + + // Update member references + getWidgetForPaintable().id = uidl.getId(); + getWidgetForPaintable().disabled = uidl.hasAttribute("disabled"); + + // Render content + final UIDL tabs = uidl.getChildUIDL(0); + + // Paintables in the TabSheet before update + ArrayList<Widget> oldWidgets = new ArrayList<Widget>(); + for (Iterator<Widget> iterator = getWidgetForPaintable() + .getWidgetIterator(); iterator.hasNext();) { + oldWidgets.add(iterator.next()); + } + + // Clear previous values + getWidgetForPaintable().tabKeys.clear(); + getWidgetForPaintable().disabledTabKeys.clear(); + + int index = 0; + for (final Iterator<Object> it = tabs.getChildIterator(); it.hasNext();) { + final UIDL tab = (UIDL) it.next(); + final String key = tab.getStringAttribute("key"); + final boolean selected = tab.getBooleanAttribute("selected"); + final boolean hidden = tab.getBooleanAttribute("hidden"); + + if (tab.getBooleanAttribute("disabled")) { + getWidgetForPaintable().disabledTabKeys.add(key); + } + + getWidgetForPaintable().tabKeys.add(key); + + if (selected) { + getWidgetForPaintable().activeTabIndex = index; + } + getWidgetForPaintable().renderTab(tab, index, selected, hidden); + index++; + } + + int tabCount = getWidgetForPaintable().getTabCount(); + while (tabCount-- > index) { + getWidgetForPaintable().removeTab(index); + } + + for (int i = 0; i < getWidgetForPaintable().getTabCount(); i++) { + VPaintableWidget p = getWidgetForPaintable().getTab(i); + // During the initial rendering the paintable might be null (this is + // weird...) + if (p != null) { + oldWidgets.remove(p.getWidgetForPaintable()); + } + } + + // Perform unregister for any paintables removed during update + for (Iterator<Widget> iterator = oldWidgets.iterator(); iterator + .hasNext();) { + Widget oldWidget = iterator.next(); + VPaintableWidget oldPaintable = VPaintableMap.get(client) + .getPaintable(oldWidget); + if (oldWidget.isAttached()) { + oldWidget.removeFromParent(); + } + VPaintableMap.get(client).unregisterPaintable(oldPaintable); + } + + } + + @Override + public VTabsheetBase getWidgetForPaintable() { + return (VTabsheetBase) super.getWidgetForPaintable(); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPaintable.java index e8d6da757e..0d32484e10 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPaintable.java @@ -1,82 +1,85 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VTabsheetPaintable extends VTabsheetBasePaintable {
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
-
- if (!uidl.getBooleanAttribute("cached")) {
- // Handle stylename changes before generics (might affect size
- // calculations)
- getWidgetForPaintable().handleStyleNames(uidl);
- }
-
- super.updateFromUIDL(uidl, client);
- if (getWidgetForPaintable().cachedUpdate) {
- getWidgetForPaintable().rendering = false;
- return;
- }
-
- // tabs; push or not
- if (!getWidgetForPaintable().isDynamicWidth()) {
- // FIXME: This makes tab sheet tabs go to 1px width on every update
- // and then back to original width
- // update width later, in updateTabScroller();
- DOM.setStyleAttribute(getWidgetForPaintable().tabs, "width", "1px");
- DOM.setStyleAttribute(getWidgetForPaintable().tabs, "overflow",
- "hidden");
- } else {
- getWidgetForPaintable().showAllTabs();
- DOM.setStyleAttribute(getWidgetForPaintable().tabs, "width", "");
- DOM.setStyleAttribute(getWidgetForPaintable().tabs, "overflow",
- "visible");
- getWidgetForPaintable().updateDynamicWidth();
- }
-
- if (!getWidgetForPaintable().isDynamicHeight()) {
- // Must update height after the styles have been set
- getWidgetForPaintable().updateContentNodeHeight();
- getWidgetForPaintable().updateOpenTabSize();
- }
-
- getWidgetForPaintable().iLayout();
-
- // Re run relative size update to ensure optimal scrollbars
- // TODO isolate to situation that visible tab has undefined height
- try {
- client.handleComponentRelativeSize(getWidgetForPaintable().tp
- .getWidget(getWidgetForPaintable().tp.getVisibleWidget()));
- } catch (Exception e) {
- // Ignore, most likely empty tabsheet
- }
-
- getWidgetForPaintable().renderInformation
- .updateSize(getWidgetForPaintable().getElement());
-
- getWidgetForPaintable().waitingForResponse = false;
- getWidgetForPaintable().rendering = false;
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VTabsheet.class);
- }
-
- @Override
- public VTabsheet getWidgetForPaintable() {
- return (VTabsheet) super.getWidgetForPaintable();
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- /* Tabsheet does not render its children's captions */
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VTabsheetPaintable extends VTabsheetBasePaintable { + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + + if (!uidl.getBooleanAttribute("cached")) { + // Handle stylename changes before generics (might affect size + // calculations) + getWidgetForPaintable().handleStyleNames(uidl); + } + + super.updateFromUIDL(uidl, client); + if (getWidgetForPaintable().cachedUpdate) { + getWidgetForPaintable().rendering = false; + return; + } + + // tabs; push or not + if (!getWidgetForPaintable().isDynamicWidth()) { + // FIXME: This makes tab sheet tabs go to 1px width on every update + // and then back to original width + // update width later, in updateTabScroller(); + DOM.setStyleAttribute(getWidgetForPaintable().tabs, "width", "1px"); + DOM.setStyleAttribute(getWidgetForPaintable().tabs, "overflow", + "hidden"); + } else { + getWidgetForPaintable().showAllTabs(); + DOM.setStyleAttribute(getWidgetForPaintable().tabs, "width", ""); + DOM.setStyleAttribute(getWidgetForPaintable().tabs, "overflow", + "visible"); + getWidgetForPaintable().updateDynamicWidth(); + } + + if (!getWidgetForPaintable().isDynamicHeight()) { + // Must update height after the styles have been set + getWidgetForPaintable().updateContentNodeHeight(); + getWidgetForPaintable().updateOpenTabSize(); + } + + getWidgetForPaintable().iLayout(); + + // Re run relative size update to ensure optimal scrollbars + // TODO isolate to situation that visible tab has undefined height + try { + client.handleComponentRelativeSize(getWidgetForPaintable().tp + .getWidget(getWidgetForPaintable().tp.getVisibleWidget())); + } catch (Exception e) { + // Ignore, most likely empty tabsheet + } + + getWidgetForPaintable().renderInformation + .updateSize(getWidgetForPaintable().getElement()); + + getWidgetForPaintable().waitingForResponse = false; + getWidgetForPaintable().rendering = false; + } + + @Override + protected Widget createWidget() { + return GWT.create(VTabsheet.class); + } + + @Override + public VTabsheet getWidgetForPaintable() { + return (VTabsheet) super.getWidgetForPaintable(); + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + /* Tabsheet does not render its children's captions */ + } + +} 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 bd58c38829..2c8ed24693 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java @@ -1,63 +1,63 @@ -/*
-@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;
-
-/**
- * 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);
- }
-
- 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; + +/** + * 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); + } + + 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/VTreePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreePaintable.java index c058a15376..69aecebb06 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTreePaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTreePaintable.java @@ -1,228 +1,231 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.Iterator;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.TooltipInfo;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.ui.VTree.TreeNode;
-
-public class VTreePaintable extends VAbstractPaintableWidget {
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- // Ensure correct implementation and let container manage caption
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- getWidgetForPaintable().rendering = true;
-
- getWidgetForPaintable().client = client;
-
- if (uidl.hasAttribute("partialUpdate")) {
- handleUpdate(uidl);
- getWidgetForPaintable().rendering = false;
- return;
- }
-
- getWidgetForPaintable().paintableId = uidl.getId();
-
- getWidgetForPaintable().immediate = uidl.hasAttribute("immediate");
-
- getWidgetForPaintable().disabled = uidl.getBooleanAttribute("disabled");
- getWidgetForPaintable().readonly = uidl.getBooleanAttribute("readonly");
-
- getWidgetForPaintable().dragMode = uidl.hasAttribute("dragMode") ? uidl
- .getIntAttribute("dragMode") : 0;
-
- getWidgetForPaintable().isNullSelectionAllowed = uidl
- .getBooleanAttribute("nullselect");
-
- if (uidl.hasAttribute("alb")) {
- getWidgetForPaintable().bodyActionKeys = uidl
- .getStringArrayAttribute("alb");
- }
-
- getWidgetForPaintable().body.clear();
- // clear out any references to nodes that no longer are attached
- getWidgetForPaintable().clearNodeToKeyMap();
- TreeNode childTree = null;
- UIDL childUidl = null;
- for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
- childUidl = (UIDL) i.next();
- if ("actions".equals(childUidl.getTag())) {
- updateActionMap(childUidl);
- continue;
- } else if ("-ac".equals(childUidl.getTag())) {
- getWidgetForPaintable().updateDropHandler(childUidl);
- continue;
- }
- childTree = getWidgetForPaintable().new TreeNode();
- updateNodeFromUIDL(childTree, childUidl);
- getWidgetForPaintable().body.add(childTree);
- childTree.addStyleDependentName("root");
- childTree.childNodeContainer.addStyleDependentName("root");
- }
- if (childTree != null && childUidl != null) {
- boolean leaf = !childUidl.getTag().equals("node");
- childTree.addStyleDependentName(leaf ? "leaf-last" : "last");
- childTree.childNodeContainer.addStyleDependentName("last");
- }
- final String selectMode = uidl.getStringAttribute("selectmode");
- getWidgetForPaintable().selectable = !"none".equals(selectMode);
- getWidgetForPaintable().isMultiselect = "multi".equals(selectMode);
-
- if (getWidgetForPaintable().isMultiselect) {
- getWidgetForPaintable().multiSelectMode = uidl
- .getIntAttribute("multiselectmode");
- }
-
- getWidgetForPaintable().selectedIds = uidl
- .getStringArrayVariableAsSet("selected");
-
- // Update lastSelection and focusedNode to point to *actual* nodes again
- // after the old ones have been cleared from the body. This fixes focus
- // and keyboard navigation issues as described in #7057 and other
- // tickets.
- if (getWidgetForPaintable().lastSelection != null) {
- getWidgetForPaintable().lastSelection = getWidgetForPaintable()
- .getNodeByKey(getWidgetForPaintable().lastSelection.key);
- }
- if (getWidgetForPaintable().focusedNode != null) {
- getWidgetForPaintable().setFocusedNode(
- getWidgetForPaintable().getNodeByKey(
- getWidgetForPaintable().focusedNode.key));
- }
-
- if (getWidgetForPaintable().lastSelection == null
- && getWidgetForPaintable().focusedNode == null
- && !getWidgetForPaintable().selectedIds.isEmpty()) {
- getWidgetForPaintable().setFocusedNode(
- getWidgetForPaintable().getNodeByKey(
- getWidgetForPaintable().selectedIds.iterator()
- .next()));
- getWidgetForPaintable().focusedNode.setFocused(false);
- }
-
- getWidgetForPaintable().rendering = false;
-
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VTree.class);
- }
-
- @Override
- public VTree getWidgetForPaintable() {
- return (VTree) super.getWidgetForPaintable();
- }
-
- private void handleUpdate(UIDL uidl) {
- final TreeNode rootNode = getWidgetForPaintable().getNodeByKey(
- uidl.getStringAttribute("rootKey"));
- if (rootNode != null) {
- if (!rootNode.getState()) {
- // expanding node happened server side
- rootNode.setState(true, false);
- }
- renderChildNodes(rootNode, (Iterator) uidl.getChildIterator());
- }
- }
-
- /**
- * Registers action for the root and also for individual nodes
- *
- * @param uidl
- */
- private void updateActionMap(UIDL uidl) {
- final Iterator<?> it = uidl.getChildIterator();
- while (it.hasNext()) {
- final UIDL action = (UIDL) it.next();
- final String key = action.getStringAttribute("key");
- final String caption = action.getStringAttribute("caption");
- String iconUrl = null;
- if (action.hasAttribute("icon")) {
- iconUrl = getConnection().translateVaadinUri(
- action.getStringAttribute("icon"));
- }
- getWidgetForPaintable().registerAction(key, caption, iconUrl);
- }
-
- }
-
- public void updateNodeFromUIDL(TreeNode treeNode, UIDL uidl) {
- String nodeKey = uidl.getStringAttribute("key");
- treeNode.setText(uidl.getStringAttribute("caption"));
- treeNode.key = nodeKey;
-
- getWidgetForPaintable().registerNode(treeNode);
-
- if (uidl.hasAttribute("al")) {
- treeNode.actionKeys = uidl.getStringArrayAttribute("al");
- }
-
- if (uidl.getTag().equals("node")) {
- if (uidl.getChildCount() == 0) {
- treeNode.childNodeContainer.setVisible(false);
- } else {
- renderChildNodes(treeNode, (Iterator) uidl.getChildIterator());
- treeNode.childrenLoaded = true;
- }
- } else {
- treeNode.addStyleName(TreeNode.CLASSNAME + "-leaf");
- }
- if (uidl.hasAttribute("style")) {
- treeNode.setNodeStyleName(uidl.getStringAttribute("style"));
- }
-
- String description = uidl.getStringAttribute("descr");
- if (description != null && getConnection() != null) {
- // Set tooltip
- TooltipInfo info = new TooltipInfo(description);
- getConnection().registerTooltip(this, nodeKey, info);
- } else {
- // Remove possible previous tooltip
- getConnection().registerTooltip(this, nodeKey, null);
- }
-
- if (uidl.getBooleanAttribute("expanded") && !treeNode.getState()) {
- treeNode.setState(true, false);
- }
-
- if (uidl.getBooleanAttribute("selected")) {
- treeNode.setSelected(true);
- // ensure that identifier is in selectedIds array (this may be a
- // partial update)
- getWidgetForPaintable().selectedIds.add(nodeKey);
- }
-
- treeNode.setIcon(uidl.getStringAttribute("icon"));
- }
-
- void renderChildNodes(TreeNode containerNode, Iterator<UIDL> i) {
- containerNode.childNodeContainer.clear();
- containerNode.childNodeContainer.setVisible(true);
- while (i.hasNext()) {
- final UIDL childUidl = i.next();
- // actions are in bit weird place, don't mix them with children,
- // but current node's actions
- if ("actions".equals(childUidl.getTag())) {
- updateActionMap(childUidl);
- continue;
- }
- final TreeNode childTree = getWidgetForPaintable().new TreeNode();
- updateNodeFromUIDL(childTree, childUidl);
- containerNode.add(childTree);
- if (!i.hasNext()) {
- childTree
- .addStyleDependentName(childTree.isLeaf() ? "leaf-last"
- : "last");
- childTree.childNodeContainer.addStyleDependentName("last");
- }
- }
- containerNode.childrenLoaded = true;
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Iterator; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.TooltipInfo; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.ui.VTree.TreeNode; + +public class VTreePaintable extends VAbstractPaintableWidget { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Ensure correct implementation and let container manage caption + if (client.updateComponent(this, uidl, true)) { + return; + } + + getWidgetForPaintable().rendering = true; + + getWidgetForPaintable().client = client; + + if (uidl.hasAttribute("partialUpdate")) { + handleUpdate(uidl); + getWidgetForPaintable().rendering = false; + return; + } + + getWidgetForPaintable().paintableId = uidl.getId(); + + getWidgetForPaintable().immediate = uidl.hasAttribute("immediate"); + + getWidgetForPaintable().disabled = uidl.getBooleanAttribute("disabled"); + getWidgetForPaintable().readonly = uidl.getBooleanAttribute("readonly"); + + getWidgetForPaintable().dragMode = uidl.hasAttribute("dragMode") ? uidl + .getIntAttribute("dragMode") : 0; + + getWidgetForPaintable().isNullSelectionAllowed = uidl + .getBooleanAttribute("nullselect"); + + if (uidl.hasAttribute("alb")) { + getWidgetForPaintable().bodyActionKeys = uidl + .getStringArrayAttribute("alb"); + } + + getWidgetForPaintable().body.clear(); + // clear out any references to nodes that no longer are attached + getWidgetForPaintable().clearNodeToKeyMap(); + TreeNode childTree = null; + UIDL childUidl = null; + for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) { + childUidl = (UIDL) i.next(); + if ("actions".equals(childUidl.getTag())) { + updateActionMap(childUidl); + continue; + } else if ("-ac".equals(childUidl.getTag())) { + getWidgetForPaintable().updateDropHandler(childUidl); + continue; + } + childTree = getWidgetForPaintable().new TreeNode(); + updateNodeFromUIDL(childTree, childUidl); + getWidgetForPaintable().body.add(childTree); + childTree.addStyleDependentName("root"); + childTree.childNodeContainer.addStyleDependentName("root"); + } + if (childTree != null && childUidl != null) { + boolean leaf = !childUidl.getTag().equals("node"); + childTree.addStyleDependentName(leaf ? "leaf-last" : "last"); + childTree.childNodeContainer.addStyleDependentName("last"); + } + final String selectMode = uidl.getStringAttribute("selectmode"); + getWidgetForPaintable().selectable = !"none".equals(selectMode); + getWidgetForPaintable().isMultiselect = "multi".equals(selectMode); + + if (getWidgetForPaintable().isMultiselect) { + getWidgetForPaintable().multiSelectMode = uidl + .getIntAttribute("multiselectmode"); + } + + getWidgetForPaintable().selectedIds = uidl + .getStringArrayVariableAsSet("selected"); + + // Update lastSelection and focusedNode to point to *actual* nodes again + // after the old ones have been cleared from the body. This fixes focus + // and keyboard navigation issues as described in #7057 and other + // tickets. + if (getWidgetForPaintable().lastSelection != null) { + getWidgetForPaintable().lastSelection = getWidgetForPaintable() + .getNodeByKey(getWidgetForPaintable().lastSelection.key); + } + if (getWidgetForPaintable().focusedNode != null) { + getWidgetForPaintable().setFocusedNode( + getWidgetForPaintable().getNodeByKey( + getWidgetForPaintable().focusedNode.key)); + } + + if (getWidgetForPaintable().lastSelection == null + && getWidgetForPaintable().focusedNode == null + && !getWidgetForPaintable().selectedIds.isEmpty()) { + getWidgetForPaintable().setFocusedNode( + getWidgetForPaintable().getNodeByKey( + getWidgetForPaintable().selectedIds.iterator() + .next())); + getWidgetForPaintable().focusedNode.setFocused(false); + } + + getWidgetForPaintable().rendering = false; + + } + + @Override + protected Widget createWidget() { + return GWT.create(VTree.class); + } + + @Override + public VTree getWidgetForPaintable() { + return (VTree) super.getWidgetForPaintable(); + } + + private void handleUpdate(UIDL uidl) { + final TreeNode rootNode = getWidgetForPaintable().getNodeByKey( + uidl.getStringAttribute("rootKey")); + if (rootNode != null) { + if (!rootNode.getState()) { + // expanding node happened server side + rootNode.setState(true, false); + } + renderChildNodes(rootNode, (Iterator) uidl.getChildIterator()); + } + } + + /** + * Registers action for the root and also for individual nodes + * + * @param uidl + */ + private void updateActionMap(UIDL uidl) { + final Iterator<?> it = uidl.getChildIterator(); + while (it.hasNext()) { + final UIDL action = (UIDL) it.next(); + final String key = action.getStringAttribute("key"); + final String caption = action.getStringAttribute("caption"); + String iconUrl = null; + if (action.hasAttribute("icon")) { + iconUrl = getConnection().translateVaadinUri( + action.getStringAttribute("icon")); + } + getWidgetForPaintable().registerAction(key, caption, iconUrl); + } + + } + + public void updateNodeFromUIDL(TreeNode treeNode, UIDL uidl) { + String nodeKey = uidl.getStringAttribute("key"); + treeNode.setText(uidl.getStringAttribute("caption")); + treeNode.key = nodeKey; + + getWidgetForPaintable().registerNode(treeNode); + + if (uidl.hasAttribute("al")) { + treeNode.actionKeys = uidl.getStringArrayAttribute("al"); + } + + if (uidl.getTag().equals("node")) { + if (uidl.getChildCount() == 0) { + treeNode.childNodeContainer.setVisible(false); + } else { + renderChildNodes(treeNode, (Iterator) uidl.getChildIterator()); + treeNode.childrenLoaded = true; + } + } else { + treeNode.addStyleName(TreeNode.CLASSNAME + "-leaf"); + } + if (uidl.hasAttribute("style")) { + treeNode.setNodeStyleName(uidl.getStringAttribute("style")); + } + + String description = uidl.getStringAttribute("descr"); + if (description != null && getConnection() != null) { + // Set tooltip + TooltipInfo info = new TooltipInfo(description); + getConnection().registerTooltip(this, nodeKey, info); + } else { + // Remove possible previous tooltip + getConnection().registerTooltip(this, nodeKey, null); + } + + if (uidl.getBooleanAttribute("expanded") && !treeNode.getState()) { + treeNode.setState(true, false); + } + + if (uidl.getBooleanAttribute("selected")) { + treeNode.setSelected(true); + // ensure that identifier is in selectedIds array (this may be a + // partial update) + getWidgetForPaintable().selectedIds.add(nodeKey); + } + + treeNode.setIcon(uidl.getStringAttribute("icon")); + } + + void renderChildNodes(TreeNode containerNode, Iterator<UIDL> i) { + containerNode.childNodeContainer.clear(); + containerNode.childNodeContainer.setVisible(true); + while (i.hasNext()) { + final UIDL childUidl = i.next(); + // actions are in bit weird place, don't mix them with children, + // but current node's actions + if ("actions".equals(childUidl.getTag())) { + updateActionMap(childUidl); + continue; + } + final TreeNode childTree = getWidgetForPaintable().new TreeNode(); + updateNodeFromUIDL(childTree, childUidl); + containerNode.childNodeContainer.add(childTree); + if (!i.hasNext()) { + childTree + .addStyleDependentName(childTree.isLeaf() ? "leaf-last" + : "last"); + childTree.childNodeContainer.addStyleDependentName("last"); + } + } + containerNode.childrenLoaded = true; + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java index 0eddca0ed3..f0c284c2d0 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java @@ -223,29 +223,6 @@ public class VTreeTable extends VScrollTable { } } - @Override - public RenderSpace getAllocatedSpace(Widget child) { - if (widgetInHierarchyColumn == child) { - final int hierarchyAndIconWidth = getHierarchyAndIconWidth(); - final RenderSpace allocatedSpace = super - .getAllocatedSpace(child); - return new RenderSpace() { - @Override - public int getWidth() { - return allocatedSpace.getWidth() - - hierarchyAndIconWidth; - } - - @Override - public int getHeight() { - return allocatedSpace.getHeight(); - } - - }; - } - return super.getAllocatedSpace(child); - } - private int getHierarchyAndIconWidth() { int consumedSpace = treeSpacer.getOffsetWidth(); if (treeSpacer.getParentElement().getChildCount() > 2) { @@ -824,4 +801,27 @@ public class VTreeTable extends VScrollTable { int newTotalRows = uidl.getIntAttribute("totalrows"); setTotalRows(newTotalRows); } + + @Override + public RenderSpace getAllocatedSpace(Widget child) { + VTreeTableRow row = (VTreeTableRow) child.getParent(); + if (row.widgetInHierarchyColumn == child) { + final int hierarchyAndIconWidth = row.getHierarchyAndIconWidth(); + final RenderSpace allocatedSpace = super.getAllocatedSpace(child); + return new RenderSpace() { + @Override + public int getWidth() { + return allocatedSpace.getWidth() - hierarchyAndIconWidth; + } + + @Override + public int getHeight() { + return allocatedSpace.getHeight(); + } + + }; + } + return super.getAllocatedSpace(child); + } + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java index 9b6f03f612..8c159f43de 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTreeTablePaintable.java @@ -1,101 +1,101 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.ui.VScrollTable.VScrollTableBody.VScrollTableRow;
-import com.vaadin.terminal.gwt.client.ui.VTreeTable.PendingNavigationEvent;
-
-public class VTreeTablePaintable extends VScrollTablePaintable {
- public static final String ATTRIBUTE_HIERARCHY_COLUMN_INDEX = "hci";
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- FocusableScrollPanel widget = null;
- int scrollPosition = 0;
- if (getWidgetForPaintable().collapseRequest) {
- widget = (FocusableScrollPanel) getWidgetForPaintable()
- .getWidget(1);
- scrollPosition = widget.getScrollPosition();
- }
- getWidgetForPaintable().animationsEnabled = uidl
- .getBooleanAttribute("animate");
- getWidgetForPaintable().colIndexOfHierarchy = uidl
- .hasAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) ? uidl
- .getIntAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) : 0;
- int oldTotalRows = getWidgetForPaintable().getTotalRows();
- super.updateFromUIDL(uidl, client);
- if (getWidgetForPaintable().collapseRequest) {
- if (getWidgetForPaintable().collapsedRowKey != null
- && getWidgetForPaintable().scrollBody != null) {
- VScrollTableRow row = getWidgetForPaintable()
- .getRenderedRowByKey(
- getWidgetForPaintable().collapsedRowKey);
- if (row != null) {
- getWidgetForPaintable().setRowFocus(row);
- getWidgetForPaintable().focus();
- }
- }
-
- int scrollPosition2 = widget.getScrollPosition();
- if (scrollPosition != scrollPosition2) {
- widget.setScrollPosition(scrollPosition);
- }
-
- // check which rows are needed from the server and initiate a
- // deferred fetch
- getWidgetForPaintable().onScroll(null);
- }
- // Recalculate table size if collapse request, or if page length is zero
- // (not sent by server) and row count changes (#7908).
- if (getWidgetForPaintable().collapseRequest
- || (!uidl.hasAttribute("pagelength") && getWidgetForPaintable()
- .getTotalRows() != oldTotalRows)) {
- /*
- * Ensure that possibly removed/added scrollbars are considered.
- * Triggers row calculations, removes cached rows etc. Basically
- * cleans up state. Be careful if touching this, you will break
- * pageLength=0 if you remove this.
- */
- getWidgetForPaintable().triggerLazyColumnAdjustment(true);
-
- getWidgetForPaintable().collapseRequest = false;
- }
- if (uidl.hasAttribute("focusedRow")) {
- String key = uidl.getStringAttribute("focusedRow");
- getWidgetForPaintable().setRowFocus(
- getWidgetForPaintable().getRenderedRowByKey(key));
- getWidgetForPaintable().focusParentResponsePending = false;
- } else if (uidl.hasAttribute("clearFocusPending")) {
- // Special case to detect a response to a focusParent request that
- // does not return any focusedRow because the selected node has no
- // parent
- getWidgetForPaintable().focusParentResponsePending = false;
- }
-
- while (!getWidgetForPaintable().collapseRequest
- && !getWidgetForPaintable().focusParentResponsePending
- && !getWidgetForPaintable().pendingNavigationEvents.isEmpty()) {
- // Keep replaying any queued events as long as we don't have any
- // potential content changes pending
- PendingNavigationEvent event = getWidgetForPaintable().pendingNavigationEvents
- .removeFirst();
- getWidgetForPaintable().handleNavigation(event.keycode, event.ctrl,
- event.shift);
- }
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VTreeTable.class);
- }
-
- @Override
- public VTreeTable getWidgetForPaintable() {
- return (VTreeTable) super.getWidgetForPaintable();
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.ui.VScrollTable.VScrollTableBody.VScrollTableRow; +import com.vaadin.terminal.gwt.client.ui.VTreeTable.PendingNavigationEvent; + +public class VTreeTablePaintable extends VScrollTablePaintable { + public static final String ATTRIBUTE_HIERARCHY_COLUMN_INDEX = "hci"; + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + FocusableScrollPanel widget = null; + int scrollPosition = 0; + if (getWidgetForPaintable().collapseRequest) { + widget = (FocusableScrollPanel) getWidgetForPaintable() + .getWidget(1); + scrollPosition = widget.getScrollPosition(); + } + getWidgetForPaintable().animationsEnabled = uidl + .getBooleanAttribute("animate"); + getWidgetForPaintable().colIndexOfHierarchy = uidl + .hasAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) ? uidl + .getIntAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) : 0; + int oldTotalRows = getWidgetForPaintable().getTotalRows(); + super.updateFromUIDL(uidl, client); + if (getWidgetForPaintable().collapseRequest) { + if (getWidgetForPaintable().collapsedRowKey != null + && getWidgetForPaintable().scrollBody != null) { + VScrollTableRow row = getWidgetForPaintable() + .getRenderedRowByKey( + getWidgetForPaintable().collapsedRowKey); + if (row != null) { + getWidgetForPaintable().setRowFocus(row); + getWidgetForPaintable().focus(); + } + } + + int scrollPosition2 = widget.getScrollPosition(); + if (scrollPosition != scrollPosition2) { + widget.setScrollPosition(scrollPosition); + } + + // check which rows are needed from the server and initiate a + // deferred fetch + getWidgetForPaintable().onScroll(null); + } + // Recalculate table size if collapse request, or if page length is zero + // (not sent by server) and row count changes (#7908). + if (getWidgetForPaintable().collapseRequest + || (!uidl.hasAttribute("pagelength") && getWidgetForPaintable() + .getTotalRows() != oldTotalRows)) { + /* + * Ensure that possibly removed/added scrollbars are considered. + * Triggers row calculations, removes cached rows etc. Basically + * cleans up state. Be careful if touching this, you will break + * pageLength=0 if you remove this. + */ + getWidgetForPaintable().triggerLazyColumnAdjustment(true); + + getWidgetForPaintable().collapseRequest = false; + } + if (uidl.hasAttribute("focusedRow")) { + String key = uidl.getStringAttribute("focusedRow"); + getWidgetForPaintable().setRowFocus( + getWidgetForPaintable().getRenderedRowByKey(key)); + getWidgetForPaintable().focusParentResponsePending = false; + } else if (uidl.hasAttribute("clearFocusPending")) { + // Special case to detect a response to a focusParent request that + // does not return any focusedRow because the selected node has no + // parent + getWidgetForPaintable().focusParentResponsePending = false; + } + + while (!getWidgetForPaintable().collapseRequest + && !getWidgetForPaintable().focusParentResponsePending + && !getWidgetForPaintable().pendingNavigationEvents.isEmpty()) { + // Keep replaying any queued events as long as we don't have any + // potential content changes pending + PendingNavigationEvent event = getWidgetForPaintable().pendingNavigationEvents + .removeFirst(); + getWidgetForPaintable().handleNavigation(event.keycode, event.ctrl, + event.shift); + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VTreeTable.class); + } + + @Override + public VTreeTable getWidgetForPaintable() { + return (VTreeTable) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java index e733b2e73b..a7fe89017b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java @@ -26,7 +26,6 @@ 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.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; @@ -616,8 +615,4 @@ public class VTwinColSelect extends VOptionGroupBase implements KeyDownHandler, return null; } - - public Widget getWidgetForPaintable() { - return this; - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java index 5378218ece..71c6d91c69 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java @@ -1,17 +1,20 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-
-public class VVerticalLayoutPaintable extends VOrderedLayoutPaintable {
-
- @Override
- public VVerticalLayout getWidgetForPaintable() {
- return (VVerticalLayout) super.getWidgetForPaintable();
- }
-
- @Override
- protected VVerticalLayout createWidget() {
- return GWT.create(VVerticalLayout.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; + +public class VVerticalLayoutPaintable extends VOrderedLayoutPaintable { + + @Override + public VVerticalLayout getWidgetForPaintable() { + return (VVerticalLayout) super.getWidgetForPaintable(); + } + + @Override + protected VVerticalLayout createWidget() { + return GWT.create(VVerticalLayout.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VVerticalSplitPanelPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VVerticalSplitPanelPaintable.java index d60a3185af..a2dc1fbbb2 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VVerticalSplitPanelPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VVerticalSplitPanelPaintable.java @@ -1,12 +1,15 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-
-public class VVerticalSplitPanelPaintable extends VAbstractSplitPanelPaintable {
-
- @Override
- protected VAbstractSplitPanel createWidget() {
- return GWT.create(VSplitPanelVertical.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; + +public class VVerticalSplitPanelPaintable extends VAbstractSplitPanelPaintable { + + @Override + protected VAbstractSplitPanel createWidget() { + return GWT.create(VSplitPanelVertical.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VVideoPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VVideoPaintable.java index a9a46671be..53b79344cf 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VVideoPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VVideoPaintable.java @@ -1,38 +1,41 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-
-public class VVideoPaintable extends VMediaBasePaintable {
- public static final String ATTR_POSTER = "poster";
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
- super.updateFromUIDL(uidl, client);
- setPosterFromUIDL(uidl);
- }
-
- private void setPosterFromUIDL(UIDL uidl) {
- if (uidl.hasAttribute(ATTR_POSTER)) {
- getWidgetForPaintable().setPoster(
- getConnection().translateVaadinUri(
- uidl.getStringAttribute(ATTR_POSTER)));
- }
- }
-
- @Override
- public VVideo getWidgetForPaintable() {
- return (VVideo) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VVideo.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; + +public class VVideoPaintable extends VMediaBasePaintable { + public static final String ATTR_POSTER = "poster"; + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, true)) { + return; + } + super.updateFromUIDL(uidl, client); + setPosterFromUIDL(uidl); + } + + private void setPosterFromUIDL(UIDL uidl) { + if (uidl.hasAttribute(ATTR_POSTER)) { + getWidgetForPaintable().setPoster( + getConnection().translateVaadinUri( + uidl.getStringAttribute(ATTR_POSTER))); + } + } + + @Override + public VVideo getWidgetForPaintable() { + return (VVideo) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VVideo.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index 7002c6279f..ea5610cdaa 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -553,8 +553,4 @@ public class VView extends SimplePanel implements Container, ResizeHandler, getElement().focus(); } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VViewPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VViewPaintable.java index ebec292ecb..94e7bfd9af 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VViewPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VViewPaintable.java @@ -1,331 +1,338 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.HashSet;
-import java.util.Iterator;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.event.dom.client.DomEvent.Type;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.RootPanel;
-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.Focusable;
-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.VPaintableMap;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-
-public class VViewPaintable extends VAbstractPaintableWidgetContainer {
-
- private static final String CLICK_EVENT_IDENTIFIER = VPanelPaintable.CLICK_EVENT_IDENTIFIER;
-
- public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().rendering = true;
-
- getWidgetForPaintable().id = uidl.getId();
- boolean firstPaint = getWidgetForPaintable().connection == null;
- getWidgetForPaintable().connection = client;
-
- getWidgetForPaintable().immediate = uidl.hasAttribute("immediate");
- getWidgetForPaintable().resizeLazy = uidl
- .hasAttribute(VView.RESIZE_LAZY);
- String newTheme = uidl.getStringAttribute("theme");
- if (getWidgetForPaintable().theme != null
- && !newTheme.equals(getWidgetForPaintable().theme)) {
- // Complete page refresh is needed due css can affect layout
- // calculations etc
- getWidgetForPaintable().reloadHostPage();
- } else {
- getWidgetForPaintable().theme = newTheme;
- }
- if (uidl.hasAttribute("style")) {
- getWidgetForPaintable().setStyleName(
- getWidgetForPaintable().getStylePrimaryName() + " "
- + uidl.getStringAttribute("style"));
- }
-
- clickEventHandler.handleEventHandlerRegistration(client);
-
- if (!getWidgetForPaintable().isEmbedded()
- && uidl.hasAttribute("caption")) {
- // only change window title if we're in charge of the whole page
- com.google.gwt.user.client.Window.setTitle(uidl
- .getStringAttribute("caption"));
- }
-
- // Process children
- int childIndex = 0;
-
- // Open URL:s
- boolean isClosed = false; // was this window closed?
- while (childIndex < uidl.getChildCount()
- && "open".equals(uidl.getChildUIDL(childIndex).getTag())) {
- final UIDL open = uidl.getChildUIDL(childIndex);
- final String url = client.translateVaadinUri(open
- .getStringAttribute("src"));
- final String target = open.getStringAttribute("name");
- if (target == null) {
- // source will be opened to this browser window, but we may have
- // to finish rendering this window in case this is a download
- // (and window stays open).
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- VView.goTo(url);
- }
- });
- } else if ("_self".equals(target)) {
- // This window is closing (for sure). Only other opens are
- // relevant in this change. See #3558, #2144
- isClosed = true;
- VView.goTo(url);
- } else {
- String options;
- if (open.hasAttribute("border")) {
- if (open.getStringAttribute("border").equals("minimal")) {
- options = "menubar=yes,location=no,status=no";
- } else {
- options = "menubar=no,location=no,status=no";
- }
-
- } else {
- options = "resizable=yes,menubar=yes,toolbar=yes,directories=yes,location=yes,scrollbars=yes,status=yes";
- }
-
- if (open.hasAttribute("width")) {
- int w = open.getIntAttribute("width");
- options += ",width=" + w;
- }
- if (open.hasAttribute("height")) {
- int h = open.getIntAttribute("height");
- options += ",height=" + h;
- }
-
- Window.open(url, target, options);
- }
- childIndex++;
- }
- if (isClosed) {
- // don't render the content, something else will be opened to this
- // browser view
- getWidgetForPaintable().rendering = false;
- return;
- }
-
- // Draw this application level window
- UIDL childUidl = uidl.getChildUIDL(childIndex);
- final VPaintableWidget lo = client.getPaintable(childUidl);
-
- if (getWidgetForPaintable().layout != null) {
- if (getWidgetForPaintable().layout != lo) {
- // remove old
- client.unregisterPaintable(getWidgetForPaintable().layout);
- // add new
- getWidgetForPaintable().setWidget(lo.getWidgetForPaintable());
- getWidgetForPaintable().layout = lo;
- }
- } else {
- getWidgetForPaintable().setWidget(lo.getWidgetForPaintable());
- getWidgetForPaintable().layout = lo;
- }
-
- getWidgetForPaintable().layout.updateFromUIDL(childUidl, client);
- if (!childUidl.getBooleanAttribute("cached")) {
- getWidgetForPaintable().updateParentFrameSize();
- }
-
- // Save currently open subwindows to track which will need to be closed
- final HashSet<VWindow> removedSubWindows = new HashSet<VWindow>(
- getWidgetForPaintable().subWindows);
-
- // Handle other UIDL children
- while ((childUidl = uidl.getChildUIDL(++childIndex)) != null) {
- String tag = childUidl.getTag().intern();
- if (tag == "actions") {
- if (getWidgetForPaintable().actionHandler == null) {
- getWidgetForPaintable().actionHandler = new ShortcutActionHandler(
- getWidgetForPaintable().id, client);
- }
- getWidgetForPaintable().actionHandler
- .updateActionMap(childUidl);
- } else if (tag == "execJS") {
- String script = childUidl.getStringAttribute("script");
- VView.eval(script);
- } else if (tag == "notifications") {
- for (final Iterator<?> it = childUidl.getChildIterator(); it
- .hasNext();) {
- final UIDL notification = (UIDL) it.next();
- VNotification.showNotification(client, notification);
- }
- } else {
- // subwindows
- final VPaintableWidget w = client.getPaintable(childUidl);
- if (getWidgetForPaintable().subWindows.contains(w)) {
- removedSubWindows.remove(w);
- } else {
- getWidgetForPaintable().subWindows.add((VWindow) w);
- }
- w.updateFromUIDL(childUidl, client);
- }
- }
-
- // Close old windows which where not in UIDL anymore
- for (final Iterator<VWindow> rem = removedSubWindows.iterator(); rem
- .hasNext();) {
- final VWindow w = rem.next();
- client.unregisterPaintable(VPaintableMap.get(getConnection())
- .getPaintable(w));
- getWidgetForPaintable().subWindows.remove(w);
- w.hide();
- }
-
- if (uidl.hasAttribute("focused")) {
- // set focused component when render phase is finished
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- VPaintableWidget paintable = (VPaintableWidget) uidl
- .getPaintableAttribute("focused", getConnection());
-
- final Widget toBeFocused = paintable
- .getWidgetForPaintable();
- /*
- * Two types of Widgets can be focused, either implementing
- * GWT HasFocus of a thinner Vaadin specific Focusable
- * interface.
- */
- if (toBeFocused instanceof com.google.gwt.user.client.ui.Focusable) {
- final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) toBeFocused;
- toBeFocusedWidget.setFocus(true);
- } else if (toBeFocused instanceof Focusable) {
- ((Focusable) toBeFocused).focus();
- } else {
- VConsole.log("Could not focus component");
- }
- }
- });
- }
-
- // Add window listeners on first paint, to prevent premature
- // variablechanges
- if (firstPaint) {
- Window.addWindowClosingHandler(getWidgetForPaintable());
- Window.addResizeHandler(getWidgetForPaintable());
- }
-
- getWidgetForPaintable().onResize();
-
- // finally set scroll position from UIDL
- if (uidl.hasVariable("scrollTop")) {
- getWidgetForPaintable().scrollable = true;
- getWidgetForPaintable().scrollTop = uidl
- .getIntVariable("scrollTop");
- DOM.setElementPropertyInt(getWidgetForPaintable().getElement(),
- "scrollTop", getWidgetForPaintable().scrollTop);
- getWidgetForPaintable().scrollLeft = uidl
- .getIntVariable("scrollLeft");
- DOM.setElementPropertyInt(getWidgetForPaintable().getElement(),
- "scrollLeft", getWidgetForPaintable().scrollLeft);
- } else {
- getWidgetForPaintable().scrollable = false;
- }
-
- // Safari workaround must be run after scrollTop is updated as it sets
- // scrollTop using a deferred command.
- if (BrowserInfo.get().isSafari()) {
- Util.runWebkitOverflowAutoFix(getWidgetForPaintable().getElement());
- }
-
- getWidgetForPaintable().scrollIntoView(uidl);
-
- if (uidl.hasAttribute(VView.FRAGMENT_VARIABLE)) {
- getWidgetForPaintable().currentFragment = uidl
- .getStringAttribute(VView.FRAGMENT_VARIABLE);
- if (!getWidgetForPaintable().currentFragment.equals(History
- .getToken())) {
- History.newItem(getWidgetForPaintable().currentFragment, true);
- }
- } else {
- // Initial request for which the server doesn't yet have a fragment
- // (and haven't shown any interest in getting one)
- getWidgetForPaintable().currentFragment = History.getToken();
-
- // Include current fragment in the next request
- client.updateVariable(getWidgetForPaintable().id,
- VView.FRAGMENT_VARIABLE,
- getWidgetForPaintable().currentFragment, false);
- }
-
- getWidgetForPaintable().rendering = false;
- }
-
- public void init(String rootPanelId,
- ApplicationConnection applicationConnection) {
- DOM.sinkEvents(getWidgetForPaintable().getElement(), Event.ONKEYDOWN
- | Event.ONSCROLL);
-
- // iview is focused when created so element needs tabIndex
- // 1 due 0 is at the end of natural tabbing order
- DOM.setElementProperty(getWidgetForPaintable().getElement(),
- "tabIndex", "1");
-
- RootPanel root = RootPanel.get(rootPanelId);
-
- // Remove the v-app-loading or any splash screen added inside the div by
- // the user
- root.getElement().setInnerHTML("");
- // For backwards compatibility with static index pages only.
- // No longer added by AbstractApplicationServlet/Portlet
- root.removeStyleName("v-app-loading");
-
- String themeUri = applicationConnection.getConfiguration()
- .getThemeUri();
- String themeName = themeUri.substring(themeUri.lastIndexOf('/'));
- themeName = themeName.replaceAll("[^a-zA-Z0-9]", "");
- root.addStyleName("v-theme-" + themeName);
-
- root.add(getWidgetForPaintable());
-
- if (applicationConnection.getConfiguration().isStandalone()) {
- // set focus to iview element by default to listen possible keyboard
- // shortcuts. For embedded applications this is unacceptable as we
- // don't want to steal focus from the main page nor we don't want
- // side-effects from focusing (scrollIntoView).
- getWidgetForPaintable().getElement().focus();
- }
-
- getWidgetForPaintable().parentFrame = VView.getParentFrame();
- }
-
- private ClickEventHandler clickEventHandler = new ClickEventHandler(this,
- CLICK_EVENT_IDENTIFIER) {
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- return getWidgetForPaintable().addDomHandler(handler, type);
- }
- };
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- // NOP The main view never draws caption for its layout
- }
-
- @Override
- public VView getWidgetForPaintable() {
- return (VView) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VView.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.HashSet; +import java.util.Iterator; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.event.dom.client.DomEvent.Type; +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.History; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.RootPanel; +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.Focusable; +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.VPaintableMap; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public class VViewPaintable extends VAbstractPaintableWidgetContainer { + + private static final String CLICK_EVENT_IDENTIFIER = VPanelPaintable.CLICK_EVENT_IDENTIFIER; + + public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().rendering = true; + // As VView is not created in the same way as all other paintables we + // have to set the id here + setId(uidl.getId()); + getWidgetForPaintable().id = uidl.getId(); + boolean firstPaint = getWidgetForPaintable().connection == null; + getWidgetForPaintable().connection = client; + + getWidgetForPaintable().immediate = uidl.hasAttribute("immediate"); + getWidgetForPaintable().resizeLazy = uidl + .hasAttribute(VView.RESIZE_LAZY); + String newTheme = uidl.getStringAttribute("theme"); + if (getWidgetForPaintable().theme != null + && !newTheme.equals(getWidgetForPaintable().theme)) { + // Complete page refresh is needed due css can affect layout + // calculations etc + getWidgetForPaintable().reloadHostPage(); + } else { + getWidgetForPaintable().theme = newTheme; + } + if (uidl.hasAttribute("style")) { + getWidgetForPaintable().setStyleName( + getWidgetForPaintable().getStylePrimaryName() + " " + + uidl.getStringAttribute("style")); + } + + clickEventHandler.handleEventHandlerRegistration(client); + + if (!getWidgetForPaintable().isEmbedded() + && uidl.hasAttribute("caption")) { + // only change window title if we're in charge of the whole page + com.google.gwt.user.client.Window.setTitle(uidl + .getStringAttribute("caption")); + } + + // Process children + int childIndex = 0; + + // Open URL:s + boolean isClosed = false; // was this window closed? + while (childIndex < uidl.getChildCount() + && "open".equals(uidl.getChildUIDL(childIndex).getTag())) { + final UIDL open = uidl.getChildUIDL(childIndex); + final String url = client.translateVaadinUri(open + .getStringAttribute("src")); + final String target = open.getStringAttribute("name"); + if (target == null) { + // source will be opened to this browser window, but we may have + // to finish rendering this window in case this is a download + // (and window stays open). + Scheduler.get().scheduleDeferred(new Command() { + public void execute() { + VView.goTo(url); + } + }); + } else if ("_self".equals(target)) { + // This window is closing (for sure). Only other opens are + // relevant in this change. See #3558, #2144 + isClosed = true; + VView.goTo(url); + } else { + String options; + if (open.hasAttribute("border")) { + if (open.getStringAttribute("border").equals("minimal")) { + options = "menubar=yes,location=no,status=no"; + } else { + options = "menubar=no,location=no,status=no"; + } + + } else { + options = "resizable=yes,menubar=yes,toolbar=yes,directories=yes,location=yes,scrollbars=yes,status=yes"; + } + + if (open.hasAttribute("width")) { + int w = open.getIntAttribute("width"); + options += ",width=" + w; + } + if (open.hasAttribute("height")) { + int h = open.getIntAttribute("height"); + options += ",height=" + h; + } + + Window.open(url, target, options); + } + childIndex++; + } + if (isClosed) { + // don't render the content, something else will be opened to this + // browser view + getWidgetForPaintable().rendering = false; + return; + } + + // Draw this application level window + UIDL childUidl = uidl.getChildUIDL(childIndex); + final VPaintableWidget lo = client.getPaintable(childUidl); + + if (getWidgetForPaintable().layout != null) { + if (getWidgetForPaintable().layout != lo) { + // remove old + client.unregisterPaintable(getWidgetForPaintable().layout); + // add new + getWidgetForPaintable().setWidget(lo.getWidgetForPaintable()); + getWidgetForPaintable().layout = lo; + } + } else { + getWidgetForPaintable().setWidget(lo.getWidgetForPaintable()); + getWidgetForPaintable().layout = lo; + } + + getWidgetForPaintable().layout.updateFromUIDL(childUidl, client); + if (!childUidl.getBooleanAttribute("cached")) { + getWidgetForPaintable().updateParentFrameSize(); + } + + // Save currently open subwindows to track which will need to be closed + final HashSet<VWindow> removedSubWindows = new HashSet<VWindow>( + getWidgetForPaintable().subWindows); + + // Handle other UIDL children + while ((childUidl = uidl.getChildUIDL(++childIndex)) != null) { + String tag = childUidl.getTag().intern(); + if (tag == "actions") { + if (getWidgetForPaintable().actionHandler == null) { + getWidgetForPaintable().actionHandler = new ShortcutActionHandler( + getWidgetForPaintable().id, client); + } + getWidgetForPaintable().actionHandler + .updateActionMap(childUidl); + } else if (tag == "execJS") { + String script = childUidl.getStringAttribute("script"); + VView.eval(script); + } else if (tag == "notifications") { + for (final Iterator<?> it = childUidl.getChildIterator(); it + .hasNext();) { + final UIDL notification = (UIDL) it.next(); + VNotification.showNotification(client, notification); + } + } else { + // subwindows + final VWindowPaintable w = (VWindowPaintable) client + .getPaintable(childUidl); + VWindow windowWidget = w.getWidgetForPaintable(); + if (getWidgetForPaintable().subWindows.contains(windowWidget)) { + removedSubWindows.remove(windowWidget); + } else { + getWidgetForPaintable().subWindows.add(windowWidget); + } + w.updateFromUIDL(childUidl, client); + } + } + + // Close old windows which where not in UIDL anymore + for (final Iterator<VWindow> rem = removedSubWindows.iterator(); rem + .hasNext();) { + final VWindow w = rem.next(); + client.unregisterPaintable(VPaintableMap.get(getConnection()) + .getPaintable(w)); + getWidgetForPaintable().subWindows.remove(w); + w.hide(); + } + + if (uidl.hasAttribute("focused")) { + // set focused component when render phase is finished + Scheduler.get().scheduleDeferred(new Command() { + public void execute() { + VPaintableWidget paintable = (VPaintableWidget) uidl + .getPaintableAttribute("focused", getConnection()); + + final Widget toBeFocused = paintable + .getWidgetForPaintable(); + /* + * Two types of Widgets can be focused, either implementing + * GWT HasFocus of a thinner Vaadin specific Focusable + * interface. + */ + if (toBeFocused instanceof com.google.gwt.user.client.ui.Focusable) { + final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) toBeFocused; + toBeFocusedWidget.setFocus(true); + } else if (toBeFocused instanceof Focusable) { + ((Focusable) toBeFocused).focus(); + } else { + VConsole.log("Could not focus component"); + } + } + }); + } + + // Add window listeners on first paint, to prevent premature + // variablechanges + if (firstPaint) { + Window.addWindowClosingHandler(getWidgetForPaintable()); + Window.addResizeHandler(getWidgetForPaintable()); + } + + getWidgetForPaintable().onResize(); + + // finally set scroll position from UIDL + if (uidl.hasVariable("scrollTop")) { + getWidgetForPaintable().scrollable = true; + getWidgetForPaintable().scrollTop = uidl + .getIntVariable("scrollTop"); + DOM.setElementPropertyInt(getWidgetForPaintable().getElement(), + "scrollTop", getWidgetForPaintable().scrollTop); + getWidgetForPaintable().scrollLeft = uidl + .getIntVariable("scrollLeft"); + DOM.setElementPropertyInt(getWidgetForPaintable().getElement(), + "scrollLeft", getWidgetForPaintable().scrollLeft); + } else { + getWidgetForPaintable().scrollable = false; + } + + // Safari workaround must be run after scrollTop is updated as it sets + // scrollTop using a deferred command. + if (BrowserInfo.get().isSafari()) { + Util.runWebkitOverflowAutoFix(getWidgetForPaintable().getElement()); + } + + getWidgetForPaintable().scrollIntoView(uidl); + + if (uidl.hasAttribute(VView.FRAGMENT_VARIABLE)) { + getWidgetForPaintable().currentFragment = uidl + .getStringAttribute(VView.FRAGMENT_VARIABLE); + if (!getWidgetForPaintable().currentFragment.equals(History + .getToken())) { + History.newItem(getWidgetForPaintable().currentFragment, true); + } + } else { + // Initial request for which the server doesn't yet have a fragment + // (and haven't shown any interest in getting one) + getWidgetForPaintable().currentFragment = History.getToken(); + + // Include current fragment in the next request + client.updateVariable(getWidgetForPaintable().id, + VView.FRAGMENT_VARIABLE, + getWidgetForPaintable().currentFragment, false); + } + + getWidgetForPaintable().rendering = false; + } + + public void init(String rootPanelId, + ApplicationConnection applicationConnection) { + DOM.sinkEvents(getWidgetForPaintable().getElement(), Event.ONKEYDOWN + | Event.ONSCROLL); + + // iview is focused when created so element needs tabIndex + // 1 due 0 is at the end of natural tabbing order + DOM.setElementProperty(getWidgetForPaintable().getElement(), + "tabIndex", "1"); + + RootPanel root = RootPanel.get(rootPanelId); + + // Remove the v-app-loading or any splash screen added inside the div by + // the user + root.getElement().setInnerHTML(""); + // For backwards compatibility with static index pages only. + // No longer added by AbstractApplicationServlet/Portlet + root.removeStyleName("v-app-loading"); + + String themeUri = applicationConnection.getConfiguration() + .getThemeUri(); + String themeName = themeUri.substring(themeUri.lastIndexOf('/')); + themeName = themeName.replaceAll("[^a-zA-Z0-9]", ""); + root.addStyleName("v-theme-" + themeName); + + root.add(getWidgetForPaintable()); + + if (applicationConnection.getConfiguration().isStandalone()) { + // set focus to iview element by default to listen possible keyboard + // shortcuts. For embedded applications this is unacceptable as we + // don't want to steal focus from the main page nor we don't want + // side-effects from focusing (scrollIntoView). + getWidgetForPaintable().getElement().focus(); + } + + getWidgetForPaintable().parentFrame = VView.getParentFrame(); + } + + private ClickEventHandler clickEventHandler = new ClickEventHandler(this, + CLICK_EVENT_IDENTIFIER) { + + @Override + protected <H extends EventHandler> HandlerRegistration registerHandler( + H handler, Type<H> type) { + return getWidgetForPaintable().addDomHandler(handler, type); + } + }; + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + // NOP The main view never draws caption for its layout + } + + @Override + public VView getWidgetForPaintable() { + return (VView) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VView.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java index 662b77a7b0..d4c8f74605 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java @@ -643,7 +643,7 @@ public class VWindow extends VOverlay implements Container, } private void onResizeEvent(Event event) { - if (resizable) { + if (resizable && Util.isTouchEventOrLeftMouseButton(event)) { switch (event.getTypeInt()) { case Event.ONMOUSEDOWN: case Event.ONTOUCHSTART: @@ -860,6 +860,10 @@ public class VWindow extends VOverlay implements Container, } private void onDragEvent(Event event) { + if (!Util.isTouchEventOrLeftMouseButton(event)) { + return; + } + switch (DOM.eventGetType(event)) { case Event.ONTOUCHSTART: if (event.getTouches().length() > 1) { @@ -971,7 +975,7 @@ public class VWindow extends VOverlay implements Container, } public RenderSpace getAllocatedSpace(Widget child) { - if (child == layout) { + if (child == layout.getWidgetForPaintable()) { return renderSpace; } else { // Exception ?? @@ -980,7 +984,7 @@ public class VWindow extends VOverlay implements Container, } public boolean hasChildComponent(Widget component) { - if (component == layout) { + if (component == layout.getWidgetForPaintable()) { return true; } else { return false; @@ -1040,8 +1044,4 @@ public class VWindow extends VOverlay implements Container, contentPanel.focus(); } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VWindowPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VWindowPaintable.java index 25fd951dd9..633e28d0c3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VWindowPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VWindowPaintable.java @@ -1,296 +1,299 @@ -package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.DomEvent.Type;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Frame;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener;
-
-public class VWindowPaintable extends VAbstractPaintableWidgetContainer
- implements BeforeShortcutActionListener {
-
- private static final String CLICK_EVENT_IDENTIFIER = VPanelPaintable.CLICK_EVENT_IDENTIFIER;
-
- private ClickEventHandler clickEventHandler = new ClickEventHandler(this,
- CLICK_EVENT_IDENTIFIER) {
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- return getWidgetForPaintable().addDomHandler(handler, type);
- }
- };
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().id = uidl.getId();
- getWidgetForPaintable().client = client;
-
- // Workaround needed for Testing Tools (GWT generates window DOM
- // slightly different in different browsers).
- DOM.setElementProperty(getWidgetForPaintable().closeBox, "id",
- getWidgetForPaintable().id + "_window_close");
-
- if (uidl.hasAttribute("invisible")) {
- getWidgetForPaintable().hide();
- return;
- }
-
- if (!uidl.hasAttribute("cached")) {
- if (uidl.getBooleanAttribute("modal") != getWidgetForPaintable().vaadinModality) {
- getWidgetForPaintable().setVaadinModality(
- !getWidgetForPaintable().vaadinModality);
- }
- if (!getWidgetForPaintable().isAttached()) {
- getWidgetForPaintable().setVisible(false); // hide until
- // possible centering
- getWidgetForPaintable().show();
- }
- if (uidl.getBooleanAttribute("resizable") != getWidgetForPaintable().resizable) {
- getWidgetForPaintable().setResizable(
- !getWidgetForPaintable().resizable);
- }
- getWidgetForPaintable().resizeLazy = uidl
- .hasAttribute(VView.RESIZE_LAZY);
-
- getWidgetForPaintable().setDraggable(
- !uidl.hasAttribute("fixedposition"));
-
- // Caption must be set before required header size is measured. If
- // the caption attribute is missing the caption should be cleared.
- getWidgetForPaintable().setCaption(
- uidl.getStringAttribute("caption"),
- uidl.getStringAttribute("icon"));
- }
-
- getWidgetForPaintable().visibilityChangesDisabled = true;
- if (client.updateComponent(this, uidl, false)) {
- return;
- }
- getWidgetForPaintable().visibilityChangesDisabled = false;
-
- clickEventHandler.handleEventHandlerRegistration(client);
-
- getWidgetForPaintable().immediate = uidl.hasAttribute("immediate");
-
- getWidgetForPaintable().setClosable(
- !uidl.getBooleanAttribute("readonly"));
-
- // Initialize the position form UIDL
- int positionx = uidl.getIntVariable("positionx");
- int positiony = uidl.getIntVariable("positiony");
- if (positionx >= 0 || positiony >= 0) {
- if (positionx < 0) {
- positionx = 0;
- }
- if (positiony < 0) {
- positiony = 0;
- }
- getWidgetForPaintable().setPopupPosition(positionx, positiony);
- }
-
- boolean showingUrl = false;
- int childIndex = 0;
- UIDL childUidl = uidl.getChildUIDL(childIndex++);
- while ("open".equals(childUidl.getTag())) {
- // TODO multiple opens with the same target will in practice just
- // open the last one - should we fix that somehow?
- final String parsedUri = client.translateVaadinUri(childUidl
- .getStringAttribute("src"));
- if (!childUidl.hasAttribute("name")) {
- final Frame frame = new Frame();
- DOM.setStyleAttribute(frame.getElement(), "width", "100%");
- DOM.setStyleAttribute(frame.getElement(), "height", "100%");
- DOM.setStyleAttribute(frame.getElement(), "border", "0px");
- frame.setUrl(parsedUri);
- getWidgetForPaintable().contentPanel.setWidget(frame);
- showingUrl = true;
- } else {
- final String target = childUidl.getStringAttribute("name");
- Window.open(parsedUri, target, "");
- }
- childUidl = uidl.getChildUIDL(childIndex++);
- }
-
- final VPaintableWidget lo = client.getPaintable(childUidl);
- if (getWidgetForPaintable().layout != null) {
- if (getWidgetForPaintable().layout != lo) {
- // remove old
- client.unregisterPaintable(getWidgetForPaintable().layout);
- getWidgetForPaintable().contentPanel
- .remove(getWidgetForPaintable().layout
- .getWidgetForPaintable());
- // add new
- if (!showingUrl) {
- getWidgetForPaintable().contentPanel.setWidget(lo
- .getWidgetForPaintable());
- }
- getWidgetForPaintable().layout = lo;
- }
- } else if (!showingUrl) {
- getWidgetForPaintable().contentPanel.setWidget(lo
- .getWidgetForPaintable());
- getWidgetForPaintable().layout = lo;
- }
-
- getWidgetForPaintable().dynamicWidth = !uidl.hasAttribute("width");
- getWidgetForPaintable().dynamicHeight = !uidl.hasAttribute("height");
-
- getWidgetForPaintable().layoutRelativeWidth = uidl
- .hasAttribute("layoutRelativeWidth");
- getWidgetForPaintable().layoutRelativeHeight = uidl
- .hasAttribute("layoutRelativeHeight");
-
- if (getWidgetForPaintable().dynamicWidth
- && getWidgetForPaintable().layoutRelativeWidth) {
- /*
- * Relative layout width, fix window width before rendering (width
- * according to caption)
- */
- getWidgetForPaintable().setNaturalWidth();
- }
-
- getWidgetForPaintable().layout.updateFromUIDL(childUidl, client);
- if (!getWidgetForPaintable().dynamicHeight
- && getWidgetForPaintable().layoutRelativeWidth) {
- /*
- * Relative layout width, and fixed height. Must update the size to
- * be able to take scrollbars into account (layout gets narrower
- * space if it is higher than the window) -> only vertical scrollbar
- */
- client.runDescendentsLayout(getWidgetForPaintable());
- }
-
- /*
- * No explicit width is set and the layout does not have relative width
- * so fix the size according to the layout.
- */
- if (getWidgetForPaintable().dynamicWidth
- && !getWidgetForPaintable().layoutRelativeWidth) {
- getWidgetForPaintable().setNaturalWidth();
- }
-
- if (getWidgetForPaintable().dynamicHeight
- && getWidgetForPaintable().layoutRelativeHeight) {
- // Prevent resizing until height has been fixed
- getWidgetForPaintable().resizable = false;
- }
-
- // we may have actions and notifications
- if (uidl.getChildCount() > 1) {
- final int cnt = uidl.getChildCount();
- for (int i = 1; i < cnt; i++) {
- childUidl = uidl.getChildUIDL(i);
- if (childUidl.getTag().equals("actions")) {
- if (getWidgetForPaintable().shortcutHandler == null) {
- getWidgetForPaintable().shortcutHandler = new ShortcutActionHandler(
- getId(), client);
- }
- getWidgetForPaintable().shortcutHandler
- .updateActionMap(childUidl);
- }
- }
-
- }
-
- // setting scrollposition must happen after children is rendered
- getWidgetForPaintable().contentPanel.setScrollPosition(uidl
- .getIntVariable("scrollTop"));
- getWidgetForPaintable().contentPanel.setHorizontalScrollPosition(uidl
- .getIntVariable("scrollLeft"));
-
- // Center this window on screen if requested
- // This has to be here because we might not know the content size before
- // everything is painted into the window
- if (uidl.getBooleanAttribute("center")) {
- // mark as centered - this is unset on move/resize
- getWidgetForPaintable().centered = true;
- getWidgetForPaintable().center();
- } else {
- // don't try to center the window anymore
- getWidgetForPaintable().centered = false;
- }
- getWidgetForPaintable().updateShadowSizeAndPosition();
- getWidgetForPaintable().setVisible(true);
-
- boolean sizeReduced = false;
- // ensure window is not larger than browser window
- if (getWidgetForPaintable().getOffsetWidth() > Window.getClientWidth()) {
- getWidgetForPaintable().setWidth(Window.getClientWidth() + "px");
- sizeReduced = true;
- }
- if (getWidgetForPaintable().getOffsetHeight() > Window
- .getClientHeight()) {
- getWidgetForPaintable().setHeight(Window.getClientHeight() + "px");
- sizeReduced = true;
- }
-
- if (getWidgetForPaintable().dynamicHeight
- && getWidgetForPaintable().layoutRelativeHeight) {
- /*
- * Window height is undefined, layout is 100% high so the layout
- * should define the initial window height but on resize the layout
- * should be as high as the window. We fix the height to deal with
- * this.
- */
-
- int h = getWidgetForPaintable().contents.getOffsetHeight()
- + getWidgetForPaintable().getExtraHeight();
- int w = getWidgetForPaintable().getElement().getOffsetWidth();
-
- client.updateVariable(getId(), "height", h, false);
- client.updateVariable(getId(), "width", w, true);
- }
-
- if (sizeReduced) {
- // If we changed the size we need to update the size of the child
- // component if it is relative (#3407)
- client.runDescendentsLayout(getWidgetForPaintable());
- }
-
- Util.runWebkitOverflowAutoFix(getWidgetForPaintable().contentPanel
- .getElement());
-
- client.getView().getWidgetForPaintable().scrollIntoView(uidl);
-
- if (uidl.hasAttribute("bringToFront")) {
- /*
- * Focus as a side-efect. Will be overridden by
- * ApplicationConnection if another component was focused by the
- * server side.
- */
- getWidgetForPaintable().contentPanel.focus();
- getWidgetForPaintable().bringToFrontSequence = uidl
- .getIntAttribute("bringToFront");
- VWindow.deferOrdering();
- }
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- // NOP, window has own caption, layout captio not rendered
- }
-
- public void onBeforeShortcutAction(Event e) {
- // NOP, nothing to update just avoid workaround ( causes excess
- // blur/focus )
- }
-
- @Override
- public VWindow getWidgetForPaintable() {
- return (VWindow) super.getWidgetForPaintable();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VWindow.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.DomEvent.Type; +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Frame; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VPaintableWidget; +import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener; + +public class VWindowPaintable extends VAbstractPaintableWidgetContainer + implements BeforeShortcutActionListener { + + private static final String CLICK_EVENT_IDENTIFIER = VPanelPaintable.CLICK_EVENT_IDENTIFIER; + + private ClickEventHandler clickEventHandler = new ClickEventHandler(this, + CLICK_EVENT_IDENTIFIER) { + + @Override + protected <H extends EventHandler> HandlerRegistration registerHandler( + H handler, Type<H> type) { + return getWidgetForPaintable().addDomHandler(handler, type); + } + }; + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().id = uidl.getId(); + getWidgetForPaintable().client = client; + + // Workaround needed for Testing Tools (GWT generates window DOM + // slightly different in different browsers). + DOM.setElementProperty(getWidgetForPaintable().closeBox, "id", + getWidgetForPaintable().id + "_window_close"); + + if (uidl.hasAttribute("invisible")) { + getWidgetForPaintable().hide(); + return; + } + + if (!uidl.hasAttribute("cached")) { + if (uidl.getBooleanAttribute("modal") != getWidgetForPaintable().vaadinModality) { + getWidgetForPaintable().setVaadinModality( + !getWidgetForPaintable().vaadinModality); + } + if (!getWidgetForPaintable().isAttached()) { + getWidgetForPaintable().setVisible(false); // hide until + // possible centering + getWidgetForPaintable().show(); + } + if (uidl.getBooleanAttribute("resizable") != getWidgetForPaintable().resizable) { + getWidgetForPaintable().setResizable( + !getWidgetForPaintable().resizable); + } + getWidgetForPaintable().resizeLazy = uidl + .hasAttribute(VView.RESIZE_LAZY); + + getWidgetForPaintable().setDraggable( + !uidl.hasAttribute("fixedposition")); + + // Caption must be set before required header size is measured. If + // the caption attribute is missing the caption should be cleared. + getWidgetForPaintable().setCaption( + uidl.getStringAttribute("caption"), + uidl.getStringAttribute("icon")); + } + + getWidgetForPaintable().visibilityChangesDisabled = true; + if (client.updateComponent(this, uidl, false)) { + return; + } + getWidgetForPaintable().visibilityChangesDisabled = false; + + clickEventHandler.handleEventHandlerRegistration(client); + + getWidgetForPaintable().immediate = uidl.hasAttribute("immediate"); + + getWidgetForPaintable().setClosable( + !uidl.getBooleanAttribute("readonly")); + + // Initialize the position form UIDL + int positionx = uidl.getIntVariable("positionx"); + int positiony = uidl.getIntVariable("positiony"); + if (positionx >= 0 || positiony >= 0) { + if (positionx < 0) { + positionx = 0; + } + if (positiony < 0) { + positiony = 0; + } + getWidgetForPaintable().setPopupPosition(positionx, positiony); + } + + boolean showingUrl = false; + int childIndex = 0; + UIDL childUidl = uidl.getChildUIDL(childIndex++); + while ("open".equals(childUidl.getTag())) { + // TODO multiple opens with the same target will in practice just + // open the last one - should we fix that somehow? + final String parsedUri = client.translateVaadinUri(childUidl + .getStringAttribute("src")); + if (!childUidl.hasAttribute("name")) { + final Frame frame = new Frame(); + DOM.setStyleAttribute(frame.getElement(), "width", "100%"); + DOM.setStyleAttribute(frame.getElement(), "height", "100%"); + DOM.setStyleAttribute(frame.getElement(), "border", "0px"); + frame.setUrl(parsedUri); + getWidgetForPaintable().contentPanel.setWidget(frame); + showingUrl = true; + } else { + final String target = childUidl.getStringAttribute("name"); + Window.open(parsedUri, target, ""); + } + childUidl = uidl.getChildUIDL(childIndex++); + } + + final VPaintableWidget lo = client.getPaintable(childUidl); + if (getWidgetForPaintable().layout != null) { + if (getWidgetForPaintable().layout != lo) { + // remove old + client.unregisterPaintable(getWidgetForPaintable().layout); + getWidgetForPaintable().contentPanel + .remove(getWidgetForPaintable().layout + .getWidgetForPaintable()); + // add new + if (!showingUrl) { + getWidgetForPaintable().contentPanel.setWidget(lo + .getWidgetForPaintable()); + } + getWidgetForPaintable().layout = lo; + } + } else if (!showingUrl) { + getWidgetForPaintable().contentPanel.setWidget(lo + .getWidgetForPaintable()); + getWidgetForPaintable().layout = lo; + } + + getWidgetForPaintable().dynamicWidth = !uidl.hasAttribute("width"); + getWidgetForPaintable().dynamicHeight = !uidl.hasAttribute("height"); + + getWidgetForPaintable().layoutRelativeWidth = uidl + .hasAttribute("layoutRelativeWidth"); + getWidgetForPaintable().layoutRelativeHeight = uidl + .hasAttribute("layoutRelativeHeight"); + + if (getWidgetForPaintable().dynamicWidth + && getWidgetForPaintable().layoutRelativeWidth) { + /* + * Relative layout width, fix window width before rendering (width + * according to caption) + */ + getWidgetForPaintable().setNaturalWidth(); + } + + getWidgetForPaintable().layout.updateFromUIDL(childUidl, client); + if (!getWidgetForPaintable().dynamicHeight + && getWidgetForPaintable().layoutRelativeWidth) { + /* + * Relative layout width, and fixed height. Must update the size to + * be able to take scrollbars into account (layout gets narrower + * space if it is higher than the window) -> only vertical scrollbar + */ + client.runDescendentsLayout(getWidgetForPaintable()); + } + + /* + * No explicit width is set and the layout does not have relative width + * so fix the size according to the layout. + */ + if (getWidgetForPaintable().dynamicWidth + && !getWidgetForPaintable().layoutRelativeWidth) { + getWidgetForPaintable().setNaturalWidth(); + } + + if (getWidgetForPaintable().dynamicHeight + && getWidgetForPaintable().layoutRelativeHeight) { + // Prevent resizing until height has been fixed + getWidgetForPaintable().resizable = false; + } + + // we may have actions and notifications + if (uidl.getChildCount() > 1) { + final int cnt = uidl.getChildCount(); + for (int i = 1; i < cnt; i++) { + childUidl = uidl.getChildUIDL(i); + if (childUidl.getTag().equals("actions")) { + if (getWidgetForPaintable().shortcutHandler == null) { + getWidgetForPaintable().shortcutHandler = new ShortcutActionHandler( + getId(), client); + } + getWidgetForPaintable().shortcutHandler + .updateActionMap(childUidl); + } + } + + } + + // setting scrollposition must happen after children is rendered + getWidgetForPaintable().contentPanel.setScrollPosition(uidl + .getIntVariable("scrollTop")); + getWidgetForPaintable().contentPanel.setHorizontalScrollPosition(uidl + .getIntVariable("scrollLeft")); + + // Center this window on screen if requested + // This has to be here because we might not know the content size before + // everything is painted into the window + if (uidl.getBooleanAttribute("center")) { + // mark as centered - this is unset on move/resize + getWidgetForPaintable().centered = true; + getWidgetForPaintable().center(); + } else { + // don't try to center the window anymore + getWidgetForPaintable().centered = false; + } + getWidgetForPaintable().updateShadowSizeAndPosition(); + getWidgetForPaintable().setVisible(true); + + boolean sizeReduced = false; + // ensure window is not larger than browser window + if (getWidgetForPaintable().getOffsetWidth() > Window.getClientWidth()) { + getWidgetForPaintable().setWidth(Window.getClientWidth() + "px"); + sizeReduced = true; + } + if (getWidgetForPaintable().getOffsetHeight() > Window + .getClientHeight()) { + getWidgetForPaintable().setHeight(Window.getClientHeight() + "px"); + sizeReduced = true; + } + + if (getWidgetForPaintable().dynamicHeight + && getWidgetForPaintable().layoutRelativeHeight) { + /* + * Window height is undefined, layout is 100% high so the layout + * should define the initial window height but on resize the layout + * should be as high as the window. We fix the height to deal with + * this. + */ + + int h = getWidgetForPaintable().contents.getOffsetHeight() + + getWidgetForPaintable().getExtraHeight(); + int w = getWidgetForPaintable().getElement().getOffsetWidth(); + + client.updateVariable(getId(), "height", h, false); + client.updateVariable(getId(), "width", w, true); + } + + if (sizeReduced) { + // If we changed the size we need to update the size of the child + // component if it is relative (#3407) + client.runDescendentsLayout(getWidgetForPaintable()); + } + + Util.runWebkitOverflowAutoFix(getWidgetForPaintable().contentPanel + .getElement()); + + client.getView().getWidgetForPaintable().scrollIntoView(uidl); + + if (uidl.hasAttribute("bringToFront")) { + /* + * Focus as a side-efect. Will be overridden by + * ApplicationConnection if another component was focused by the + * server side. + */ + getWidgetForPaintable().contentPanel.focus(); + getWidgetForPaintable().bringToFrontSequence = uidl + .getIntAttribute("bringToFront"); + VWindow.deferOrdering(); + } + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + // NOP, window has own caption, layout captio not rendered + } + + public void onBeforeShortcutAction(Event e) { + // NOP, nothing to update just avoid workaround ( causes excess + // blur/focus ) + } + + @Override + public VWindow getWidgetForPaintable() { + return (VWindow) super.getWidgetForPaintable(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VWindow.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java index 269afde25d..c57f705c75 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/label/VLabelPaintable.java @@ -1,71 +1,71 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui.label;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.PreElement;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget;
-
-public class VLabelPaintable extends VAbstractPaintableWidget {
- public VLabelPaintable() {
- }
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- boolean sinkOnloads = false;
-
- final String mode = uidl.getStringAttribute("mode");
- if (mode == null || "text".equals(mode)) {
- getWidgetForPaintable().setText(uidl.getChildString(0));
- } else if ("pre".equals(mode)) {
- PreElement preElement = Document.get().createPreElement();
- preElement.setInnerText(uidl.getChildUIDL(0).getChildString(0));
- // clear existing content
- getWidgetForPaintable().setHTML("");
- // add preformatted text to dom
- getWidgetForPaintable().getElement().appendChild(preElement);
- } else if ("uidl".equals(mode)) {
- getWidgetForPaintable().setHTML(uidl.getChildrenAsXML());
- } else if ("xhtml".equals(mode)) {
- UIDL content = uidl.getChildUIDL(0).getChildUIDL(0);
- if (content.getChildCount() > 0) {
- getWidgetForPaintable().setHTML(content.getChildString(0));
- } else {
- getWidgetForPaintable().setHTML("");
- }
- sinkOnloads = true;
- } else if ("xml".equals(mode)) {
- getWidgetForPaintable().setHTML(
- uidl.getChildUIDL(0).getChildString(0));
- } else if ("raw".equals(mode)) {
- getWidgetForPaintable().setHTML(
- uidl.getChildUIDL(0).getChildString(0));
- sinkOnloads = true;
- } else {
- getWidgetForPaintable().setText("");
- }
- if (sinkOnloads) {
- Util.sinkOnloadForImages(getWidgetForPaintable().getElement());
- }
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VLabel.class);
- }
-
- @Override
- public VLabel getWidgetForPaintable() {
- return (VLabel) super.getWidgetForPaintable();
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.label; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.PreElement; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget; + +public class VLabelPaintable extends VAbstractPaintableWidget { + public VLabelPaintable() { + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, true)) { + return; + } + + boolean sinkOnloads = false; + + final String mode = uidl.getStringAttribute("mode"); + if (mode == null || "text".equals(mode)) { + getWidgetForPaintable().setText(uidl.getChildString(0)); + } else if ("pre".equals(mode)) { + PreElement preElement = Document.get().createPreElement(); + preElement.setInnerText(uidl.getChildUIDL(0).getChildString(0)); + // clear existing content + getWidgetForPaintable().setHTML(""); + // add preformatted text to dom + getWidgetForPaintable().getElement().appendChild(preElement); + } else if ("uidl".equals(mode)) { + getWidgetForPaintable().setHTML(uidl.getChildrenAsXML()); + } else if ("xhtml".equals(mode)) { + UIDL content = uidl.getChildUIDL(0).getChildUIDL(0); + if (content.getChildCount() > 0) { + getWidgetForPaintable().setHTML(content.getChildString(0)); + } else { + getWidgetForPaintable().setHTML(""); + } + sinkOnloads = true; + } else if ("xml".equals(mode)) { + getWidgetForPaintable().setHTML( + uidl.getChildUIDL(0).getChildString(0)); + } else if ("raw".equals(mode)) { + getWidgetForPaintable().setHTML( + uidl.getChildUIDL(0).getChildString(0)); + sinkOnloads = true; + } else { + getWidgetForPaintable().setText(""); + } + if (sinkOnloads) { + Util.sinkOnloadForImages(getWidgetForPaintable().getElement()); + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VLabel.class); + } + + @Override + public VLabel getWidgetForPaintable() { + return (VLabel) super.getWidgetForPaintable(); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayoutPaintable.java index e99425311b..c41652fb3d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayoutPaintable.java @@ -1,81 +1,84 @@ -package com.vaadin.terminal.gwt.client.ui.layout;
-
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidgetContainer;
-import com.vaadin.terminal.gwt.client.ui.VMarginInfo;
-
-public abstract class CellBasedLayoutPaintable extends
- VAbstractPaintableWidgetContainer {
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().client = client;
-
- // Only non-cached UIDL:s can introduce changes
- if (uidl.getBooleanAttribute("cached")) {
- return;
- }
-
- /**
- * Margin and spacind detection depends on classNames and must be set
- * before setting size. Here just update the details from UIDL and from
- * overridden setStyleName run actual margin detections.
- */
- updateMarginAndSpacingInfo(uidl);
-
- /*
- * This call should be made first. Ensure correct implementation, handle
- * size etc.
- */
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- handleDynamicDimensions(uidl);
- }
-
- private void handleDynamicDimensions(UIDL uidl) {
- String w = uidl.hasAttribute("width") ? uidl
- .getStringAttribute("width") : "";
-
- String h = uidl.hasAttribute("height") ? uidl
- .getStringAttribute("height") : "";
-
- if (w.equals("")) {
- getWidgetForPaintable().dynamicWidth = true;
- } else {
- getWidgetForPaintable().dynamicWidth = false;
- }
-
- if (h.equals("")) {
- getWidgetForPaintable().dynamicHeight = true;
- } else {
- getWidgetForPaintable().dynamicHeight = false;
- }
-
- }
-
- void updateMarginAndSpacingInfo(UIDL uidl) {
- if (!uidl.hasAttribute("invisible")) {
- int bitMask = uidl.getIntAttribute("margins");
- if (getWidgetForPaintable().activeMarginsInfo.getBitMask() != bitMask) {
- getWidgetForPaintable().activeMarginsInfo = new VMarginInfo(
- bitMask);
- getWidgetForPaintable().marginsNeedsRecalculation = true;
- }
- boolean spacing = uidl.getBooleanAttribute("spacing");
- if (spacing != getWidgetForPaintable().spacingEnabled) {
- getWidgetForPaintable().marginsNeedsRecalculation = true;
- getWidgetForPaintable().spacingEnabled = spacing;
- }
- }
- }
-
- @Override
- protected abstract CellBasedLayout createWidget();
-
- @Override
- public CellBasedLayout getWidgetForPaintable() {
- return (CellBasedLayout) super.getWidgetForPaintable();
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.layout; + +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidgetContainer; +import com.vaadin.terminal.gwt.client.ui.VMarginInfo; + +public abstract class CellBasedLayoutPaintable extends + VAbstractPaintableWidgetContainer { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().client = client; + + // Only non-cached UIDL:s can introduce changes + if (uidl.getBooleanAttribute("cached")) { + return; + } + + /** + * Margin and spacind detection depends on classNames and must be set + * before setting size. Here just update the details from UIDL and from + * overridden setStyleName run actual margin detections. + */ + updateMarginAndSpacingInfo(uidl); + + /* + * This call should be made first. Ensure correct implementation, handle + * size etc. + */ + if (client.updateComponent(this, uidl, true)) { + return; + } + + handleDynamicDimensions(uidl); + } + + private void handleDynamicDimensions(UIDL uidl) { + String w = uidl.hasAttribute("width") ? uidl + .getStringAttribute("width") : ""; + + String h = uidl.hasAttribute("height") ? uidl + .getStringAttribute("height") : ""; + + if (w.equals("")) { + getWidgetForPaintable().dynamicWidth = true; + } else { + getWidgetForPaintable().dynamicWidth = false; + } + + if (h.equals("")) { + getWidgetForPaintable().dynamicHeight = true; + } else { + getWidgetForPaintable().dynamicHeight = false; + } + + } + + void updateMarginAndSpacingInfo(UIDL uidl) { + if (!uidl.hasAttribute("invisible")) { + int bitMask = uidl.getIntAttribute("margins"); + if (getWidgetForPaintable().activeMarginsInfo.getBitMask() != bitMask) { + getWidgetForPaintable().activeMarginsInfo = new VMarginInfo( + bitMask); + getWidgetForPaintable().marginsNeedsRecalculation = true; + } + boolean spacing = uidl.getBooleanAttribute("spacing"); + if (spacing != getWidgetForPaintable().spacingEnabled) { + getWidgetForPaintable().marginsNeedsRecalculation = true; + getWidgetForPaintable().spacingEnabled = spacing; + } + } + } + + @Override + protected abstract CellBasedLayout createWidget(); + + @Override + public CellBasedLayout getWidgetForPaintable() { + return (CellBasedLayout) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java b/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java index a586929d13..c1678369b3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java +++ b/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java @@ -346,8 +346,4 @@ public class VRichTextArea extends Composite implements Field, ChangeHandler, rta.setTabIndex(index); } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextAreaPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextAreaPaintable.java index 477cd13dd5..ec83f294f2 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextAreaPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextAreaPaintable.java @@ -1,76 +1,79 @@ -package com.vaadin.terminal.gwt.client.ui.richtextarea;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener;
-import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget;
-
-public class VRichTextAreaPaintable extends VAbstractPaintableWidget implements
- BeforeShortcutActionListener {
-
- public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) {
- getWidgetForPaintable().client = client;
- getWidgetForPaintable().id = uidl.getId();
-
- if (uidl.hasVariable("text")) {
- getWidgetForPaintable().currentValue = uidl
- .getStringVariable("text");
- if (getWidgetForPaintable().rta.isAttached()) {
- getWidgetForPaintable().rta
- .setHTML(getWidgetForPaintable().currentValue);
- } else {
- getWidgetForPaintable().html
- .setHTML(getWidgetForPaintable().currentValue);
- }
- }
- if (!uidl.hasAttribute("cached")) {
- getWidgetForPaintable().setEnabled(
- !uidl.getBooleanAttribute("disabled"));
- }
-
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- getWidgetForPaintable().setReadOnly(
- uidl.getBooleanAttribute("readonly"));
- getWidgetForPaintable().immediate = uidl
- .getBooleanAttribute("immediate");
- int newMaxLength = uidl.hasAttribute("maxLength") ? uidl
- .getIntAttribute("maxLength") : -1;
- if (newMaxLength >= 0) {
- if (getWidgetForPaintable().maxLength == -1) {
- getWidgetForPaintable().keyPressHandler = getWidgetForPaintable().rta
- .addKeyPressHandler(getWidgetForPaintable());
- }
- getWidgetForPaintable().maxLength = newMaxLength;
- } else if (getWidgetForPaintable().maxLength != -1) {
- getWidgetForPaintable().getElement().setAttribute("maxlength", "");
- getWidgetForPaintable().maxLength = -1;
- getWidgetForPaintable().keyPressHandler.removeHandler();
- }
-
- if (uidl.hasAttribute("selectAll")) {
- getWidgetForPaintable().selectAll();
- }
-
- }
-
- public void onBeforeShortcutAction(Event e) {
- getWidgetForPaintable().synchronizeContentToServer();
- }
-
- @Override
- public VRichTextArea getWidgetForPaintable() {
- return (VRichTextArea) super.getWidgetForPaintable();
- };
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VRichTextArea.class);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.richtextarea; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener; +import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget; + +public class VRichTextAreaPaintable extends VAbstractPaintableWidget implements + BeforeShortcutActionListener { + + public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().client = client; + getWidgetForPaintable().id = uidl.getId(); + + if (uidl.hasVariable("text")) { + getWidgetForPaintable().currentValue = uidl + .getStringVariable("text"); + if (getWidgetForPaintable().rta.isAttached()) { + getWidgetForPaintable().rta + .setHTML(getWidgetForPaintable().currentValue); + } else { + getWidgetForPaintable().html + .setHTML(getWidgetForPaintable().currentValue); + } + } + if (!uidl.hasAttribute("cached")) { + getWidgetForPaintable().setEnabled( + !uidl.getBooleanAttribute("disabled")); + } + + if (client.updateComponent(this, uidl, true)) { + return; + } + + getWidgetForPaintable().setReadOnly( + uidl.getBooleanAttribute("readonly")); + getWidgetForPaintable().immediate = uidl + .getBooleanAttribute("immediate"); + int newMaxLength = uidl.hasAttribute("maxLength") ? uidl + .getIntAttribute("maxLength") : -1; + if (newMaxLength >= 0) { + if (getWidgetForPaintable().maxLength == -1) { + getWidgetForPaintable().keyPressHandler = getWidgetForPaintable().rta + .addKeyPressHandler(getWidgetForPaintable()); + } + getWidgetForPaintable().maxLength = newMaxLength; + } else if (getWidgetForPaintable().maxLength != -1) { + getWidgetForPaintable().getElement().setAttribute("maxlength", ""); + getWidgetForPaintable().maxLength = -1; + getWidgetForPaintable().keyPressHandler.removeHandler(); + } + + if (uidl.hasAttribute("selectAll")) { + getWidgetForPaintable().selectAll(); + } + + } + + public void onBeforeShortcutAction(Event e) { + getWidgetForPaintable().synchronizeContentToServer(); + } + + @Override + public VRichTextArea getWidgetForPaintable() { + return (VRichTextArea) super.getWidgetForPaintable(); + }; + + @Override + protected Widget createWidget() { + return GWT.create(VRichTextArea.class); + } + +} diff --git a/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java b/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java index 93627c1ff1..2c9828b66b 100644 --- a/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java +++ b/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java @@ -1,175 +1,175 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.portlet.ClientDataRequest;
-import javax.portlet.PortletRequest;
-import javax.portlet.ResourceRequest;
-
-import com.vaadin.terminal.CombinedRequest;
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.WrappedRequest;
-
-/**
- * Wrapper for {@link PortletRequest} and its subclasses.
- *
- * @author Vaadin Ltd.
- * @since 7.0
- *
- * @see WrappedRequest
- * @see WrappedPortletResponse
- */
-public class WrappedPortletRequest implements WrappedRequest {
-
- private final PortletRequest request;
- private final DeploymentConfiguration deploymentConfiguration;
-
- /**
- * Wraps a portlet request and an associated deployment configuration
- *
- * @param request
- * the portlet request to wrap
- * @param deploymentConfiguration
- * the associated deployment configuration
- */
- public WrappedPortletRequest(PortletRequest request,
- DeploymentConfiguration deploymentConfiguration) {
- this.request = request;
- this.deploymentConfiguration = deploymentConfiguration;
- }
-
- public Object getAttribute(String name) {
- return request.getAttribute(name);
- }
-
- public int getContentLength() {
- try {
- return ((ClientDataRequest) request).getContentLength();
- } catch (ClassCastException e) {
- throw new IllegalStateException(
- "Content lenght only available for ClientDataRequests");
- }
- }
-
- public InputStream getInputStream() throws IOException {
- try {
- return ((ClientDataRequest) request).getPortletInputStream();
- } catch (ClassCastException e) {
- throw new IllegalStateException(
- "Input data only available for ClientDataRequests");
- }
- }
-
- public String getParameter(String name) {
- return request.getParameter(name);
- }
-
- public Map<String, String[]> getParameterMap() {
- return request.getParameterMap();
- }
-
- public void setAttribute(String name, Object o) {
- request.setAttribute(name, o);
- }
-
- public String getRequestPathInfo() {
- if (request instanceof ResourceRequest) {
- return ((ResourceRequest) request).getResourceID();
- } else {
- return null;
- }
- }
-
- public int getSessionMaxInactiveInterval() {
- return request.getPortletSession().getMaxInactiveInterval();
- }
-
- public Object getSessionAttribute(String name) {
- return request.getPortletSession().getAttribute(name);
- }
-
- public void setSessionAttribute(String name, Object attribute) {
- request.getPortletSession().setAttribute(name, attribute);
- }
-
- /**
- * Gets the original, unwrapped portlet request.
- *
- * @return the unwrapped portlet request
- */
- public PortletRequest getPortletRequest() {
- return request;
- }
-
- public String getContentType() {
- try {
- return ((ResourceRequest) request).getContentType();
- } catch (ClassCastException e) {
- throw new IllegalStateException(
- "Content type only available for ResourceRequests");
- }
- }
-
- public BrowserDetails getBrowserDetails() {
- // No browserDetails available for normal requests
- return null;
- }
-
- public Locale getLocale() {
- return request.getLocale();
- }
-
- public String getRemoteAddr() {
- return null;
- }
-
- public boolean isSecure() {
- return request.isSecure();
- }
-
- public String getHeader(String string) {
- return null;
- }
-
- /**
- * Reads a portal property from the portal context of the wrapped request.
- *
- * @param name
- * a string with the name of the portal property to get
- * @return a string with the value of the property, or <code>null</code> if
- * the property is not defined
- */
- public String getPortalProperty(String name) {
- return request.getPortalContext().getProperty(name);
- }
-
- public DeploymentConfiguration getDeploymentConfiguration() {
- return deploymentConfiguration;
- }
-
- /**
- * Helper method to get a <code>WrappedPortlettRequest</code> from a
- * <code>WrappedRequest</code>. Aside from casting, this method also takes
- * care of situations where there's another level of wrapping.
- *
- * @param request
- * a wrapped request
- * @return a wrapped portlet request
- * @throws ClassCastException
- * if the wrapped request doesn't wrap a portlet request
- */
- public static WrappedPortletRequest cast(WrappedRequest request) {
- if (request instanceof CombinedRequest) {
- CombinedRequest combinedRequest = (CombinedRequest) request;
- request = combinedRequest.getSecondRequest();
- }
- return (WrappedPortletRequest) request;
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.server; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; +import java.util.Map; + +import javax.portlet.ClientDataRequest; +import javax.portlet.PortletRequest; +import javax.portlet.ResourceRequest; + +import com.vaadin.terminal.CombinedRequest; +import com.vaadin.terminal.DeploymentConfiguration; +import com.vaadin.terminal.WrappedRequest; + +/** + * Wrapper for {@link PortletRequest} and its subclasses. + * + * @author Vaadin Ltd. + * @since 7.0 + * + * @see WrappedRequest + * @see WrappedPortletResponse + */ +public class WrappedPortletRequest implements WrappedRequest { + + private final PortletRequest request; + private final DeploymentConfiguration deploymentConfiguration; + + /** + * Wraps a portlet request and an associated deployment configuration + * + * @param request + * the portlet request to wrap + * @param deploymentConfiguration + * the associated deployment configuration + */ + public WrappedPortletRequest(PortletRequest request, + DeploymentConfiguration deploymentConfiguration) { + this.request = request; + this.deploymentConfiguration = deploymentConfiguration; + } + + public Object getAttribute(String name) { + return request.getAttribute(name); + } + + public int getContentLength() { + try { + return ((ClientDataRequest) request).getContentLength(); + } catch (ClassCastException e) { + throw new IllegalStateException( + "Content lenght only available for ClientDataRequests"); + } + } + + public InputStream getInputStream() throws IOException { + try { + return ((ClientDataRequest) request).getPortletInputStream(); + } catch (ClassCastException e) { + throw new IllegalStateException( + "Input data only available for ClientDataRequests"); + } + } + + public String getParameter(String name) { + return request.getParameter(name); + } + + public Map<String, String[]> getParameterMap() { + return request.getParameterMap(); + } + + public void setAttribute(String name, Object o) { + request.setAttribute(name, o); + } + + public String getRequestPathInfo() { + if (request instanceof ResourceRequest) { + return ((ResourceRequest) request).getResourceID(); + } else { + return null; + } + } + + public int getSessionMaxInactiveInterval() { + return request.getPortletSession().getMaxInactiveInterval(); + } + + public Object getSessionAttribute(String name) { + return request.getPortletSession().getAttribute(name); + } + + public void setSessionAttribute(String name, Object attribute) { + request.getPortletSession().setAttribute(name, attribute); + } + + /** + * Gets the original, unwrapped portlet request. + * + * @return the unwrapped portlet request + */ + public PortletRequest getPortletRequest() { + return request; + } + + public String getContentType() { + try { + return ((ResourceRequest) request).getContentType(); + } catch (ClassCastException e) { + throw new IllegalStateException( + "Content type only available for ResourceRequests"); + } + } + + public BrowserDetails getBrowserDetails() { + // No browserDetails available for normal requests + return null; + } + + public Locale getLocale() { + return request.getLocale(); + } + + public String getRemoteAddr() { + return null; + } + + public boolean isSecure() { + return request.isSecure(); + } + + public String getHeader(String string) { + return null; + } + + /** + * Reads a portal property from the portal context of the wrapped request. + * + * @param name + * a string with the name of the portal property to get + * @return a string with the value of the property, or <code>null</code> if + * the property is not defined + */ + public String getPortalProperty(String name) { + return request.getPortalContext().getProperty(name); + } + + public DeploymentConfiguration getDeploymentConfiguration() { + return deploymentConfiguration; + } + + /** + * Helper method to get a <code>WrappedPortlettRequest</code> from a + * <code>WrappedRequest</code>. Aside from casting, this method also takes + * care of situations where there's another level of wrapping. + * + * @param request + * a wrapped request + * @return a wrapped portlet request + * @throws ClassCastException + * if the wrapped request doesn't wrap a portlet request + */ + public static WrappedPortletRequest cast(WrappedRequest request) { + if (request instanceof CombinedRequest) { + CombinedRequest combinedRequest = (CombinedRequest) request; + request = combinedRequest.getSecondRequest(); + } + return (WrappedPortletRequest) request; + } +} diff --git a/src/com/vaadin/ui/AbstractOrderedLayout.java b/src/com/vaadin/ui/AbstractOrderedLayout.java index 8bba9fc46d..fc3ef5056d 100644 --- a/src/com/vaadin/ui/AbstractOrderedLayout.java +++ b/src/com/vaadin/ui/AbstractOrderedLayout.java @@ -54,7 +54,7 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements @Override public void addComponent(Component c) { // Add to components before calling super.addComponent - // so that it is available to AttachListeners + // so that it is available to AttachListeners components.add(c); try { super.addComponent(c); @@ -75,7 +75,7 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements public void addComponentAsFirst(Component c) { // If c is already in this, we must remove it before proceeding // see ticket #7668 - if (c.getParent() == this) { + if(c.getParent() == this) { removeComponent(c); } components.addFirst(c); @@ -100,9 +100,9 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements public void addComponent(Component c, int index) { // If c is already in this, we must remove it before proceeding // see ticket #7668 - if (c.getParent() == this) { + if(c.getParent() == this) { // When c is removed, all components after it are shifted down - if (index > getComponentIndex(c)) { + if(index > getComponentIndex(c)) { index--; } removeComponent(c); diff --git a/src/com/vaadin/ui/ComboBox.java b/src/com/vaadin/ui/ComboBox.java index b4307188a7..013fe6ab85 100644 --- a/src/com/vaadin/ui/ComboBox.java +++ b/src/com/vaadin/ui/ComboBox.java @@ -1,130 +1,130 @@ -/*
-@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;
-import com.vaadin.terminal.gwt.client.ui.VFilterSelectPaintable;
-
-/**
- * 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(VFilterSelectPaintable.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; +import com.vaadin.terminal.gwt.client.ui.VFilterSelectPaintable; + +/** + * 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(VFilterSelectPaintable.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 b0e830a75a..b4160604ff 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.VDateFieldCalendarPaintable;
-
-/**
- * <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(VDateFieldCalendarPaintable.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.VDateFieldCalendarPaintable; + +/** + * <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(VDateFieldCalendarPaintable.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(); + } + +} |