diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-02-07 10:58:50 +0200 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2012-02-07 10:58:50 +0200 |
commit | e30776113d6a0403fa500e9d6b3892bafbc1ee17 (patch) | |
tree | 25dd75052f17162c7338b9a505c919b0ec2b72a4 /src | |
parent | 226e0ab34ae8ac22037a94fdc3568e6f93a06374 (diff) | |
parent | 787eedd131c5694a7db55d3b89bf4ddb4a6d673f (diff) | |
download | vaadin-framework-e30776113d6a0403fa500e9d6b3892bafbc1ee17.tar.gz vaadin-framework-e30776113d6a0403fa500e9d6b3892bafbc1ee17.zip |
Merge remote branch 'origin/master' into layoutperformance
Conflicts:
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/client/Util.java
src/com/vaadin/terminal/gwt/client/VPaintableMap.java
src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java
Diffstat (limited to 'src')
200 files changed, 16069 insertions, 15262 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/ApplicationConfiguration.java b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java index 169934024b..f9be8bf019 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java @@ -17,7 +17,7 @@ import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.Timer; -import com.vaadin.terminal.gwt.client.ui.VUnknownComponent; +import com.vaadin.terminal.gwt.client.ui.VUnknownComponentPaintable; public class ApplicationConfiguration implements EntryPoint { @@ -381,13 +381,14 @@ public class ApplicationConfiguration implements EntryPoint { return useDebugIdInDom; } - public Class<? extends VPaintableWidget> getWidgetClassByEncodedTag(String tag) { + public Class<? extends VPaintableWidget> getWidgetClassByEncodedTag( + String tag) { try { int parseInt = Integer.parseInt(tag); return classes[parseInt]; } catch (Exception e) { // component was not present in mappings - return VUnknownComponent.class; + return VUnknownComponentPaintable.class; } } @@ -397,7 +398,7 @@ public class ApplicationConfiguration implements EntryPoint { String key = keyArray.get(i).intern(); int value = valueMap.getInt(key); classes[value] = widgetSet.getImplementationByClassName(key); - if (classes[value] == VUnknownComponent.class) { + if (classes[value] == VUnknownComponentPaintable.class) { if (unknownComponents == null) { unknownComponents = new HashMap<String, String>(); } diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 064c2404ad..f20243d959 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -38,11 +38,10 @@ import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage; 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; @@ -140,7 +139,7 @@ public class ApplicationConnection { private Timer loadTimer3; private Element loadElement; - private final VView view; + private final VViewPaintable view; protected boolean applicationRunning = false; @@ -171,7 +170,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) { @@ -829,7 +829,8 @@ public class ApplicationConnection { if (loadElement == null) { loadElement = DOM.createDiv(); DOM.setStyleAttribute(loadElement, "position", "absolute"); - DOM.appendChild(view.getElement(), loadElement); + DOM.appendChild(view.getWidgetForPaintable().getElement(), + loadElement); VConsole.log("inserting load indicator"); } DOM.setElementProperty(loadElement, "className", "v-loading-indicator"); @@ -970,7 +971,7 @@ public class ApplicationConnection { meta = json.getValueMap("meta"); if (meta.containsKey("repaintAll")) { repaintAll = true; - view.clear(); + view.getWidgetForPaintable().clear(); getPaintableMap().clear(); if (meta.containsKey("invalidLayouts")) { validatingLayouts = true; @@ -1643,11 +1644,7 @@ public class ApplicationConnection { // Changed invisibile <-> visible if (wasVisible && manageCaption) { // Must hide caption when component is hidden - final Container parent = Util.getLayout(component); - if (parent != null) { - parent.updateCaption(paintable, uidl); - } - + paintable.getParent().updateCaption(paintable, uidl); } } @@ -1692,10 +1689,7 @@ public class ApplicationConnection { // Set captions if (manageCaption) { - final Container parent = Util.getLayout(component); - if (parent != null) { - parent.updateCaption(paintable, uidl); - } + paintable.getParent().updateCaption(paintable, uidl); } // add error classname to components w/ error @@ -1705,13 +1699,6 @@ public class ApplicationConnection { tooltipInfo.setErrorUidl(null); } - // Set captions - if (manageCaption) { - final Container parent = Util.getLayout(component); - if (parent != null) { - parent.updateCaption(paintable, uidl); - } - } /* * updateComponentSize need to be after caption update so caption can be * taken into account @@ -1915,10 +1902,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); @@ -2077,7 +2063,7 @@ public class ApplicationConnection { @Override public void run() { VConsole.log("Running re-layout of " + view.getClass().getName()); - runDescendentsLayout(view); + runDescendentsLayout(view.getWidgetForPaintable()); isPending = false; } }; @@ -2112,7 +2098,7 @@ public class ApplicationConnection { * * @return the main view */ - public VView getView() { + public VViewPaintable getView() { return view; } diff --git a/src/com/vaadin/terminal/gwt/client/ComponentLocator.java b/src/com/vaadin/terminal/gwt/client/ComponentLocator.java index b03bc708e2..f49f99a477 100644 --- a/src/com/vaadin/terminal/gwt/client/ComponentLocator.java +++ b/src/com/vaadin/terminal/gwt/client/ComponentLocator.java @@ -375,7 +375,7 @@ public class ComponentLocator { } else if (w instanceof VWindow) { VWindow win = (VWindow) w; ArrayList<VWindow> subWindowList = client.getView() - .getSubWindowList(); + .getWidgetForPaintable().getSubWindowList(); int indexOfSubWindow = subWindowList.indexOf(win); return PARENTCHILD_SEPARATOR + "VWindow[" + indexOfSubWindow + "]"; } else if (w instanceof RootPanel) { @@ -435,7 +435,7 @@ public class ComponentLocator { if (part.equals(ROOT_ID)) { w = RootPanel.get(); } else if (part.equals("")) { - w = client.getView(); + w = client.getView().getWidgetForPaintable(); } else if (w == null) { // Must be static pid (PID_S*) w = ((VPaintableWidget) VPaintableMap.get(client).getPaintable( @@ -465,7 +465,8 @@ public class ComponentLocator { * compatibility */ if (widgetClassName.equals("VWindow")) { - iterator = client.getView().getSubWindowList().iterator(); + iterator = client.getView().getWidgetForPaintable() + .getSubWindowList().iterator(); } else if (widgetClassName.equals("VContextMenu")) { return client.getContextMenu(); } else { diff --git a/src/com/vaadin/terminal/gwt/client/Container.java b/src/com/vaadin/terminal/gwt/client/Container.java index db6bbf0ee4..b573fd934e 100644 --- a/src/com/vaadin/terminal/gwt/client/Container.java +++ b/src/com/vaadin/terminal/gwt/client/Container.java @@ -8,7 +8,11 @@ import java.util.Set; import com.google.gwt.user.client.ui.Widget; -public interface Container extends VPaintableWidget { +/** + * @deprecated To be removed before 7.0.0 + */ +@Deprecated +public interface Container { /** * Replace child of this layout with another component. @@ -33,23 +37,6 @@ public interface Container extends VPaintableWidget { boolean hasChildComponent(Widget component); /** - * Update child components caption, description and error message. - * - * <p> - * Each component is responsible for maintaining its caption, description - * and error message. In most cases components doesn't want to do that and - * those elements reside outside of the component. Because of this layouts - * must provide service for it's childen to show those elements for them. - * </p> - * - * @param paintable - * Child component for which service is requested. - * @param uidl - * UIDL of the child component. - */ - void updateCaption(VPaintableWidget paintable, UIDL uidl); - - /** * Called when a child components size has been updated in the rendering * phase. * 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 39b44a506c..67339c984a 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -678,7 +678,7 @@ public class Util { */ public static VPaintableWidget getChildPaintableForElement( ApplicationConnection client, Container parent, Element element) { - Element rootElement = parent.getWidgetForPaintable().getElement(); + Element rootElement = ((Widget) parent).getElement(); while (element != null && element != rootElement) { VPaintableWidget paintable = VPaintableMap.get(client) .getPaintable(element); @@ -1145,4 +1145,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/VDebugConsole.java b/src/com/vaadin/terminal/gwt/client/VDebugConsole.java index fdaf944b9f..76c312676a 100644 --- a/src/com/vaadin/terminal/gwt/client/VDebugConsole.java +++ b/src/com/vaadin/terminal/gwt/client/VDebugConsole.java @@ -91,7 +91,7 @@ public class VDebugConsole extends VOverlay implements Console { for (ApplicationConnection a : ApplicationConfiguration .getRunningApplications()) { VPaintableWidget paintable = Util.getPaintableForElement(a, - a.getView(), eventTarget); + a.getView().getWidgetForPaintable(), eventTarget); if (paintable == null) { paintable = Util.getPaintableForElement(a, RootPanel.get(), eventTarget); @@ -120,7 +120,7 @@ public class VDebugConsole extends VOverlay implements Console { for (ApplicationConnection a : ApplicationConfiguration .getRunningApplications()) { VPaintableWidget paintable = Util.getPaintableForElement(a, - a.getView(), eventTarget); + a.getView().getWidgetForPaintable(), eventTarget); if (paintable == null) { paintable = Util.getPaintableForElement(a, RootPanel.get(), eventTarget); @@ -534,8 +534,7 @@ public class VDebugConsole extends VOverlay implements Console { emphasisInUi.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { if (paintable != null) { - Element element2 = layout.getWidgetForPaintable() - .getElement(); + Element element2 = ((Widget) layout).getElement(); Widget.setStyleName(element2, "invalidlayout", emphasisInUi.getValue()); } 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 31aec87aa0..309c527e7a 100644 --- a/src/com/vaadin/terminal/gwt/client/VPaintableMap.java +++ b/src/com/vaadin/terminal/gwt/client/VPaintableMap.java @@ -1,408 +1,408 @@ -/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client;
-
-import java.util.ArrayList;
-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.MeasureManager.MeasuredSize;
-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);
- }
-
- }
-
- public VPaintableWidget[] getRegisteredPaintableWidgets() {
- ArrayList<VPaintableWidget> result = new ArrayList<VPaintableWidget>();
-
- for (VPaintable paintable : getPaintables()) {
- if (paintable instanceof VPaintableWidget) {
- VPaintableWidget paintableWidget = (VPaintableWidget) paintable;
- if (!unregistryBag.contains(getPid(paintable))) {
- result.add(paintableWidget);
- }
- }
- }
-
- return result.toArray(new VPaintableWidget[result.size()]);
- }
-
- 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);
- }
- /*
- * 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 void setOffsetSize(VPaintableWidget paintable, Size newSize) {
- getComponentDetail(paintable).setOffsetSize(newSize);
- }
-
- 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;
- }
-
- /**
- * FIXME: Should not be here
- */
- @Deprecated
- public MeasuredSize getMeasuredSize(VPaintableWidget paintable) {
- ComponentDetail componentDetail = getComponentDetail(paintable);
- if (componentDetail == null) {
- return null;
- }
-
- return componentDetail.getMeasuredSize();
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client; + +import java.util.ArrayList; +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.MeasureManager.MeasuredSize; +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); + } + + } + + public VPaintableWidget[] getRegisteredPaintableWidgets() { + ArrayList<VPaintableWidget> result = new ArrayList<VPaintableWidget>(); + + for (VPaintable paintable : getPaintables()) { + if (paintable instanceof VPaintableWidget) { + VPaintableWidget paintableWidget = (VPaintableWidget) paintable; + if (!unregistryBag.contains(getPid(paintable))) { + result.add(paintableWidget); + } + } + } + + return result.toArray(new VPaintableWidget[result.size()]); + } + + 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); + } + /* + * 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 void setOffsetSize(VPaintableWidget paintable, Size newSize) { + getComponentDetail(paintable).setOffsetSize(newSize); + } + + 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; + } + + /** + * FIXME: Should not be here + */ + @Deprecated + public MeasuredSize getMeasuredSize(VPaintableWidget paintable) { + ComponentDetail componentDetail = getComponentDetail(paintable); + if (componentDetail == null) { + return null; + } + + return componentDetail.getMeasuredSize(); + } + +}
\ No newline at end of file diff --git a/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java b/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java index 2f0cae1cc1..4b8720b132 100644 --- a/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java +++ b/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java @@ -21,4 +21,11 @@ public interface VPaintableWidget extends VPaintable { */ public Widget getWidgetForPaintable(); + /** + * Returns the parent {@link VPaintableWidgetContainer} + * + * @return + */ + // FIXME: Rename to getParent() + public VPaintableWidgetContainer getParent(); } diff --git a/src/com/vaadin/terminal/gwt/client/VPaintableWidgetContainer.java b/src/com/vaadin/terminal/gwt/client/VPaintableWidgetContainer.java new file mode 100644 index 0000000000..baf266546d --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/VPaintableWidgetContainer.java @@ -0,0 +1,45 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client; + +import com.google.gwt.user.client.ui.HasWidgets; + +/** + * An interface used by client-side paintables whose widget is a component + * container (implements {@link HasWidgets}). + */ +public interface VPaintableWidgetContainer extends VPaintableWidget { + + /** + * Update child components caption, description and error message. + * + * <p> + * Each component is responsible for maintaining its caption, description + * and error message. In most cases components doesn't want to do that and + * those elements reside outside of the component. Because of this layouts + * must provide service for it's childen to show those elements for them. + * </p> + * + * @param paintable + * Child component for which service is requested. + * @param uidl + * UIDL of the child component. + */ + void updateCaption(VPaintableWidget paintable, UIDL uidl); + + /** + * Returns the children for this paintable. + * <p> + * The children for this paintable are defined as all + * {@link VPaintableWidget}s whose parent is this + * {@link VPaintableWidgetContainer}. + * </p> + * + * @return A collection of children for this paintable. An empty collection + * if there are no children. + */ + // public Collection<VPaintableWidget> getChildren(); + +} 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/VUIDLBrowser.java b/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java index bcf7f14a9d..e63bcf98d9 100644 --- a/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java +++ b/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java @@ -24,7 +24,7 @@ import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ui.VUnknownComponent; +import com.vaadin.terminal.gwt.client.ui.VUnknownComponentPaintable; import com.vaadin.terminal.gwt.client.ui.VWindow; public class VUIDLBrowser extends SimpleTree { @@ -99,7 +99,7 @@ public class VUIDLBrowser extends SimpleTree { String name) { Class<? extends VPaintableWidget> widgetClassByDecodedTag = conf .getWidgetClassByEncodedTag(name); - if (widgetClassByDecodedTag == VUnknownComponent.class) { + if (widgetClassByDecodedTag == VUnknownComponentPaintable.class) { return conf.getUnknownServerClassNameByEncodedTagName(name) + "(NO CLIENT IMPLEMENTATION FOUND)"; } else { diff --git a/src/com/vaadin/terminal/gwt/client/WidgetSet.java b/src/com/vaadin/terminal/gwt/client/WidgetSet.java index b78091950b..390d79ce17 100644 --- a/src/com/vaadin/terminal/gwt/client/WidgetSet.java +++ b/src/com/vaadin/terminal/gwt/client/WidgetSet.java @@ -6,13 +6,9 @@ package com.vaadin.terminal.gwt.client; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ui.VFilterSelect; -import com.vaadin.terminal.gwt.client.ui.VListSelect; -import com.vaadin.terminal.gwt.client.ui.VSplitPanelHorizontal; -import com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical; -import com.vaadin.terminal.gwt.client.ui.VUnknownComponent; -import com.vaadin.terminal.gwt.client.ui.VView; -import com.vaadin.terminal.gwt.client.ui.VWindow; +import com.vaadin.terminal.gwt.client.ui.VFilterSelectPaintable; +import com.vaadin.terminal.gwt.client.ui.VListSelectPaintable; +import com.vaadin.terminal.gwt.client.ui.VUnknownComponentPaintable; public class WidgetSet { @@ -25,7 +21,8 @@ public class WidgetSet { /** * Create an uninitialized component that best matches given UIDL. The - * component must be a {@link Widget} that implements {@link VPaintableWidget}. + * component must be a {@link Widget} that implements + * {@link VPaintableWidget}. * * @param uidl * UIDL to be painted with returned component. @@ -35,7 +32,8 @@ public class WidgetSet { * @return New uninitialized and unregistered component that can paint given * UIDL. */ - public VPaintableWidget createWidget(UIDL uidl, ApplicationConfiguration conf) { + public VPaintableWidget createWidget(UIDL uidl, + ApplicationConfiguration conf) { /* * Yes, this (including the generated code in WidgetMap) may look very * odd code, but due the nature of GWT, we cannot do this any cleaner. @@ -46,16 +44,15 @@ public class WidgetSet { * TODO should try to get rid of these exceptions here */ - final Class<? extends VPaintableWidget> classType = resolveWidgetType(uidl, - conf); - if (classType == null || classType == VUnknownComponent.class) { + final Class<? extends VPaintableWidget> classType = resolveWidgetType( + uidl, conf); + if (classType == null || classType == VUnknownComponentPaintable.class) { String serverSideName = conf .getUnknownServerClassNameByEncodedTagName(uidl.getTag()); - VUnknownComponent c = GWT.create(VUnknownComponent.class); + VUnknownComponentPaintable c = GWT + .create(VUnknownComponentPaintable.class); c.setServerSideClassName(serverSideName); return c; - } else if (VWindow.class == classType) { - return GWT.create(VWindow.class); } else { /* * let the auto generated code instantiate this type @@ -74,20 +71,14 @@ public class WidgetSet { // add our historical quirks - if (widgetClass == VView.class && uidl.hasAttribute("sub")) { - return VWindow.class; - } else if (widgetClass == VFilterSelect.class) { + if (widgetClass == VFilterSelectPaintable.class) { if (uidl.hasAttribute("type")) { final String type = uidl.getStringAttribute("type").intern(); if ("legacy-multi" == type) { - return VListSelect.class; + return VListSelectPaintable.class; } } - } else if (widgetClass == VSplitPanelHorizontal.class - && uidl.hasAttribute("vertical")) { - return VSplitPanelVertical.class; } - return widgetClass; } @@ -119,7 +110,7 @@ public class WidgetSet { public Class<? extends VPaintableWidget> getImplementationByClassName( String fullyqualifiedName) { if (fullyqualifiedName == null) { - return VUnknownComponent.class; + return VUnknownComponentPaintable.class; } Class<? extends VPaintableWidget> implementationByServerSideClassName = widgetMap .getImplementationByServerSideClassName(fullyqualifiedName); @@ -131,9 +122,7 @@ public class WidgetSet { * *actually* be VListSelect, when the annotation says VFilterSelect */ if (fullyqualifiedName.equals("com.vaadin.ui.Select")) { - loadImplementation(VListSelect.class); - } else if (fullyqualifiedName.equals("com.vaadin.ui.SplitPanel")) { - loadImplementation(VSplitPanelVertical.class); + loadImplementation(VListSelectPaintable.class); } return implementationByServerSideClassName; 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 e5982b1078..7ac44bc4b7 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java @@ -4,7 +4,6 @@ package com.vaadin.terminal.gwt.client.ui; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; @@ -13,9 +12,6 @@ import java.util.Set; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Style; -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.Element; import com.google.gwt.user.client.ui.ComplexPanel; @@ -23,7 +19,6 @@ import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Container; -import com.vaadin.terminal.gwt.client.EventId; import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; @@ -49,26 +44,11 @@ public class VAbsoluteLayout extends ComplexPanel implements Container { private Object previousStyleName; - private Map<String, AbsoluteWrapper> pidToComponentWrappper = new HashMap<String, AbsoluteWrapper>(); + Map<String, AbsoluteWrapper> pidToComponentWrappper = new HashMap<String, AbsoluteWrapper>(); protected ApplicationConnection client; - private boolean rendering; - - private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( - this, EventId.LAYOUT_CLICK) { - - @Override - protected VPaintableWidget getChildComponent(Element element) { - return getComponent(element); - } - - @Override - protected <H extends EventHandler> HandlerRegistration registerHandler( - H handler, Type<H> type) { - return addDomHandler(handler, type); - } - }; + boolean rendering; public VAbsoluteLayout() { setElement(Document.get().createDivElement()); @@ -137,46 +117,7 @@ public class VAbsoluteLayout extends ComplexPanel implements Container { return true; } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - AbsoluteWrapper parent2 = (AbsoluteWrapper) (component - .getWidgetForPaintable()).getParent(); - parent2.updateCaption(uidl); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - rendering = true; - this.client = client; - // TODO margin handling - if (client.updateComponent(this, uidl, true)) { - rendering = false; - return; - } - - clickEventHandler.handleEventHandlerRegistration(client); - - HashSet<String> unrenderedPids = new HashSet<String>( - 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()); - getWrapper(client, componentUIDL).updateFromUIDL(cc); - } - } - - for (String pid : unrenderedPids) { - AbsoluteWrapper absoluteWrapper = pidToComponentWrappper.get(pid); - pidToComponentWrappper.remove(pid); - absoluteWrapper.destroy(); - } - rendering = false; - } - - private AbsoluteWrapper getWrapper(ApplicationConnection client, - UIDL componentUIDL) { + AbsoluteWrapper getWrapper(ApplicationConnection client, UIDL componentUIDL) { AbsoluteWrapper wrapper = pidToComponentWrappper.get(componentUIDL .getId()); if (wrapper == null) { @@ -364,12 +305,8 @@ public class VAbsoluteLayout extends ComplexPanel implements Container { * @return The Paintable which the element is a part of. Null if the element * belongs to the layout and not to a child. */ - private VPaintableWidget getComponent(Element element) { + VPaintableWidget getComponent(Element element) { 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 new file mode 100644 index 0000000000..9d73e75b09 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayoutPaintable.java @@ -0,0 +1,87 @@ +/* +@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 9a2e728454..474e9c416d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java @@ -1,75 +1,106 @@ -/*
-@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.VPaintableWidget;
-
-public abstract class VAbstractPaintableWidget implements VPaintableWidget {
-
- private Widget widget;
- private ApplicationConnection connection;
-
- /* 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;
- // }
-}
+/* +@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; + private VPaintableWidgetContainer parent; + + /* 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 getParent() { + if (parent != null) + return parent; + + // FIXME: Hierarchy should be set by framework instead of looked up here + VPaintableMap paintableMap = VPaintableMap.get(getConnection()); + + Widget w = getWidgetForPaintable(); + while (w != null) { + w = w.getParent(); + if (paintableMap.isPaintable(w)) { + parent = (VPaintableWidgetContainer) paintableMap.getPaintable(w); + return parent; + } + } + + return null; + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidgetContainer.java b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidgetContainer.java new file mode 100644 index 0000000000..1f78c02f58 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidgetContainer.java @@ -0,0 +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() { + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanel.java index 0d44609bb0..f1a932b3a3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanel.java @@ -6,9 +6,7 @@ package com.vaadin.terminal.gwt.client.ui; import java.util.Set; -import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Node; -import com.google.gwt.event.dom.client.DomEvent.Type; import com.google.gwt.event.dom.client.TouchCancelEvent; import com.google.gwt.event.dom.client.TouchCancelHandler; import com.google.gwt.event.dom.client.TouchEndEvent; @@ -17,8 +15,6 @@ import com.google.gwt.event.dom.client.TouchMoveEvent; import com.google.gwt.event.dom.client.TouchMoveHandler; import com.google.gwt.event.dom.client.TouchStartEvent; import com.google.gwt.event.dom.client.TouchStartHandler; -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.Element; import com.google.gwt.user.client.Event; @@ -30,61 +26,16 @@ import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.ContainerResizedListener; import com.vaadin.terminal.gwt.client.RenderInformation; import com.vaadin.terminal.gwt.client.RenderSpace; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.VPaintableMap; -import com.vaadin.terminal.gwt.client.VPaintableWidget; -public class VSplitPanel extends ComplexPanel implements Container, +public class VAbstractSplitPanel extends ComplexPanel implements Container, ContainerResizedListener { private boolean enabled = false; public static final String CLASSNAME = "v-splitpanel"; - public static final String SPLITTER_CLICK_EVENT_IDENTIFIER = "sp_click"; - - private ClickEventHandler clickEventHandler = new ClickEventHandler(this, - SPLITTER_CLICK_EVENT_IDENTIFIER) { - - @Override - protected <H extends EventHandler> HandlerRegistration registerHandler( - H handler, Type<H> type) { - if ((Event.getEventsSunk(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 addHandler(handler, type); - } else { - return addDomHandler(handler, type); - } - } - - @Override - public void onContextMenu( - com.google.gwt.event.dom.client.ContextMenuEvent event) { - Element target = event.getNativeEvent().getEventTarget().cast(); - if (splitter.isOrHasChild(target)) { - super.onContextMenu(event); - } - }; - - @Override - protected void fireClick(NativeEvent event) { - Element target = event.getEventTarget().cast(); - if (splitter.isOrHasChild(target)) { - super.fireClick(event); - } - } - - @Override - protected Element getRelativeToElement() { - return null; - } - - }; - public static final int ORIENTATION_HORIZONTAL = 0; public static final int ORIENTATION_VERTICAL = 1; @@ -93,9 +44,9 @@ public class VSplitPanel extends ComplexPanel implements Container, private int orientation = ORIENTATION_HORIZONTAL; - private Widget firstChild; + Widget firstChild; - private Widget secondChild; + Widget secondChild; private final Element wrapper = DOM.createDiv(); @@ -103,7 +54,7 @@ public class VSplitPanel extends ComplexPanel implements Container, private final Element secondContainer = DOM.createDiv(); - private final Element splitter = DOM.createDiv(); + final Element splitter = DOM.createDiv(); private boolean resizing; @@ -121,11 +72,11 @@ public class VSplitPanel extends ComplexPanel implements Container, private boolean positionReversed = false; - private String[] componentStyleNames; + String[] componentStyleNames; private Element draggingCurtain; - private ApplicationConnection client; + ApplicationConnection client; private String width = ""; @@ -136,14 +87,14 @@ public class VSplitPanel extends ComplexPanel implements Container, RenderInformation renderInformation = new RenderInformation(); - private String id; + String id; - private boolean immediate; + boolean immediate; - private boolean rendering = false; + boolean rendering = false; /* The current position of the split handle in either percentages or pixels */ - private String position; + String position; protected Element scrolledContainer; @@ -151,11 +102,11 @@ public class VSplitPanel extends ComplexPanel implements Container, private TouchScrollDelegate touchScrollDelegate; - public VSplitPanel() { + public VAbstractSplitPanel() { this(ORIENTATION_HORIZONTAL); } - public VSplitPanel(int orientation) { + public VAbstractSplitPanel(int orientation) { setElement(DOM.createDiv()); switch (orientation) { case ORIENTATION_HORIZONTAL: @@ -255,69 +206,6 @@ public class VSplitPanel extends ComplexPanel implements Container, + "-second-container"); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - id = uidl.getId(); - rendering = true; - - immediate = uidl.hasAttribute("immediate"); - - if (client.updateComponent(this, uidl, true)) { - rendering = false; - return; - } - setEnabled(!uidl.getBooleanAttribute("disabled")); - - clickEventHandler.handleEventHandlerRegistration(client); - if (uidl.hasAttribute("style")) { - componentStyleNames = uidl.getStringAttribute("style").split(" "); - } else { - componentStyleNames = new String[0]; - } - - setLocked(uidl.getBooleanAttribute("locked")); - - setPositionReversed(uidl.getBooleanAttribute("reversed")); - - setStylenames(); - - position = uidl.getStringAttribute("position"); - setSplitPosition(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 (firstChild != newFirstChild) { - if (firstChild != null) { - client.unregisterPaintable(VPaintableMap.get(client) - .getPaintable(firstChild)); - } - setFirstWidget(newFirstChild); - } - if (secondChild != newSecondChild) { - if (secondChild != null) { - client.unregisterPaintable(VPaintableMap.get(client) - .getPaintable(secondChild)); - } - setSecondWidget(newSecondChild); - } - newFirstChildPaintable.updateFromUIDL(uidl.getChildUIDL(0), client); - newSecondChildPaintable.updateFromUIDL(uidl.getChildUIDL(1), client); - - renderInformation.updateSize(getElement()); - - // This is needed at least for cases like #3458 to take - // appearing/disappearing scrollbars into account. - client.runDescendentsLayout(this); - - rendering = false; - - } - @Override public boolean remove(Widget w) { boolean removed = super.remove(w); @@ -331,7 +219,7 @@ public class VSplitPanel extends ComplexPanel implements Container, return removed; } - private void setLocked(boolean newValue) { + void setLocked(boolean newValue) { if (locked != newValue) { locked = newValue; splitterSize = -1; @@ -339,7 +227,7 @@ public class VSplitPanel extends ComplexPanel implements Container, } } - private void setPositionReversed(boolean reversed) { + void setPositionReversed(boolean reversed) { if (positionReversed != reversed) { if (orientation == ORIENTATION_HORIZONTAL) { DOM.setStyleAttribute(splitter, "right", ""); @@ -353,7 +241,7 @@ public class VSplitPanel extends ComplexPanel implements Container, } } - private void setSplitPosition(String pos) { + void setSplitPosition(String pos) { if (pos == null) { return; } @@ -473,7 +361,7 @@ public class VSplitPanel extends ComplexPanel implements Container, } - private void setFirstWidget(Widget w) { + void setFirstWidget(Widget w) { if (firstChild != null) { firstChild.removeFromParent(); } @@ -481,7 +369,7 @@ public class VSplitPanel extends ComplexPanel implements Container, firstChild = w; } - private void setSecondWidget(Widget w) { + void setSecondWidget(Widget w) { if (secondChild != null) { secondChild.removeFromParent(); } @@ -791,10 +679,6 @@ public class VSplitPanel extends ComplexPanel implements Container, } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - // TODO Implement caption handling - } - /** * Updates the new split position back to server. */ @@ -810,7 +694,7 @@ public class VSplitPanel extends ComplexPanel implements Container, client.updateVariable(id, "position", pos, immediate); } - private void setStylenames() { + void setStylenames() { final String splitterSuffix = (orientation == ORIENTATION_HORIZONTAL ? "-hsplitter" : "-vsplitter"); final String firstContainerSuffix = "-first-container"; @@ -846,7 +730,4 @@ public class VSplitPanel 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 new file mode 100644 index 0000000000..9c7e5f04f9 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanelPaintable.java @@ -0,0 +1,143 @@ +/* +@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/VAccordion.java b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java index 7fe87713c3..3e4f21477b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java @@ -15,7 +15,6 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ContainerResizedListener; import com.vaadin.terminal.gwt.client.RenderInformation; import com.vaadin.terminal.gwt.client.RenderSpace; @@ -36,58 +35,23 @@ public class VAccordion extends VTabsheetBase implements private String width = ""; - private HashMap<StackItem, UIDL> lazyUpdateMap = new HashMap<StackItem, UIDL>(); + HashMap<StackItem, UIDL> lazyUpdateMap = new HashMap<StackItem, UIDL>(); private RenderSpace renderSpace = new RenderSpace(0, 0, true); - private StackItem openTab = null; + StackItem openTab = null; - private boolean rendering = false; + boolean rendering = false; - private int selectedUIDLItemIndex = -1; + int selectedUIDLItemIndex = -1; - private RenderInformation renderInformation = new RenderInformation(); + RenderInformation renderInformation = new RenderInformation(); public VAccordion() { super(CLASSNAME); } @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - rendering = true; - selectedUIDLItemIndex = -1; - super.updateFromUIDL(uidl, client); - /* - * Render content after all tabs have been created and we know how large - * the content area is - */ - if (selectedUIDLItemIndex >= 0) { - StackItem selectedItem = getStackItem(selectedUIDLItemIndex); - UIDL selectedTabUIDL = lazyUpdateMap.remove(selectedItem); - open(selectedUIDLItemIndex); - - selectedItem.setContent(selectedTabUIDL); - } else if (!uidl.getBooleanAttribute("cached") && openTab != null) { - close(openTab); - } - - iLayout(); - // finally render possible hidden tabs - if (lazyUpdateMap.size() > 0) { - for (Iterator iterator = lazyUpdateMap.keySet().iterator(); iterator - .hasNext();) { - StackItem item = (StackItem) iterator.next(); - item.setContent(lazyUpdateMap.get(item)); - } - lazyUpdateMap.clear(); - } - - renderInformation.updateSize(getElement()); - - rendering = false; - } - - @Override protected void renderTab(UIDL tabUidl, int index, boolean selected, boolean hidden) { StackItem item; @@ -182,7 +146,7 @@ public class VAccordion extends VTabsheetBase implements return item; } - private void open(int itemIndex) { + void open(int itemIndex) { StackItem item = (StackItem) getWidget(itemIndex); boolean alreadyOpen = false; if (openTab != null) { @@ -205,7 +169,7 @@ public class VAccordion extends VTabsheetBase implements updateOpenTabSize(); } - private void close(StackItem item) { + void close(StackItem item) { if (!item.isOpen()) { return; } @@ -581,10 +545,6 @@ public class VAccordion extends VTabsheetBase implements } } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - /* Accordion does not render its children's captions */ - } - public boolean requestLayout(Set<Widget> children) { if (!isDynamicHeight() && !isDynamicWidth()) { /* @@ -646,12 +606,8 @@ public class VAccordion extends VTabsheetBase implements return null; } - private StackItem getStackItem(int index) { + StackItem getStackItem(int index) { return (StackItem) getWidget(index); } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAccordionPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VAccordionPaintable.java new file mode 100644 index 0000000000..6b03300a09 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VAccordionPaintable.java @@ -0,0 +1,71 @@ +/* +@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/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/VButton.java index f8397d4a39..21b5d8bbe8 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VButton.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VButton.java @@ -19,7 +19,6 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.Accessibility; import com.google.gwt.user.client.ui.FocusWidget; -import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.EventId; @@ -450,9 +449,4 @@ public class VButton extends FocusWidget implements ClickHandler, FocusHandler, public void onBlur(BlurEvent arg0) { client.updateVariable(paintableId, EventId.BLUR, "", true); } - - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VButtonPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VButtonPaintable.java index 1367d412a8..98f2888700 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VButtonPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VButtonPaintable.java @@ -1,3 +1,7 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + package com.vaadin.terminal.gwt.client.ui; import com.google.gwt.core.client.GWT; 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 ffd7fc49b2..839b84061c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCssLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCssLayout.java @@ -11,9 +11,6 @@ import java.util.Iterator; import java.util.Set; import com.google.gwt.dom.client.Style; -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.Element; import com.google.gwt.user.client.ui.FlowPanel; @@ -22,7 +19,6 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.Container; -import com.vaadin.terminal.gwt.client.EventId; import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.StyleConstants; import com.vaadin.terminal.gwt.client.UIDL; @@ -33,33 +29,17 @@ import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.ValueMap; -public class VCssLayout extends SimplePanel implements VPaintableWidget, - Container { +public class VCssLayout extends SimplePanel implements Container { public static final String TAGNAME = "csslayout"; public static final String CLASSNAME = "v-" + TAGNAME; - private FlowPane panel = new FlowPane(); + FlowPane panel = new FlowPane(); - private Element margin = DOM.createDiv(); - - private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( - this, EventId.LAYOUT_CLICK) { - - @Override - protected VPaintableWidget getChildComponent(Element element) { - return panel.getComponent(element); - } - - @Override - protected <H extends EventHandler> HandlerRegistration registerHandler( - H handler, Type<H> type) { - return addDomHandler(handler, type); - } - }; + Element margin = DOM.createDiv(); private boolean hasHeight; private boolean hasWidth; - private boolean rendering; + boolean rendering; public VCssLayout() { super(); @@ -94,32 +74,6 @@ public class VCssLayout extends SimplePanel implements VPaintableWidget, } } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - rendering = true; - - if (client.updateComponent(this, uidl, true)) { - rendering = false; - return; - } - clickEventHandler.handleEventHandlerRegistration(client); - - final VMarginInfo margins = new VMarginInfo( - uidl.getIntAttribute("margins")); - setStyleName(margin, CLASSNAME + "-" + StyleConstants.MARGIN_TOP, - margins.hasTop()); - setStyleName(margin, CLASSNAME + "-" + StyleConstants.MARGIN_RIGHT, - margins.hasRight()); - setStyleName(margin, CLASSNAME + "-" + StyleConstants.MARGIN_BOTTOM, - margins.hasBottom()); - setStyleName(margin, CLASSNAME + "-" + StyleConstants.MARGIN_LEFT, - margins.hasLeft()); - - setStyleName(margin, CLASSNAME + "-" + "spacing", - uidl.hasAttribute("spacing")); - panel.updateFromUIDL(uidl, client); - rendering = false; - } - public boolean hasChildComponent(Widget component) { return panel.hasChildComponent(component); } @@ -128,10 +82,6 @@ public class VCssLayout extends SimplePanel implements VPaintableWidget, panel.replaceChildComponent(oldComponent, newComponent); } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - panel.updateCaption(component, uidl); - } - public class FlowPane extends FlowPanel { private final HashMap<Widget, VCaption> widgetToCaption = new HashMap<Widget, VCaption>(); @@ -275,7 +225,7 @@ public class VCssLayout extends SimplePanel implements VPaintableWidget, } } - private VPaintableWidget getComponent(Element element) { + VPaintableWidget getComponent(Element element) { return Util .getPaintableForElement(client, VCssLayout.this, element); } @@ -344,7 +294,27 @@ public class VCssLayout extends SimplePanel implements VPaintableWidget, return cssProperty; } - public Widget getWidgetForPaintable() { - return this; + /** + * Sets CSS classes for margin and spacing based on the given parameters. + * + * @param margins + * A {@link VMarginInfo} object that provides info on + * top/left/bottom/right margins + * @param spacing + * true to enable spacing, false otherwise + */ + protected void setMarginAndSpacingStyles(VMarginInfo margins, + boolean spacing) { + setStyleName(margin, VCssLayout.CLASSNAME + "-" + + StyleConstants.MARGIN_TOP, margins.hasTop()); + setStyleName(margin, VCssLayout.CLASSNAME + "-" + + StyleConstants.MARGIN_RIGHT, margins.hasRight()); + setStyleName(margin, VCssLayout.CLASSNAME + "-" + + StyleConstants.MARGIN_BOTTOM, margins.hasBottom()); + setStyleName(margin, VCssLayout.CLASSNAME + "-" + + StyleConstants.MARGIN_LEFT, margins.hasLeft()); + + setStyleName(margin, VCssLayout.CLASSNAME + "-" + "spacing", spacing); + } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCssLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VCssLayoutPaintable.java new file mode 100644 index 0000000000..4d551fa5e8 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VCssLayoutPaintable.java @@ -0,0 +1,64 @@ +/* +@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 39d1ee462c..d8181cf00c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCustomComponent.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCustomComponent.java @@ -6,81 +6,28 @@ package com.vaadin.terminal.gwt.client.ui; import java.util.Set; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.user.client.Command; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.RenderSpace; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VPaintableMap; -import com.vaadin.terminal.gwt.client.VPaintableWidget; public class VCustomComponent extends SimplePanel implements Container { private static final String CLASSNAME = "v-customcomponent"; private String height; - private ApplicationConnection client; - private boolean rendering; + ApplicationConnection client; + boolean rendering; private String width; - private RenderSpace renderSpace = new RenderSpace(); + RenderSpace renderSpace = new RenderSpace(); public VCustomComponent() { super(); setStyleName(CLASSNAME); } - public void updateFromUIDL(UIDL uidl, final ApplicationConnection client) { - rendering = true; - if (client.updateComponent(this, uidl, true)) { - rendering = false; - return; - } - this.client = client; - - final UIDL child = uidl.getChildUIDL(0); - if (child != null) { - final VPaintableWidget paintable = client.getPaintable(child); - Widget widget = paintable.getWidgetForPaintable(); - if (widget != getWidget()) { - if (getWidget() != null) { - client.unregisterPaintable(VPaintableMap.get(client) - .getPaintable(getWidget())); - clear(); - } - setWidget(widget); - } - paintable.updateFromUIDL(child, client); - } - - boolean updateDynamicSize = 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(VCustomComponent.this); - - } - }); - } - - renderSpace.setWidth(getElement().getOffsetWidth()); - renderSpace.setHeight(getElement().getOffsetHeight()); - - /* - * Needed to update client size if the size of this component has - * changed and the child uses relative size(s). - */ - client.runDescendentsLayout(this); - - rendering = false; - } - - private boolean updateDynamicSize() { + boolean updateDynamicSize() { boolean updated = false; if (isDynamicWidth()) { int childWidth = Util.getRequiredWidth(getWidget()); @@ -121,10 +68,6 @@ public class VCustomComponent extends SimplePanel implements Container { } } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - // NOP, custom component dont render composition roots caption - } - public boolean requestLayout(Set<Widget> children) { // If a child grows in size, it will not necessarily be calculated // correctly unless we remove previous size definitions @@ -168,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 new file mode 100644 index 0000000000..585466f4f7 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VCustomComponentPaintable.java @@ -0,0 +1,82 @@ +/* +@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 40b6acd28a..5782c74c9a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCustomLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCustomLayout.java @@ -35,8 +35,8 @@ import com.vaadin.terminal.gwt.client.VPaintableWidget; * @author Vaadin Ltd * */ -public class VCustomLayout extends ComplexPanel implements VPaintableWidget, - Container, ContainerResizedListener { +public class VCustomLayout extends ComplexPanel implements Container, + ContainerResizedListener { public static final String CLASSNAME = "v-customlayout"; @@ -44,7 +44,7 @@ public class VCustomLayout extends ComplexPanel implements VPaintableWidget, private final HashMap<String, Element> locationToElement = new HashMap<String, Element>(); /** Location-name to contained widget map */ - private final HashMap<String, Widget> locationToWidget = new HashMap<String, Widget>(); + final HashMap<String, Widget> locationToWidget = new HashMap<String, Widget>(); /** Widget to captionwrapper map */ private final HashMap<VPaintableWidget, VCaptionWrapper> paintableToCaptionWrapper = new HashMap<VPaintableWidget, VCaptionWrapper>(); @@ -53,12 +53,12 @@ public class VCustomLayout extends ComplexPanel implements VPaintableWidget, String currentTemplateName; /** Unexecuted scripts loaded from the template */ - private String scripts = ""; + String scripts = ""; /** Paintable ID of this paintable */ - private String pid; + String pid; - private ApplicationConnection client; + ApplicationConnection client; /** Has the template been loaded from contents passed in UIDL **/ private boolean hasTemplateContents = false; @@ -132,66 +132,8 @@ public class VCustomLayout extends ComplexPanel implements VPaintableWidget, locationToWidget.put(location, widget); } - /** Update the layout from UIDL */ - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - // ApplicationConnection manages generic component features - if (client.updateComponent(this, uidl, true)) { - return; - } - - pid = uidl.getId(); - if (!hasTemplate()) { - // Update HTML template only once - initializeHTML(uidl, client); - } - - // Evaluate scripts - eval(scripts); - scripts = null; - - iLayout(); - // TODO Check if this is needed - client.runDescendentsLayout(this); - - Set<Widget> oldWidgets = new HashSet<Widget>(); - oldWidgets.addAll(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 { - 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 - remove(oldWidget); - } - } - - iLayout(); - // TODO Check if this is needed - client.runDescendentsLayout(this); - - } - /** Initialize HTML-layout. */ - private void initializeHTML(UIDL uidl, ApplicationConnection client) { + void initializeHTML(UIDL uidl, ApplicationConnection client) { final String newTemplateContents = uidl .getStringAttribute("templateContents"); @@ -264,7 +206,7 @@ public class VCustomLayout extends ComplexPanel implements VPaintableWidget, return false; }-*/; - private boolean hasTemplate() { + boolean hasTemplate() { if (currentTemplateName == null && !hasTemplateContents) { return false; } else { @@ -295,7 +237,7 @@ public class VCustomLayout extends ComplexPanel implements VPaintableWidget, } /** Evaluate given script in browser document */ - private static native void eval(String script) + static native void eval(String script) /*-{ try { if (script != null) @@ -574,8 +516,4 @@ public class VCustomLayout extends ComplexPanel implements VPaintableWidget, 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 new file mode 100644 index 0000000000..9cf877f446 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VCustomLayoutPaintable.java @@ -0,0 +1,90 @@ +/* +@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/VDateField.java b/src/com/vaadin/terminal/gwt/client/ui/VDateField.java index d21a20229e..14c3b99210 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VDateField.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VDateField.java @@ -8,22 +8,17 @@ import java.util.Date; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.DateTimeService; -import com.vaadin.terminal.gwt.client.LocaleNotLoadedException; -import com.vaadin.terminal.gwt.client.VPaintableWidget; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VConsole; import com.vaadin.terminal.gwt.client.VTooltip; -public class VDateField extends FlowPanel implements VPaintableWidget, Field { +public class VDateField extends FlowPanel implements Field { public static final String CLASSNAME = "v-datefield"; - private String id; + protected String paintableId; - private ApplicationConnection client; + protected ApplicationConnection client; protected boolean immediate; @@ -65,7 +60,7 @@ public class VDateField extends FlowPanel implements VPaintableWidget, Field { protected DateTimeService dts; - private boolean showISOWeekNumbers = false; + protected boolean showISOWeekNumbers = false; public VDateField() { setStyleName(CLASSNAME); @@ -77,80 +72,7 @@ public class VDateField extends FlowPanel implements VPaintableWidget, Field { public void onBrowserEvent(Event event) { super.onBrowserEvent(event); if (client != null) { - client.handleTooltipEvent(event, this); - } - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Ensure correct implementation and let layout manage caption - if (client.updateComponent(this, uidl, true)) { - return; - } - - // Save details - this.client = client; - id = uidl.getId(); - immediate = uidl.getBooleanAttribute("immediate"); - - readonly = uidl.getBooleanAttribute("readonly"); - enabled = !uidl.getBooleanAttribute("disabled"); - - if (uidl.hasAttribute("locale")) { - final String locale = uidl.getStringAttribute("locale"); - try { - dts.setLocale(locale); - currentLocale = locale; - } catch (final LocaleNotLoadedException e) { - currentLocale = dts.getLocale(); - VConsole.error("Tried to use an unloaded locale \"" + locale - + "\". Using default locale (" + currentLocale + ")."); - VConsole.error(e); - } - } - - // We show week numbers only if the week starts with Monday, as ISO 8601 - // specifies - showISOWeekNumbers = uidl.getBooleanAttribute(WEEK_NUMBERS) - && dts.getFirstDayOfWeek() == 1; - - int newResolution; - if (uidl.hasVariable("sec")) { - newResolution = RESOLUTION_SEC; - } else if (uidl.hasVariable("min")) { - newResolution = RESOLUTION_MIN; - } else if (uidl.hasVariable("hour")) { - newResolution = RESOLUTION_HOUR; - } else if (uidl.hasVariable("day")) { - newResolution = RESOLUTION_DAY; - } else if (uidl.hasVariable("month")) { - newResolution = RESOLUTION_MONTH; - } else { - newResolution = RESOLUTION_YEAR; - } - - currentResolution = newResolution; - - // Add stylename that indicates current resolution - addStyleName(CLASSNAME + "-" + resolutionToString(currentResolution)); - - final int year = uidl.getIntVariable("year"); - final int month = (currentResolution >= RESOLUTION_MONTH) ? uidl - .getIntVariable("month") : -1; - final int day = (currentResolution >= RESOLUTION_DAY) ? uidl - .getIntVariable("day") : -1; - final int hour = (currentResolution >= RESOLUTION_HOUR) ? uidl - .getIntVariable("hour") : 0; - final int min = (currentResolution >= RESOLUTION_MIN) ? uidl - .getIntVariable("min") : 0; - final int sec = (currentResolution >= RESOLUTION_SEC) ? uidl - .getIntVariable("sec") : 0; - - // Construct new date for this datefield (only if not null) - if (year > -1) { - setCurrentDate(new Date((long) getTime(year, month, day, hour, min, - sec, 0))); - } else { - setCurrentDate(null); + client.handleWidgetTooltipEvent(event, this); } } @@ -158,7 +80,7 @@ public class VDateField extends FlowPanel implements VPaintableWidget, Field { * We need this redundant native function because Java's Date object doesn't * have a setMilliseconds method. */ - private static native double getTime(int y, int m, int d, int h, int mi, + protected static native double getTime(int y, int m, int d, int h, int mi, int s, int ms) /*-{ try { @@ -227,7 +149,7 @@ public class VDateField extends FlowPanel implements VPaintableWidget, Field { } public String getId() { - return id; + return paintableId; } public ApplicationConnection getClient() { @@ -270,8 +192,4 @@ public class VDateField extends FlowPanel implements VPaintableWidget, Field { protected void setDate(Date date) { this.date = date; } - - public Widget getWidgetForPaintable() { - return this; - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java index 73bfe27700..6bf1d4a3a7 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendar.java @@ -1,153 +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.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.DateTimeService;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusChangeListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusOutListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.SubmitListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.TimeChangeListener;
-
-/**
- * A client side implementation for InlineDateField
- */
-public class VDateFieldCalendar extends VDateField {
-
- private final VCalendarPanel calendarPanel;
-
- public VDateFieldCalendar() {
- super();
- calendarPanel = new VCalendarPanel();
- add(calendarPanel);
- calendarPanel.setSubmitListener(new SubmitListener() {
- public void onSubmit() {
- updateValueFromPanel();
- }
-
- public void onCancel() {
- // TODO Auto-generated method stub
-
- }
- });
- calendarPanel.setFocusOutListener(new FocusOutListener() {
- public boolean onFocusOut(DomEvent<?> event) {
- updateValueFromPanel();
- return false;
- }
- });
- }
-
- @Override
- @SuppressWarnings("deprecation")
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- super.updateFromUIDL(uidl, client);
- calendarPanel.setShowISOWeekNumbers(isShowISOWeekNumbers());
- calendarPanel.setDateTimeService(getDateTimeService());
- calendarPanel.setResolution(getCurrentResolution());
- Date currentDate = getCurrentDate();
- if (currentDate != null) {
- calendarPanel.setDate(new Date(currentDate.getTime()));
- } else {
- calendarPanel.setDate(null);
- }
-
- if (currentResolution > RESOLUTION_DAY) {
- calendarPanel.setTimeChangeListener(new TimeChangeListener() {
- public void changed(int hour, int min, int sec, int msec) {
- Date d = getDate();
- if (d == null) {
- // date currently null, use the value from calendarPanel
- // (~ client time at the init of the widget)
- d = (Date) calendarPanel.getDate().clone();
- }
- d.setHours(hour);
- d.setMinutes(min);
- d.setSeconds(sec);
- DateTimeService.setMilliseconds(d, msec);
-
- // Always update time changes to the server
- calendarPanel.setDate(d);
- updateValueFromPanel();
- }
- });
- }
-
- if (currentResolution <= RESOLUTION_MONTH) {
- calendarPanel.setFocusChangeListener(new FocusChangeListener() {
- public void focusChanged(Date date) {
- Date date2 = new Date();
- if (calendarPanel.getDate() != null) {
- date2.setTime(calendarPanel.getDate().getTime());
- }
- /*
- * Update the value of calendarPanel
- */
- date2.setYear(date.getYear());
- date2.setMonth(date.getMonth());
- calendarPanel.setDate(date2);
- /*
- * Then update the value from panel to server
- */
- updateValueFromPanel();
- }
- });
- } else {
- calendarPanel.setFocusChangeListener(null);
- }
-
- // Update possible changes
- calendarPanel.renderCalendar();
- }
-
- /**
- * TODO refactor: almost same method as in VPopupCalendar.updateValue
- */
- @SuppressWarnings("deprecation")
- private void updateValueFromPanel() {
- Date date2 = calendarPanel.getDate();
- Date currentDate = getCurrentDate();
- if (currentDate == null || date2.getTime() != currentDate.getTime()) {
- setCurrentDate((Date) date2.clone());
- getClient().updateVariable(getId(), "year", date2.getYear() + 1900,
- false);
- if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) {
- getClient().updateVariable(getId(), "month",
- date2.getMonth() + 1, false);
- if (getCurrentResolution() > RESOLUTION_MONTH) {
- getClient().updateVariable(getId(), "day", date2.getDate(),
- false);
- if (getCurrentResolution() > RESOLUTION_DAY) {
- getClient().updateVariable(getId(), "hour",
- date2.getHours(), false);
- if (getCurrentResolution() > RESOLUTION_HOUR) {
- getClient().updateVariable(getId(), "min",
- date2.getMinutes(), false);
- if (getCurrentResolution() > RESOLUTION_MIN) {
- getClient().updateVariable(getId(), "sec",
- date2.getSeconds(), false);
- if (getCurrentResolution() > RESOLUTION_SEC) {
- getClient().updateVariable(
- getId(),
- "msec",
- DateTimeService
- .getMilliseconds(date2),
- false);
- }
- }
- }
- }
- }
- }
- if (isImmediate()) {
- getClient().sendPendingVariableChanges();
- }
- }
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Date; + +import com.google.gwt.event.dom.client.DomEvent; +import com.vaadin.terminal.gwt.client.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/VDateFieldCalendarPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendarPaintable.java new file mode 100644 index 0000000000..8dced06235 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldCalendarPaintable.java @@ -0,0 +1,101 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Date; + +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.DateTimeService; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusChangeListener; +import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.TimeChangeListener; + +public class VDateFieldCalendarPaintable extends VDateFieldPaintable { + + @Override + @SuppressWarnings("deprecation") + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + super.updateFromUIDL(uidl, client); + getWidgetForPaintable().calendarPanel + .setShowISOWeekNumbers(getWidgetForPaintable() + .isShowISOWeekNumbers()); + getWidgetForPaintable().calendarPanel + .setDateTimeService(getWidgetForPaintable() + .getDateTimeService()); + getWidgetForPaintable().calendarPanel + .setResolution(getWidgetForPaintable().getCurrentResolution()); + Date currentDate = getWidgetForPaintable().getCurrentDate(); + if (currentDate != null) { + getWidgetForPaintable().calendarPanel.setDate(new Date(currentDate + .getTime())); + } else { + getWidgetForPaintable().calendarPanel.setDate(null); + } + + if (getWidgetForPaintable().currentResolution > VDateField.RESOLUTION_DAY) { + getWidgetForPaintable().calendarPanel + .setTimeChangeListener(new TimeChangeListener() { + public void changed(int hour, int min, int sec, int msec) { + Date d = getWidgetForPaintable().getDate(); + if (d == null) { + // date currently null, use the value from + // calendarPanel + // (~ client time at the init of the widget) + d = (Date) getWidgetForPaintable().calendarPanel + .getDate().clone(); + } + d.setHours(hour); + d.setMinutes(min); + d.setSeconds(sec); + DateTimeService.setMilliseconds(d, msec); + + // Always update time changes to the server + getWidgetForPaintable().calendarPanel.setDate(d); + getWidgetForPaintable().updateValueFromPanel(); + } + }); + } + + if (getWidgetForPaintable().currentResolution <= VDateField.RESOLUTION_MONTH) { + getWidgetForPaintable().calendarPanel + .setFocusChangeListener(new FocusChangeListener() { + public void focusChanged(Date date) { + Date date2 = new Date(); + if (getWidgetForPaintable().calendarPanel.getDate() != null) { + date2.setTime(getWidgetForPaintable().calendarPanel + .getDate().getTime()); + } + /* + * Update the value of calendarPanel + */ + date2.setYear(date.getYear()); + date2.setMonth(date.getMonth()); + getWidgetForPaintable().calendarPanel + .setDate(date2); + /* + * Then update the value from panel to server + */ + getWidgetForPaintable().updateValueFromPanel(); + } + }); + } else { + getWidgetForPaintable().calendarPanel.setFocusChangeListener(null); + } + + // Update possible changes + getWidgetForPaintable().calendarPanel.renderCalendar(); + } + + @Override + protected Widget createWidget() { + return GWT.create(VDateFieldCalendar.class); + } + + @Override + public VDateFieldCalendar getWidgetForPaintable() { + return (VDateFieldCalendar) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDateFieldPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldPaintable.java new file mode 100644 index 0000000000..a4bbe64a30 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VDateFieldPaintable.java @@ -0,0 +1,109 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Date; + +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.LocaleNotLoadedException; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VConsole; + +public class VDateFieldPaintable extends VAbstractPaintableWidget { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Ensure correct implementation and let layout manage caption + if (client.updateComponent(this, uidl, true)) { + return; + } + + // Save details + getWidgetForPaintable().client = client; + getWidgetForPaintable().paintableId = uidl.getId(); + getWidgetForPaintable().immediate = uidl + .getBooleanAttribute("immediate"); + + getWidgetForPaintable().readonly = uidl.getBooleanAttribute("readonly"); + getWidgetForPaintable().enabled = !uidl.getBooleanAttribute("disabled"); + + if (uidl.hasAttribute("locale")) { + final String locale = uidl.getStringAttribute("locale"); + try { + getWidgetForPaintable().dts.setLocale(locale); + getWidgetForPaintable().currentLocale = locale; + } catch (final LocaleNotLoadedException e) { + getWidgetForPaintable().currentLocale = getWidgetForPaintable().dts + .getLocale(); + VConsole.error("Tried to use an unloaded locale \"" + locale + + "\". Using default locale (" + + getWidgetForPaintable().currentLocale + ")."); + VConsole.error(e); + } + } + + // We show week numbers only if the week starts with Monday, as ISO 8601 + // specifies + getWidgetForPaintable().showISOWeekNumbers = uidl + .getBooleanAttribute(VDateField.WEEK_NUMBERS) + && getWidgetForPaintable().dts.getFirstDayOfWeek() == 1; + + int newResolution; + if (uidl.hasVariable("sec")) { + newResolution = VDateField.RESOLUTION_SEC; + } else if (uidl.hasVariable("min")) { + newResolution = VDateField.RESOLUTION_MIN; + } else if (uidl.hasVariable("hour")) { + newResolution = VDateField.RESOLUTION_HOUR; + } else if (uidl.hasVariable("day")) { + newResolution = VDateField.RESOLUTION_DAY; + } else if (uidl.hasVariable("month")) { + newResolution = VDateField.RESOLUTION_MONTH; + } else { + newResolution = VDateField.RESOLUTION_YEAR; + } + + getWidgetForPaintable().currentResolution = newResolution; + + // Add stylename that indicates current resolution + getWidgetForPaintable() + .addStyleName( + VDateField.CLASSNAME + + "-" + + VDateField + .resolutionToString(getWidgetForPaintable().currentResolution)); + + final int year = uidl.getIntVariable("year"); + final int month = (getWidgetForPaintable().currentResolution >= VDateField.RESOLUTION_MONTH) ? uidl + .getIntVariable("month") : -1; + final int day = (getWidgetForPaintable().currentResolution >= VDateField.RESOLUTION_DAY) ? uidl + .getIntVariable("day") : -1; + final int hour = (getWidgetForPaintable().currentResolution >= VDateField.RESOLUTION_HOUR) ? uidl + .getIntVariable("hour") : 0; + final int min = (getWidgetForPaintable().currentResolution >= VDateField.RESOLUTION_MIN) ? uidl + .getIntVariable("min") : 0; + final int sec = (getWidgetForPaintable().currentResolution >= VDateField.RESOLUTION_SEC) ? uidl + .getIntVariable("sec") : 0; + + // Construct new date for this datefield (only if not null) + if (year > -1) { + getWidgetForPaintable().setCurrentDate( + new Date((long) getWidgetForPaintable().getTime(year, + month, day, hour, min, sec, 0))); + } else { + getWidgetForPaintable().setCurrentDate(null); + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VDateField.class); + } + + @Override + public VDateField getWidgetForPaintable() { + return (VDateField) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java index 3251a03d6a..0297e8df3f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java @@ -4,10 +4,8 @@ package com.vaadin.terminal.gwt.client.ui; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArrayString; @@ -28,7 +26,6 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.RenderInformation; import com.vaadin.terminal.gwt.client.RenderInformation.Size; -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.VPaintable; @@ -97,7 +94,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements super.onBrowserEvent(event); if (client != null) { - client.handleTooltipEvent(event, this); + client.handleWidgetTooltipEvent(event, this); } } @@ -111,7 +108,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements private boolean startDrag(NativeEvent event) { if (dragStartMode == WRAPPER || dragStartMode == COMPONENT) { VTransferable transferable = new VTransferable(); - transferable.setDragSource(VDragAndDropWrapper.this); + transferable.setDragSource(VPaintableMap.get(client).getPaintable( + VDragAndDropWrapper.this)); VPaintableWidget paintable = Util.findPaintable(client, (Element) event.getEventTarget().cast()); @@ -140,58 +138,15 @@ public class VDragAndDropWrapper extends VCustomComponent implements protected int dragStartMode; - private ApplicationConnection client; - private VAbstractDropHandler dropHandler; + ApplicationConnection client; + VAbstractDropHandler dropHandler; private VDragEvent vaadinDragEvent; - private int filecounter = 0; - private Map<String, String> fileIdToReceiver; - private ValueMap html5DataFlavors; + int filecounter = 0; + Map<String, String> fileIdToReceiver; + ValueMap html5DataFlavors; private Element dragStartElement; - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - super.updateFromUIDL(uidl, client); - if (!uidl.hasAttribute("cached") && !uidl.hasAttribute("hidden")) { - UIDL acceptCrit = uidl.getChildByTagName("-ac"); - if (acceptCrit == null) { - dropHandler = null; - } else { - if (dropHandler == null) { - dropHandler = new CustomDropHandler(); - } - 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 (fileIdToReceiver == null) { - fileIdToReceiver = new HashMap<String, String>(); - } - if ("".equals(receiverUrl)) { - Integer id = Integer.parseInt(fileId); - int indexOf = fileIds.indexOf(id); - if (indexOf != -1) { - files.remove(indexOf); - fileIds.remove(indexOf); - } - } else { - fileIdToReceiver.put(fileId, receiverUrl); - } - } - } - startNextUpload(); - - dragStartMode = uidl.getIntAttribute(DRAG_START_MODE); - initDragStartMode(); - html5DataFlavors = uidl.getMapAttribute(HTML5_DATA_FLAVORS); - } - } - protected void initDragStartMode() { Element div = getElement(); if (dragStartMode == HTML5) { @@ -231,7 +186,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements }; private Timer dragleavetimer; - private void startNextUpload() { + void startNextUpload() { Scheduler.get().scheduleDeferred(new Command() { public void execute() { @@ -287,7 +242,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements } if (VDragAndDropManager.get().getCurrentDropHandler() != getDropHandler()) { VTransferable transferable = new VTransferable(); - transferable.setDragSource(this); + transferable.setDragSource(VPaintableMap.get(client) + .getPaintable(this)); vaadinDragEvent = VDragAndDropManager.get().startDrag( transferable, event, false); @@ -455,8 +411,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements * @param fileId * @param data */ - private List<Integer> fileIds = new ArrayList<Integer>(); - private List<VHtml5File> files = new ArrayList<VHtml5File>(); + List<Integer> fileIds = new ArrayList<Integer>(); + List<VHtml5File> files = new ArrayList<VHtml5File>(); private void queueFilePost(final int fileId, final VHtml5File file) { fileIds.add(fileId); @@ -544,7 +500,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements @Override public VPaintableWidget getPaintable() { - return VDragAndDropWrapper.this; + return VPaintableMap.get(client).getPaintable( + VDragAndDropWrapper.this); } public ApplicationConnection getApplicationConnection() { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperPaintable.java new file mode 100644 index 0000000000..2d2f0fcad3 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperPaintable.java @@ -0,0 +1,74 @@ +/* +@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/VEmbedded.java b/src/com/vaadin/terminal/gwt/client/ui/VEmbedded.java index 54385c665f..549a7b4549 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VEmbedded.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VEmbedded.java @@ -8,190 +8,31 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.dom.client.ObjectElement; -import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Unit; -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.Element; import com.google.gwt.user.client.Event; 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.VPaintableWidget; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.VTooltip; -public class VEmbedded extends HTML implements VPaintableWidget { - public static final String CLICK_EVENT_IDENTIFIER = "click"; +public class VEmbedded extends HTML { + public static String CLASSNAME = "v-embedded"; - private static String CLASSNAME = "v-embedded"; + protected String height; + protected String width; + protected Element browserElement; - private String height; - private String width; - private Element browserElement; + protected String type; - private String type; - - private ApplicationConnection client; - - private final ClickEventHandler clickEventHandler = new ClickEventHandler( - this, CLICK_EVENT_IDENTIFIER) { - - @Override - protected <H extends EventHandler> HandlerRegistration registerHandler( - H handler, Type<H> type) { - return addDomHandler(handler, type); - } - - }; + protected ApplicationConnection client; public VEmbedded() { setStyleName(CLASSNAME); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, true)) { - return; - } - this.client = client; - - boolean clearBrowserElement = true; - - clickEventHandler.handleEventHandlerRegistration(client); - - if (uidl.hasAttribute("type")) { - type = uidl.getStringAttribute("type"); - if (type.equals("image")) { - addStyleName(CLASSNAME + "-image"); - Element el = null; - boolean created = false; - NodeList<Node> nodes = getElement().getChildNodes(); - if (nodes != null && nodes.getLength() == 1) { - Node n = nodes.getItem(0); - if (n.getNodeType() == Node.ELEMENT_NODE) { - Element e = (Element) n; - if (e.getTagName().equals("IMG")) { - el = e; - } - } - } - if (el == null) { - setHTML(""); - el = DOM.createImg(); - created = true; - DOM.sinkEvents(el, Event.ONLOAD); - } - - // Set attributes - Style style = el.getStyle(); - String w = uidl.getStringAttribute("width"); - if (w != null) { - style.setProperty("width", w); - } else { - style.setProperty("width", ""); - } - String h = uidl.getStringAttribute("height"); - if (h != null) { - style.setProperty("height", h); - } else { - style.setProperty("height", ""); - } - DOM.setElementProperty(el, "src", getSrc(uidl, client)); - - if (created) { - // insert in dom late - getElement().appendChild(el); - } - - /* - * Sink tooltip events so tooltip is displayed when hovering the - * image. - */ - sinkEvents(VTooltip.TOOLTIP_EVENTS); - - } else if (type.equals("browser")) { - addStyleName(CLASSNAME + "-browser"); - if (browserElement == null) { - setHTML("<iframe width=\"100%\" height=\"100%\" frameborder=\"0\"" - + " allowTransparency=\"true\" src=\"\"" - + " name=\"" + uidl.getId() + "\"></iframe>"); - browserElement = DOM.getFirstChild(getElement()); - } - DOM.setElementAttribute(browserElement, "src", - getSrc(uidl, client)); - clearBrowserElement = false; - } else { - VConsole.log("Unknown Embedded type '" + type + "'"); - } - } else if (uidl.hasAttribute("mimetype")) { - final String mime = uidl.getStringAttribute("mimetype"); - if (mime.equals("application/x-shockwave-flash")) { - // Handle embedding of Flash - addStyleName(CLASSNAME + "-flash"); - setHTML(createFlashEmbed(uidl)); - - } else if (mime.equals("image/svg+xml")) { - addStyleName(CLASSNAME + "-svg"); - String data; - Map<String, String> parameters = getParameters(uidl); - if (parameters.get("data") == null) { - data = getSrc(uidl, client); - } else { - data = "data:image/svg+xml," + parameters.get("data"); - } - setHTML(""); - ObjectElement obj = Document.get().createObjectElement(); - obj.setType(mime); - obj.setData(data); - if (width != null) { - obj.getStyle().setProperty("width", "100%"); - } - if (height != null) { - obj.getStyle().setProperty("height", "100%"); - } - if (uidl.hasAttribute("classid")) { - obj.setAttribute("classid", - uidl.getStringAttribute("classid")); - } - if (uidl.hasAttribute("codebase")) { - obj.setAttribute("codebase", - uidl.getStringAttribute("codebase")); - } - if (uidl.hasAttribute("codetype")) { - obj.setAttribute("codetype", - uidl.getStringAttribute("codetype")); - } - if (uidl.hasAttribute("archive")) { - obj.setAttribute("archive", - uidl.getStringAttribute("archive")); - } - if (uidl.hasAttribute("standby")) { - obj.setAttribute("standby", - uidl.getStringAttribute("standby")); - } - getElement().appendChild(obj); - - } else { - VConsole.log("Unknown Embedded mimetype '" + mime + "'"); - } - } else { - VConsole.log("Unknown Embedded; no type or mimetype attribute"); - } - - if (clearBrowserElement) { - browserElement = null; - } - } - /** * Creates the Object and Embed tags for the Flash plugin so it works * cross-browser @@ -200,7 +41,7 @@ public class VEmbedded extends HTML implements VPaintableWidget { * The UIDL * @return Tags concatenated into a string */ - private String createFlashEmbed(UIDL uidl) { + protected String createFlashEmbed(UIDL uidl) { /* * To ensure cross-browser compatibility we are using the twice-cooked * method to embed flash i.e. we add a OBJECT tag for IE ActiveX and @@ -318,7 +159,7 @@ public class VEmbedded extends HTML implements VPaintableWidget { * @param uidl * @return */ - private static Map<String, String> getParameters(UIDL uidl) { + protected static Map<String, String> getParameters(UIDL uidl) { Map<String, String> parameters = new HashMap<String, String>(); Iterator<Object> childIterator = uidl.getChildIterator(); @@ -347,7 +188,7 @@ public class VEmbedded extends HTML implements VPaintableWidget { * @param client * @return */ - private String getSrc(UIDL uidl, ApplicationConnection client) { + protected String getSrc(UIDL uidl, ApplicationConnection client) { String url = client.translateVaadinUri(uidl.getStringAttribute("src")); if (url == null) { return ""; @@ -412,7 +253,7 @@ public class VEmbedded extends HTML implements VPaintableWidget { Util.notifyParentOfSizeChange(this, true); } - client.handleTooltipEvent(event, this); + client.handleWidgetTooltipEvent(event, this); } /** @@ -432,9 +273,4 @@ public class VEmbedded extends HTML implements VPaintableWidget { Unit.PX); } } - - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VEmbeddedPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VEmbeddedPaintable.java new file mode 100644 index 0000000000..bdb34b6d14 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VEmbeddedPaintable.java @@ -0,0 +1,198 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Map; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.Node; +import com.google.gwt.dom.client.NodeList; +import com.google.gwt.dom.client.ObjectElement; +import com.google.gwt.dom.client.Style; +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.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.VConsole; +import com.vaadin.terminal.gwt.client.VTooltip; + +public class VEmbeddedPaintable extends VAbstractPaintableWidget { + + public static final String CLICK_EVENT_IDENTIFIER = "click"; + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, true)) { + return; + } + + // Save details + getWidgetForPaintable().client = client; + + boolean clearBrowserElement = true; + + clickEventHandler.handleEventHandlerRegistration(client); + + if (uidl.hasAttribute("type")) { + getWidgetForPaintable().type = uidl.getStringAttribute("type"); + if (getWidgetForPaintable().type.equals("image")) { + getWidgetForPaintable().addStyleName( + VEmbedded.CLASSNAME + "-image"); + Element el = null; + boolean created = false; + NodeList<Node> nodes = getWidgetForPaintable().getElement() + .getChildNodes(); + if (nodes != null && nodes.getLength() == 1) { + Node n = nodes.getItem(0); + if (n.getNodeType() == Node.ELEMENT_NODE) { + Element e = (Element) n; + if (e.getTagName().equals("IMG")) { + el = e; + } + } + } + if (el == null) { + getWidgetForPaintable().setHTML(""); + el = DOM.createImg(); + created = true; + DOM.sinkEvents(el, Event.ONLOAD); + } + + // Set attributes + Style style = el.getStyle(); + String w = uidl.getStringAttribute("width"); + if (w != null) { + style.setProperty("width", w); + } else { + style.setProperty("width", ""); + } + String h = uidl.getStringAttribute("height"); + if (h != null) { + style.setProperty("height", h); + } else { + style.setProperty("height", ""); + } + DOM.setElementProperty(el, "src", getWidgetForPaintable() + .getSrc(uidl, client)); + + if (created) { + // insert in dom late + getWidgetForPaintable().getElement().appendChild(el); + } + + /* + * Sink tooltip events so tooltip is displayed when hovering the + * image. + */ + getWidgetForPaintable().sinkEvents(VTooltip.TOOLTIP_EVENTS); + + } else if (getWidgetForPaintable().type.equals("browser")) { + getWidgetForPaintable().addStyleName( + VEmbedded.CLASSNAME + "-browser"); + if (getWidgetForPaintable().browserElement == null) { + getWidgetForPaintable().setHTML( + "<iframe width=\"100%\" height=\"100%\" frameborder=\"0\"" + + " allowTransparency=\"true\" src=\"\"" + + " name=\"" + uidl.getId() + + "\"></iframe>"); + getWidgetForPaintable().browserElement = DOM + .getFirstChild(getWidgetForPaintable().getElement()); + } + DOM.setElementAttribute(getWidgetForPaintable().browserElement, + "src", getWidgetForPaintable().getSrc(uidl, client)); + clearBrowserElement = false; + } else { + VConsole.log("Unknown Embedded type '" + + getWidgetForPaintable().type + "'"); + } + } else if (uidl.hasAttribute("mimetype")) { + final String mime = uidl.getStringAttribute("mimetype"); + if (mime.equals("application/x-shockwave-flash")) { + // Handle embedding of Flash + getWidgetForPaintable().addStyleName( + VEmbedded.CLASSNAME + "-flash"); + getWidgetForPaintable().setHTML( + getWidgetForPaintable().createFlashEmbed(uidl)); + + } else if (mime.equals("image/svg+xml")) { + getWidgetForPaintable().addStyleName( + VEmbedded.CLASSNAME + "-svg"); + String data; + Map<String, String> parameters = VEmbedded.getParameters(uidl); + if (parameters.get("data") == null) { + data = getWidgetForPaintable().getSrc(uidl, client); + } else { + data = "data:image/svg+xml," + parameters.get("data"); + } + getWidgetForPaintable().setHTML(""); + ObjectElement obj = Document.get().createObjectElement(); + obj.setType(mime); + obj.setData(data); + if (getWidgetForPaintable().width != null) { + obj.getStyle().setProperty("width", "100%"); + } + if (getWidgetForPaintable().height != null) { + obj.getStyle().setProperty("height", "100%"); + } + if (uidl.hasAttribute("classid")) { + obj.setAttribute("classid", + uidl.getStringAttribute("classid")); + } + if (uidl.hasAttribute("codebase")) { + obj.setAttribute("codebase", + uidl.getStringAttribute("codebase")); + } + if (uidl.hasAttribute("codetype")) { + obj.setAttribute("codetype", + uidl.getStringAttribute("codetype")); + } + if (uidl.hasAttribute("archive")) { + obj.setAttribute("archive", + uidl.getStringAttribute("archive")); + } + if (uidl.hasAttribute("standby")) { + obj.setAttribute("standby", + uidl.getStringAttribute("standby")); + } + getWidgetForPaintable().getElement().appendChild(obj); + + } else { + VConsole.log("Unknown Embedded mimetype '" + mime + "'"); + } + } else { + VConsole.log("Unknown Embedded; no type or mimetype attribute"); + } + + if (clearBrowserElement) { + getWidgetForPaintable().browserElement = null; + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VEmbedded.class); + } + + @Override + public VEmbedded getWidgetForPaintable() { + return (VEmbedded) super.getWidgetForPaintable(); + } + + protected final 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); + } + + }; +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java index b6bbe5dd19..b54c3dd943 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java @@ -42,12 +42,10 @@ import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.PopupPanel.PositionCallback; import com.google.gwt.user.client.ui.SuggestOracle.Suggestion; import com.google.gwt.user.client.ui.TextBox; -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.Focusable; -import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VConsole; @@ -59,9 +57,8 @@ import com.vaadin.terminal.gwt.client.VTooltip; * TODO needs major refactoring (to be extensible etc) */ @SuppressWarnings("deprecation") -public class VFilterSelect extends Composite implements VPaintableWidget, Field, - KeyDownHandler, KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, - Focusable { +public class VFilterSelect extends Composite implements Field, KeyDownHandler, + KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, Focusable { /** * Represents a suggestion in the suggestion popup box @@ -153,7 +150,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, private static final String Z_INDEX = "30000"; - private final SuggestionMenu menu; + protected final SuggestionMenu menu; private final Element up = DOM.createDiv(); private final Element down = DOM.createDiv(); @@ -776,7 +773,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, return keyboardSelectedItem; } - private void setKeyboardSelectedItem(MenuItem firstItem) { + protected void setKeyboardSelectedItem(MenuItem firstItem) { keyboardSelectedItem = firstItem; } @@ -803,7 +800,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, /** * The text box where the filter is written */ - private final TextBox tb = new TextBox() { + protected final TextBox tb = new TextBox() { /* * (non-Javadoc) * @@ -815,7 +812,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, public void onBrowserEvent(Event event) { super.onBrowserEvent(event); if (client != null) { - client.handleTooltipEvent(event, VFilterSelect.this); + client.handleWidgetTooltipEvent(event, VFilterSelect.this); } } @@ -830,7 +827,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, }; }; - private final SuggestionPopup suggestionPopup = new SuggestionPopup(); + protected final SuggestionPopup suggestionPopup = new SuggestionPopup(); /** * Used when measuring the width of the popup @@ -848,7 +845,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, public void onBrowserEvent(Event event) { super.onBrowserEvent(event); if (client != null) { - client.handleTooltipEvent(event, VFilterSelect.this); + client.handleWidgetTooltipEvent(event, VFilterSelect.this); } /* @@ -861,73 +858,73 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, private final Image selectedItemIcon = new Image(); - private ApplicationConnection client; + protected ApplicationConnection client; - private String paintableId; + protected String paintableId; - private int currentPage; + protected int currentPage; /** * A collection of available suggestions (options) as received from the * server. */ - private final List<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>(); + protected final List<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>(); - private boolean immediate; + protected boolean immediate; - private String selectedOptionKey; + protected String selectedOptionKey; - private boolean waitingForFilteringResponse = false; - private boolean updateSelectionWhenReponseIsReceived = false; + protected boolean waitingForFilteringResponse = false; + protected boolean updateSelectionWhenReponseIsReceived = false; private boolean tabPressedWhenPopupOpen = false; - private boolean initDone = false; + protected boolean initDone = false; - private String lastFilter = ""; + protected String lastFilter = ""; - private enum Select { + protected enum Select { NONE, FIRST, LAST }; - private Select selectPopupItemWhenResponseIsReceived = Select.NONE; + protected Select selectPopupItemWhenResponseIsReceived = Select.NONE; /** * The current suggestion selected from the dropdown. This is one of the * values in currentSuggestions except when filtering, in this case * currentSuggestion might not be in currentSuggestions. */ - private FilterSelectSuggestion currentSuggestion; + protected FilterSelectSuggestion currentSuggestion; - private int totalMatches; - private boolean allowNewItem; - private boolean nullSelectionAllowed; - private boolean nullSelectItem; - private boolean enabled; - private boolean readonly; + protected int totalMatches; + protected boolean allowNewItem; + protected boolean nullSelectionAllowed; + protected boolean nullSelectItem; + protected boolean enabled; + protected boolean readonly; - private int filteringmode = FILTERINGMODE_OFF; + protected int filteringmode = FILTERINGMODE_OFF; // shown in unfocused empty field, disappears on focus (e.g "Search here") private static final String CLASSNAME_PROMPT = "prompt"; - private static final String ATTR_INPUTPROMPT = "prompt"; + protected static final String ATTR_INPUTPROMPT = "prompt"; public static final String ATTR_NO_TEXT_INPUT = "noInput"; - private String inputPrompt = ""; - private boolean prompting = false; + protected String inputPrompt = ""; + protected boolean prompting = false; // Set true when popupopened has been clicked. Cleared on each UIDL-update. // This handles the special case where are not filtering yet and the // selected value has changed on the server-side. See #2119 - private boolean popupOpenerClicked; + protected boolean popupOpenerClicked; private String width = null; private int textboxPadding = -1; private int componentPadding = -1; - private int suggestionPopupMinWidth = 0; + protected int suggestionPopupMinWidth = 0; private int popupWidth = -1; /* * Stores the last new item string to avoid double submissions. Cleared on * uidl updates */ - private String lastNewItemString; - private boolean focused = false; + protected String lastNewItemString; + protected boolean focused = false; private int horizPaddingAndBorder = 2; /** @@ -1006,6 +1003,20 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, * 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, @@ -1025,209 +1036,16 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, waitingForFilteringResponse = true; client.updateVariable(paintableId, "filter", filter, false); - client.updateVariable(paintableId, "page", page, true); + client.updateVariable(paintableId, "page", page, immediate); lastFilter = filter; currentPage = page; } - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal - * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection) - */ - @SuppressWarnings("deprecation") - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - paintableId = uidl.getId(); - this.client = client; - - readonly = uidl.hasAttribute("readonly"); - enabled = !uidl.hasAttribute("disabled"); - - tb.setEnabled(enabled); - updateReadOnly(); - - if (client.updateComponent(this, uidl, true)) { - return; - } - - // Inverse logic here to make the default case (text input enabled) - // work without additional UIDL messages - boolean noTextInput = uidl.hasAttribute(ATTR_NO_TEXT_INPUT) - && uidl.getBooleanAttribute(ATTR_NO_TEXT_INPUT); - setTextInputEnabled(!noTextInput); - - // not a FocusWidget -> needs own tabindex handling - if (uidl.hasAttribute("tabindex")) { - tb.setTabIndex(uidl.getIntAttribute("tabindex")); - } - - if (uidl.hasAttribute("filteringmode")) { - filteringmode = uidl.getIntAttribute("filteringmode"); - } - - immediate = uidl.hasAttribute("immediate"); - - nullSelectionAllowed = uidl.hasAttribute("nullselect"); - - nullSelectItem = uidl.hasAttribute("nullselectitem") - && uidl.getBooleanAttribute("nullselectitem"); - - currentPage = uidl.getIntVariable("page"); - - if (uidl.hasAttribute("pagelength")) { - pageLength = uidl.getIntAttribute("pagelength"); - } - - if (uidl.hasAttribute(ATTR_INPUTPROMPT)) { - // input prompt changed from server - inputPrompt = uidl.getStringAttribute(ATTR_INPUTPROMPT); - } else { - inputPrompt = ""; - } - - suggestionPopup.updateStyleNames(uidl); - - allowNewItem = uidl.hasAttribute("allownewitem"); - lastNewItemString = null; - - currentSuggestions.clear(); - if (!waitingForFilteringResponse) { - /* - * Clear the current suggestions as the server response always - * includes the new ones. Exception is when filtering, then we need - * to retain the value if the user does not select any of the - * options matching the filter. - */ - currentSuggestion = null; - /* - * Also ensure no old items in menu. Unless cleared the old values - * may cause odd effects on blur events. Suggestions in menu might - * not necessary exist in select at all anymore. - */ - suggestionPopup.menu.clearItems(); - - } - - final UIDL options = uidl.getChildUIDL(0); - if (uidl.hasAttribute("totalMatches")) { - totalMatches = uidl.getIntAttribute("totalMatches"); - } else { - totalMatches = 0; - } - - // used only to calculate minimum popup width - String captions = Util.escapeHTML(inputPrompt); - - for (final Iterator<?> i = options.getChildIterator(); i.hasNext();) { - final UIDL optionUidl = (UIDL) i.next(); - final FilterSelectSuggestion suggestion = new FilterSelectSuggestion( - optionUidl); - currentSuggestions.add(suggestion); - if (optionUidl.hasAttribute("selected")) { - if (!waitingForFilteringResponse || popupOpenerClicked) { - String newSelectedOptionKey = Integer.toString(suggestion - .getOptionKey()); - if (!newSelectedOptionKey.equals(selectedOptionKey) - || suggestion.getReplacementString().equals( - tb.getText())) { - // Update text field if we've got a new selection - // Also update if we've got the same text to retain old - // text selection behavior - setPromptingOff(suggestion.getReplacementString()); - selectedOptionKey = newSelectedOptionKey; - } - } - currentSuggestion = suggestion; - setSelectedItemIcon(suggestion.getIconUri()); - } - - // Collect captions so we can calculate minimum width for textarea - if (captions.length() > 0) { - captions += "|"; - } - captions += Util.escapeHTML(suggestion.getReplacementString()); - } - - if ((!waitingForFilteringResponse || popupOpenerClicked) - && uidl.hasVariable("selected") - && uidl.getStringArrayVariable("selected").length == 0) { - // select nulled - if (!waitingForFilteringResponse || !popupOpenerClicked) { - if (!focused) { - /* - * client.updateComponent overwrites all styles so we must - * ALWAYS set the prompting style at this point, even though - * we think it has been set already... - */ - prompting = false; - setPromptingOn(); - } else { - // we have focus in field, prompting can't be set on, - // instead just clear the input - tb.setValue(""); - } - } - selectedOptionKey = null; - } - - if (waitingForFilteringResponse - && lastFilter.toLowerCase().equals( - uidl.getStringVariable("filter"))) { - suggestionPopup.showSuggestions(currentSuggestions, currentPage, - totalMatches); - waitingForFilteringResponse = false; - if (!popupOpenerClicked - && selectPopupItemWhenResponseIsReceived != Select.NONE) { - // we're paging w/ arrows - if (selectPopupItemWhenResponseIsReceived == Select.LAST) { - suggestionPopup.menu.selectLastItem(); - } else { - suggestionPopup.menu.selectFirstItem(); - } - - // This is used for paging so we update the keyboard selection - // variable as well. - MenuItem activeMenuItem = suggestionPopup.menu - .getSelectedItem(); - suggestionPopup.menu.setKeyboardSelectedItem(activeMenuItem); - - // Update text field to contain the correct text - setTextboxText(activeMenuItem.getText()); - tb.setSelectionRange(lastFilter.length(), activeMenuItem - .getText().length() - lastFilter.length()); - - selectPopupItemWhenResponseIsReceived = Select.NONE; // reset - } - if (updateSelectionWhenReponseIsReceived) { - suggestionPopup.menu.doPostFilterSelectedItemAction(); - } - } - - // Calculate minumum textarea width - suggestionPopupMinWidth = minWidth(captions); - - popupOpenerClicked = false; - - if (!initDone) { - updateRootWidth(); - } - - // Focus dependent style names are lost during the update, so we add - // them here back again - if (focused) { - addStyleDependentName("focus"); - } - - initDone = true; - } - - private void updateReadOnly() { + protected void updateReadOnly() { tb.setReadOnly(readonly || !textInputEnabled); } - private void setTextInputEnabled(boolean textInputEnabled) { + protected void setTextInputEnabled(boolean textInputEnabled) { // Always update styles as they might have been overwritten if (textInputEnabled) { removeStyleDependentName(STYLE_NO_INPUT); @@ -1249,7 +1067,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, * @param text * the text to set in the text box */ - private void setTextboxText(final String text) { + protected void setTextboxText(final String text) { tb.setText(text); } @@ -1273,7 +1091,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, * Turns prompting on. When prompting is turned on a command prompt is shown * in the text box if nothing has been entered. */ - private void setPromptingOn() { + protected void setPromptingOn() { if (!prompting) { prompting = true; addStyleDependentName(CLASSNAME_PROMPT); @@ -1288,7 +1106,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, * @param text * The text the text box should contain. */ - private void setPromptingOff(String text) { + protected void setPromptingOff(String text) { setTextboxText(text); if (prompting) { prompting = false; @@ -1338,7 +1156,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, * @param iconUri * The URI of the icon */ - private void setSelectedItemIcon(String iconUri) { + protected void setSelectedItemIcon(String iconUri) { if (iconUri == null || iconUri == "") { panel.remove(selectedItemIcon); updateRootWidth(); @@ -1600,7 +1418,12 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, // 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 = ""; } @@ -1613,7 +1436,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, /** * Calculate minimum width for FilterSelect textarea */ - private native int minWidth(String captions) + protected native int minWidth(String captions) /*-{ if(!captions || captions.length <= 0) return 0; @@ -1665,7 +1488,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, } addStyleDependentName("focus"); - if (client.hasEventListeners(this, EventId.FOCUS)) { + if (client.hasWidgetEventListeners(this, EventId.FOCUS)) { client.updateVariable(paintableId, EventId.FOCUS, "", true); } } @@ -1730,7 +1553,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, } removeStyleDependentName("focus"); - if (client.hasEventListeners(this, EventId.BLUR)) { + if (client.hasWidgetEventListeners(this, EventId.BLUR)) { client.updateVariable(paintableId, EventId.BLUR, "", true); } } @@ -1784,7 +1607,7 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, * Calculates the width of the select if the select has undefined width. * Should be called when the width changes or when the icon changes. */ - private void updateRootWidth() { + protected void updateRootWidth() { if (width == null) { /* * When the width is not specified we must specify width for root @@ -1934,8 +1757,4 @@ public class VFilterSelect extends Composite implements VPaintableWidget, Field, super.onDetach(); suggestionPopup.hide(); } - - public Widget getWidgetForPaintable() { - return this; - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelectPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelectPaintable.java new file mode 100644 index 0000000000..3249ea17d5 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelectPaintable.java @@ -0,0 +1,244 @@ +/* +@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.Util; +import com.vaadin.terminal.gwt.client.ui.VFilterSelect.FilterSelectSuggestion; + +public class VFilterSelectPaintable extends VAbstractPaintableWidget { + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal + * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection) + */ + @SuppressWarnings("deprecation") + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Save details + getWidgetForPaintable().client = client; + getWidgetForPaintable().paintableId = uidl.getId(); + + getWidgetForPaintable().readonly = uidl.hasAttribute("readonly"); + getWidgetForPaintable().enabled = !uidl.hasAttribute("disabled"); + + getWidgetForPaintable().tb.setEnabled(getWidgetForPaintable().enabled); + getWidgetForPaintable().updateReadOnly(); + + if (client.updateComponent(this, uidl, true)) { + return; + } + + // Inverse logic here to make the default case (text input enabled) + // work without additional UIDL messages + boolean noTextInput = uidl + .hasAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT) + && uidl.getBooleanAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT); + getWidgetForPaintable().setTextInputEnabled(!noTextInput); + + // not a FocusWidget -> needs own tabindex handling + if (uidl.hasAttribute("tabindex")) { + getWidgetForPaintable().tb.setTabIndex(uidl + .getIntAttribute("tabindex")); + } + + if (uidl.hasAttribute("filteringmode")) { + getWidgetForPaintable().filteringmode = uidl + .getIntAttribute("filteringmode"); + } + + getWidgetForPaintable().immediate = uidl.hasAttribute("immediate"); + + getWidgetForPaintable().nullSelectionAllowed = uidl + .hasAttribute("nullselect"); + + getWidgetForPaintable().nullSelectItem = uidl + .hasAttribute("nullselectitem") + && uidl.getBooleanAttribute("nullselectitem"); + + getWidgetForPaintable().currentPage = uidl.getIntVariable("page"); + + if (uidl.hasAttribute("pagelength")) { + getWidgetForPaintable().pageLength = uidl + .getIntAttribute("pagelength"); + } + + if (uidl.hasAttribute(VFilterSelect.ATTR_INPUTPROMPT)) { + // input prompt changed from server + getWidgetForPaintable().inputPrompt = uidl + .getStringAttribute(VFilterSelect.ATTR_INPUTPROMPT); + } else { + getWidgetForPaintable().inputPrompt = ""; + } + + getWidgetForPaintable().suggestionPopup.updateStyleNames(uidl); + + getWidgetForPaintable().allowNewItem = uidl + .hasAttribute("allownewitem"); + getWidgetForPaintable().lastNewItemString = null; + + getWidgetForPaintable().currentSuggestions.clear(); + if (!getWidgetForPaintable().waitingForFilteringResponse) { + /* + * Clear the current suggestions as the server response always + * includes the new ones. Exception is when filtering, then we need + * to retain the value if the user does not select any of the + * options matching the filter. + */ + getWidgetForPaintable().currentSuggestion = null; + /* + * Also ensure no old items in menu. Unless cleared the old values + * may cause odd effects on blur events. Suggestions in menu might + * not necessary exist in select at all anymore. + */ + getWidgetForPaintable().suggestionPopup.menu.clearItems(); + + } + + final UIDL options = uidl.getChildUIDL(0); + if (uidl.hasAttribute("totalMatches")) { + getWidgetForPaintable().totalMatches = uidl + .getIntAttribute("totalMatches"); + } else { + getWidgetForPaintable().totalMatches = 0; + } + + // used only to calculate minimum popup width + String captions = Util.escapeHTML(getWidgetForPaintable().inputPrompt); + + for (final Iterator<?> i = options.getChildIterator(); i.hasNext();) { + final UIDL optionUidl = (UIDL) i.next(); + final FilterSelectSuggestion suggestion = getWidgetForPaintable().new FilterSelectSuggestion( + optionUidl); + getWidgetForPaintable().currentSuggestions.add(suggestion); + if (optionUidl.hasAttribute("selected")) { + if (!getWidgetForPaintable().waitingForFilteringResponse + || getWidgetForPaintable().popupOpenerClicked) { + String newSelectedOptionKey = Integer.toString(suggestion + .getOptionKey()); + if (!newSelectedOptionKey + .equals(getWidgetForPaintable().selectedOptionKey) + || suggestion.getReplacementString().equals( + getWidgetForPaintable().tb.getText())) { + // Update text field if we've got a new selection + // Also update if we've got the same text to retain old + // text selection behavior + getWidgetForPaintable().setPromptingOff( + suggestion.getReplacementString()); + getWidgetForPaintable().selectedOptionKey = newSelectedOptionKey; + } + } + getWidgetForPaintable().currentSuggestion = suggestion; + getWidgetForPaintable().setSelectedItemIcon( + suggestion.getIconUri()); + } + + // Collect captions so we can calculate minimum width for textarea + if (captions.length() > 0) { + captions += "|"; + } + captions += Util.escapeHTML(suggestion.getReplacementString()); + } + + if ((!getWidgetForPaintable().waitingForFilteringResponse || getWidgetForPaintable().popupOpenerClicked) + && uidl.hasVariable("selected") + && uidl.getStringArrayVariable("selected").length == 0) { + // select nulled + if (!getWidgetForPaintable().waitingForFilteringResponse + || !getWidgetForPaintable().popupOpenerClicked) { + if (!getWidgetForPaintable().focused) { + /* + * client.updateComponent overwrites all styles so we must + * ALWAYS set the prompting style at this point, even though + * we think it has been set already... + */ + getWidgetForPaintable().prompting = false; + getWidgetForPaintable().setPromptingOn(); + } else { + // we have focus in field, prompting can't be set on, + // instead just clear the input + getWidgetForPaintable().tb.setValue(""); + } + } + getWidgetForPaintable().selectedOptionKey = null; + } + + if (getWidgetForPaintable().waitingForFilteringResponse + && getWidgetForPaintable().lastFilter.toLowerCase().equals( + uidl.getStringVariable("filter"))) { + getWidgetForPaintable().suggestionPopup.showSuggestions( + getWidgetForPaintable().currentSuggestions, + getWidgetForPaintable().currentPage, + getWidgetForPaintable().totalMatches); + getWidgetForPaintable().waitingForFilteringResponse = false; + if (!getWidgetForPaintable().popupOpenerClicked + && getWidgetForPaintable().selectPopupItemWhenResponseIsReceived != VFilterSelect.Select.NONE) { + // we're paging w/ arrows + if (getWidgetForPaintable().selectPopupItemWhenResponseIsReceived == VFilterSelect.Select.LAST) { + getWidgetForPaintable().suggestionPopup.menu + .selectLastItem(); + } else { + getWidgetForPaintable().suggestionPopup.menu + .selectFirstItem(); + } + + // This is used for paging so we update the keyboard selection + // variable as well. + MenuItem activeMenuItem = getWidgetForPaintable().suggestionPopup.menu + .getSelectedItem(); + getWidgetForPaintable().suggestionPopup.menu + .setKeyboardSelectedItem(activeMenuItem); + + // Update text field to contain the correct text + getWidgetForPaintable() + .setTextboxText(activeMenuItem.getText()); + getWidgetForPaintable().tb.setSelectionRange( + getWidgetForPaintable().lastFilter.length(), + activeMenuItem.getText().length() + - getWidgetForPaintable().lastFilter.length()); + + getWidgetForPaintable().selectPopupItemWhenResponseIsReceived = VFilterSelect.Select.NONE; // reset + } + if (getWidgetForPaintable().updateSelectionWhenReponseIsReceived) { + getWidgetForPaintable().suggestionPopup.menu + .doPostFilterSelectedItemAction(); + } + } + + // Calculate minumum textarea width + getWidgetForPaintable().suggestionPopupMinWidth = getWidgetForPaintable() + .minWidth(captions); + + getWidgetForPaintable().popupOpenerClicked = false; + + if (!getWidgetForPaintable().initDone) { + getWidgetForPaintable().updateRootWidth(); + } + + // Focus dependent style names are lost during the update, so we add + // them here back again + if (getWidgetForPaintable().focused) { + getWidgetForPaintable().addStyleDependentName("focus"); + } + + getWidgetForPaintable().initDone = true; + } + + @Override + protected Widget createWidget() { + return GWT.create(VFilterSelect.class); + } + + @Override + public VFilterSelect getWidgetForPaintable() { + return (VFilterSelect) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VForm.java b/src/com/vaadin/terminal/gwt/client/ui/VForm.java index a329e1eaef..f3276db008 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VForm.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VForm.java @@ -19,12 +19,9 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.RenderInformation; import com.vaadin.terminal.gwt.client.RenderSpace; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VConsole; import com.vaadin.terminal.gwt.client.VErrorMessage; -import com.vaadin.terminal.gwt.client.VPaintableMap; -import com.vaadin.terminal.gwt.client.VPaintableWidget; public class VForm extends ComplexPanel implements Container, KeyDownHandler { @@ -36,33 +33,33 @@ public class VForm extends ComplexPanel implements Container, KeyDownHandler { public static final String CLASSNAME = "v-form"; - private Container lo; - private Element legend = DOM.createLegend(); - private Element caption = DOM.createSpan(); + Widget lo; + Element legend = DOM.createLegend(); + Element caption = DOM.createSpan(); private Element errorIndicatorElement = DOM.createDiv(); - private Element desc = DOM.createDiv(); - private Icon icon; - private VErrorMessage errorMessage = new VErrorMessage(); + Element desc = DOM.createDiv(); + Icon icon; + VErrorMessage errorMessage = new VErrorMessage(); - private Element fieldContainer = DOM.createDiv(); + Element fieldContainer = DOM.createDiv(); - private Element footerContainer = DOM.createDiv(); + Element footerContainer = DOM.createDiv(); - private Element fieldSet = DOM.createFieldSet(); + Element fieldSet = DOM.createFieldSet(); - private Container footer; + Widget footer; - private ApplicationConnection client; + ApplicationConnection client; private RenderInformation renderInformation = new RenderInformation(); private int borderPaddingHorizontal = -1; - private boolean rendering = false; + boolean rendering = false; ShortcutActionHandler shortcutHandler; - private HandlerRegistration keyDownRegistration; + HandlerRegistration keyDownRegistration; public VForm() { setElement(DOM.createDiv()); @@ -84,130 +81,6 @@ public class VForm extends ComplexPanel implements Container, KeyDownHandler { fieldSet.appendChild(footerContainer); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - rendering = true; - this.client = client; - id = uidl.getId(); - - if (client.updateComponent(this, uidl, false)) { - rendering = false; - return; - } - - boolean legendEmpty = true; - if (uidl.hasAttribute("caption")) { - caption.setInnerText(uidl.getStringAttribute("caption")); - legendEmpty = false; - } else { - caption.setInnerText(""); - } - if (uidl.hasAttribute("icon")) { - if (icon == null) { - icon = new Icon(client); - legend.insertFirst(icon.getElement()); - } - icon.setUri(uidl.getStringAttribute("icon")); - legendEmpty = false; - } else { - if (icon != null) { - legend.removeChild(icon.getElement()); - } - } - if (legendEmpty) { - addStyleDependentName("nocaption"); - } else { - removeStyleDependentName("nocaption"); - } - - if (uidl.hasAttribute("error")) { - final UIDL errorUidl = uidl.getErrors(); - errorMessage.updateFromUIDL(errorUidl); - errorMessage.setVisible(true); - - } else { - errorMessage.setVisible(false); - } - - if (uidl.hasAttribute("description")) { - desc.setInnerHTML(uidl.getStringAttribute("description")); - if (desc.getParentElement() == null) { - fieldSet.insertAfter(desc, legend); - } - } else { - desc.setInnerHTML(""); - if (desc.getParentElement() != null) { - fieldSet.removeChild(desc); - } - } - - updateSize(); - - // first render footer so it will be easier to handle relative height of - // main layout - if (uidl.getChildCount() > 1 - && !uidl.getChildUIDL(1).getTag().equals("actions")) { - // render footer - Container newFooter = (Container) client.getPaintable(uidl - .getChildUIDL(1)); - if (footer == null) { - add(newFooter.getWidgetForPaintable(), footerContainer); - footer = newFooter; - } else if (newFooter != footer) { - remove(footer.getWidgetForPaintable()); - client.unregisterPaintable(footer); - add(newFooter.getWidgetForPaintable(), footerContainer); - } - footer = newFooter; - footer.updateFromUIDL(uidl.getChildUIDL(1), client); - // needed for the main layout to know the space it has available - updateSize(); - } else { - if (footer != null) { - remove(footer.getWidgetForPaintable()); - client.unregisterPaintable(footer); - // needed for the main layout to know the space it has available - updateSize(); - } - } - - final UIDL layoutUidl = uidl.getChildUIDL(0); - Container newLo = (Container) client.getPaintable(layoutUidl); - if (lo == null) { - lo = newLo; - add(lo.getWidgetForPaintable(), fieldContainer); - } else if (lo != newLo) { - client.unregisterPaintable(lo); - remove(lo.getWidgetForPaintable()); - lo = newLo; - add(lo.getWidgetForPaintable(), fieldContainer); - } - lo.updateFromUIDL(layoutUidl, client); - - // also recalculates size of the footer if undefined size form - see - // #3710 - updateSize(); - client.runDescendentsLayout(this); - - // We may have actions attached - if (uidl.getChildCount() > 1) { - UIDL childUidl = uidl.getChildByTagName("actions"); - if (childUidl != null) { - if (shortcutHandler == null) { - shortcutHandler = new ShortcutActionHandler(id, client); - keyDownRegistration = addDomHandler(this, - KeyDownEvent.getType()); - } - shortcutHandler.updateActionMap(childUidl); - } - } else if (shortcutHandler != null) { - keyDownRegistration.removeHandler(); - shortcutHandler = null; - keyDownRegistration = null; - } - - rendering = false; - } - public void updateSize() { renderInformation.updateSize(getElement()); @@ -241,12 +114,10 @@ public class VForm extends ComplexPanel implements Container, KeyDownHandler { } remove(oldComponent); if (oldComponent == lo) { - lo = (Container) VPaintableMap.get(client).getPaintable( - newComponent); + lo = newComponent; add(newComponent, fieldContainer); } else { - footer = (Container) VPaintableMap.get(client).getPaintable( - newComponent); + footer = newComponent; add(newComponent, footerContainer); } @@ -272,11 +143,6 @@ public class VForm extends ComplexPanel implements Container, KeyDownHandler { } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - // NOP form don't render caption for neither field layout nor footer - // layout - } - @Override public void setHeight(String height) { if (this.height.equals(height)) { @@ -329,7 +195,10 @@ 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 + // once functionality from VFormPaintable is moved to VForm. + super.add(child, container); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java index e6305b3c42..6d3072f407 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java @@ -38,13 +38,13 @@ public class VFormLayout extends SimplePanel implements Container { private final static String CLASSNAME = "v-formlayout"; - private ApplicationConnection client; - private VFormLayoutTable table; + ApplicationConnection client; + VFormLayoutTable table; private String width = ""; private String height = ""; - private boolean rendering = false; + boolean rendering = false; public VFormLayout() { super(); @@ -279,21 +279,6 @@ public class VFormLayout extends SimplePanel implements Container { } } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - rendering = true; - - this.client = client; - - if (client.updateComponent(this, uidl, true)) { - rendering = false; - return; - } - - table.updateFromUIDL(uidl, client); - - rendering = false; - } - public boolean isDynamicWidth() { return width.equals(""); } @@ -306,10 +291,6 @@ public class VFormLayout extends SimplePanel implements Container { table.replaceChildComponent(oldComponent, newComponent); } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - table.updateCaption(component, uidl); - } - public class Caption extends HTML { public static final String CLASSNAME = "v-caption"; @@ -545,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 new file mode 100644 index 0000000000..3be2a028c5 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VFormLayoutPaintable.java @@ -0,0 +1,42 @@ +/* +@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 new file mode 100644 index 0000000000..e2533591ea --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VFormPaintable.java @@ -0,0 +1,176 @@ +/* +@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 b37032e987..5302fa6f67 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java @@ -14,16 +14,12 @@ import java.util.Set; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; -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.AbsolutePanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Container; -import com.vaadin.terminal.gwt.client.EventId; import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.StyleConstants; import com.vaadin.terminal.gwt.client.UIDL; @@ -33,59 +29,43 @@ import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.ui.layout.CellBasedLayout; import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer; -public class VGridLayout extends SimplePanel implements VPaintableWidget, - Container { +public class VGridLayout extends SimplePanel implements Container { public static final String CLASSNAME = "v-gridlayout"; private DivElement margin = Document.get().createDivElement(); - private final AbsolutePanel canvas = new AbsolutePanel(); + final AbsolutePanel canvas = new AbsolutePanel(); - private ApplicationConnection client; + ApplicationConnection client; protected HashMap<Widget, ChildComponentContainer> widgetToComponentContainer = new HashMap<Widget, ChildComponentContainer>(); - private HashMap<Widget, Cell> widgetToCell = new HashMap<Widget, Cell>(); + HashMap<Widget, Cell> widgetToCell = new HashMap<Widget, Cell>(); private int spacingPixelsHorizontal; private int spacingPixelsVertical; - private int[] columnWidths; - private int[] rowHeights; + int[] columnWidths; + int[] rowHeights; private String height; private String width; - private int[] colExpandRatioArray; + int[] colExpandRatioArray; - private int[] rowExpandRatioArray; + int[] rowExpandRatioArray; - private int[] minColumnWidths; + int[] minColumnWidths; private int[] minRowHeights; - private boolean rendering; + boolean rendering; - private HashMap<Widget, ChildComponentContainer> nonRenderedWidgets; + HashMap<Widget, ChildComponentContainer> nonRenderedWidgets; - private boolean sizeChangedDuringRendering = false; - - private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( - this, EventId.LAYOUT_CLICK) { - - @Override - protected VPaintableWidget getChildComponent(Element element) { - return getComponent(element); - } - - @Override - protected <H extends EventHandler> HandlerRegistration registerHandler( - H handler, Type<H> type) { - return addDomHandler(handler, type); - } - }; + boolean sizeChangedDuringRendering = false; public VGridLayout() { super(); @@ -135,126 +115,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, return spacingPixelsVertical; } - @SuppressWarnings("unchecked") - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - rendering = true; - this.client = client; - - if (client.updateComponent(this, uidl, true)) { - rendering = false; - return; - } - clickEventHandler.handleEventHandlerRegistration(client); - - canvas.setWidth("0px"); - - handleMargins(uidl); - detectSpacing(uidl); - - int cols = uidl.getIntAttribute("w"); - int rows = uidl.getIntAttribute("h"); - - columnWidths = new int[cols]; - rowHeights = new int[rows]; - - if (cells == null) { - cells = new Cell[cols][rows]; - } else if (cells.length != cols || cells[0].length != rows) { - Cell[][] newCells = new Cell[cols][rows]; - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < cells[i].length; j++) { - if (i < cols && j < rows) { - newCells[i][j] = cells[i][j]; - } - } - } - cells = newCells; - } - - nonRenderedWidgets = (HashMap<Widget, ChildComponentContainer>) 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 = getCell(c); - if (cell.hasContent()) { - boolean rendered = cell.renderIfNoRelativeWidth(); - cell.alignment = alignments[alignmentIndex++]; - if (!rendered) { - pendingCells.add(cell); - } - - if (cell.colspan > 1) { - storeColSpannedCell(cell); - } else if (rendered) { - // strore non-colspanned widths to columnWidth - // array - if (columnWidths[cell.col] < cell.getWidth()) { - columnWidths[cell.col] = cell.getWidth(); - } - } - if (cell.hasRelativeHeight()) { - relativeHeighted.add(cell); - } - } - } - } - } - } - - colExpandRatioArray = uidl.getIntArrayAttribute("colExpand"); - rowExpandRatioArray = uidl.getIntArrayAttribute("rowExpand"); - distributeColSpanWidths(); - - minColumnWidths = cloneArray(columnWidths); - expandColumns(); - - renderRemainingComponentsWithNoRelativeHeight(pendingCells); - - detectRowHeights(); - - expandRows(); - - 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(); - } - - layoutCells(); - - // clean non rendered components - for (Widget w : nonRenderedWidgets.keySet()) { - ChildComponentContainer childComponentContainer = widgetToComponentContainer - .get(w); - widgetToCell.remove(w); - widgetToComponentContainer.remove(w); - childComponentContainer.removeFromParent(); - VPaintableMap paintableMap = VPaintableMap.get(client); - paintableMap.unregisterPaintable(paintableMap.getPaintable(w)); - } - nonRenderedWidgets = null; - - rendering = false; - sizeChangedDuringRendering = false; - - } - - private static int[] cloneArray(int[] toBeCloned) { + static int[] cloneArray(int[] toBeCloned) { int[] clone = new int[toBeCloned.length]; for (int i = 0; i < clone.length; i++) { clone[i] = toBeCloned[i] * 1; @@ -262,7 +123,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, return clone; } - private void expandRows() { + void expandRows() { if (!"".equals(height)) { int usedSpace = minRowHeights[0]; for (int i = 1; i < minRowHeights.length; i++) { @@ -401,7 +262,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, } } - private void expandColumns() { + void expandColumns() { if (!"".equals(width)) { int usedSpace = minColumnWidths[0]; for (int i = 1; i < minColumnWidths.length; i++) { @@ -428,7 +289,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, } } - private void layoutCells() { + void layoutCells() { int x = 0; int y = 0; for (int i = 0; i < cells.length; i++) { @@ -470,13 +331,13 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, return "".equals(width); } - private void renderRemainingComponents(LinkedList<Cell> pendingCells) { + void renderRemainingComponents(LinkedList<Cell> pendingCells) { for (Cell cell : pendingCells) { cell.render(); } } - private void detectRowHeights() { + void detectRowHeights() { // collect min rowheight from non-rowspanned cells for (int i = 0; i < cells.length; i++) { @@ -531,7 +392,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, l.cells.add(cell); } - private void renderRemainingComponentsWithNoRelativeHeight( + void renderRemainingComponentsWithNoRelativeHeight( LinkedList<Cell> pendingCells) { for (Iterator<Cell> iterator = pendingCells.iterator(); iterator @@ -549,7 +410,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, * Iterates colspanned cells, ensures cols have enough space to accommodate * them */ - private void distributeColSpanWidths() { + void distributeColSpanWidths() { for (SpanList list : colSpans) { for (Cell cell : list.cells) { // cells with relative content may return non 0 here if on @@ -643,7 +504,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, } } - private void storeColSpannedCell(Cell cell) { + void storeColSpannedCell(Cell cell) { SpanList l = null; for (SpanList list : colSpans) { if (list.span < cell.colspan) { @@ -666,7 +527,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, l.cells.add(cell); } - private void detectSpacing(UIDL uidl) { + void detectSpacing(UIDL uidl) { DivElement spacingmeter = Document.get().createDivElement(); spacingmeter.setClassName(CLASSNAME + "-" + "spacing-" + (uidl.getBooleanAttribute("spacing") ? "on" : "off")); @@ -678,7 +539,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, canvas.getElement().removeChild(spacingmeter); } - private void handleMargins(UIDL uidl) { + void handleMargins(UIDL uidl) { final VMarginInfo margins = new VMarginInfo( uidl.getIntAttribute("margins")); @@ -719,23 +580,6 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, widgetToCell.put(newComponent, widgetToCell.get(oldComponent)); } - public void updateCaption(VPaintableWidget paintable, UIDL uidl) { - Widget widget = paintable.getWidgetForPaintable(); - ChildComponentContainer cc = widgetToComponentContainer.get(widget); - if (cc != null) { - cc.updateCaption(uidl, client); - } - if (!rendering) { - // ensure rel size details are updated - widgetToCell.get(widget).updateRelSizeStatus(uidl); - /* - * This was a component-only update and the possible size change - * must be propagated to the layout - */ - client.captionSizeUpdated(widget); - } - } - public boolean requestLayout(final Set<Widget> changedChildren) { boolean needsLayout = false; boolean reDistributeColSpanWidths = false; @@ -895,12 +739,12 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, return cell.getAllocatedSpace(); } - private Cell[][] cells; + Cell[][] cells; /** * Private helper class. */ - private class Cell { + class Cell { private boolean relHeight = false; private boolean relWidth = false; private boolean widthCanAffectHeight = false; @@ -1109,7 +953,7 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, } } - private Cell getCell(UIDL c) { + Cell getCell(UIDL c) { int row = c.getIntAttribute("y"); int col = c.getIntAttribute("x"); Cell cell = cells[col][row]; @@ -1132,12 +976,8 @@ public class VGridLayout extends SimplePanel implements VPaintableWidget, * @return The Paintable which the element is a part of. Null if the element * belongs to the layout and not to a child. */ - private VPaintableWidget getComponent(Element element) { + VPaintableWidget getComponent(Element element) { 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 new file mode 100644 index 0000000000..8f84f27297 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java @@ -0,0 +1,196 @@ +/* +@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 new file mode 100644 index 0000000000..acc49ece18 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayoutPaintable.java @@ -0,0 +1,20 @@ +/* +@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 new file mode 100644 index 0000000000..44141107aa --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VHorizontalSplitPanelPaintable.java @@ -0,0 +1,16 @@ +/* +@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/VLink.java b/src/com/vaadin/terminal/gwt/client/ui/VLink.java index 0ade84aaf5..df651c0a4d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VLink.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VLink.java @@ -11,44 +11,41 @@ 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.VPaintableWidget; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VTooltip; -public class VLink extends HTML implements VPaintableWidget, ClickHandler { +public class VLink extends HTML implements ClickHandler { public static final String CLASSNAME = "v-link"; - private static final int BORDER_STYLE_DEFAULT = 0; - private static final int BORDER_STYLE_MINIMAL = 1; - private static final int BORDER_STYLE_NONE = 2; + protected static final int BORDER_STYLE_DEFAULT = 0; + protected static final int BORDER_STYLE_MINIMAL = 1; + protected static final int BORDER_STYLE_NONE = 2; - private String src; + protected String src; - private String target; + protected String target; - private int borderStyle = BORDER_STYLE_DEFAULT; + protected int borderStyle = BORDER_STYLE_DEFAULT; - private boolean enabled; + protected boolean enabled; - private boolean readonly; + protected boolean readonly; - private int targetWidth; + protected int targetWidth; - private int targetHeight; + protected int targetHeight; - private Element errorIndicatorElement; + protected Element errorIndicatorElement; - private final Element anchor = DOM.createAnchor(); + protected final Element anchor = DOM.createAnchor(); - private final Element captionElement = DOM.createSpan(); + protected final Element captionElement = DOM.createSpan(); - private Icon icon; + protected Icon icon; - private ApplicationConnection client; + protected ApplicationConnection client; public VLink() { super(); @@ -59,68 +56,6 @@ public class VLink extends HTML implements VPaintableWidget, ClickHandler { setStyleName(CLASSNAME); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - // Ensure correct implementation, - // but don't let container manage caption etc. - if (client.updateComponent(this, uidl, false)) { - return; - } - - this.client = client; - - enabled = uidl.hasAttribute("disabled") ? false : true; - readonly = uidl.hasAttribute("readonly") ? true : false; - - if (uidl.hasAttribute("name")) { - target = uidl.getStringAttribute("name"); - anchor.setAttribute("target", target); - } - if (uidl.hasAttribute("src")) { - src = client.translateVaadinUri(uidl.getStringAttribute("src")); - anchor.setAttribute("href", src); - } - - if (uidl.hasAttribute("border")) { - if ("none".equals(uidl.getStringAttribute("border"))) { - borderStyle = BORDER_STYLE_NONE; - } else { - borderStyle = BORDER_STYLE_MINIMAL; - } - } else { - borderStyle = BORDER_STYLE_DEFAULT; - } - - targetHeight = uidl.hasAttribute("targetHeight") ? uidl - .getIntAttribute("targetHeight") : -1; - targetWidth = uidl.hasAttribute("targetWidth") ? uidl - .getIntAttribute("targetWidth") : -1; - - // Set link caption - captionElement.setInnerText(uidl.getStringAttribute("caption")); - - // handle error - if (uidl.hasAttribute("error")) { - if (errorIndicatorElement == null) { - errorIndicatorElement = DOM.createDiv(); - DOM.setElementProperty(errorIndicatorElement, "className", - "v-errorindicator"); - } - DOM.insertChild(getElement(), errorIndicatorElement, 0); - } else if (errorIndicatorElement != null) { - DOM.setStyleAttribute(errorIndicatorElement, "display", "none"); - } - - if (uidl.hasAttribute("icon")) { - if (icon == null) { - icon = new Icon(client); - anchor.insertBefore(icon.getElement(), captionElement); - } - icon.setUri(uidl.getStringAttribute("icon")); - } - - } - public void onClick(ClickEvent event) { if (enabled && !readonly) { if (target == null) { @@ -168,7 +103,7 @@ public class VLink extends HTML implements VPaintableWidget, ClickHandler { Util.notifyParentOfSizeChange(this, true); } if (client != null) { - client.handleTooltipEvent(event, this); + client.handleWidgetTooltipEvent(event, this); } if (target == captionElement || target == anchor || (icon != null && target == icon.getElement())) { @@ -180,8 +115,4 @@ public class VLink extends HTML implements VPaintableWidget, ClickHandler { } - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VLinkPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VLinkPaintable.java new file mode 100644 index 0000000000..3fbd796c4b --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VLinkPaintable.java @@ -0,0 +1,100 @@ +/* +@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; + +public class VLinkPaintable extends VAbstractPaintableWidget { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + // Ensure correct implementation, + // but don't let container manage caption etc. + if (client.updateComponent(this, uidl, false)) { + return; + } + + getWidgetForPaintable().client = client; + + getWidgetForPaintable().enabled = uidl.hasAttribute("disabled") ? false + : true; + getWidgetForPaintable().readonly = uidl.hasAttribute("readonly") ? true + : false; + + if (uidl.hasAttribute("name")) { + getWidgetForPaintable().target = uidl.getStringAttribute("name"); + getWidgetForPaintable().anchor.setAttribute("target", + getWidgetForPaintable().target); + } + if (uidl.hasAttribute("src")) { + getWidgetForPaintable().src = client.translateVaadinUri(uidl + .getStringAttribute("src")); + getWidgetForPaintable().anchor.setAttribute("href", + getWidgetForPaintable().src); + } + + if (uidl.hasAttribute("border")) { + if ("none".equals(uidl.getStringAttribute("border"))) { + getWidgetForPaintable().borderStyle = VLink.BORDER_STYLE_NONE; + } else { + getWidgetForPaintable().borderStyle = VLink.BORDER_STYLE_MINIMAL; + } + } else { + getWidgetForPaintable().borderStyle = VLink.BORDER_STYLE_DEFAULT; + } + + getWidgetForPaintable().targetHeight = uidl + .hasAttribute("targetHeight") ? uidl + .getIntAttribute("targetHeight") : -1; + getWidgetForPaintable().targetWidth = uidl.hasAttribute("targetWidth") ? uidl + .getIntAttribute("targetWidth") : -1; + + // Set link caption + getWidgetForPaintable().captionElement.setInnerText(uidl + .getStringAttribute("caption")); + + // handle error + if (uidl.hasAttribute("error")) { + if (getWidgetForPaintable().errorIndicatorElement == null) { + getWidgetForPaintable().errorIndicatorElement = DOM.createDiv(); + DOM.setElementProperty( + getWidgetForPaintable().errorIndicatorElement, + "className", "v-errorindicator"); + } + DOM.insertChild(getWidgetForPaintable().getElement(), + getWidgetForPaintable().errorIndicatorElement, 0); + } else if (getWidgetForPaintable().errorIndicatorElement != null) { + DOM.setStyleAttribute( + getWidgetForPaintable().errorIndicatorElement, "display", + "none"); + } + + if (uidl.hasAttribute("icon")) { + if (getWidgetForPaintable().icon == null) { + getWidgetForPaintable().icon = new Icon(client); + getWidgetForPaintable().anchor.insertBefore( + getWidgetForPaintable().icon.getElement(), + getWidgetForPaintable().captionElement); + } + getWidgetForPaintable().icon + .setUri(uidl.getStringAttribute("icon")); + } + + } + + @Override + protected Widget createWidget() { + return GWT.create(VLink.class); + } + + @Override + public VLink getWidgetForPaintable() { + return (VLink) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VListSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VListSelect.java index 25bd6f35b2..1ea2f4f705 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VListSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VListSelect.java @@ -12,7 +12,6 @@ import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.VTooltip; @@ -81,11 +80,11 @@ public class VListSelect extends VOptionGroupBase { } else { lastSelectedIndex = si; if (isMultiselect()) { - client.updateVariable(id, "selected", getSelectedItems(), - isImmediate()); + client.updateVariable(paintableId, "selected", + getSelectedItems(), isImmediate()); } else { - client.updateVariable(id, "selected", new String[] { "" - + getSelectedItem() }, isImmediate()); + client.updateVariable(paintableId, "selected", + new String[] { "" + getSelectedItem() }, isImmediate()); } } } @@ -110,11 +109,6 @@ public class VListSelect extends VOptionGroupBase { public void focus() { select.setFocus(true); } - - public Widget getWidgetForPaintable() { - return this; - } - } /** @@ -123,7 +117,7 @@ public class VListSelect extends VOptionGroupBase { */ class TooltipListBox extends ListBox { private ApplicationConnection client; - private VPaintableWidget pntbl; + private Widget widget; TooltipListBox(boolean isMultiselect) { super(isMultiselect); @@ -134,15 +128,15 @@ class TooltipListBox extends ListBox { this.client = client; } - public void setSelect(VPaintableWidget s) { - pntbl = s; + public void setSelect(Widget widget) { + this.widget = widget; } @Override public void onBrowserEvent(Event event) { super.onBrowserEvent(event); if (client != null) { - client.handleTooltipEvent(event, pntbl); + client.handleWidgetTooltipEvent(event, widget); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VListSelectPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VListSelectPaintable.java new file mode 100644 index 0000000000..b77bfa33e3 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VListSelectPaintable.java @@ -0,0 +1,21 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; + +public class VListSelectPaintable extends VOptionGroupBasePaintable { + + @Override + protected Widget createWidget() { + return GWT.create(VListSelect.class); + } + + @Override + public VListSelect getWidgetForPaintable() { + return (VListSelect) super.getWidgetForPaintable(); + } +} 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/VNativeButton.java b/src/com/vaadin/terminal/gwt/client/ui/VNativeButton.java index 9991769e46..94e5cdf40c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VNativeButton.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VNativeButton.java @@ -15,7 +15,6 @@ 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.ui.Button; -import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.EventId; @@ -145,8 +144,4 @@ public class VNativeButton extends Button implements ClickHandler, setStyleName(ApplicationConnection.DISABLED_CLASSNAME, !enabled); } } - - public Widget getWidgetForPaintable() { - return this; - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VNativeButtonPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VNativeButtonPaintable.java index 5e0dceea75..ebf9cad264 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VNativeButtonPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VNativeButtonPaintable.java @@ -1,3 +1,6 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ package com.vaadin.terminal.gwt.client.ui; import com.google.gwt.core.client.GWT; diff --git a/src/com/vaadin/terminal/gwt/client/ui/VNativeSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VNativeSelect.java index 038b598555..ec2f6e42a1 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VNativeSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VNativeSelect.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.Iterator; import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.UIDL; public class VNativeSelect extends VOptionGroupBase implements Field { @@ -74,10 +73,10 @@ public class VNativeSelect extends VOptionGroupBase implements Field { public void onChange(ChangeEvent event) { if (select.isMultipleSelect()) { - client.updateVariable(id, "selected", getSelectedItems(), + client.updateVariable(paintableId, "selected", getSelectedItems(), isImmediate()); } else { - client.updateVariable(id, "selected", new String[] { "" + client.updateVariable(paintableId, "selected", new String[] { "" + getSelectedItem() }, isImmediate()); } if (firstValueIsTemporaryNullItem) { @@ -107,8 +106,4 @@ public class VNativeSelect extends VOptionGroupBase implements Field { public void focus() { select.setFocus(true); } - - public Widget getWidgetForPaintable() { - return this; - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VNativeSelectPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VNativeSelectPaintable.java new file mode 100644 index 0000000000..37defb605f --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VNativeSelectPaintable.java @@ -0,0 +1,21 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Widget; + +public class VNativeSelectPaintable extends VOptionGroupBasePaintable { + + @Override + protected Widget createWidget() { + return GWT.create(VNativeSelect.class); + } + + @Override + public VNativeSelect getWidgetForPaintable() { + return (VNativeSelect) 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/VOptionGroup.java b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroup.java index 0175134355..bf89a01a03 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VOptionGroup.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroup.java @@ -4,7 +4,6 @@ package com.vaadin.terminal.gwt.client.ui; -import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -38,14 +37,14 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler, public static final String CLASSNAME = "v-select-optiongroup"; - private final Panel panel; + protected final Panel panel; private final Map<CheckBox, String> optionsToKeys; - private boolean sendFocusEvents = false; - private boolean sendBlurEvents = false; - private List<HandlerRegistration> focusHandlers = null; - private List<HandlerRegistration> blurHandlers = null; + protected boolean sendFocusEvents = false; + protected boolean sendBlurEvents = false; + protected List<HandlerRegistration> focusHandlers = null; + protected List<HandlerRegistration> blurHandlers = null; private final LoadHandler iconLoadHandler = new LoadHandler() { public void onLoad(LoadEvent event) { @@ -62,7 +61,7 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler, */ private boolean blurOccured = false; - private boolean htmlContentAllowed = false; + protected boolean htmlContentAllowed = false; public VOptionGroup() { super(CLASSNAME); @@ -70,43 +69,6 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler, optionsToKeys = new HashMap<CheckBox, String>(); } - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - htmlContentAllowed = uidl.hasAttribute(HTML_CONTENT_ALLOWED); - - super.updateFromUIDL(uidl, client); - - sendFocusEvents = client.hasEventListeners(this, EventId.FOCUS); - sendBlurEvents = client.hasEventListeners(this, EventId.BLUR); - - if (focusHandlers != null) { - for (HandlerRegistration reg : focusHandlers) { - reg.removeHandler(); - } - focusHandlers.clear(); - focusHandlers = null; - - for (HandlerRegistration reg : blurHandlers) { - reg.removeHandler(); - } - blurHandlers.clear(); - blurHandlers = null; - } - - if (sendFocusEvents || sendBlurEvents) { - focusHandlers = new ArrayList<HandlerRegistration>(); - blurHandlers = new ArrayList<HandlerRegistration>(); - - // add focus and blur handlers to checkboxes / radio buttons - for (Widget wid : panel) { - if (wid instanceof CheckBox) { - focusHandlers.add(((CheckBox) wid).addFocusHandler(this)); - blurHandlers.add(((CheckBox) wid).addBlurHandler(this)); - } - } - } - } - /* * Return true if no elements were changed, false otherwise. */ @@ -133,7 +95,7 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler, op = new VCheckBox(); op.setHTML(itemHtml); } else { - op = new RadioButton(id, itemHtml, true); + op = new RadioButton(paintableId, itemHtml, true); op.setStyleName("v-radiobutton"); } @@ -174,7 +136,7 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler, } else { selectedKeys.remove(key); } - client.updateVariable(id, "selected", getSelectedItems(), + client.updateVariable(paintableId, "selected", getSelectedItems(), isImmediate()); } } @@ -200,7 +162,7 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler, // panel was blurred => fire the event to the server side if // requested by server side if (sendFocusEvents) { - client.updateVariable(id, EventId.FOCUS, "", true); + client.updateVariable(paintableId, EventId.FOCUS, "", true); } } else { // blur occured before this focus event @@ -219,16 +181,12 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler, // check whether blurOccured still is true and then send the // event out to the server if (blurOccured) { - client.updateVariable(id, EventId.BLUR, "", true); + client.updateVariable(paintableId, EventId.BLUR, "", + true); blurOccured = false; } } }); } } - - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java index c4d92783c8..bcd5cc891f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java @@ -19,35 +19,34 @@ import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.UIDL; -abstract class VOptionGroupBase extends Composite implements VPaintableWidget, - Field, ClickHandler, ChangeHandler, KeyPressHandler, Focusable { +abstract class VOptionGroupBase extends Composite implements Field, + ClickHandler, ChangeHandler, KeyPressHandler, Focusable { public static final String CLASSNAME_OPTION = "v-select-option"; protected ApplicationConnection client; - protected String id; + protected String paintableId; protected Set<String> selectedKeys; - private boolean immediate; + protected boolean immediate; - private boolean multiselect; + protected boolean multiselect; - private boolean disabled; + protected boolean disabled; - private boolean readonly; + protected boolean readonly; - private int cols = 0; + protected int cols = 0; - private int rows = 0; + protected int rows = 0; - private boolean nullSelectionAllowed = true; + protected boolean nullSelectionAllowed = true; - private boolean nullSelectionItemAvailable = false; + protected boolean nullSelectionItemAvailable = false; /** * Widget holding the different options (e.g. ListBox or Panel for radio @@ -58,11 +57,11 @@ abstract class VOptionGroupBase extends Composite implements VPaintableWidget, /** * Panel containing the component */ - private final Panel container; + protected final Panel container; - private VTextField newItemField; + protected VTextField newItemField; - private VNativeButton newItemButton; + protected VNativeButton newItemButton; public VOptionGroupBase(String classname) { container = new FlowPanel(); @@ -122,84 +121,23 @@ abstract class VOptionGroupBase extends Composite implements VPaintableWidget, return rows; } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - id = uidl.getId(); - - if (client.updateComponent(this, uidl, true)) { - return; - } - - selectedKeys = uidl.getStringArrayVariableAsSet("selected"); - - readonly = uidl.getBooleanAttribute("readonly"); - disabled = uidl.getBooleanAttribute("disabled"); - multiselect = "multi".equals(uidl.getStringAttribute("selectmode")); - immediate = uidl.getBooleanAttribute("immediate"); - nullSelectionAllowed = uidl.getBooleanAttribute("nullselect"); - nullSelectionItemAvailable = uidl.getBooleanAttribute("nullselectitem"); - - if (uidl.hasAttribute("cols")) { - cols = uidl.getIntAttribute("cols"); - } - if (uidl.hasAttribute("rows")) { - rows = uidl.getIntAttribute("rows"); - } - - final UIDL ops = uidl.getChildUIDL(0); - - if (getColumns() > 0) { - container.setWidth(getColumns() + "em"); - if (container != optionsContainer) { - optionsContainer.setWidth("100%"); - } - } - - buildOptions(ops); - - if (uidl.getBooleanAttribute("allownewitem")) { - if (newItemField == null) { - newItemButton = new VNativeButton(); - newItemButton.setText("+"); - newItemButton.addClickHandler(this); - newItemField = new VTextField(); - newItemField.addKeyPressHandler(this); - } - newItemField.setEnabled(!disabled && !readonly); - newItemButton.setEnabled(!disabled && !readonly); - - if (newItemField == null || newItemField.getParent() != container) { - container.add(newItemField); - container.add(newItemButton); - final int w = container.getOffsetWidth() - - newItemButton.getOffsetWidth(); - newItemField.setWidth(Math.max(w, 0) + "px"); - } - } else if (newItemField != null) { - container.remove(newItemField); - container.remove(newItemButton); - } - - setTabIndex(uidl.hasAttribute("tabindex") ? uidl - .getIntAttribute("tabindex") : 0); - - } - abstract protected void setTabIndex(int tabIndex); public void onClick(ClickEvent event) { if (event.getSource() == newItemButton && !newItemField.getText().equals("")) { - client.updateVariable(id, "newitem", newItemField.getText(), true); + client.updateVariable(paintableId, "newitem", + newItemField.getText(), true); newItemField.setText(""); } } public void onChange(ChangeEvent event) { if (multiselect) { - client.updateVariable(id, "selected", getSelectedItems(), immediate); + client.updateVariable(paintableId, "selected", getSelectedItems(), + immediate); } else { - client.updateVariable(id, "selected", new String[] { "" + client.updateVariable(paintableId, "selected", new String[] { "" + getSelectedItem() }, immediate); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBasePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBasePaintable.java new file mode 100644 index 0000000000..76486ff8a3 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBasePaintable.java @@ -0,0 +1,103 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.UIDL; + +public abstract class VOptionGroupBasePaintable extends + VAbstractPaintableWidget { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + // Save details + getWidgetForPaintable().client = client; + getWidgetForPaintable().paintableId = uidl.getId(); + + if (client.updateComponent(this, uidl, true)) { + return; + } + + getWidgetForPaintable().selectedKeys = uidl + .getStringArrayVariableAsSet("selected"); + + getWidgetForPaintable().readonly = uidl.getBooleanAttribute("readonly"); + getWidgetForPaintable().disabled = uidl.getBooleanAttribute("disabled"); + getWidgetForPaintable().multiselect = "multi".equals(uidl + .getStringAttribute("selectmode")); + getWidgetForPaintable().immediate = uidl + .getBooleanAttribute("immediate"); + getWidgetForPaintable().nullSelectionAllowed = uidl + .getBooleanAttribute("nullselect"); + getWidgetForPaintable().nullSelectionItemAvailable = uidl + .getBooleanAttribute("nullselectitem"); + + if (uidl.hasAttribute("cols")) { + getWidgetForPaintable().cols = uidl.getIntAttribute("cols"); + } + if (uidl.hasAttribute("rows")) { + getWidgetForPaintable().rows = uidl.getIntAttribute("rows"); + } + + final UIDL ops = uidl.getChildUIDL(0); + + if (getWidgetForPaintable().getColumns() > 0) { + getWidgetForPaintable().container.setWidth(getWidgetForPaintable() + .getColumns() + "em"); + if (getWidgetForPaintable().container != getWidgetForPaintable().optionsContainer) { + getWidgetForPaintable().optionsContainer.setWidth("100%"); + } + } + + getWidgetForPaintable().buildOptions(ops); + + if (uidl.getBooleanAttribute("allownewitem")) { + if (getWidgetForPaintable().newItemField == null) { + getWidgetForPaintable().newItemButton = new VNativeButton(); + getWidgetForPaintable().newItemButton.setText("+"); + getWidgetForPaintable().newItemButton + .addClickHandler(getWidgetForPaintable()); + getWidgetForPaintable().newItemField = new VTextField(); + getWidgetForPaintable().newItemField + .addKeyPressHandler(getWidgetForPaintable()); + } + getWidgetForPaintable().newItemField + .setEnabled(!getWidgetForPaintable().disabled + && !getWidgetForPaintable().readonly); + getWidgetForPaintable().newItemButton + .setEnabled(!getWidgetForPaintable().disabled + && !getWidgetForPaintable().readonly); + + if (getWidgetForPaintable().newItemField == null + || getWidgetForPaintable().newItemField.getParent() != getWidgetForPaintable().container) { + getWidgetForPaintable().container + .add(getWidgetForPaintable().newItemField); + getWidgetForPaintable().container + .add(getWidgetForPaintable().newItemButton); + final int w = getWidgetForPaintable().container + .getOffsetWidth() + - getWidgetForPaintable().newItemButton + .getOffsetWidth(); + getWidgetForPaintable().newItemField.setWidth(Math.max(w, 0) + + "px"); + } + } else if (getWidgetForPaintable().newItemField != null) { + getWidgetForPaintable().container + .remove(getWidgetForPaintable().newItemField); + getWidgetForPaintable().container + .remove(getWidgetForPaintable().newItemButton); + } + + getWidgetForPaintable().setTabIndex( + uidl.hasAttribute("tabindex") ? uidl + .getIntAttribute("tabindex") : 0); + + } + + @Override + public VOptionGroupBase getWidgetForPaintable() { + return (VOptionGroupBase) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupPaintable.java new file mode 100644 index 0000000000..f4ffc4f0da --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VOptionGroupPaintable.java @@ -0,0 +1,71 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +import java.util.ArrayList; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.ui.CheckBox; +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; + +public class VOptionGroupPaintable extends VOptionGroupBasePaintable { + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().htmlContentAllowed = uidl + .hasAttribute(VOptionGroup.HTML_CONTENT_ALLOWED); + + super.updateFromUIDL(uidl, client); + + getWidgetForPaintable().sendFocusEvents = client.hasEventListeners( + this, EventId.FOCUS); + getWidgetForPaintable().sendBlurEvents = client.hasEventListeners(this, + EventId.BLUR); + + if (getWidgetForPaintable().focusHandlers != null) { + for (HandlerRegistration reg : getWidgetForPaintable().focusHandlers) { + reg.removeHandler(); + } + getWidgetForPaintable().focusHandlers.clear(); + getWidgetForPaintable().focusHandlers = null; + + for (HandlerRegistration reg : getWidgetForPaintable().blurHandlers) { + reg.removeHandler(); + } + getWidgetForPaintable().blurHandlers.clear(); + getWidgetForPaintable().blurHandlers = null; + } + + if (getWidgetForPaintable().sendFocusEvents + || getWidgetForPaintable().sendBlurEvents) { + getWidgetForPaintable().focusHandlers = new ArrayList<HandlerRegistration>(); + getWidgetForPaintable().blurHandlers = new ArrayList<HandlerRegistration>(); + + // add focus and blur handlers to checkboxes / radio buttons + for (Widget wid : getWidgetForPaintable().panel) { + if (wid instanceof CheckBox) { + getWidgetForPaintable().focusHandlers.add(((CheckBox) wid) + .addFocusHandler(getWidgetForPaintable())); + getWidgetForPaintable().blurHandlers.add(((CheckBox) wid) + .addBlurHandler(getWidgetForPaintable())); + } + } + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VOptionGroup.class); + } + + @Override + public VOptionGroup getWidgetForPaintable() { + return (VOptionGroup) 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 9eec275b59..82b362a385 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java @@ -8,11 +8,8 @@ import java.util.Set; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; -import com.google.gwt.event.dom.client.DomEvent.Type; import com.google.gwt.event.dom.client.TouchStartEvent; import com.google.gwt.event.dom.client.TouchStartHandler; -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.Element; import com.google.gwt.user.client.Event; @@ -33,28 +30,27 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHan public class VPanel extends SimplePanel implements Container, ShortcutActionHandlerOwner, Focusable { - public static final String CLICK_EVENT_IDENTIFIER = "click"; public static final String CLASSNAME = "v-panel"; ApplicationConnection client; String id; - private final Element captionNode = DOM.createDiv(); + final Element captionNode = DOM.createDiv(); private final Element captionText = DOM.createSpan(); private Icon icon; - private final Element bottomDecoration = DOM.createDiv(); + final Element bottomDecoration = DOM.createDiv(); - private final Element contentNode = DOM.createDiv(); + final Element contentNode = DOM.createDiv(); private Element errorIndicatorElement; private String height; - private VPaintableWidget layout; + VPaintableWidget layout; ShortcutActionHandler shortcutHandler; @@ -62,9 +58,9 @@ public class VPanel extends SimplePanel implements Container, private Element geckoCaptionMeter; - private int scrollTop; + int scrollTop; - private int scrollLeft; + int scrollLeft; private RenderInformation renderInformation = new RenderInformation(); @@ -76,21 +72,12 @@ public class VPanel extends SimplePanel implements Container, private int captionMarginLeft = -1; - private boolean rendering; + boolean rendering; private int contentMarginLeft = -1; private String previousStyleName; - private ClickEventHandler clickEventHandler = new ClickEventHandler(this, - CLICK_EVENT_IDENTIFIER) { - - @Override - protected <H extends EventHandler> HandlerRegistration registerHandler( - H handler, Type<H> type) { - return addDomHandler(handler, type); - } - }; private TouchScrollDelegate touchScrollDelegate; public VPanel() { @@ -157,129 +144,10 @@ public class VPanel extends SimplePanel implements Container, return contentNode; } - private void setCaption(String text) { + void setCaption(String text) { DOM.setInnerHTML(captionText, text); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - rendering = true; - if (!uidl.hasAttribute("cached")) { - - // Handle caption displaying and style names, prior generics. - // Affects size - // calculations - - // Restore default stylenames - contentNode.setClassName(CLASSNAME + "-content"); - bottomDecoration.setClassName(CLASSNAME + "-deco"); - captionNode.setClassName(CLASSNAME + "-caption"); - boolean hasCaption = false; - if (uidl.hasAttribute("caption") - && !uidl.getStringAttribute("caption").equals("")) { - setCaption(uidl.getStringAttribute("caption")); - hasCaption = true; - } else { - setCaption(""); - captionNode.setClassName(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 = CLASSNAME - + (hasCaption ? "-caption" : "-nocaption"); - final String contentBaseClass = CLASSNAME + "-content"; - final String decoBaseClass = 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]; - } - captionNode.setClassName(captionClass); - contentNode.setClassName(contentClass); - bottomDecoration.setClassName(decoClass); - - } - } - // Ensure correct implementation - if (client.updateComponent(this, uidl, false)) { - rendering = false; - return; - } - - clickEventHandler.handleEventHandlerRegistration(client); - - this.client = client; - id = uidl.getId(); - - setIconUri(uidl, client); - - handleError(uidl); - - // Render content - final UIDL layoutUidl = uidl.getChildUIDL(0); - final VPaintableWidget newLayout = client.getPaintable(layoutUidl); - if (newLayout != layout) { - if (layout != null) { - client.unregisterPaintable(layout); - } - setWidget(newLayout.getWidgetForPaintable()); - layout = newLayout; - } - 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 (shortcutHandler == null) { - shortcutHandler = new ShortcutActionHandler(id, client); - } - shortcutHandler.updateActionMap(childUidl); - } - } - } - - if (uidl.hasVariable("scrollTop") - && uidl.getIntVariable("scrollTop") != scrollTop) { - scrollTop = uidl.getIntVariable("scrollTop"); - contentNode.setScrollTop(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 - scrollTop = contentNode.getScrollTop(); - } - - if (uidl.hasVariable("scrollLeft") - && uidl.getIntVariable("scrollLeft") != scrollLeft) { - scrollLeft = uidl.getIntVariable("scrollLeft"); - contentNode.setScrollLeft(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 - scrollLeft = contentNode.getScrollLeft(); - } - - // Must be run after scrollTop is set as Webkit overflow fix re-sets the - // scrollTop - runHacks(false); - - // And apply tab index - if (uidl.hasVariable("tabindex")) { - contentNode.setTabIndex(uidl.getIntVariable("tabindex")); - } - - rendering = false; - - } - @Override public void setStyleName(String style) { if (!style.equals(previousStyleName)) { @@ -289,7 +157,7 @@ public class VPanel extends SimplePanel implements Container, } } - private void handleError(UIDL uidl) { + void handleError(UIDL uidl) { if (uidl.hasAttribute("error")) { if (errorIndicatorElement == null) { errorIndicatorElement = DOM.createSpan(); @@ -305,7 +173,7 @@ public class VPanel extends SimplePanel implements Container, } } - private void setIconUri(UIDL uidl, ApplicationConnection client) { + void setIconUri(UIDL uidl, ApplicationConnection client) { final String iconUri = uidl.hasAttribute("icon") ? uidl .getStringAttribute("icon") : null; if (iconUri == null) { @@ -394,7 +262,7 @@ public class VPanel extends SimplePanel implements Container, } } else if (captionNode.isOrHasChild(target)) { if (client != null) { - client.handleTooltipEvent(event, this); + client.handleWidgetTooltipEvent(event, this); } } } @@ -554,10 +422,6 @@ public class VPanel extends SimplePanel implements Container, return !renderInformation.updateSize(getElement()); } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - // NOP: layouts caption, errors etc not rendered in Panel - } - @Override protected void onAttach() { super.onAttach(); @@ -568,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 new file mode 100644 index 0000000000..df4554ea5e --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VPanelPaintable.java @@ -0,0 +1,178 @@ +/* +@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/VPasswordFieldPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VPasswordFieldPaintable.java new file mode 100644 index 0000000000..98be1250a3 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VPasswordFieldPaintable.java @@ -0,0 +1,28 @@ +/* +@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 VPasswordFieldPaintable extends VTextFieldPaintable { + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + super.updateFromUIDL(uidl, client); + } + + @Override + protected Widget createWidget() { + return GWT.create(VPasswordField.class); + } + + @Override + public VPasswordField getWidgetForPaintable() { + return (VPasswordField) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java index 44fb9ac69c..1c0b937e05 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java @@ -1,474 +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.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.DateTimeService;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusChangeListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusOutListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.SubmitListener;
-import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.TimeChangeListener;
-
-/**
- * Represents a date selection component with a text field and a popup date
- * selector.
- *
- * <b>Note:</b> To change the keyboard assignments used in the popup dialog you
- * should extend <code>com.vaadin.terminal.gwt.client.ui.VCalendarPanel</code>
- * and then pass set it by calling the
- * <code>setCalendarPanel(VCalendarPanel panel)</code> method.
- *
- */
-public class VPopupCalendar extends VTextualDate implements VPaintableWidget,
- Field, ClickHandler, CloseHandler<PopupPanel>, SubPartAware {
-
- private static final String POPUP_PRIMARY_STYLE_NAME = VDateField.CLASSNAME
- + "-popup";
-
- private final Button calendarToggle;
-
- private VCalendarPanel calendar;
-
- private final VOverlay popup;
- private boolean open = false;
- private boolean parsable = true;
-
- public VPopupCalendar() {
- super();
-
- calendarToggle = new Button();
- calendarToggle.setStyleName(CLASSNAME + "-button");
- calendarToggle.setText("");
- calendarToggle.addClickHandler(this);
- // -2 instead of -1 to avoid FocusWidget.onAttach to reset it
- calendarToggle.getElement().setTabIndex(-2);
- add(calendarToggle);
-
- calendar = GWT.create(VCalendarPanel.class);
- calendar.setFocusOutListener(new FocusOutListener() {
- public boolean onFocusOut(DomEvent<?> event) {
- event.preventDefault();
- closeCalendarPanel();
- return true;
- }
- });
-
- calendar.setSubmitListener(new SubmitListener() {
- public void onSubmit() {
- // Update internal value and send valuechange event if immediate
- updateValue(calendar.getDate());
-
- // Update text field (a must when not immediate).
- buildDate(true);
-
- closeCalendarPanel();
- }
-
- public void onCancel() {
- closeCalendarPanel();
- }
- });
-
- popup = new VOverlay(true, true, true);
- popup.setStyleName(POPUP_PRIMARY_STYLE_NAME);
- popup.setWidget(calendar);
- popup.addCloseHandler(this);
-
- DOM.setElementProperty(calendar.getElement(), "id",
- "PID_VAADIN_POPUPCAL");
-
- sinkEvents(Event.ONKEYDOWN);
-
- }
-
- @SuppressWarnings("deprecation")
- private void updateValue(Date newDate) {
- Date currentDate = getCurrentDate();
- if (currentDate == null || newDate.getTime() != currentDate.getTime()) {
- setCurrentDate((Date) newDate.clone());
- getClient().updateVariable(getId(), "year",
- newDate.getYear() + 1900, false);
- if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) {
- getClient().updateVariable(getId(), "month",
- newDate.getMonth() + 1, false);
- if (getCurrentResolution() > RESOLUTION_MONTH) {
- getClient().updateVariable(getId(), "day",
- newDate.getDate(), false);
- if (getCurrentResolution() > RESOLUTION_DAY) {
- getClient().updateVariable(getId(), "hour",
- newDate.getHours(), false);
- if (getCurrentResolution() > RESOLUTION_HOUR) {
- getClient().updateVariable(getId(), "min",
- newDate.getMinutes(), false);
- if (getCurrentResolution() > RESOLUTION_MIN) {
- getClient().updateVariable(getId(), "sec",
- newDate.getSeconds(), false);
- }
- }
- }
- }
- }
- if (isImmediate()) {
- getClient().sendPendingVariableChanges();
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.ui.VTextualDate#updateFromUIDL(com.vaadin
- * .terminal.gwt.client.UIDL,
- * com.vaadin.terminal.gwt.client.ApplicationConnection)
- */
- @Override
- @SuppressWarnings("deprecation")
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- boolean lastReadOnlyState = readonly;
- boolean lastEnabledState = isEnabled();
-
- parsable = uidl.getBooleanAttribute("parsable");
-
- super.updateFromUIDL(uidl, client);
-
- String popupStyleNames = ApplicationConnection.getStyleName(
- POPUP_PRIMARY_STYLE_NAME, uidl, false);
- popupStyleNames += " " + VDateField.CLASSNAME + "-"
- + resolutionToString(currentResolution);
- popup.setStyleName(popupStyleNames);
-
- calendar.setDateTimeService(getDateTimeService());
- calendar.setShowISOWeekNumbers(isShowISOWeekNumbers());
- if (calendar.getResolution() != currentResolution) {
- calendar.setResolution(currentResolution);
- if (calendar.getDate() != null) {
- calendar.setDate((Date) getCurrentDate().clone());
- // force re-render when changing resolution only
- calendar.renderCalendar();
- }
- }
- calendarToggle.setEnabled(enabled);
-
- if (currentResolution <= RESOLUTION_MONTH) {
- calendar.setFocusChangeListener(new FocusChangeListener() {
- public void focusChanged(Date date) {
- updateValue(date);
- buildDate();
- Date date2 = calendar.getDate();
- date2.setYear(date.getYear());
- date2.setMonth(date.getMonth());
- }
- });
- } else {
- calendar.setFocusChangeListener(null);
- }
-
- if (currentResolution > RESOLUTION_DAY) {
- calendar.setTimeChangeListener(new TimeChangeListener() {
- public void changed(int hour, int min, int sec, int msec) {
- Date d = getDate();
- if (d == null) {
- // date currently null, use the value from calendarPanel
- // (~ client time at the init of the widget)
- d = (Date) calendar.getDate().clone();
- }
- d.setHours(hour);
- d.setMinutes(min);
- d.setSeconds(sec);
- DateTimeService.setMilliseconds(d, msec);
-
- // Always update time changes to the server
- updateValue(d);
-
- // Update text field
- buildDate();
- }
- });
- }
-
- if (readonly) {
- calendarToggle.addStyleName(CLASSNAME + "-button-readonly");
- } else {
- calendarToggle.removeStyleName(CLASSNAME + "-button-readonly");
- }
-
- if (lastReadOnlyState != readonly || lastEnabledState != isEnabled()) {
- // Enabled or readonly state changed. Differences in theming might
- // affect the width (for instance if the popup button is hidden) so
- // we have to recalculate the width (IF the width of the field is
- // fixed)
- updateWidth();
- }
-
- calendarToggle.setEnabled(true);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.user.client.ui.UIObject#setStyleName(java.lang.String)
- */
- @Override
- public void setStyleName(String style) {
- // make sure the style is there before size calculation
- super.setStyleName(style + " " + CLASSNAME + "-popupcalendar");
- }
-
- /**
- * Opens the calendar panel popup
- */
- public void openCalendarPanel() {
-
- if (!open && !readonly) {
- open = true;
-
- if (getCurrentDate() != null) {
- calendar.setDate((Date) getCurrentDate().clone());
- } else {
- calendar.setDate(new Date());
- }
-
- // clear previous values
- popup.setWidth("");
- popup.setHeight("");
- popup.setPopupPositionAndShow(new PositionCallback() {
- public void setPosition(int offsetWidth, int offsetHeight) {
- final int w = offsetWidth;
- final int h = offsetHeight;
- final int browserWindowWidth = Window.getClientWidth()
- + Window.getScrollLeft();
- final int browserWindowHeight = Window.getClientHeight()
- + Window.getScrollTop();
- int t = calendarToggle.getAbsoluteTop();
- int l = calendarToggle.getAbsoluteLeft();
-
- // Add a little extra space to the right to avoid
- // problems with IE7 scrollbars and to make it look
- // nicer.
- int extraSpace = 30;
-
- boolean overflowRight = false;
- if (l + +w + extraSpace > browserWindowWidth) {
- overflowRight = true;
- // Part of the popup is outside the browser window
- // (to the right)
- l = browserWindowWidth - w - extraSpace;
- }
-
- if (t + h + calendarToggle.getOffsetHeight() + 30 > browserWindowHeight) {
- // Part of the popup is outside the browser window
- // (below)
- t = browserWindowHeight - h
- - calendarToggle.getOffsetHeight() - 30;
- if (!overflowRight) {
- // Show to the right of the popup button unless we
- // are in the lower right corner of the screen
- l += calendarToggle.getOffsetWidth();
- }
- }
-
- // fix size
- popup.setWidth(w + "px");
- popup.setHeight(h + "px");
-
- popup.setPopupPosition(l,
- t + calendarToggle.getOffsetHeight() + 2);
-
- /*
- * We have to wait a while before focusing since the popup
- * needs to be opened before we can focus
- */
- Timer focusTimer = new Timer() {
- @Override
- public void run() {
- setFocus(true);
- }
- };
-
- focusTimer.schedule(100);
- }
- });
- } else {
- VConsole.error("Cannot reopen popup, it is already open!");
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event
- * .dom.client.ClickEvent)
- */
- public void onClick(ClickEvent event) {
- if (event.getSource() == calendarToggle && isEnabled()) {
- openCalendarPanel();
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt
- * .event.logical.shared.CloseEvent)
- */
- public void onClose(CloseEvent<PopupPanel> event) {
- if (event.getSource() == popup) {
- buildDate();
- if (!BrowserInfo.get().isTouchDevice()) {
- /*
- * Move focus to textbox, unless on touch device (avoids opening
- * virtual keyboard).
- */
- focus();
- }
-
- // TODO resolve what the "Sigh." is all about and document it here
- // Sigh.
- Timer t = new Timer() {
- @Override
- public void run() {
- open = false;
- }
- };
- t.schedule(100);
- }
- }
-
- /**
- * Sets focus to Calendar panel.
- *
- * @param focus
- */
- public void setFocus(boolean focus) {
- calendar.setFocus(focus);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#getFieldExtraWidth()
- */
- @Override
- protected int getFieldExtraWidth() {
- if (fieldExtraWidth < 0) {
- fieldExtraWidth = super.getFieldExtraWidth();
- fieldExtraWidth += calendarToggle.getOffsetWidth();
- }
- return fieldExtraWidth;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#buildDate()
- */
- @Override
- protected void buildDate() {
- // Save previous value
- String previousValue = getText();
- super.buildDate();
-
- // Restore previous value if the input could not be parsed
- if (!parsable) {
- setText(previousValue);
- }
- }
-
- /**
- * Update the text field contents from the date. See {@link #buildDate()}.
- *
- * @param forceValid
- * true to force the text field to be updated, false to only
- * update if the parsable flag is true.
- */
- protected void buildDate(boolean forceValid) {
- if (forceValid) {
- parsable = true;
- }
- buildDate();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.ui.VDateField#onBrowserEvent(com.google
- * .gwt.user.client.Event)
- */
- @Override
- public void onBrowserEvent(com.google.gwt.user.client.Event event) {
- super.onBrowserEvent(event);
- if (DOM.eventGetType(event) == Event.ONKEYDOWN
- && event.getKeyCode() == getOpenCalenderPanelKey()) {
- openCalendarPanel();
- event.preventDefault();
- }
- }
-
- /**
- * Get the key code that opens the calendar panel. By default it is the down
- * key but you can override this to be whatever you like
- *
- * @return
- */
- protected int getOpenCalenderPanelKey() {
- return KeyCodes.KEY_DOWN;
- }
-
- /**
- * Closes the open popup panel
- */
- public void closeCalendarPanel() {
- if (open) {
- popup.hide(true);
- }
- }
-
- private final String CALENDAR_TOGGLE_ID = "popupButton";
-
- @Override
- public Element getSubPartElement(String subPart) {
- if (subPart.equals(CALENDAR_TOGGLE_ID)) {
- return calendarToggle.getElement();
- }
-
- return super.getSubPartElement(subPart);
- }
-
- @Override
- public String getSubPartName(Element subElement) {
- if (calendarToggle.getElement().isOrHasChild(subElement)) {
- return CALENDAR_TOGGLE_ID;
- }
-
- return super.getSubPartName(subElement);
- }
-
-}
+/* +@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/VPopupCalendarPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendarPaintable.java new file mode 100644 index 0000000000..96e966a993 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendarPaintable.java @@ -0,0 +1,138 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Date; + +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.DateTimeService; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.FocusChangeListener; +import com.vaadin.terminal.gwt.client.ui.VCalendarPanel.TimeChangeListener; + +public class VPopupCalendarPaintable extends VTextualDatePaintable { + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.terminal.gwt.client.ui.VTextualDate#updateFromUIDL(com.vaadin + * .terminal.gwt.client.UIDL, + * com.vaadin.terminal.gwt.client.ApplicationConnection) + */ + @Override + @SuppressWarnings("deprecation") + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + boolean lastReadOnlyState = getWidgetForPaintable().readonly; + boolean lastEnabledState = getWidgetForPaintable().isEnabled(); + + getWidgetForPaintable().parsable = uidl.getBooleanAttribute("parsable"); + + super.updateFromUIDL(uidl, client); + + String popupStyleNames = ApplicationConnection.getStyleName( + VPopupCalendar.POPUP_PRIMARY_STYLE_NAME, uidl, false); + popupStyleNames += " " + + VDateField.CLASSNAME + + "-" + + VPopupCalendar + .resolutionToString(getWidgetForPaintable().currentResolution); + getWidgetForPaintable().popup.setStyleName(popupStyleNames); + + getWidgetForPaintable().calendar + .setDateTimeService(getWidgetForPaintable() + .getDateTimeService()); + getWidgetForPaintable().calendar + .setShowISOWeekNumbers(getWidgetForPaintable() + .isShowISOWeekNumbers()); + if (getWidgetForPaintable().calendar.getResolution() != getWidgetForPaintable().currentResolution) { + getWidgetForPaintable().calendar + .setResolution(getWidgetForPaintable().currentResolution); + if (getWidgetForPaintable().calendar.getDate() != null) { + getWidgetForPaintable().calendar + .setDate((Date) getWidgetForPaintable() + .getCurrentDate().clone()); + // force re-render when changing resolution only + getWidgetForPaintable().calendar.renderCalendar(); + } + } + getWidgetForPaintable().calendarToggle + .setEnabled(getWidgetForPaintable().enabled); + + if (getWidgetForPaintable().currentResolution <= VPopupCalendar.RESOLUTION_MONTH) { + getWidgetForPaintable().calendar + .setFocusChangeListener(new FocusChangeListener() { + public void focusChanged(Date date) { + getWidgetForPaintable().updateValue(date); + getWidgetForPaintable().buildDate(); + Date date2 = getWidgetForPaintable().calendar + .getDate(); + date2.setYear(date.getYear()); + date2.setMonth(date.getMonth()); + } + }); + } else { + getWidgetForPaintable().calendar.setFocusChangeListener(null); + } + + if (getWidgetForPaintable().currentResolution > VPopupCalendar.RESOLUTION_DAY) { + getWidgetForPaintable().calendar + .setTimeChangeListener(new TimeChangeListener() { + public void changed(int hour, int min, int sec, int msec) { + Date d = getWidgetForPaintable().getDate(); + if (d == null) { + // date currently null, use the value from + // calendarPanel + // (~ client time at the init of the widget) + d = (Date) getWidgetForPaintable().calendar + .getDate().clone(); + } + d.setHours(hour); + d.setMinutes(min); + d.setSeconds(sec); + DateTimeService.setMilliseconds(d, msec); + + // Always update time changes to the server + getWidgetForPaintable().updateValue(d); + + // Update text field + getWidgetForPaintable().buildDate(); + } + }); + } + + if (getWidgetForPaintable().readonly) { + getWidgetForPaintable().calendarToggle + .addStyleName(VPopupCalendar.CLASSNAME + "-button-readonly"); + } else { + getWidgetForPaintable().calendarToggle + .removeStyleName(VPopupCalendar.CLASSNAME + + "-button-readonly"); + } + + if (lastReadOnlyState != getWidgetForPaintable().readonly + || lastEnabledState != getWidgetForPaintable().isEnabled()) { + // Enabled or readonly state changed. Differences in theming might + // affect the width (for instance if the popup button is hidden) so + // we have to recalculate the width (IF the width of the field is + // fixed) + getWidgetForPaintable().updateWidth(); + } + + getWidgetForPaintable().calendarToggle.setEnabled(true); + } + + @Override + protected Widget createWidget() { + return GWT.create(VPopupCalendar.class); + } + + @Override + public VPopupCalendar getWidgetForPaintable() { + return (VPopupCalendar) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPopupView.java b/src/com/vaadin/terminal/gwt/client/ui/VPopupView.java index e667489dda..b3acc9a9a7 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPopupView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupView.java @@ -29,7 +29,6 @@ import com.vaadin.terminal.gwt.client.RenderInformation.Size; import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VCaption; import com.vaadin.terminal.gwt.client.VCaptionWrapper; import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.VTooltip; @@ -40,13 +39,13 @@ public class VPopupView extends HTML implements Container, Iterable<Widget> { public static final String CLASSNAME = "v-popupview"; /** For server-client communication */ - private String uidlId; - private ApplicationConnection client; + String uidlId; + ApplicationConnection client; /** This variable helps to communicate popup visibility to the server */ - private boolean hostPopupVisible; + boolean hostPopupVisible; - private final CustomPopup popup; + final CustomPopup popup; private final Label loading = new Label(); /** @@ -82,61 +81,6 @@ public class VPopupView extends HTML implements Container, Iterable<Widget> { } /** - * - * - * @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 - this.client = client; - uidlId = uidl.getId(); - - hostPopupVisible = uidl.getBooleanVariable("popupVisibility"); - - setHTML(uidl.getStringAttribute("html")); - - if (uidl.hasAttribute("hideOnMouseOut")) { - popup.setHideOnMouseOut(uidl.getBooleanAttribute("hideOnMouseOut")); - } - - // Render the popup if visible and show it. - if (hostPopupVisible) { - UIDL popupUIDL = uidl.getChildUIDL(0); - - // showPopupOnTop(popup, hostReference); - preparePopup(popup); - popup.updateFromUIDL(popupUIDL, client); - if (uidl.hasAttribute("style")) { - final String[] styles = uidl.getStringAttribute("style").split( - " "); - final StringBuffer styleBuf = new StringBuffer(); - final String primaryName = popup.getStylePrimaryName(); - styleBuf.append(primaryName); - for (int i = 0; i < styles.length; i++) { - styleBuf.append(" "); - styleBuf.append(primaryName); - styleBuf.append("-"); - styleBuf.append(styles[i]); - } - popup.setStyleName(styleBuf.toString()); - } else { - popup.setStyleName(popup.getStylePrimaryName()); - } - showPopup(popup); - - // The popup shouldn't be visible, try to hide it. - } else { - popup.hide(); - } - }// updateFromUIDL - - /** * Update popup visibility to server * * @param visibility @@ -149,7 +93,7 @@ public class VPopupView extends HTML implements Container, Iterable<Widget> { } } - private void preparePopup(final CustomPopup popup) { + void preparePopup(final CustomPopup popup) { popup.setVisible(false); popup.show(); } @@ -231,8 +175,8 @@ public class VPopupView extends HTML implements Container, Iterable<Widget> { protected class CustomPopup extends VOverlay { private VPaintableWidget popupComponentPaintable = null; - private Widget popupComponentWidget = null; - private VCaptionWrapper captionWrapper = null; + Widget popupComponentWidget = null; + VCaptionWrapper captionWrapper = null; private boolean hasHadMouseOver = false; private boolean hideOnMouseOut = true; @@ -446,27 +390,11 @@ public class VPopupView extends HTML implements Container, Iterable<Widget> { return true; } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - if (VCaption.isNeeded(uidl)) { - if (popup.captionWrapper != null) { - popup.captionWrapper.updateCaption(uidl); - } else { - popup.captionWrapper = new VCaptionWrapper(component, client); - popup.setWidget(popup.captionWrapper); - popup.captionWrapper.updateCaption(uidl); - } - } else { - if (popup.captionWrapper != null) { - popup.setWidget(popup.popupComponentWidget); - } - } - } - @Override public void onBrowserEvent(Event event) { super.onBrowserEvent(event); if (client != null) { - client.handleTooltipEvent(event, this); + client.handleWidgetTooltipEvent(event, this); } } @@ -496,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 new file mode 100644 index 0000000000..cd8965ffc6 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupViewPaintable.java @@ -0,0 +1,107 @@ +/* + @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/VProgressIndicator.java b/src/com/vaadin/terminal/gwt/client/ui/VProgressIndicator.java index f7cc4240b7..cff6bf89bd 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VProgressIndicator.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VProgressIndicator.java @@ -9,20 +9,18 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.VPaintableWidget; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; -public class VProgressIndicator extends Widget implements VPaintableWidget { +public class VProgressIndicator extends Widget { - private static final String CLASSNAME = "v-progressindicator"; + public static final String CLASSNAME = "v-progressindicator"; Element wrapper = DOM.createDiv(); Element indicator = DOM.createDiv(); - private ApplicationConnection client; - private final Poller poller; - private boolean indeterminate = false; + protected ApplicationConnection client; + protected final Poller poller; + protected boolean indeterminate = false; private boolean pollerSuspendedDueDetach; - private int interval; + protected int interval; public VProgressIndicator() { setElement(DOM.createDiv()); @@ -34,38 +32,6 @@ public class VProgressIndicator extends Widget implements VPaintableWidget { poller = new Poller(); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - if (!uidl.getBooleanAttribute("cached")) { - poller.cancel(); - } - if (client.updateComponent(this, uidl, true)) { - return; - } - - indeterminate = uidl.getBooleanAttribute("indeterminate"); - - if (indeterminate) { - String basename = CLASSNAME + "-indeterminate"; - VProgressIndicator.setStyleName(getElement(), basename, true); - VProgressIndicator.setStyleName(getElement(), basename - + "-disabled", uidl.getBooleanAttribute("disabled")); - } else { - try { - final float f = Float.parseFloat(uidl - .getStringAttribute("state")); - final int size = Math.round(100 * f); - DOM.setStyleAttribute(indicator, "width", size + "%"); - } catch (final Exception e) { - } - } - - if (!uidl.getBooleanAttribute("disabled")) { - interval = uidl.getIntAttribute("pollinginterval"); - poller.scheduleRepeating(interval); - } - } - @Override protected void onAttach() { super.onAttach(); @@ -102,9 +68,4 @@ public class VProgressIndicator extends Widget implements VPaintableWidget { } } - - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VProgressIndicatorPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VProgressIndicatorPaintable.java new file mode 100644 index 0000000000..39ffe1ad96 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VProgressIndicatorPaintable.java @@ -0,0 +1,65 @@ +/* +@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; + +public class VProgressIndicatorPaintable extends VAbstractPaintableWidget { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + // Ensure correct implementation, + // but don't let container manage caption etc. + if (client.updateComponent(this, uidl, false)) { + return; + } + + // Save details + getWidgetForPaintable().client = client; + + getWidgetForPaintable().indeterminate = uidl + .getBooleanAttribute("indeterminate"); + + if (getWidgetForPaintable().indeterminate) { + String basename = VProgressIndicator.CLASSNAME + "-indeterminate"; + getWidgetForPaintable().addStyleName(basename); + if (uidl.getBooleanAttribute("disabled")) { + getWidgetForPaintable().addStyleName(basename + "-disabled"); + } else { + getWidgetForPaintable().removeStyleName(basename + "-disabled"); + } + } else { + try { + final float f = Float.parseFloat(uidl + .getStringAttribute("state")); + final int size = Math.round(100 * f); + DOM.setStyleAttribute(getWidgetForPaintable().indicator, + "width", size + "%"); + } catch (final Exception e) { + } + } + + if (!uidl.getBooleanAttribute("disabled")) { + getWidgetForPaintable().interval = uidl + .getIntAttribute("pollinginterval"); + getWidgetForPaintable().poller + .scheduleRepeating(getWidgetForPaintable().interval); + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VProgressIndicator.class); + } + + @Override + public VProgressIndicator getWidgetForPaintable() { + return (VProgressIndicator) super.getWidgetForPaintable(); + } +} 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/VSplitPanelHorizontal.java b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanelHorizontal.java index ff1e2e6b78..3902f064a5 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanelHorizontal.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanelHorizontal.java @@ -4,9 +4,9 @@ package com.vaadin.terminal.gwt.client.ui; -public class VSplitPanelHorizontal extends VSplitPanel { +public class VSplitPanelHorizontal extends VAbstractSplitPanel { public VSplitPanelHorizontal() { - super(VSplitPanel.ORIENTATION_HORIZONTAL); + super(VAbstractSplitPanel.ORIENTATION_HORIZONTAL); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanelVertical.java b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanelVertical.java index dcf7622e50..e61f8cf5e5 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanelVertical.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanelVertical.java @@ -4,9 +4,9 @@ package com.vaadin.terminal.gwt.client.ui; -public class VSplitPanelVertical extends VSplitPanel { +public class VSplitPanelVertical extends VAbstractSplitPanel { public VSplitPanelVertical() { - super(VSplitPanel.ORIENTATION_VERTICAL); + super(VAbstractSplitPanel.ORIENTATION_VERTICAL); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTablePaging.java b/src/com/vaadin/terminal/gwt/client/ui/VTablePaging.java deleted file mode 100644 index cf35dc8e88..0000000000 --- a/src/com/vaadin/terminal/gwt/client/ui/VTablePaging.java +++ /dev/null @@ -1,450 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.ui; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Set; - -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -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.Button; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.VerticalPanel; -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; - -/** - * TODO make this work (just an early prototype). We may want to have paging - * style table which will be much lighter than VScrollTable is. - */ -public class VTablePaging extends Composite implements Table, VPaintableWidget, - ClickHandler { - - private final Grid tBody = new Grid(); - private final Button nextPage = new Button(">"); - private final Button prevPage = new Button("<"); - private final Button firstPage = new Button("<<"); - private final Button lastPage = new Button(">>"); - - private int pageLength = 15; - - private boolean rowHeaders = false; - - private ApplicationConnection client; - private String id; - - private boolean immediate = false; - - private int selectMode = Table.SELECT_MODE_NONE; - - private final ArrayList<String> selectedRowKeys = new ArrayList<String>(); - - private int totalRows; - - private final HashMap<?, ?> visibleColumns = new HashMap<Object, Object>(); - - private int rows; - - private int firstRow; - private boolean sortAscending = true; - private final HorizontalPanel pager; - - public HashMap<String, TableRow> rowKeysToTableRows = new HashMap<String, TableRow>(); - - public VTablePaging() { - - tBody.setStyleName("itable-tbody"); - - final VerticalPanel panel = new VerticalPanel(); - - pager = new HorizontalPanel(); - pager.add(firstPage); - firstPage.addClickHandler(this); - pager.add(prevPage); - prevPage.addClickHandler(this); - pager.add(nextPage); - nextPage.addClickHandler(this); - pager.add(lastPage); - lastPage.addClickHandler(this); - - panel.add(pager); - panel.add(tBody); - - initWidget(panel); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, true)) { - return; - } - - this.client = client; - id = uidl.getStringAttribute("id"); - immediate = uidl.getBooleanAttribute("immediate"); - totalRows = uidl.getIntAttribute("totalrows"); - pageLength = uidl.getIntAttribute("pagelength"); - firstRow = uidl.getIntAttribute("firstrow"); - rows = uidl.getIntAttribute("rows"); - - if (uidl.hasAttribute("selectmode")) { - if (uidl.getStringAttribute("selectmode").equals("multi")) { - selectMode = Table.SELECT_MODE_MULTI; - } else { - selectMode = Table.SELECT_MODE_SINGLE; - } - - if (uidl.hasAttribute("selected")) { - final Set<String> selectedKeys = uidl - .getStringArrayVariableAsSet("selected"); - selectedRowKeys.clear(); - for (final Iterator<String> it = selectedKeys.iterator(); it - .hasNext();) { - selectedRowKeys.add(it.next()); - } - } - } - - if (uidl.hasVariable("sortascending")) { - sortAscending = uidl.getBooleanVariable("sortascending"); - } - - if (uidl.hasAttribute("rowheaders")) { - rowHeaders = true; - } - - UIDL rowData = null; - UIDL visibleColumns = null; - for (final Iterator<?> it = uidl.getChildIterator(); it.hasNext();) { - final UIDL c = (UIDL) it.next(); - if (c.getTag().equals("rows")) { - rowData = c; - } else if (c.getTag().equals("actions")) { - updateActionMap(c); - } else if (c.getTag().equals("visiblecolumns")) { - visibleColumns = c; - } - } - tBody.resize(rows + 1, uidl.getIntAttribute("cols") - + (rowHeaders ? 1 : 0)); - updateHeader(visibleColumns); - updateBody(rowData); - - updatePager(); - } - - private void updateHeader(UIDL c) { - final Iterator<?> it = c.getChildIterator(); - visibleColumns.clear(); - int colIndex = (rowHeaders ? 1 : 0); - while (it.hasNext()) { - final UIDL col = (UIDL) it.next(); - final String cid = col.getStringAttribute("cid"); - if (!col.hasAttribute("collapsed")) { - tBody.setWidget(0, colIndex, - new HeaderCell(cid, col.getStringAttribute("caption"))); - - } - colIndex++; - } - } - - private void updateActionMap(UIDL c) { - // TODO Auto-generated method stub - - } - - /** - * Updates row data from uidl. UpdateFromUIDL delegates updating tBody to - * this method. - * - * Updates may be to different part of tBody, depending on update type. It - * can be initial row data, scroll up, scroll down... - * - * @param uidl - * which contains row data - */ - private void updateBody(UIDL uidl) { - final Iterator<?> it = uidl.getChildIterator(); - - int curRowIndex = 1; - while (it.hasNext()) { - final UIDL rowUidl = (UIDL) it.next(); - final TableRow row = new TableRow(curRowIndex, - String.valueOf(rowUidl.getIntAttribute("key")), - rowUidl.hasAttribute("selected")); - int colIndex = 0; - if (rowHeaders) { - tBody.setWidget(curRowIndex, colIndex, new BodyCell(row, - rowUidl.getStringAttribute("caption"))); - colIndex++; - } - final Iterator<?> cells = rowUidl.getChildIterator(); - while (cells.hasNext()) { - final Object cell = cells.next(); - if (cell instanceof String) { - tBody.setWidget(curRowIndex, colIndex, new BodyCell(row, - (String) cell)); - } else { - final VPaintableWidget cellContent = client - .getPaintable((UIDL) cell); - final BodyCell bodyCell = new BodyCell(row); - bodyCell.setWidget(cellContent.getWidgetForPaintable()); - tBody.setWidget(curRowIndex, colIndex, bodyCell); - } - colIndex++; - } - curRowIndex++; - } - } - - private void updatePager() { - if (pageLength == 0) { - pager.setVisible(false); - return; - } - if (isFirstPage()) { - firstPage.setEnabled(false); - prevPage.setEnabled(false); - } else { - firstPage.setEnabled(true); - prevPage.setEnabled(true); - } - if (hasNextPage()) { - nextPage.setEnabled(true); - lastPage.setEnabled(true); - } else { - nextPage.setEnabled(false); - lastPage.setEnabled(false); - - } - } - - private boolean hasNextPage() { - if (firstRow + rows + 1 > totalRows) { - return false; - } - return true; - } - - private boolean isFirstPage() { - if (firstRow == 0) { - return true; - } - return false; - } - - public void onClick(ClickEvent event) { - Object sender = event.getSource(); - if (sender instanceof Button) { - if (sender == firstPage) { - client.updateVariable(id, "firstvisible", 0, true); - } else if (sender == nextPage) { - client.updateVariable(id, "firstvisible", - firstRow + pageLength, true); - } else if (sender == prevPage) { - int newFirst = firstRow - pageLength; - if (newFirst < 0) { - newFirst = 0; - } - client.updateVariable(id, "firstvisible", newFirst, true); - } else if (sender == lastPage) { - client.updateVariable(id, "firstvisible", totalRows - - pageLength, true); - } - } - if (sender instanceof HeaderCell) { - final HeaderCell hCell = (HeaderCell) sender; - client.updateVariable(id, "sortcolumn", hCell.getCid(), false); - client.updateVariable(id, "sortascending", (sortAscending ? false - : true), true); - } - } - - private class HeaderCell extends HTML { - - private String cid; - - public String getCid() { - return cid; - } - - public void setCid(String pid) { - cid = pid; - } - - HeaderCell(String pid, String caption) { - super(); - cid = pid; - addClickHandler(VTablePaging.this); - setText(caption); - // TODO remove debug color - DOM.setStyleAttribute(getElement(), "color", "brown"); - DOM.setStyleAttribute(getElement(), "font-weight", "bold"); - } - } - - /** - * Abstraction of table cell content. In needs to know on which row it is in - * case of context click. - * - * @author mattitahvonen - */ - public class BodyCell extends SimplePanel { - private final TableRow row; - - public BodyCell(TableRow row) { - super(); - sinkEvents(Event.BUTTON_LEFT | Event.BUTTON_RIGHT); - this.row = row; - } - - public BodyCell(TableRow row2, String textContent) { - super(); - sinkEvents(Event.BUTTON_LEFT | Event.BUTTON_RIGHT); - row = row2; - setWidget(new Label(textContent)); - } - - @Override - public void onBrowserEvent(Event event) { - System.out.println("CEll event: " + event.toString()); - switch (DOM.eventGetType(event)) { - case Event.BUTTON_RIGHT: - row.showContextMenu(event); - Window.alert("context menu un-implemented"); - DOM.eventCancelBubble(event, true); - break; - case Event.BUTTON_LEFT: - if (selectMode > Table.SELECT_MODE_NONE) { - row.toggleSelected(); - } - break; - default: - break; - } - super.onBrowserEvent(event); - } - } - - private class TableRow { - - private final String key; - private final int rowIndex; - private boolean selected = false; - - public TableRow(int rowIndex, String rowKey, boolean selected) { - rowKeysToTableRows.put(rowKey, this); - this.rowIndex = rowIndex; - key = rowKey; - setSelected(selected); - } - - /** - * This method is used to set row status. Does not change value on - * server. - * - * @param selected - */ - public void setSelected(boolean sel) { - selected = sel; - if (selected) { - selectedRowKeys.add(key); - DOM.setStyleAttribute( - tBody.getRowFormatter().getElement(rowIndex), - "background", "yellow"); - - } else { - selectedRowKeys.remove(key); - DOM.setStyleAttribute( - tBody.getRowFormatter().getElement(rowIndex), - "background", "transparent"); - } - } - - public void setContextMenuOptions(HashMap<?, ?> options) { - - } - - /** - * Toggles rows select state. Also updates state to server according to - * tables immediate flag. - * - */ - public void toggleSelected() { - if (selected) { - setSelected(false); - } else { - if (selectMode == Table.SELECT_MODE_SINGLE) { - deselectAll(); - } - setSelected(true); - } - client.updateVariable( - id, - "selected", - selectedRowKeys.toArray(new String[selectedRowKeys.size()]), - immediate); - } - - /** - * Shows context menu for this row. - * - * @param event - * Event which triggered context menu. Correct place for - * context menu can be determined with it. - */ - public void showContextMenu(Event event) { - System.out.println("TODO: Show context menu"); - } - } - - public void deselectAll() { - final Object[] keys = selectedRowKeys.toArray(); - for (int i = 0; i < keys.length; i++) { - final TableRow tableRow = rowKeysToTableRows.get(keys[i]); - if (tableRow != null) { - tableRow.setSelected(false); - } - } - // still ensure all selects are removed from - selectedRowKeys.clear(); - } - - public void add(Widget w) { - // TODO Auto-generated method stub - - } - - public void clear() { - // TODO Auto-generated method stub - - } - - public Iterator<Widget> iterator() { - // TODO Auto-generated method stub - return null; - } - - public boolean remove(Widget w) { - // TODO Auto-generated method stub - return false; - } - - public Widget getWidgetForPaintable() { - return this; - } -} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java index 74ff328710..809c1a0380 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java @@ -54,7 +54,7 @@ public class VTabsheet extends VTabsheetBase { /** * Representation of a single "tab" shown in the TabBar - * + * */ private static class Tab extends SimplePanel { private static final String TD_CLASSNAME = CLASSNAME + "-tabitemcell"; @@ -206,9 +206,10 @@ public class VTabsheet extends VTabsheetBase { if (uidl.hasAttribute(ATTRIBUTE_ERROR)) { tooltipInfo.setErrorUidl(uidl.getErrors()); } - client.registerTooltip(getTabsheet(), getElement(), tooltipInfo); + client.registerWidgetTooltip(getTabsheet(), getElement(), + tooltipInfo); } else { - client.registerTooltip(getTabsheet(), getElement(), null); + client.registerWidgetTooltip(getTabsheet(), getElement(), null); } boolean ret = super.updateCaption(uidl); @@ -236,7 +237,7 @@ public class VTabsheet extends VTabsheetBase { if (event.getTypeInt() == Event.ONLOAD) { getTabsheet().tabSizeMightHaveChanged(getTab()); } - client.handleTooltipEvent(event, getTabsheet(), getElement()); + client.handleWidgetTooltipEvent(event, getTabsheet(), getElement()); } public Tab getTab() { @@ -469,7 +470,7 @@ public class VTabsheet extends VTabsheetBase { // Can't use "style" as it's already in use public static final String TAB_STYLE_NAME = "tabstyle"; - private final Element tabs; // tabbar and 'scroller' container + final Element tabs; // tabbar and 'scroller' container private final Element scroller; // tab-scroller element private final Element scrollerNext; // tab-scroller next button element private final Element scrollerPrev; // tab-scroller prev button element @@ -480,15 +481,15 @@ public class VTabsheet extends VTabsheetBase { private int scrollerIndex = 0; private final TabBar tb = new TabBar(this); - private final VTabsheetPanel tp = new VTabsheetPanel(); + final VTabsheetPanel tp = new VTabsheetPanel(); private final Element contentNode, deco; private String height; private String width; - private boolean waitingForResponse; + boolean waitingForResponse; - private final RenderInformation renderInformation = new RenderInformation(); + final RenderInformation renderInformation = new RenderInformation(); /** * Previous visible widget is set invisible with CSS (not display: none, but @@ -497,7 +498,7 @@ public class VTabsheet extends VTabsheetBase { */ private Widget previousVisibleWidget; - private boolean rendering = false; + boolean rendering = false; private String currentStyle; @@ -545,11 +546,11 @@ public class VTabsheet extends VTabsheetBase { client.updateVariable(id, "close", tabKeys.get(tabIndex), true); } - private boolean isDynamicWidth() { + boolean isDynamicWidth() { return width == null || width.equals(""); } - private boolean isDynamicHeight() { + boolean isDynamicHeight() { return height == null || height.equals(""); } @@ -633,60 +634,7 @@ public class VTabsheet extends VTabsheetBase { return scrollerIndex > index; } - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - rendering = true; - - if (!uidl.getBooleanAttribute("cached")) { - // Handle stylename changes before generics (might affect size - // calculations) - handleStyleNames(uidl); - } - - super.updateFromUIDL(uidl, client); - if (cachedUpdate) { - rendering = false; - return; - } - - // tabs; push or not - if (!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(tabs, "width", "1px"); - DOM.setStyleAttribute(tabs, "overflow", "hidden"); - } else { - showAllTabs(); - DOM.setStyleAttribute(tabs, "width", ""); - DOM.setStyleAttribute(tabs, "overflow", "visible"); - updateDynamicWidth(); - } - - if (!isDynamicHeight()) { - // Must update height after the styles have been set - updateContentNodeHeight(); - updateOpenTabSize(); - } - - iLayout(); - - // Re run relative size update to ensure optimal scrollbars - // TODO isolate to situation that visible tab has undefined height - try { - client.handleComponentRelativeSize(tp.getWidget(tp - .getVisibleWidget())); - } catch (Exception e) { - // Ignore, most likely empty tabsheet - } - - renderInformation.updateSize(getElement()); - - waitingForResponse = false; - rendering = false; - } - - private void handleStyleNames(UIDL uidl) { + void handleStyleNames(UIDL uidl) { // Add proper stylenames for all elements (easier to prevent unwanted // style inheritance) if (uidl.hasAttribute("style")) { @@ -728,7 +676,7 @@ public class VTabsheet extends VTabsheetBase { } } - private void updateDynamicWidth() { + void updateDynamicWidth() { // Find width consumed by tabs TableCellElement spacerCell = ((TableElement) tb.getElement().cast()) .getRows().getItem(0).getCells().getItem(tb.getTabCount()); @@ -923,7 +871,7 @@ public class VTabsheet extends VTabsheetBase { } } - private void updateContentNodeHeight() { + void updateContentNodeHeight() { if (height != null && !"".equals(height)) { int contentHeight = getOffsetHeight(); contentHeight -= DOM.getElementPropertyInt(deco, "offsetHeight"); @@ -990,7 +938,7 @@ public class VTabsheet extends VTabsheetBase { * position: absolute (to work around a firefox flickering bug) we must keep * this up-to-date by hand. */ - private void updateOpenTabSize() { + void updateOpenTabSize() { /* * The overflow=auto element must have a height specified, otherwise it * will be just as high as the contents and no scrollbars will appear @@ -1066,7 +1014,7 @@ public class VTabsheet extends VTabsheetBase { } - private void showAllTabs() { + void showAllTabs() { scrollerIndex = tb.getFirstVisibleTab(); for (int i = 0; i < tb.getTabCount(); i++) { Tab t = tb.getTab(i); @@ -1114,10 +1062,6 @@ public class VTabsheet extends VTabsheetBase { tp.replaceComponent(oldComponent, newComponent); } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - /* Tabsheet does not render its children's captions */ - } - public boolean requestLayout(Set<Widget> children) { if (!isDynamicHeight() && !isDynamicWidth()) { /* @@ -1193,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/VTabsheetBase.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBase.java index 9dd74474f3..271aed1859 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBase.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBase.java @@ -14,7 +14,6 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.VPaintableWidget; abstract class VTabsheetBase extends ComplexPanel implements Container { @@ -34,81 +33,6 @@ abstract class VTabsheetBase extends ComplexPanel implements Container { setStyleName(classname); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - - // Ensure correct implementation - cachedUpdate = client.updateComponent(this, uidl, true); - if (cachedUpdate) { - return; - } - - // Update member references - id = uidl.getId(); - 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 = getWidgetIterator(); iterator - .hasNext();) { - oldWidgets.add(iterator.next()); - } - - // Clear previous values - tabKeys.clear(); - 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")) { - disabledTabKeys.add(key); - } - - tabKeys.add(key); - - if (selected) { - activeTabIndex = index; - } - renderTab(tab, index, selected, hidden); - index++; - } - - int tabCount = getTabCount(); - while (tabCount-- > index) { - removeTab(index); - } - - for (int i = 0; i < getTabCount(); i++) { - VPaintableWidget p = 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); - } - - } - /** * @return a list of currently shown Paintables * diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBasePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBasePaintable.java new file mode 100644 index 0000000000..79f6012ed1 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetBasePaintable.java @@ -0,0 +1,99 @@ +/* +@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 new file mode 100644 index 0000000000..0d32484e10 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPaintable.java @@ -0,0 +1,85 @@ +/* +@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 cd09e24d67..2c8ed24693 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java @@ -1,79 +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;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.UIDL;
-
-/**
- * This class represents a multiline textfield (textarea).
- *
- * TODO consider replacing this with a RichTextArea based implementation. IE
- * does not support CSS height for textareas in Strict mode :-(
- *
- * @author Vaadin Ltd.
- *
- */
-public class VTextArea extends VTextField {
- public static final String CLASSNAME = "v-textarea";
-
- public VTextArea() {
- super(DOM.createTextArea());
- setStyleName(CLASSNAME);
- }
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- // Call parent renderer explicitly
- super.updateFromUIDL(uidl, client);
-
- if (uidl.hasAttribute("rows")) {
- setRows(uidl.getIntAttribute("rows"));
- }
-
- if (getMaxLength() >= 0) {
- sinkEvents(Event.ONKEYUP);
- }
- }
-
- public void setRows(int rows) {
- setRows(getElement(), rows);
- }
-
- private native void setRows(Element e, int r)
- /*-{
- try {
- if(e.tagName.toLowerCase() == "textarea")
- e.rows = r;
- } catch (e) {}
- }-*/;
-
- @Override
- public void onBrowserEvent(Event event) {
- if (getMaxLength() >= 0 && event.getTypeInt() == Event.ONKEYUP) {
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- if (getText().length() > getMaxLength()) {
- setText(getText().substring(0, getMaxLength()));
- }
- }
- });
- }
- super.onBrowserEvent(event);
- }
-
- @Override
- public int getCursorPos() {
- // This is needed so that TextBoxImplIE6 is used to return the correct
- // position for old Internet Explorer versions where it has to be
- // detected in a different way.
- return getImpl().getTextAreaCursorPos(getElement());
- }
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Event; + +/** + * 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/VTextAreaPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTextAreaPaintable.java new file mode 100644 index 0000000000..3c21a4ab2f --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VTextAreaPaintable.java @@ -0,0 +1,38 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.ui; + +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; + +public class VTextAreaPaintable extends VTextFieldPaintable { + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Call parent renderer explicitly + super.updateFromUIDL(uidl, client); + + if (uidl.hasAttribute("rows")) { + getWidgetForPaintable().setRows(uidl.getIntAttribute("rows")); + } + + if (getWidgetForPaintable().getMaxLength() >= 0) { + getWidgetForPaintable().sinkEvents(Event.ONKEYUP); + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VTextArea.class); + } + + @Override + public VTextArea getWidgetForPaintable() { + return (VTextArea) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java index 80dad78e58..80b27e6c8c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java @@ -4,7 +4,6 @@ package com.vaadin.terminal.gwt.client.ui; -import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Style.Overflow; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; @@ -15,21 +14,16 @@ import com.google.gwt.event.dom.client.FocusHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.TextBoxBase; -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.VPaintableWidget; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VTooltip; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener; /** * This class represents a basic text input field with one row. @@ -37,9 +31,8 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutAct * @author Vaadin Ltd. * */ -public class VTextField extends TextBoxBase implements VPaintableWidget, Field, - ChangeHandler, FocusHandler, BlurHandler, BeforeShortcutActionListener, - KeyDownHandler { +public class VTextField extends TextBoxBase implements Field, ChangeHandler, + FocusHandler, BlurHandler, KeyDownHandler { public static final String VAR_CUR_TEXT = "curText"; @@ -53,11 +46,11 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, */ public static final String CLASSNAME_FOCUS = "focus"; - protected String id; + protected String paintableId; protected ApplicationConnection client; - private String valueBeforeEdit = null; + protected String valueBeforeEdit = null; /** * Set to false if a text change event has been sent since the last value @@ -66,20 +59,20 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, */ private boolean valueBeforeEditIsSynced = true; - private boolean immediate = false; + protected boolean immediate = false; private int extraHorizontalPixels = -1; private int extraVerticalPixels = -1; private int maxLength = -1; private static final String CLASSNAME_PROMPT = "prompt"; - private static final String ATTR_INPUTPROMPT = "prompt"; + protected static final String ATTR_INPUTPROMPT = "prompt"; public static final String ATTR_TEXTCHANGE_TIMEOUT = "iet"; public static final String VAR_CURSOR = "c"; public static final String ATTR_TEXTCHANGE_EVENTMODE = "iem"; - private static final String TEXTCHANGE_MODE_EAGER = "EAGER"; + protected static final String TEXTCHANGE_MODE_EAGER = "EAGER"; private static final String TEXTCHANGE_MODE_TIMEOUT = "TIMEOUT"; - private String inputPrompt = null; + protected String inputPrompt = null; private boolean prompting = false; private int lastCursorPos = -1; private boolean wordwrap = true; @@ -112,14 +105,14 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, * Eager polling for a change is bit dum and heavy operation, so I guess we * should first try to survive without. */ - private static final int TEXTCHANGE_EVENTS = Event.ONPASTE + protected static final int TEXTCHANGE_EVENTS = Event.ONPASTE | Event.KEYEVENTS | Event.ONMOUSEUP; @Override public void onBrowserEvent(Event event) { super.onBrowserEvent(event); if (client != null) { - client.handleTooltipEvent(event, this); + client.handleWidgetTooltipEvent(event, this); } if (listenTextChangeEvents @@ -158,7 +151,7 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, client.sendPendingVariableChanges(); } else { // Default case - just send an immediate text change message - client.updateVariable(id, VAR_CUR_TEXT, text, true); + client.updateVariable(paintableId, VAR_CUR_TEXT, text, true); // Shouldn't investigate valueBeforeEdit to avoid duplicate text // change events as the states are not in sync any more @@ -180,9 +173,9 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, } }; private boolean scheduled = false; - private boolean listenTextChangeEvents; - private String textChangeEventMode; - private int textChangeEventTimeout; + protected boolean listenTextChangeEvents; + protected String textChangeEventMode; + protected int textChangeEventTimeout; private void deferTextChangeEvent() { if (textChangeEventMode.equals(TEXTCHANGE_MODE_TIMEOUT) && scheduled) { @@ -215,88 +208,7 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, super.setReadOnly(readOnly); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - id = uidl.getId(); - - if (client.updateComponent(this, uidl, true)) { - return; - } - - if (uidl.getBooleanAttribute("readonly")) { - setReadOnly(true); - } else { - setReadOnly(false); - } - - inputPrompt = uidl.getStringAttribute(ATTR_INPUTPROMPT); - - setMaxLength(uidl.hasAttribute("maxLength") ? uidl - .getIntAttribute("maxLength") : -1); - - immediate = uidl.getBooleanAttribute("immediate"); - - listenTextChangeEvents = client.hasEventListeners(this, "ie"); - if (listenTextChangeEvents) { - textChangeEventMode = uidl - .getStringAttribute(ATTR_TEXTCHANGE_EVENTMODE); - if (textChangeEventMode.equals(TEXTCHANGE_MODE_EAGER)) { - textChangeEventTimeout = 1; - } else { - textChangeEventTimeout = uidl - .getIntAttribute(ATTR_TEXTCHANGE_TIMEOUT); - if (textChangeEventTimeout < 1) { - // Sanitize and allow lazy/timeout with timeout set to 0 to - // work as eager - textChangeEventTimeout = 1; - } - } - sinkEvents(TEXTCHANGE_EVENTS); - attachCutEventListener(getElement()); - } - - if (uidl.hasAttribute("cols")) { - setColumns(new Integer(uidl.getStringAttribute("cols")).intValue()); - } - - final String text = uidl.getStringVariable("text"); - - /* - * We skip the text content update if field has been repainted, but text - * has not been changed. Additional sanity check verifies there is no - * change in the que (in which case we count more on the server side - * value). - */ - if (!(uidl.getBooleanAttribute(ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS) - && valueBeforeEdit != null && text.equals(valueBeforeEdit))) { - updateFieldContent(text); - } - - if (uidl.hasAttribute("selpos")) { - final int pos = uidl.getIntAttribute("selpos"); - final int length = uidl.getIntAttribute("sellen"); - /* - * Gecko defers setting the text so we need to defer the selection. - */ - Scheduler.get().scheduleDeferred(new Command() { - public void execute() { - setSelectionRange(pos, length); - } - }); - } - - // Here for backward compatibility; to be moved to TextArea. - // Optimization: server does not send attribute for the default 'true' - // state. - if (uidl.hasAttribute("wordwrap") - && uidl.getBooleanAttribute("wordwrap") == false) { - setWordwrap(false); - } else { - setWordwrap(true); - } - } - - private void updateFieldContent(final String text) { + protected void updateFieldContent(final String text) { setPrompting(inputPrompt != null && focusedTextField != this && (text.equals(""))); @@ -350,7 +262,7 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, } } - private void setMaxLength(int newMaxLength) { + protected void setMaxLength(int newMaxLength) { if (newMaxLength >= 0) { maxLength = newMaxLength; if (getElement().getTagName().toLowerCase().equals("textarea")) { @@ -386,20 +298,20 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, * true if the field was blurred */ public void valueChange(boolean blurred) { - if (client != null && id != null) { + if (client != null && paintableId != null) { boolean sendBlurEvent = false; boolean sendValueChange = false; - if (blurred && client.hasEventListeners(this, EventId.BLUR)) { + if (blurred && client.hasWidgetEventListeners(this, EventId.BLUR)) { sendBlurEvent = true; - client.updateVariable(id, EventId.BLUR, "", false); + client.updateVariable(paintableId, EventId.BLUR, "", false); } String newText = getText(); if (!prompting && newText != null && !newText.equals(valueBeforeEdit)) { sendValueChange = immediate; - client.updateVariable(id, "text", getText(), false); + client.updateVariable(paintableId, "text", getText(), false); valueBeforeEdit = newText; valueBeforeEditIsSynced = true; } @@ -432,7 +344,7 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, if (Util.isAttachedAndDisplayed(this)) { int cursorPos = getCursorPos(); if (lastCursorPos != cursorPos) { - client.updateVariable(id, VAR_CURSOR, cursorPos, false); + client.updateVariable(paintableId, VAR_CURSOR, cursorPos, false); lastCursorPos = cursorPos; return true; } @@ -456,8 +368,8 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, setPrompting(false); } focusedTextField = this; - if (client.hasEventListeners(this, EventId.FOCUS)) { - client.updateVariable(id, EventId.FOCUS, "", true); + if (client.hasWidgetEventListeners(this, EventId.FOCUS)) { + client.updateVariable(paintableId, EventId.FOCUS, "", true); } } @@ -568,10 +480,6 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, } } - public void onBeforeShortcutAction(Event e) { - valueChange(false); - } - // Here for backward compatibility; to be moved to TextArea public void setWordwrap(boolean enabled) { if (enabled == wordwrap) { @@ -601,8 +509,4 @@ public class VTextField extends TextBoxBase implements VPaintableWidget, Field, valueChange(false); } } - - public Widget getWidgetForPaintable() { - return this; - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextFieldPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTextFieldPaintable.java new file mode 100644 index 0000000000..e3eecd5a09 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VTextFieldPaintable.java @@ -0,0 +1,124 @@ +/* +@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.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; + +public class VTextFieldPaintable extends VAbstractPaintableWidget implements + BeforeShortcutActionListener { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Save details + getWidgetForPaintable().client = client; + getWidgetForPaintable().paintableId = uidl.getId(); + + if (client.updateComponent(this, uidl, true)) { + return; + } + + if (uidl.getBooleanAttribute("readonly")) { + getWidgetForPaintable().setReadOnly(true); + } else { + getWidgetForPaintable().setReadOnly(false); + } + + getWidgetForPaintable().inputPrompt = uidl + .getStringAttribute(VTextField.ATTR_INPUTPROMPT); + + getWidgetForPaintable().setMaxLength( + uidl.hasAttribute("maxLength") ? uidl + .getIntAttribute("maxLength") : -1); + + getWidgetForPaintable().immediate = uidl + .getBooleanAttribute("immediate"); + + getWidgetForPaintable().listenTextChangeEvents = client + .hasEventListeners(this, "ie"); + if (getWidgetForPaintable().listenTextChangeEvents) { + getWidgetForPaintable().textChangeEventMode = uidl + .getStringAttribute(VTextField.ATTR_TEXTCHANGE_EVENTMODE); + if (getWidgetForPaintable().textChangeEventMode + .equals(VTextField.TEXTCHANGE_MODE_EAGER)) { + getWidgetForPaintable().textChangeEventTimeout = 1; + } else { + getWidgetForPaintable().textChangeEventTimeout = uidl + .getIntAttribute(VTextField.ATTR_TEXTCHANGE_TIMEOUT); + if (getWidgetForPaintable().textChangeEventTimeout < 1) { + // Sanitize and allow lazy/timeout with timeout set to 0 to + // work as eager + getWidgetForPaintable().textChangeEventTimeout = 1; + } + } + getWidgetForPaintable().sinkEvents(VTextField.TEXTCHANGE_EVENTS); + getWidgetForPaintable().attachCutEventListener( + getWidgetForPaintable().getElement()); + } + + if (uidl.hasAttribute("cols")) { + getWidgetForPaintable().setColumns( + new Integer(uidl.getStringAttribute("cols")).intValue()); + } + + final String text = uidl.getStringVariable("text"); + + /* + * We skip the text content update if field has been repainted, but text + * has not been changed. Additional sanity check verifies there is no + * change in the que (in which case we count more on the server side + * value). + */ + if (!(uidl + .getBooleanAttribute(VTextField.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS) + && getWidgetForPaintable().valueBeforeEdit != null && text + .equals(getWidgetForPaintable().valueBeforeEdit))) { + getWidgetForPaintable().updateFieldContent(text); + } + + if (uidl.hasAttribute("selpos")) { + final int pos = uidl.getIntAttribute("selpos"); + final int length = uidl.getIntAttribute("sellen"); + /* + * Gecko defers setting the text so we need to defer the selection. + */ + Scheduler.get().scheduleDeferred(new Command() { + public void execute() { + getWidgetForPaintable().setSelectionRange(pos, length); + } + }); + } + + // Here for backward compatibility; to be moved to TextArea. + // Optimization: server does not send attribute for the default 'true' + // state. + if (uidl.hasAttribute("wordwrap") + && uidl.getBooleanAttribute("wordwrap") == false) { + getWidgetForPaintable().setWordwrap(false); + } else { + getWidgetForPaintable().setWordwrap(true); + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VTextField.class); + } + + @Override + public VTextField getWidgetForPaintable() { + return (VTextField) super.getWidgetForPaintable(); + } + + public void onBeforeShortcutAction(Event e) { + getWidgetForPaintable().valueChange(false); + } + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java b/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java index a522c79736..bb808321b9 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java @@ -14,25 +14,22 @@ import com.google.gwt.event.dom.client.FocusEvent; import com.google.gwt.event.dom.client.FocusHandler; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.TextBox; -import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ContainerResizedListener; import com.vaadin.terminal.gwt.client.EventId; import com.vaadin.terminal.gwt.client.Focusable; import com.vaadin.terminal.gwt.client.LocaleNotLoadedException; import com.vaadin.terminal.gwt.client.LocaleService; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.VPaintableWidget; -public class VTextualDate extends VDateField implements VPaintableWidget, - Field, ChangeHandler, ContainerResizedListener, Focusable, SubPartAware { +public class VTextualDate extends VDateField implements Field, ChangeHandler, + ContainerResizedListener, Focusable, SubPartAware { private static final String PARSE_ERROR_CLASSNAME = CLASSNAME + "-parseerror"; - private final TextBox text; + protected final TextBox text; - private String formatStr; + protected String formatStr; private String width; @@ -40,11 +37,11 @@ public class VTextualDate extends VDateField implements VPaintableWidget, protected int fieldExtraWidth = -1; - private boolean lenient; + protected boolean lenient; private static final String CLASSNAME_PROMPT = "prompt"; - private static final String ATTR_INPUTPROMPT = "prompt"; - private String inputPrompt = ""; + protected static final String ATTR_INPUTPROMPT = "prompt"; + protected String inputPrompt = ""; private boolean prompting = false; public VTextualDate() { @@ -65,8 +62,8 @@ public class VTextualDate extends VDateField implements VPaintableWidget, setPrompting(false); } if (getClient() != null - && getClient().hasEventListeners(VTextualDate.this, - EventId.FOCUS)) { + && getClient().hasWidgetEventListeners( + VTextualDate.this, EventId.FOCUS)) { getClient() .updateVariable(getId(), EventId.FOCUS, "", true); } @@ -83,8 +80,8 @@ public class VTextualDate extends VDateField implements VPaintableWidget, text.setText(readonly ? "" : inputPrompt); } if (getClient() != null - && getClient().hasEventListeners(VTextualDate.this, - EventId.BLUR)) { + && getClient().hasWidgetEventListeners( + VTextualDate.this, EventId.BLUR)) { getClient().updateVariable(getId(), EventId.BLUR, "", true); } } @@ -92,37 +89,6 @@ public class VTextualDate extends VDateField implements VPaintableWidget, add(text); } - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - int origRes = currentResolution; - String oldLocale = currentLocale; - super.updateFromUIDL(uidl, client); - if (origRes != currentResolution || oldLocale != currentLocale) { - // force recreating format string - formatStr = null; - } - if (uidl.hasAttribute("format")) { - formatStr = uidl.getStringAttribute("format"); - } - - inputPrompt = uidl.getStringAttribute(ATTR_INPUTPROMPT); - - lenient = !uidl.getBooleanAttribute("strict"); - - buildDate(); - // not a FocusWidget -> needs own tabindex handling - if (uidl.hasAttribute("tabindex")) { - text.setTabIndex(uidl.getIntAttribute("tabindex")); - } - - if (readonly) { - text.addStyleDependentName("readonly"); - } else { - text.removeStyleDependentName("readonly"); - } - - } - protected String getFormatString() { if (formatStr == null) { if (currentResolution == RESOLUTION_YEAR) { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextualDatePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTextualDatePaintable.java new file mode 100644 index 0000000000..6a9da31269 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VTextualDatePaintable.java @@ -0,0 +1,58 @@ +/* +@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 VTextualDatePaintable extends VDateFieldPaintable { + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + int origRes = getWidgetForPaintable().currentResolution; + String oldLocale = getWidgetForPaintable().currentLocale; + super.updateFromUIDL(uidl, client); + if (origRes != getWidgetForPaintable().currentResolution + || oldLocale != getWidgetForPaintable().currentLocale) { + // force recreating format string + getWidgetForPaintable().formatStr = null; + } + if (uidl.hasAttribute("format")) { + getWidgetForPaintable().formatStr = uidl + .getStringAttribute("format"); + } + + getWidgetForPaintable().inputPrompt = uidl + .getStringAttribute(VTextualDate.ATTR_INPUTPROMPT); + + getWidgetForPaintable().lenient = !uidl.getBooleanAttribute("strict"); + + getWidgetForPaintable().buildDate(); + // not a FocusWidget -> needs own tabindex handling + if (uidl.hasAttribute("tabindex")) { + getWidgetForPaintable().text.setTabIndex(uidl + .getIntAttribute("tabindex")); + } + + if (getWidgetForPaintable().readonly) { + getWidgetForPaintable().text.addStyleDependentName("readonly"); + } else { + getWidgetForPaintable().text.removeStyleDependentName("readonly"); + } + + } + + @Override + protected Widget createWidget() { + return GWT.create(VTextualDate.class); + } + + @Override + public VTextualDate getWidgetForPaintable() { + return (VTextualDate) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTree.java b/src/com/vaadin/terminal/gwt/client/ui/VTree.java index de7f6c652a..be337ae0cb 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTree.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTree.java @@ -40,10 +40,10 @@ 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.MouseEventDetails; -import com.vaadin.terminal.gwt.client.VPaintableWidget; -import com.vaadin.terminal.gwt.client.TooltipInfo; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.VTooltip; import com.vaadin.terminal.gwt.client.ui.dd.DDUtil; import com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler; @@ -58,9 +58,9 @@ import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; /** * */ -public class VTree extends FocusElementPanel implements VPaintableWidget, - VHasDropHandler, FocusHandler, BlurHandler, KeyPressHandler, - KeyDownHandler, SubPartAware, ActionOwner { +public class VTree extends FocusElementPanel implements VHasDropHandler, + FocusHandler, BlurHandler, KeyPressHandler, KeyDownHandler, + SubPartAware, ActionOwner { public static final String CLASSNAME = "v-tree"; @@ -71,17 +71,17 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, private static final int CHARCODE_SPACE = 32; - private final FlowPanel body = new FlowPanel(); + final FlowPanel body = new FlowPanel(); - private Set<String> selectedIds = new HashSet<String>(); - private ApplicationConnection client; - private String paintableId; - private boolean selectable; - private boolean isMultiselect; + Set<String> selectedIds = new HashSet<String>(); + ApplicationConnection client; + String paintableId; + boolean selectable; + boolean isMultiselect; private String currentMouseOverKey; - private TreeNode lastSelection; - private TreeNode focusedNode; - private int multiSelectMode = MULTISELECT_MODE_DEFAULT; + TreeNode lastSelection; + TreeNode focusedNode; + int multiSelectMode = MULTISELECT_MODE_DEFAULT; private final HashMap<String, TreeNode> keyToNode = new HashMap<String, TreeNode>(); @@ -91,23 +91,23 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, */ private final HashMap<String, String> actionMap = new HashMap<String, String>(); - private boolean immediate; + boolean immediate; - private boolean isNullSelectionAllowed = true; + boolean isNullSelectionAllowed = true; - private boolean disabled = false; + boolean disabled = false; - private boolean readonly; + boolean readonly; - private boolean rendering; + boolean rendering; private VAbstractDropHandler dropHandler; - private int dragMode; + int dragMode; private boolean selectionHasChanged = false; - private String[] bodyActionKeys; + String[] bodyActionKeys; public VLazyExecutor iconLoaded = new VLazyExecutor(50, new ScheduledCommand() { @@ -206,24 +206,6 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, } } - private void updateActionMap(UIDL c) { - final Iterator<?> it = c.getChildIterator(); - while (it.hasNext()) { - final UIDL action = (UIDL) it.next(); - final String key = action.getStringAttribute("key"); - final String caption = action.getStringAttribute("caption"); - actionMap.put(key + "_c", caption); - if (action.hasAttribute("icon")) { - // TODO need some uri handling ?? - actionMap.put(key + "_i", client.translateVaadinUri(action - .getStringAttribute("icon"))); - } else { - actionMap.remove(key + "_i"); - } - } - - } - public String getActionCaption(String actionKey) { return actionMap.get(actionKey + "_c"); } @@ -232,94 +214,6 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, return actionMap.get(actionKey + "_i"); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Ensure correct implementation and let container manage caption - if (client.updateComponent(this, uidl, true)) { - return; - } - - rendering = true; - - this.client = client; - - if (uidl.hasAttribute("partialUpdate")) { - handleUpdate(uidl); - rendering = false; - return; - } - - paintableId = uidl.getId(); - - immediate = uidl.hasAttribute("immediate"); - - disabled = uidl.getBooleanAttribute("disabled"); - readonly = uidl.getBooleanAttribute("readonly"); - - dragMode = uidl.hasAttribute("dragMode") ? uidl - .getIntAttribute("dragMode") : 0; - - isNullSelectionAllowed = uidl.getBooleanAttribute("nullselect"); - - if (uidl.hasAttribute("alb")) { - bodyActionKeys = uidl.getStringArrayAttribute("alb"); - } - - body.clear(); - // clear out any references to nodes that no longer are attached - keyToNode.clear(); - 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())) { - updateDropHandler(childUidl); - continue; - } - childTree = new TreeNode(); - childTree.updateFromUIDL(childUidl, client); - 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"); - selectable = !"none".equals(selectMode); - isMultiselect = "multi".equals(selectMode); - - if (isMultiselect) { - multiSelectMode = uidl.getIntAttribute("multiselectmode"); - } - - 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 (lastSelection != null) { - lastSelection = keyToNode.get(lastSelection.key); - } - if (focusedNode != null) { - setFocusedNode(keyToNode.get(focusedNode.key)); - } - - if (lastSelection == null && focusedNode == null - && !selectedIds.isEmpty()) { - setFocusedNode(keyToNode.get(selectedIds.iterator().next())); - focusedNode.setFocused(false); - } - - rendering = false; - - } - /** * Returns the first root node of the tree or null if there are no root * nodes. @@ -366,7 +260,7 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, drag.getDropDetails().put("itemIdOver", currentMouseOverKey); if (currentMouseOverKey != null) { - TreeNode treeNode = keyToNode.get(currentMouseOverKey); + TreeNode treeNode = getNodeByKey(currentMouseOverKey); VerticalDropLocation detail = treeNode.getDropDetail(drag .getCurrentGwtEvent()); Boolean overTreeNode = null; @@ -388,7 +282,7 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, return treeNode == null ? null : treeNode.key; } - private void updateDropHandler(UIDL childUidl) { + void updateDropHandler(UIDL childUidl) { if (dropHandler == null) { dropHandler = new VAbstractDropHandler() { @@ -430,7 +324,7 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, .getDropDetails().get("detail"); if (curDetail == detail && newKey.equals(currentMouseOverKey)) { - keyToNode.get(newKey).emphasis(detail); + getNodeByKey(newKey).emphasis(detail); } /* * Else drag is already on a different @@ -452,7 +346,7 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, private void cleanUp() { if (currentMouseOverKey != null) { - keyToNode.get(currentMouseOverKey).emphasis(null); + getNodeByKey(currentMouseOverKey).emphasis(null); currentMouseOverKey = null; } } @@ -465,7 +359,7 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, @Override public VPaintableWidget getPaintable() { - return VTree.this; + return VPaintableMap.get(client).getPaintable(VTree.this); } public ApplicationConnection getApplicationConnection() { @@ -477,24 +371,12 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, dropHandler.updateAcceptRules(childUidl); } - private void handleUpdate(UIDL uidl) { - final TreeNode rootNode = keyToNode.get(uidl - .getStringAttribute("rootKey")); - if (rootNode != null) { - if (!rootNode.getState()) { - // expanding node happened server side - rootNode.setState(true, false); - } - rootNode.renderChildNodes(uidl.getChildIterator()); - } - } - public void setSelected(TreeNode treeNode, boolean selected) { if (selected) { if (!isMultiselect) { while (selectedIds.size() > 0) { final String id = selectedIds.iterator().next(); - final TreeNode oldSelection = keyToNode.get(id); + final TreeNode oldSelection = getNodeByKey(id); if (oldSelection != null) { // can be null if the node is not visible (parent // collapsed) @@ -563,15 +445,15 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, public String key; - private String[] actionKeys = null; + String[] actionKeys = null; - private boolean childrenLoaded; + boolean childrenLoaded; - private Element nodeCaptionDiv; + Element nodeCaptionDiv; protected Element nodeCaptionSpan; - private FlowPanel childNodeContainer; + FlowPanel childNodeContainer; private boolean open; @@ -760,14 +642,14 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, } if (target == nodeCaptionSpan) { - client.handleTooltipEvent(event, VTree.this, key); + client.handleWidgetTooltipEvent(event, VTree.this, key); } final boolean inCaption = target == nodeCaptionSpan || (icon != null && target == icon.getElement()); if (inCaption - && client - .hasEventListeners(VTree.this, ITEM_CLICK_EVENT_ID) + && client.hasWidgetEventListeners(VTree.this, + ITEM_CLICK_EVENT_ID) && (type == Event.ONDBLCLICK || type == Event.ONMOUSEUP)) { fireClick(event); @@ -828,7 +710,8 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, if (mouseDownEvent != null) { // start actual drag on slight move when mouse is down VTransferable t = new VTransferable(); - t.setDragSource(VTree.this); + t.setDragSource(VPaintableMap.get(client).getPaintable( + VTree.this)); t.setData("itemId", key); VDragEvent drag = VDragAndDropManager.get().startDrag( t, mouseDownEvent, true); @@ -944,71 +827,6 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, setWidget(childNodeContainer); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - setText(uidl.getStringAttribute("caption")); - key = uidl.getStringAttribute("key"); - - keyToNode.put(key, this); - - if (uidl.hasAttribute("al")) { - actionKeys = uidl.getStringArrayAttribute("al"); - } - - if (uidl.getTag().equals("node")) { - if (uidl.getChildCount() == 0) { - childNodeContainer.setVisible(false); - } else { - renderChildNodes(uidl.getChildIterator()); - childrenLoaded = true; - } - } else { - addStyleName(CLASSNAME + "-leaf"); - } - if (uidl.hasAttribute("style")) { - addStyleName(CLASSNAME + "-" + uidl.getStringAttribute("style")); - Widget.setStyleName(nodeCaptionDiv, CLASSNAME + "-caption-" - + uidl.getStringAttribute("style"), true); - childNodeContainer.addStyleName(CLASSNAME + "-children-" - + uidl.getStringAttribute("style")); - } - - String description = uidl.getStringAttribute("descr"); - if (description != null && client != null) { - // Set tooltip - TooltipInfo info = new TooltipInfo(description); - client.registerTooltip(VTree.this, key, info); - } else { - // Remove possible previous tooltip - client.registerTooltip(VTree.this, key, null); - } - - if (uidl.getBooleanAttribute("expanded") && !getState()) { - setState(true, false); - } - - if (uidl.getBooleanAttribute("selected")) { - setSelected(true); - // ensure that identifier is in selectedIds array (this may be a - // partial update) - selectedIds.add(key); - } - - if (uidl.hasAttribute("icon")) { - if (icon == null) { - icon = new Icon(client); - DOM.insertBefore(DOM.getFirstChild(nodeCaptionDiv), - icon.getElement(), nodeCaptionSpan); - } - icon.setUri(uidl.getStringAttribute("icon")); - } else { - if (icon != null) { - DOM.removeChild(DOM.getFirstChild(nodeCaptionDiv), - icon.getElement()); - icon = null; - } - } - } - public boolean isLeaf() { String[] styleNames = getStyleName().split(" "); for (String styleName : styleNames) { @@ -1019,7 +837,7 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, return false; } - private void setState(boolean state, boolean notifyServer) { + void setState(boolean state, boolean notifyServer) { if (open == state) { return; } @@ -1050,38 +868,14 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, } } - private boolean getState() { + boolean getState() { return open; } - private void setText(String text) { + void setText(String text) { DOM.setInnerText(nodeCaptionSpan, text); } - private void renderChildNodes(Iterator<?> i) { - childNodeContainer.clear(); - childNodeContainer.setVisible(true); - while (i.hasNext()) { - final UIDL childUidl = (UIDL) 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 = new TreeNode(); - childTree.updateFromUIDL(childUidl, client); - childNodeContainer.add(childTree); - if (!i.hasNext()) { - childTree - .addStyleDependentName(childTree.isLeaf() ? "leaf-last" - : "last"); - childTree.childNodeContainer.addStyleDependentName("last"); - } - } - childrenLoaded = true; - } - public boolean isChildrenLoaded() { return childrenLoaded; } @@ -1231,6 +1025,34 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, Util.scrollIntoViewVertically(nodeCaptionDiv); } + public void setIcon(String iconUrl) { + if (iconUrl != null) { + // Add icon if not present + if (icon == null) { + icon = new Icon(client); + DOM.insertBefore(DOM.getFirstChild(nodeCaptionDiv), + icon.getElement(), nodeCaptionSpan); + } + icon.setUri(iconUrl); + } else { + // Remove icon if present + if (icon != null) { + DOM.removeChild(DOM.getFirstChild(nodeCaptionDiv), + icon.getElement()); + icon = null; + } + } + } + + public void setNodeStyleName(String styleName) { + addStyleName(TreeNode.CLASSNAME + "-" + styleName); + setStyleName(nodeCaptionDiv, TreeNode.CLASSNAME + "-caption-" + + styleName, true); + childNodeContainer.addStyleName(TreeNode.CLASSNAME + "-children-" + + styleName); + + } + } public VDropHandler getDropHandler() { @@ -2243,7 +2065,22 @@ public class VTree extends FocusElementPanel implements VPaintableWidget, } } - public Widget getWidgetForPaintable() { - return this; + public void registerAction(String key, String caption, String iconUrl) { + actionMap.put(key + "_c", caption); + if (iconUrl != null) { + actionMap.put(key + "_i", iconUrl); + } else { + actionMap.remove(key + "_i"); + } + } + + public void registerNode(TreeNode treeNode) { + keyToNode.put(treeNode.key, treeNode); + } + + public void clearNodeToKeyMap() { + keyToNode.clear(); + } + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreePaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreePaintable.java new file mode 100644 index 0000000000..69aecebb06 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VTreePaintable.java @@ -0,0 +1,231 @@ +/* +@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 3a5d5f3b41..a7fe89017b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java @@ -26,8 +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.ApplicationConnection; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; @@ -157,18 +155,7 @@ public class VTwinColSelect extends VOptionGroupBase implements KeyDownHandler, return selectionsCaption; } - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Captions are updated before super call to ensure the widths are set - // correctly - if (!uidl.getBooleanAttribute("cached")) { - updateCaptions(uidl); - } - - super.updateFromUIDL(uidl, client); - } - - private void updateCaptions(UIDL uidl) { + protected void updateCaptions(UIDL uidl) { String leftCaption = (uidl.hasAttribute(ATTRIBUTE_LEFT_CAPTION) ? uidl .getStringAttribute(ATTRIBUTE_LEFT_CAPTION) : null); String rightCaption = (uidl.hasAttribute(ATTRIBUTE_RIGHT_CAPTION) ? uidl @@ -297,7 +284,7 @@ public class VTwinColSelect extends VOptionGroupBase implements KeyDownHandler, Set<String> movedItems = moveSelectedItems(options, selections); selectedKeys.addAll(movedItems); - client.updateVariable(id, "selected", + client.updateVariable(paintableId, "selected", selectedKeys.toArray(new String[selectedKeys.size()]), isImmediate()); } @@ -306,7 +293,7 @@ public class VTwinColSelect extends VOptionGroupBase implements KeyDownHandler, Set<String> movedItems = moveSelectedItems(selections, options); selectedKeys.removeAll(movedItems); - client.updateVariable(id, "selected", + client.updateVariable(paintableId, "selected", selectedKeys.toArray(new String[selectedKeys.size()]), isImmediate()); } @@ -628,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/VTwinColSelectPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelectPaintable.java new file mode 100644 index 0000000000..ce176113da --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VTwinColSelectPaintable.java @@ -0,0 +1,34 @@ +/* +@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 VTwinColSelectPaintable extends VOptionGroupBasePaintable { + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Captions are updated before super call to ensure the widths are set + // correctly + if (!uidl.getBooleanAttribute("cached")) { + getWidgetForPaintable().updateCaptions(uidl); + } + + super.updateFromUIDL(uidl, client); + } + + @Override + protected Widget createWidget() { + return GWT.create(VTwinColSelect.class); + } + + @Override + public VTwinColSelect getWidgetForPaintable() { + return (VTwinColSelect) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponent.java b/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponent.java index 5b3790f521..ad702430f6 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponent.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponent.java @@ -6,19 +6,14 @@ package com.vaadin.terminal.gwt.client.ui; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.VerticalPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.SimpleTree; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VUIDLBrowser; -public class VUnknownComponent extends Composite implements VPaintableWidget { +public class VUnknownComponent extends Composite { com.google.gwt.user.client.ui.Label caption = new com.google.gwt.user.client.ui.Label();; SimpleTree uidlTree; - private VerticalPanel panel; - private String serverClassName = "unkwnown"; + protected VerticalPanel panel; + protected String serverClassName = "unkwnown"; public VUnknownComponent() { panel = new VerticalPanel(); @@ -32,33 +27,7 @@ public class VUnknownComponent extends Composite implements VPaintableWidget { this.serverClassName = serverClassName; } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, false)) { - return; - } - setCaption("Widgetset does not contain implementation for " - + serverClassName - + ". Check its @ClientWidget mapping, widgetsets " - + "GWT module description file and re-compile your" - + " widgetset. In case you have downloaded a vaadin" - + " add-on package, you might want to refer to " - + "<a href='http://vaadin.com/using-addons'>add-on " - + "instructions</a>. Unrendered UIDL:"); - if (uidlTree != null) { - uidlTree.removeFromParent(); - } - - uidlTree = new VUIDLBrowser(uidl, client.getConfiguration()); - uidlTree.open(true); - uidlTree.setText("Unrendered UIDL"); - panel.add(uidlTree); - } - public void setCaption(String c) { caption.getElement().setInnerHTML(c); } - - public Widget getWidgetForPaintable() { - return this; - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponentPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponentPaintable.java new file mode 100644 index 0000000000..252d7528ca --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponentPaintable.java @@ -0,0 +1,52 @@ +/* +@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.VUIDLBrowser; + +public class VUnknownComponentPaintable extends VAbstractPaintableWidget { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, false)) { + return; + } + getWidgetForPaintable().setCaption( + "Widgetset does not contain implementation for " + + getWidgetForPaintable().serverClassName + + ". Check its @ClientWidget mapping, widgetsets " + + "GWT module description file and re-compile your" + + " widgetset. In case you have downloaded a vaadin" + + " add-on package, you might want to refer to " + + "<a href='http://vaadin.com/using-addons'>add-on " + + "instructions</a>. Unrendered UIDL:"); + if (getWidgetForPaintable().uidlTree != null) { + getWidgetForPaintable().uidlTree.removeFromParent(); + } + + getWidgetForPaintable().uidlTree = new VUIDLBrowser(uidl, + client.getConfiguration()); + getWidgetForPaintable().uidlTree.open(true); + getWidgetForPaintable().uidlTree.setText("Unrendered UIDL"); + getWidgetForPaintable().panel.add(getWidgetForPaintable().uidlTree); + } + + @Override + protected Widget createWidget() { + return GWT.create(VUnknownComponent.class); + } + + @Override + public VUnknownComponent getWidgetForPaintable() { + return (VUnknownComponent) super.getWidgetForPaintable(); + } + + public void setServerSideClassName(String serverClassName) { + getWidgetForPaintable().setServerSideClassName(serverClassName); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VUpload.java b/src/com/vaadin/terminal/gwt/client/ui/VUpload.java index 66894417f3..bc94ae317a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VUpload.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VUpload.java @@ -21,12 +21,9 @@ import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.Hidden; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.VTooltip; /** @@ -35,7 +32,7 @@ import com.vaadin.terminal.gwt.client.VTooltip; * events even though the upload component is already detached. * */ -public class VUpload extends SimplePanel implements VPaintableWidget { +public class VUpload extends SimplePanel { private final class MyFileUpload extends FileUpload { @Override @@ -73,19 +70,19 @@ public class VUpload extends SimplePanel implements VPaintableWidget { ApplicationConnection client; - private String paintableId; + protected String paintableId; /** * Button that initiates uploading */ - private final VButton submitButton; + protected final VButton submitButton; /** * When expecting big files, programmer may initiate some UI changes when * uploading the file starts. Bit after submitting file we'll visit the * server to check possible changes. */ - private Timer t; + protected Timer t; /** * some browsers tries to send form twice if submit is called in button @@ -100,11 +97,11 @@ public class VUpload extends SimplePanel implements VPaintableWidget { private Hidden maxfilesize = new Hidden(); - private FormElement element; + protected FormElement element; private com.google.gwt.dom.client.Element synthesizedFrame; - private int nextUploadId; + protected int nextUploadId; public VUpload() { super(com.google.gwt.dom.client.Document.get().createFormElement()); @@ -137,7 +134,7 @@ public class VUpload extends SimplePanel implements VPaintableWidget { @Override public void onBrowserEvent(Event event) { if ((event.getTypeInt() & VTooltip.TOOLTIP_EVENTS) > 0) { - client.handleTooltipEvent(event, this); + client.handleWidgetTooltipEvent(event, this); } super.onBrowserEvent(event); } @@ -147,43 +144,7 @@ public class VUpload extends SimplePanel implements VPaintableWidget { form.enctype = encoding; }-*/; - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, true)) { - return; - } - if (uidl.hasAttribute("notStarted")) { - t.schedule(400); - return; - } - if (uidl.hasAttribute("forceSubmit")) { - submit(); - return; - } - setImmediate(uidl.getBooleanAttribute("immediate")); - this.client = client; - paintableId = uidl.getId(); - nextUploadId = uidl.getIntAttribute("nextid"); - final String action = client.translateVaadinUri(uidl - .getStringVariable("action")); - element.setAction(action); - if (uidl.hasAttribute("buttoncaption")) { - submitButton.setText(uidl.getStringAttribute("buttoncaption")); - submitButton.setVisible(true); - } else { - submitButton.setVisible(false); - } - fu.setName(paintableId + "_file"); - - if (uidl.hasAttribute("disabled") || uidl.hasAttribute("readonly")) { - disableUpload(); - } else if (!uidl.getBooleanAttribute("state")) { - // Enable the button only if an upload is not in progress - enableUpload(); - ensureTargetFrame(); - } - } - - private void setImmediate(boolean booleanAttribute) { + protected void setImmediate(boolean booleanAttribute) { if (immediate != booleanAttribute) { immediate = booleanAttribute; if (immediate) { @@ -277,7 +238,7 @@ public class VUpload extends SimplePanel implements VPaintableWidget { }); } - private void submit() { + protected void submit() { if (fu.getFilename().length() == 0 || submitted || !enabled) { VConsole.log("Submit cancelled (disabled, no file or already submitted)"); return; @@ -315,15 +276,12 @@ public class VUpload extends SimplePanel implements VPaintableWidget { } } - private void ensureTargetFrame() { + protected void ensureTargetFrame() { if (synthesizedFrame == null) { // Attach a hidden IFrame to the form. This is the target iframe to - // which - // the form will be submitted. We have to create the iframe using - // innerHTML, - // because setting an iframe's 'name' property dynamically doesn't - // work on - // most browsers. + // which the form will be submitted. We have to create the iframe + // using innerHTML, because setting an iframe's 'name' property + // dynamically doesn't work on most browsers. DivElement dummy = Document.get().createDivElement(); dummy.setInnerHTML("<iframe src=\"javascript:''\" name='" + getFrameName() @@ -354,9 +312,4 @@ public class VUpload extends SimplePanel implements VPaintableWidget { synthesizedFrame = null; } } - - public Widget getWidgetForPaintable() { - return this; - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VUploadPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VUploadPaintable.java new file mode 100644 index 0000000000..7fd59fc176 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VUploadPaintable.java @@ -0,0 +1,62 @@ +/* +@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 VUploadPaintable extends VAbstractPaintableWidget { + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, true)) { + return; + } + if (uidl.hasAttribute("notStarted")) { + getWidgetForPaintable().t.schedule(400); + return; + } + if (uidl.hasAttribute("forceSubmit")) { + getWidgetForPaintable().submit(); + return; + } + getWidgetForPaintable().setImmediate( + uidl.getBooleanAttribute("immediate")); + getWidgetForPaintable().client = client; + getWidgetForPaintable().paintableId = uidl.getId(); + getWidgetForPaintable().nextUploadId = uidl.getIntAttribute("nextid"); + final String action = client.translateVaadinUri(uidl + .getStringVariable("action")); + getWidgetForPaintable().element.setAction(action); + if (uidl.hasAttribute("buttoncaption")) { + getWidgetForPaintable().submitButton.setText(uidl + .getStringAttribute("buttoncaption")); + getWidgetForPaintable().submitButton.setVisible(true); + } else { + getWidgetForPaintable().submitButton.setVisible(false); + } + getWidgetForPaintable().fu.setName(getWidgetForPaintable().paintableId + + "_file"); + + if (uidl.hasAttribute("disabled") || uidl.hasAttribute("readonly")) { + getWidgetForPaintable().disableUpload(); + } else if (!uidl.getBooleanAttribute("state")) { + // Enable the button only if an upload is not in progress + getWidgetForPaintable().enableUpload(); + getWidgetForPaintable().ensureTargetFrame(); + } + } + + @Override + protected Widget createWidget() { + return GWT.create(VUpload.class); + } + + @Override + public VUpload getWidgetForPaintable() { + return (VUpload) super.getWidgetForPaintable(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java new file mode 100644 index 0000000000..71c6d91c69 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java @@ -0,0 +1,20 @@ +/* +@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 new file mode 100644 index 0000000000..a2dc1fbbb2 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VVerticalSplitPanelPaintable.java @@ -0,0 +1,15 @@ +/* +@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 e3aba21096..ea5610cdaa 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -5,8 +5,6 @@ package com.vaadin.terminal.gwt.client.ui; import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; @@ -17,12 +15,10 @@ import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.event.dom.client.DomEvent.Type; import com.google.gwt.event.logical.shared.ResizeEvent; import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; -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; @@ -30,7 +26,6 @@ import com.google.gwt.user.client.Event; import com.google.gwt.user.client.History; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; @@ -56,15 +51,15 @@ public class VView extends SimplePanel implements Container, ResizeHandler, public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain"; - private String theme; + String theme; - private VPaintableWidget layout; + VPaintableWidget layout; - private final LinkedHashSet<VWindow> subWindows = new LinkedHashSet<VWindow>(); + final LinkedHashSet<VWindow> subWindows = new LinkedHashSet<VWindow>(); - private String id; + String id; - private ShortcutActionHandler actionHandler; + ShortcutActionHandler actionHandler; /** stored width for IE resize optimization */ private int width; @@ -72,7 +67,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, /** stored height for IE resize optimization */ private int height; - private ApplicationConnection connection; + ApplicationConnection connection; /** Identifies the click event */ public static final String CLICK_EVENT_ID = "click"; @@ -85,17 +80,17 @@ public class VView extends SimplePanel implements Container, ResizeHandler, */ private Timer resizeTimer; - private int scrollTop; + int scrollTop; - private int scrollLeft; + int scrollLeft; - private boolean rendering; + boolean rendering; - private boolean scrollable; + boolean scrollable; - private boolean immediate; + boolean immediate; - private boolean resizeLazy = false; + boolean resizeLazy = false; /** * Attribute name for the lazy resize setting . @@ -106,7 +101,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, * Reference to the parent frame/iframe. Null if there is no parent (i)frame * or if the application and parent frame are in different domains. */ - private Element parentFrame; + Element parentFrame; private HandlerRegistration historyHandlerRegistration; @@ -114,7 +109,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, * The current URI fragment, used to avoid sending updates if nothing has * changed. */ - private String currentFragment; + String currentFragment; /** * Listener for URI fragment changes. Notifies the server of the new value @@ -133,16 +128,6 @@ public class VView extends SimplePanel implements Container, ResizeHandler, } }; - private ClickEventHandler clickEventHandler = new ClickEventHandler(this, - VPanel.CLICK_EVENT_IDENTIFIER) { - - @Override - protected <H extends EventHandler> HandlerRegistration registerHandler( - H handler, Type<H> type) { - return addDomHandler(handler, type); - } - }; - private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200, new ScheduledCommand() { public void execute() { @@ -212,7 +197,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, /** * Used to reload host page on theme changes. */ - private static native void reloadHostPage() + static native void reloadHostPage() /*-{ $wnd.location.reload(); }-*/; @@ -223,7 +208,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, * @param script * Script to be executed. */ - private static native void eval(String script) + static native void eval(String script) /*-{ try { if (script == null) return; @@ -244,229 +229,6 @@ public class VView extends SimplePanel implements Container, ResizeHandler, .contains(ApplicationConnection.GENERATED_BODY_CLASSNAME); } - public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) { - rendering = true; - - id = uidl.getId(); - boolean firstPaint = connection == null; - connection = client; - - immediate = uidl.hasAttribute("immediate"); - resizeLazy = uidl.hasAttribute(RESIZE_LAZY); - String newTheme = uidl.getStringAttribute("theme"); - if (theme != null && !newTheme.equals(theme)) { - // Complete page refresh is needed due css can affect layout - // calculations etc - reloadHostPage(); - } else { - theme = newTheme; - } - if (uidl.hasAttribute("style")) { - setStyleName(getStylePrimaryName() + " " - + uidl.getStringAttribute("style")); - } - - clickEventHandler.handleEventHandlerRegistration(client); - - if (!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() { - 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; - 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 - rendering = false; - return; - } - - // Draw this application level window - UIDL childUidl = uidl.getChildUIDL(childIndex); - final VPaintableWidget lo = client.getPaintable(childUidl); - - if (layout != null) { - if (layout != lo) { - // remove old - client.unregisterPaintable(layout); - // add new - setWidget(lo.getWidgetForPaintable()); - layout = lo; - } - } else { - setWidget(lo.getWidgetForPaintable()); - layout = lo; - } - - layout.updateFromUIDL(childUidl, client); - if (!childUidl.getBooleanAttribute("cached")) { - updateParentFrameSize(); - } - - // Save currently open subwindows to track which will need to be closed - final HashSet<VWindow> removedSubWindows = new HashSet<VWindow>( - subWindows); - - // Handle other UIDL children - while ((childUidl = uidl.getChildUIDL(++childIndex)) != null) { - String tag = childUidl.getTag().intern(); - if (tag == "actions") { - if (actionHandler == null) { - actionHandler = new ShortcutActionHandler(id, client); - } - actionHandler.updateActionMap(childUidl); - } else if (tag == "execJS") { - String script = childUidl.getStringAttribute("script"); - 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 (subWindows.contains(w)) { - removedSubWindows.remove(w); - } else { - 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(w); - 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", connection); - - 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(this); - Window.addResizeHandler(this); - } - - onResize(); - - // finally set scroll position from UIDL - if (uidl.hasVariable("scrollTop")) { - scrollable = true; - scrollTop = uidl.getIntVariable("scrollTop"); - DOM.setElementPropertyInt(getElement(), "scrollTop", scrollTop); - scrollLeft = uidl.getIntVariable("scrollLeft"); - DOM.setElementPropertyInt(getElement(), "scrollLeft", scrollLeft); - } else { - 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(getElement()); - } - - scrollIntoView(uidl); - - if (uidl.hasAttribute(FRAGMENT_VARIABLE)) { - currentFragment = uidl.getStringAttribute(FRAGMENT_VARIABLE); - if (!currentFragment.equals(History.getToken())) { - History.newItem(currentFragment, true); - } - } else { - // Initial request for which the server doesn't yet have a fragment - // (and haven't shown any interest in getting one) - currentFragment = History.getToken(); - - // Include current fragment in the next request - client.updateVariable(id, FRAGMENT_VARIABLE, currentFragment, false); - } - - rendering = false; - } - /** * Tries to scroll paintable referenced from given UIDL snippet to be * visible. @@ -530,7 +292,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, /** * Called when a resize event is received. */ - private void onResize() { + void onResize() { /* * IE (pre IE9 at least) will give us some false resize events due to * problems with scrollbars. Firefox 3 might also produce some extra @@ -742,7 +504,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, } - private void updateParentFrameSize() { + void updateParentFrameSize() { if (parentFrame == null) { return; } @@ -754,7 +516,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, parentFrame.getStyle().setPropertyPx("height", childHeight); } - private static native Element getParentFrame() + static native Element getParentFrame() /*-{ try { var frameElement = $wnd.frameElement; @@ -769,10 +531,6 @@ public class VView extends SimplePanel implements Container, ResizeHandler, return null; }-*/; - public void updateCaption(VPaintableWidget component, UIDL uidl) { - // NOP Subwindows never draw caption for their first child (layout) - } - /** * Return an iterator for current subwindows. This method is meant for * testing purposes only. @@ -787,42 +545,6 @@ public class VView extends SimplePanel implements Container, ResizeHandler, return windows; } - public void init(String rootPanelId, - ApplicationConnection applicationConnection) { - DOM.sinkEvents(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(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(this); - - 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). - getElement().focus(); - } - - parentFrame = getParentFrame(); - } - public ShortcutActionHandler getShortcutActionHandler() { return actionHandler; } @@ -831,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 new file mode 100644 index 0000000000..94e7bfd9af --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VViewPaintable.java @@ -0,0 +1,338 @@ +/* +@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 95ab0dc773..d4c8f74605 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java @@ -13,21 +13,17 @@ import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.DomEvent.Type; import com.google.gwt.event.dom.client.FocusEvent; import com.google.gwt.event.dom.client.FocusHandler; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.event.dom.client.ScrollEvent; import com.google.gwt.event.dom.client.ScrollHandler; -import com.google.gwt.event.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.Element; 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.HasWidgets; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; @@ -38,10 +34,8 @@ import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.EventId; import com.vaadin.terminal.gwt.client.Focusable; import com.vaadin.terminal.gwt.client.RenderSpace; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VPaintableWidget; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener; import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; /** @@ -51,7 +45,7 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHan */ public class VWindow extends VOverlay implements Container, ShortcutActionHandlerOwner, ScrollHandler, KeyDownHandler, - FocusHandler, BlurHandler, BeforeShortcutActionListener, Focusable { + FocusHandler, BlurHandler, Focusable { /** * Minimum allowed height of a window. This refers to the content area, not @@ -88,9 +82,9 @@ public class VWindow extends VOverlay implements Container, public static final int Z_INDEX = 10000; - private VPaintableWidget layout; + VPaintableWidget layout; - private Element contents; + Element contents; private Element header; @@ -98,7 +92,7 @@ public class VWindow extends VOverlay implements Container, private Element resizeBox; - private final FocusableScrollPanel contentPanel = new FocusableScrollPanel(); + final FocusableScrollPanel contentPanel = new FocusableScrollPanel(); private boolean dragging; @@ -116,11 +110,11 @@ public class VWindow extends VOverlay implements Container, private int origH; - private Element closeBox; + Element closeBox; protected ApplicationConnection client; - private String id; + String id; ShortcutActionHandler shortcutHandler; @@ -130,13 +124,13 @@ public class VWindow extends VOverlay implements Container, /** Last known positiony read from UIDL or updated to application connection */ private int uidlPositionY = -1; - private boolean vaadinModality = false; + boolean vaadinModality = false; - private boolean resizable = true; + boolean resizable = true; private boolean draggable = true; - private boolean resizeLazy = false; + boolean resizeLazy = false; private Element modalityCurtain; private Element draggingCurtain; @@ -163,23 +157,13 @@ public class VWindow extends VOverlay implements Container, private String height; - private boolean immediate; + boolean immediate; private Element wrapper, wrapper2; - private ClickEventHandler clickEventHandler = new ClickEventHandler(this, - VPanel.CLICK_EVENT_IDENTIFIER) { + boolean visibilityChangesDisabled; - @Override - protected <H extends EventHandler> HandlerRegistration registerHandler( - H handler, Type<H> type) { - return addDomHandler(handler, type); - } - }; - - private boolean visibilityChangesDisabled; - - private int bringToFrontSequence = -1; + int bringToFrontSequence = -1; private VLazyExecutor delayedContentsSizeUpdater = new VLazyExecutor(200, new ScheduledCommand() { @@ -284,230 +268,12 @@ public class VWindow extends VOverlay implements Container, } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - id = uidl.getId(); - this.client = client; - - // Workaround needed for Testing Tools (GWT generates window DOM - // slightly different in different browsers). - DOM.setElementProperty(closeBox, "id", id + "_window_close"); - - if (uidl.hasAttribute("invisible")) { - hide(); - return; - } - - if (!uidl.hasAttribute("cached")) { - if (uidl.getBooleanAttribute("modal") != vaadinModality) { - setVaadinModality(!vaadinModality); - } - if (!isAttached()) { - setVisible(false); // hide until possible centering - show(); - } - if (uidl.getBooleanAttribute("resizable") != resizable) { - setResizable(!resizable); - } - resizeLazy = uidl.hasAttribute(VView.RESIZE_LAZY); - - 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. - setCaption(uidl.getStringAttribute("caption"), - uidl.getStringAttribute("icon")); - } - - visibilityChangesDisabled = true; - if (client.updateComponent(this, uidl, false)) { - return; - } - visibilityChangesDisabled = false; - - clickEventHandler.handleEventHandlerRegistration(client); - - immediate = uidl.hasAttribute("immediate"); - - 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; - } - 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); - 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 (layout != null) { - if (layout != lo) { - // remove old - client.unregisterPaintable(layout); - contentPanel.remove(layout.getWidgetForPaintable()); - // add new - if (!showingUrl) { - contentPanel.setWidget(lo.getWidgetForPaintable()); - } - layout = lo; - } - } else if (!showingUrl) { - contentPanel.setWidget(lo.getWidgetForPaintable()); - layout = lo; - } - - dynamicWidth = !uidl.hasAttribute("width"); - dynamicHeight = !uidl.hasAttribute("height"); - - layoutRelativeWidth = uidl.hasAttribute("layoutRelativeWidth"); - layoutRelativeHeight = uidl.hasAttribute("layoutRelativeHeight"); - - if (dynamicWidth && layoutRelativeWidth) { - /* - * Relative layout width, fix window width before rendering (width - * according to caption) - */ - setNaturalWidth(); - } - - layout.updateFromUIDL(childUidl, client); - if (!dynamicHeight && 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(this); - } - - /* - * No explicit width is set and the layout does not have relative width - * so fix the size according to the layout. - */ - if (dynamicWidth && !layoutRelativeWidth) { - setNaturalWidth(); - } - - if (dynamicHeight && layoutRelativeHeight) { - // Prevent resizing until height has been fixed - 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 (shortcutHandler == null) { - shortcutHandler = new ShortcutActionHandler(id, client); - } - shortcutHandler.updateActionMap(childUidl); - } - } - - } - - // setting scrollposition must happen after children is rendered - contentPanel.setScrollPosition(uidl.getIntVariable("scrollTop")); - 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 - centered = true; - center(); - } else { - // don't try to center the window anymore - centered = false; - } - updateShadowSizeAndPosition(); - setVisible(true); - - boolean sizeReduced = false; - // ensure window is not larger than browser window - if (getOffsetWidth() > Window.getClientWidth()) { - setWidth(Window.getClientWidth() + "px"); - sizeReduced = true; - } - if (getOffsetHeight() > Window.getClientHeight()) { - setHeight(Window.getClientHeight() + "px"); - sizeReduced = true; - } - - if (dynamicHeight && 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 = contents.getOffsetHeight() + getExtraHeight(); - int w = getElement().getOffsetWidth(); - - client.updateVariable(id, "height", h, false); - client.updateVariable(id, "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(this); - } - - Util.runWebkitOverflowAutoFix(contentPanel.getElement()); - - client.getView().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. - */ - contentPanel.focus(); - bringToFrontSequence = uidl.getIntAttribute("bringToFront"); - deferOrdering(); - } - } - /** * Calling this method will defer ordering algorithm, to order windows based * on servers bringToFront and modality instructions. Non changed windows * will be left intact. */ - private static void deferOrdering() { + static void deferOrdering() { if (!orderingDefered) { orderingDefered = true; Scheduler.get().scheduleFinally(new Command() { @@ -562,7 +328,7 @@ public class VWindow extends VOverlay implements Container, } } - private void setDraggable(boolean draggable) { + void setDraggable(boolean draggable) { if (this.draggable == draggable) { return; } @@ -573,7 +339,7 @@ public class VWindow extends VOverlay implements Container, } private void setCursorProperties() { - if (!this.draggable) { + if (!draggable) { header.getStyle().setProperty("cursor", "default"); footer.getStyle().setProperty("cursor", "default"); } else { @@ -582,7 +348,7 @@ public class VWindow extends VOverlay implements Container, } } - private void setNaturalWidth() { + void setNaturalWidth() { /* * Use max(layout width, window width) i.e layout content width or * caption width. We remove the previous set width so the width is @@ -676,7 +442,7 @@ public class VWindow extends VOverlay implements Container, super.hide(); } - private void setVaadinModality(boolean modality) { + void setVaadinModality(boolean modality) { vaadinModality = modality; if (vaadinModality) { if (isAttached()) { @@ -767,7 +533,7 @@ public class VWindow extends VOverlay implements Container, return curtain; } - private void setResizable(boolean resizability) { + void setResizable(boolean resizability) { resizable = resizability; if (resizability) { DOM.setElementProperty(footer, "className", CLASSNAME + "-footer"); @@ -832,7 +598,7 @@ public class VWindow extends VOverlay implements Container, if (client != null && header.isOrHasChild(target)) { // Handle window caption tooltips - client.handleTooltipEvent(event, this); + client.handleWidgetTooltipEvent(event, this); } if (resizing || resizeBox == target) { @@ -877,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: @@ -1088,12 +854,16 @@ public class VWindow extends VOverlay implements Container, private int extraH = 0; - private int getExtraHeight() { + int getExtraHeight() { extraH = header.getOffsetHeight() + footer.getOffsetHeight(); return extraH; } private void onDragEvent(Event event) { + if (!Util.isTouchEventOrLeftMouseButton(event)) { + return; + } + switch (DOM.eventGetType(event)) { case Event.ONTOUCHSTART: if (event.getTouches().length() > 1) { @@ -1205,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 ?? @@ -1214,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; @@ -1238,10 +1008,6 @@ public class VWindow extends VOverlay implements Container, return true; } - public void updateCaption(VPaintableWidget component, UIDL uidl) { - // NOP, window has own caption, layout captio not rendered - } - public ShortcutActionHandler getShortcutActionHandler() { return shortcutHandler; } @@ -1263,28 +1029,19 @@ public class VWindow extends VOverlay implements Container, } public void onBlur(BlurEvent event) { - if (client.hasEventListeners(this, EventId.BLUR)) { + if (client.hasWidgetEventListeners(this, EventId.BLUR)) { client.updateVariable(id, EventId.BLUR, "", true); } } public void onFocus(FocusEvent event) { - if (client.hasEventListeners(this, EventId.FOCUS)) { + if (client.hasWidgetEventListeners(this, EventId.FOCUS)) { client.updateVariable(id, EventId.FOCUS, "", true); } } - public void onBeforeShortcutAction(Event e) { - // NOP, nothing to update just avoid workaround ( causes excess - // blur/focus ) - } - public void focus() { 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 new file mode 100644 index 0000000000..633e28d0c3 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VWindowPaintable.java @@ -0,0 +1,299 @@ +/* +@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/CellBasedLayout.java b/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayout.java index 85f48859a4..9b38ba23ae 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayout.java @@ -3,6 +3,7 @@ */ package com.vaadin.terminal.gwt.client.ui.layout; +import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -17,7 +18,6 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.Container; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.ui.VMarginInfo; @@ -28,7 +28,7 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container protected ApplicationConnection client = null; - protected DivElement root; + public DivElement root; public static final int ORIENTATION_VERTICAL = 0; public static final int ORIENTATION_HORIZONTAL = 1; @@ -40,15 +40,15 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container protected final Spacing spacingFromCSS = new Spacing(12, 12); protected final Spacing activeSpacing = new Spacing(0, 0); - private boolean dynamicWidth; + boolean dynamicWidth; - private boolean dynamicHeight; + boolean dynamicHeight; private final DivElement clearElement = Document.get().createDivElement(); private String lastStyleName = ""; - private boolean marginsNeedsRecalculation = false; + boolean marginsNeedsRecalculation = false; protected String STYLENAME_SPACING = ""; protected String STYLENAME_MARGIN_TOP = ""; @@ -105,32 +105,6 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container return widgetToComponentContainer.containsKey(component); } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.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); - } - @Override public void setStyleName(String styleName) { super.setStyleName(styleName); @@ -159,27 +133,6 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container } } - private void handleDynamicDimensions(UIDL uidl) { - String w = uidl.hasAttribute("width") ? uidl - .getStringAttribute("width") : ""; - - String h = uidl.hasAttribute("height") ? uidl - .getStringAttribute("height") : ""; - - if (w.equals("")) { - dynamicWidth = true; - } else { - dynamicWidth = false; - } - - if (h.equals("")) { - dynamicHeight = true; - } else { - dynamicHeight = false; - } - - } - @Override public void setHeight(String height) { super.setHeight(height); @@ -195,7 +148,7 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container } } - protected void addOrMoveChild(ChildComponentContainer childComponent, + public void addOrMoveChild(ChildComponentContainer childComponent, int position) { if (childComponent.getParent() == this) { if (getWidgetIndex(childComponent) != position) { @@ -235,33 +188,22 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container } - protected ChildComponentContainer getComponentContainer(Widget child) { + public Collection<ChildComponentContainer> getComponentContainers() { + return widgetToComponentContainer.values(); + } + + public ChildComponentContainer getComponentContainer(Widget child) { return widgetToComponentContainer.get(child); } - protected boolean isDynamicWidth() { + public boolean isDynamicWidth() { return dynamicWidth; } - protected boolean isDynamicHeight() { + public boolean isDynamicHeight() { return dynamicHeight; } - private void updateMarginAndSpacingInfo(UIDL uidl) { - if (!uidl.hasAttribute("invisible")) { - int bitMask = uidl.getIntAttribute("margins"); - if (activeMarginsInfo.getBitMask() != bitMask) { - activeMarginsInfo = new VMarginInfo(bitMask); - marginsNeedsRecalculation = true; - } - boolean spacing = uidl.getBooleanAttribute("spacing"); - if (spacing != spacingEnabled) { - marginsNeedsRecalculation = true; - spacingEnabled = spacing; - } - } - } - private static DivElement measurement; private static DivElement measurement2; private static DivElement measurement3; @@ -342,7 +284,7 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container return (ChildComponentContainer) getChildren().get(0); } - protected void removeChildrenAfter(int pos) { + public void removeChildrenAfter(int pos) { // Remove all children after position "pos" but leave the clear element // in place diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayoutPaintable.java new file mode 100644 index 0000000000..c41652fb3d --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayoutPaintable.java @@ -0,0 +1,84 @@ +/* +@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 35d3247f9b..c1678369b3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java +++ b/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java @@ -17,7 +17,6 @@ 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.Element; -import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; @@ -27,12 +26,10 @@ import com.google.gwt.user.client.ui.RichTextArea; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.VPaintableWidget; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.ui.Field; import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener; import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; /** @@ -41,9 +38,8 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHan * @author Vaadin Ltd. * */ -public class VRichTextArea extends Composite implements VPaintableWidget, Field, - ChangeHandler, BlurHandler, KeyPressHandler, KeyDownHandler, - BeforeShortcutActionListener, Focusable { +public class VRichTextArea extends Composite implements Field, ChangeHandler, + BlurHandler, KeyPressHandler, KeyDownHandler, Focusable { /** * The input node CSS classname. @@ -54,13 +50,13 @@ public class VRichTextArea extends Composite implements VPaintableWidget, Field, protected ApplicationConnection client; - private boolean immediate = false; + boolean immediate = false; - private RichTextArea rta; + RichTextArea rta; private VRichTextToolbar formatter; - private HTML html = new HTML(); + HTML html = new HTML(); private final FlowPanel fp = new FlowPanel(); @@ -69,15 +65,15 @@ public class VRichTextArea extends Composite implements VPaintableWidget, Field, private int extraHorizontalPixels = -1; private int extraVerticalPixels = -1; - private int maxLength = -1; + int maxLength = -1; private int toolbarNaturalWidth = 500; - private HandlerRegistration keyPressHandler; + HandlerRegistration keyPressHandler; private ShortcutActionHandlerOwner hasShortcutActionHandler; - private String currentValue = ""; + String currentValue = ""; private boolean readOnly = false; @@ -127,48 +123,7 @@ public class VRichTextArea extends Composite implements VPaintableWidget, Field, } } - public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) { - this.client = client; - id = uidl.getId(); - - if (uidl.hasVariable("text")) { - currentValue = uidl.getStringVariable("text"); - if (rta.isAttached()) { - rta.setHTML(currentValue); - } else { - html.setHTML(currentValue); - } - } - if (!uidl.hasAttribute("cached")) { - setEnabled(!uidl.getBooleanAttribute("disabled")); - } - - if (client.updateComponent(this, uidl, true)) { - return; - } - - setReadOnly(uidl.getBooleanAttribute("readonly")); - immediate = uidl.getBooleanAttribute("immediate"); - int newMaxLength = uidl.hasAttribute("maxLength") ? uidl - .getIntAttribute("maxLength") : -1; - if (newMaxLength >= 0) { - if (maxLength == -1) { - keyPressHandler = rta.addKeyPressHandler(this); - } - maxLength = newMaxLength; - } else if (maxLength != -1) { - getElement().setAttribute("maxlength", ""); - maxLength = -1; - keyPressHandler.removeHandler(); - } - - if (uidl.hasAttribute("selectAll")) { - selectAll(); - } - - } - - private void selectAll() { + void selectAll() { /* * There is a timing issue if trying to select all immediately on first * render. Simple deferred command is not enough. Using Timer with @@ -190,7 +145,7 @@ public class VRichTextArea extends Composite implements VPaintableWidget, Field, }.schedule(320); } - private void setReadOnly(boolean b) { + void setReadOnly(boolean b) { if (isReadOnly() != b) { swapEditableArea(); readOnly = b; @@ -346,7 +301,8 @@ public class VRichTextArea extends Composite implements VPaintableWidget, Field, if (shortcutHandler != null) { shortcutHandler .handleKeyboardEvent(com.google.gwt.user.client.Event - .as(event.getNativeEvent()), this); + .as(event.getNativeEvent()), + VPaintableMap.get(client).getPaintable(this)); } } @@ -364,10 +320,6 @@ public class VRichTextArea extends Composite implements VPaintableWidget, Field, return hasShortcutActionHandler; } - public void onBeforeShortcutAction(Event e) { - synchronizeContentToServer(); - } - public int getTabIndex() { return rta.getTabIndex(); } @@ -394,8 +346,4 @@ public class VRichTextArea extends Composite implements VPaintableWidget, Field, 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 new file mode 100644 index 0000000000..ec83f294f2 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextAreaPaintable.java @@ -0,0 +1,79 @@ +/* +@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/ComponentSizeValidator.java b/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java index fad5220eb7..d3095512bb 100644 --- a/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java +++ b/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java @@ -18,6 +18,7 @@ import java.util.logging.Logger; import com.vaadin.terminal.Sizeable.Unit; import com.vaadin.ui.AbstractOrderedLayout; +import com.vaadin.ui.AbstractSplitPanel; import com.vaadin.ui.Component; import com.vaadin.ui.ComponentContainer; import com.vaadin.ui.CustomComponent; @@ -26,7 +27,6 @@ import com.vaadin.ui.GridLayout; import com.vaadin.ui.GridLayout.Area; import com.vaadin.ui.Layout; import com.vaadin.ui.Panel; -import com.vaadin.ui.SplitPanel; import com.vaadin.ui.TabSheet; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; @@ -449,7 +449,7 @@ public class ComponentSizeValidator implements Serializable { } } - if (parent instanceof Panel || parent instanceof SplitPanel + if (parent instanceof Panel || parent instanceof AbstractSplitPanel || parent instanceof TabSheet || parent instanceof CustomComponent) { // height undefined, we know how how component works and no @@ -552,7 +552,7 @@ public class ComponentSizeValidator implements Serializable { * the component width */ return hasNonRelativeWidthComponent((Form) parent); - } else if (parent instanceof SplitPanel + } else if (parent instanceof AbstractSplitPanel || parent instanceof TabSheet || parent instanceof CustomComponent) { // FIXME Could we use com.vaadin package name here and 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/terminal/gwt/widgetsetutils/WidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java index aeef1951c8..2150748b54 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java @@ -24,7 +24,7 @@ import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; import com.vaadin.terminal.Paintable; import com.vaadin.terminal.gwt.client.VPaintableWidget; -import com.vaadin.terminal.gwt.client.ui.VView; +import com.vaadin.terminal.gwt.client.ui.VViewPaintable; import com.vaadin.ui.ClientWidget; import com.vaadin.ui.ClientWidget.LoadStyle; import com.vaadin.ui.Root; @@ -258,7 +258,7 @@ public class WidgetMapGenerator extends Generator { if (widgetsWithInstantiator.contains(clientClass)) { continue; } - if (clientClass == VView.class) { + if (clientClass == VViewPaintable.class) { // VView's are not instantiated by widgetset continue; } @@ -374,7 +374,7 @@ public class WidgetMapGenerator extends Generator { sourceWriter.print("else "); } sourceWriter - .println("return com.vaadin.terminal.gwt.client.ui.VUnknownComponent.class;"); + .println("return com.vaadin.terminal.gwt.client.ui.VUnknownComponentPaintable.class;"); sourceWriter.outdent(); sourceWriter.println("}"); @@ -384,7 +384,7 @@ public class WidgetMapGenerator extends Generator { Class<? extends Paintable> class1) { Class<? extends com.vaadin.terminal.gwt.client.VPaintableWidget> clientClass; if (Root.class == class1) { - clientClass = VView.class; + clientClass = VViewPaintable.class; } else { ClientWidget annotation = class1.getAnnotation(ClientWidget.class); clientClass = annotation.value(); diff --git a/src/com/vaadin/ui/AbsoluteLayout.java b/src/com/vaadin/ui/AbsoluteLayout.java index d6f9897664..c75073c02b 100644 --- a/src/com/vaadin/ui/AbsoluteLayout.java +++ b/src/com/vaadin/ui/AbsoluteLayout.java @@ -17,7 +17,7 @@ import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Sizeable; import com.vaadin.terminal.gwt.client.EventId; -import com.vaadin.terminal.gwt.client.ui.VAbsoluteLayout; +import com.vaadin.terminal.gwt.client.ui.VAbsoluteLayoutPaintable; /** * AbsoluteLayout is a layout implementation that mimics html absolute @@ -25,7 +25,7 @@ import com.vaadin.terminal.gwt.client.ui.VAbsoluteLayout; * */ @SuppressWarnings("serial") -@ClientWidget(VAbsoluteLayout.class) +@ClientWidget(VAbsoluteLayoutPaintable.class) public class AbsoluteLayout extends AbstractLayout implements LayoutClickNotifier { 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/AbstractSplitPanel.java b/src/com/vaadin/ui/AbstractSplitPanel.java index e0a2d24aaa..e03e73a781 100644 --- a/src/com/vaadin/ui/AbstractSplitPanel.java +++ b/src/com/vaadin/ui/AbstractSplitPanel.java @@ -15,7 +15,7 @@ import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Sizeable; import com.vaadin.terminal.gwt.client.MouseEventDetails; -import com.vaadin.terminal.gwt.client.ui.VSplitPanel; +import com.vaadin.terminal.gwt.client.ui.VAbstractSplitPanelPaintable; import com.vaadin.tools.ReflectTools; /** @@ -43,7 +43,7 @@ public abstract class AbstractSplitPanel extends AbstractLayout { private boolean locked = false; - private static final String SPLITTER_CLICK_EVENT = VSplitPanel.SPLITTER_CLICK_EVENT_IDENTIFIER; + private static final String SPLITTER_CLICK_EVENT = VAbstractSplitPanelPaintable.SPLITTER_CLICK_EVENT_IDENTIFIER; /** * Modifiable and Serializable Iterator for the components, used by diff --git a/src/com/vaadin/ui/Accordion.java b/src/com/vaadin/ui/Accordion.java index 5cf805615c..4ee75326ff 100644 --- a/src/com/vaadin/ui/Accordion.java +++ b/src/com/vaadin/ui/Accordion.java @@ -3,7 +3,7 @@ */ package com.vaadin.ui; -import com.vaadin.terminal.gwt.client.ui.VAccordion; +import com.vaadin.terminal.gwt.client.ui.VAccordionPaintable; /** * An accordion is a component similar to a {@link TabSheet}, but with a @@ -16,8 +16,7 @@ import com.vaadin.terminal.gwt.client.ui.VAccordion; * * @see TabSheet */ -@SuppressWarnings("serial") -@ClientWidget(VAccordion.class) +@ClientWidget(VAccordionPaintable.class) public class Accordion extends TabSheet { } diff --git a/src/com/vaadin/ui/ComboBox.java b/src/com/vaadin/ui/ComboBox.java index 0fb8b9d873..013fe6ab85 100644 --- a/src/com/vaadin/ui/ComboBox.java +++ b/src/com/vaadin/ui/ComboBox.java @@ -1,129 +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;
-
-/**
- * A filtering dropdown single-select. Suitable for newItemsAllowed, but it's
- * turned of by default to avoid mistakes. Items are filtered based on user
- * input, and loaded dynamically ("lazy-loading") from the server. You can turn
- * on newItemsAllowed and change filtering mode (and also turn it off), but you
- * can not turn on multi-select mode.
- *
- */
-@SuppressWarnings("serial")
-@ClientWidget(VFilterSelect.class)
-public class ComboBox extends Select {
-
- private String inputPrompt = null;
-
- /**
- * If text input is not allowed, the ComboBox behaves like a pretty
- * NativeSelect - the user can not enter any text and clicking the text
- * field opens the drop down with options
- */
- private boolean textInputAllowed = true;
-
- public ComboBox() {
- setMultiSelect(false);
- setNewItemsAllowed(false);
- }
-
- public ComboBox(String caption, Collection<?> options) {
- super(caption, options);
- setMultiSelect(false);
- setNewItemsAllowed(false);
- }
-
- public ComboBox(String caption, Container dataSource) {
- super(caption, dataSource);
- setMultiSelect(false);
- setNewItemsAllowed(false);
- }
-
- public ComboBox(String caption) {
- super(caption);
- setMultiSelect(false);
- setNewItemsAllowed(false);
- }
-
- @Override
- public void setMultiSelect(boolean multiSelect) {
- if (multiSelect && !isMultiSelect()) {
- throw new UnsupportedOperationException("Multiselect not supported");
- }
- super.setMultiSelect(multiSelect);
- }
-
- /**
- * Gets the current input prompt.
- *
- * @see #setInputPrompt(String)
- * @return the current input prompt, or null if not enabled
- */
- public String getInputPrompt() {
- return inputPrompt;
- }
-
- /**
- * Sets the input prompt - a textual prompt that is displayed when the
- * select would otherwise be empty, to prompt the user for input.
- *
- * @param inputPrompt
- * the desired input prompt, or null to disable
- */
- public void setInputPrompt(String inputPrompt) {
- this.inputPrompt = inputPrompt;
- requestRepaint();
- }
-
- @Override
- public void paintContent(PaintTarget target) throws PaintException {
- if (inputPrompt != null) {
- target.addAttribute("prompt", inputPrompt);
- }
- super.paintContent(target);
-
- if (!textInputAllowed) {
- target.addAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT, true);
- }
- }
-
- /**
- * Sets whether it is possible to input text into the field or whether the
- * field area of the component is just used to show what is selected. By
- * disabling text input, the comboBox will work in the same way as a
- * {@link NativeSelect}
- *
- * @see #isTextInputAllowed()
- *
- * @param textInputAllowed
- * true to allow entering text, false to just show the current
- * selection
- */
- public void setTextInputAllowed(boolean textInputAllowed) {
- this.textInputAllowed = textInputAllowed;
- requestRepaint();
- }
-
- /**
- * Returns true if the user can enter text into the field to either filter
- * the selections or enter a new value if {@link #isNewItemsAllowed()}
- * returns true. If text input is disabled, the comboBox will work in the
- * same way as a {@link NativeSelect}
- *
- * @return
- */
- public boolean isTextInputAllowed() {
- return textInputAllowed;
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.ui; + +import java.util.Collection; + +import com.vaadin.data.Container; +import com.vaadin.terminal.PaintException; +import com.vaadin.terminal.PaintTarget; +import com.vaadin.terminal.gwt.client.ui.VFilterSelect; +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/CssLayout.java b/src/com/vaadin/ui/CssLayout.java index b9432df6b6..ebfee5a787 100644 --- a/src/com/vaadin/ui/CssLayout.java +++ b/src/com/vaadin/ui/CssLayout.java @@ -14,7 +14,7 @@ import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Paintable; import com.vaadin.terminal.gwt.client.EventId; -import com.vaadin.terminal.gwt.client.ui.VCssLayout; +import com.vaadin.terminal.gwt.client.ui.VCssLayoutPaintable; /** * CssLayout is a layout component that can be used in browser environment only. @@ -57,7 +57,7 @@ import com.vaadin.terminal.gwt.client.ui.VCssLayout; * @since 6.1 brought in from "FastLayouts" incubator project * */ -@ClientWidget(VCssLayout.class) +@ClientWidget(VCssLayoutPaintable.class) public class CssLayout extends AbstractLayout implements LayoutClickNotifier { private static final String CLICK_EVENT = EventId.LAYOUT_CLICK; diff --git a/src/com/vaadin/ui/CustomComponent.java b/src/com/vaadin/ui/CustomComponent.java index 0f891ac0fa..7aba34b6bb 100644 --- a/src/com/vaadin/ui/CustomComponent.java +++ b/src/com/vaadin/ui/CustomComponent.java @@ -9,7 +9,7 @@ import java.util.Iterator; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.VCustomComponent; +import com.vaadin.terminal.gwt.client.ui.VCustomComponentPaintable; import com.vaadin.ui.ClientWidget.LoadStyle; /** @@ -27,7 +27,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(value = VCustomComponent.class, loadStyle = LoadStyle.EAGER) +@ClientWidget(value = VCustomComponentPaintable.class, loadStyle = LoadStyle.EAGER) public class CustomComponent extends AbstractComponentContainer { /** diff --git a/src/com/vaadin/ui/CustomField.java b/src/com/vaadin/ui/CustomField.java index 72f863ca8b..73f9050363 100644 --- a/src/com/vaadin/ui/CustomField.java +++ b/src/com/vaadin/ui/CustomField.java @@ -11,7 +11,7 @@ import java.util.Iterator; import com.vaadin.data.Property; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.VCustomComponent; +import com.vaadin.terminal.gwt.client.ui.VCustomComponentPaintable; /** * A {@link Field} whose UI content can be constructed by the user, enabling the @@ -35,7 +35,7 @@ import com.vaadin.terminal.gwt.client.ui.VCustomComponent; * * @since 7.0 */ -@ClientWidget(VCustomComponent.class) +@ClientWidget(VCustomComponentPaintable.class) public abstract class CustomField<T> extends AbstractField<T> implements ComponentContainer { diff --git a/src/com/vaadin/ui/CustomLayout.java b/src/com/vaadin/ui/CustomLayout.java index dc473fb549..fb0c369969 100644 --- a/src/com/vaadin/ui/CustomLayout.java +++ b/src/com/vaadin/ui/CustomLayout.java @@ -12,7 +12,7 @@ import java.util.Iterator; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.VCustomLayout; +import com.vaadin.terminal.gwt.client.ui.VCustomLayoutPaintable; /** * <p> @@ -44,7 +44,7 @@ import com.vaadin.terminal.gwt.client.ui.VCustomLayout; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(VCustomLayout.class) +@ClientWidget(VCustomLayoutPaintable.class) public class CustomLayout extends AbstractLayout { private static final int BUFFER_SIZE = 10000; diff --git a/src/com/vaadin/ui/DateField.java b/src/com/vaadin/ui/DateField.java index b3f54a0a78..9589414f4d 100644 --- a/src/com/vaadin/ui/DateField.java +++ b/src/com/vaadin/ui/DateField.java @@ -27,7 +27,7 @@ import com.vaadin.event.FieldEvents.FocusListener; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.gwt.client.ui.VDateField; -import com.vaadin.terminal.gwt.client.ui.VPopupCalendar; +import com.vaadin.terminal.gwt.client.ui.VPopupCalendarPaintable; /** * <p> @@ -50,7 +50,7 @@ import com.vaadin.terminal.gwt.client.ui.VPopupCalendar; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(VPopupCalendar.class) +@ClientWidget(VPopupCalendarPaintable.class) public class DateField extends AbstractField<Date> implements FieldEvents.BlurNotifier, FieldEvents.FocusNotifier { diff --git a/src/com/vaadin/ui/DragAndDropWrapper.java b/src/com/vaadin/ui/DragAndDropWrapper.java index c6522f15c7..512b70e118 100644 --- a/src/com/vaadin/ui/DragAndDropWrapper.java +++ b/src/com/vaadin/ui/DragAndDropWrapper.java @@ -22,11 +22,12 @@ import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.StreamVariable; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper; +import com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapperPaintable; import com.vaadin.terminal.gwt.client.ui.dd.HorizontalDropLocation; import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; @SuppressWarnings("serial") -@ClientWidget(VDragAndDropWrapper.class) +@ClientWidget(VDragAndDropWrapperPaintable.class) public class DragAndDropWrapper extends CustomComponent implements DropTarget, DragSource { diff --git a/src/com/vaadin/ui/Embedded.java b/src/com/vaadin/ui/Embedded.java index dc14cc6ef8..f655b55711 100644 --- a/src/com/vaadin/ui/Embedded.java +++ b/src/com/vaadin/ui/Embedded.java @@ -14,7 +14,7 @@ import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; import com.vaadin.terminal.gwt.client.MouseEventDetails; -import com.vaadin.terminal.gwt.client.ui.VEmbedded; +import com.vaadin.terminal.gwt.client.ui.VEmbeddedPaintable; /** * Component for embedding external objects. @@ -25,10 +25,10 @@ import com.vaadin.terminal.gwt.client.ui.VEmbedded; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(VEmbedded.class) +@ClientWidget(VEmbeddedPaintable.class) public class Embedded extends AbstractComponent { - private static final String CLICK_EVENT = VEmbedded.CLICK_EVENT_IDENTIFIER; + private static final String CLICK_EVENT = VEmbeddedPaintable.CLICK_EVENT_IDENTIFIER; /** * General object type. diff --git a/src/com/vaadin/ui/Form.java b/src/com/vaadin/ui/Form.java index 47210e1aed..c79804c7e7 100644 --- a/src/com/vaadin/ui/Form.java +++ b/src/com/vaadin/ui/Form.java @@ -27,7 +27,7 @@ import com.vaadin.terminal.CompositeErrorMessage; import com.vaadin.terminal.ErrorMessage; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.VForm; +import com.vaadin.terminal.gwt.client.ui.VFormPaintable; /** * Form component provides easy way of creating and managing sets fields. @@ -62,8 +62,7 @@ import com.vaadin.terminal.gwt.client.ui.VForm; * @deprecated Use {@link FieldGroup} instead of {@link Form} for more * flexibility. */ -@SuppressWarnings("serial") -@ClientWidget(VForm.class) +@ClientWidget(VFormPaintable.class) @Deprecated public class Form extends AbstractField<Object> implements Item.Editor, Buffered, Item, Validatable, Action.Notifier { diff --git a/src/com/vaadin/ui/FormLayout.java b/src/com/vaadin/ui/FormLayout.java index eecf3372bb..c5c211924e 100644 --- a/src/com/vaadin/ui/FormLayout.java +++ b/src/com/vaadin/ui/FormLayout.java @@ -4,7 +4,7 @@ package com.vaadin.ui; -import com.vaadin.terminal.gwt.client.ui.VFormLayout; +import com.vaadin.terminal.gwt.client.ui.VFormLayoutPaintable; /** * FormLayout is used by {@link Form} to layout fields. It may also be used @@ -21,7 +21,7 @@ import com.vaadin.terminal.gwt.client.ui.VFormLayout; * bottom are by default on. * */ -@ClientWidget(VFormLayout.class) +@ClientWidget(VFormLayoutPaintable.class) public class FormLayout extends AbstractOrderedLayout { public FormLayout() { diff --git a/src/com/vaadin/ui/GridLayout.java b/src/com/vaadin/ui/GridLayout.java index 24a57d462b..4588328345 100644 --- a/src/com/vaadin/ui/GridLayout.java +++ b/src/com/vaadin/ui/GridLayout.java @@ -18,7 +18,7 @@ import com.vaadin.event.LayoutEvents.LayoutClickNotifier; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.gwt.client.EventId; -import com.vaadin.terminal.gwt.client.ui.VGridLayout; +import com.vaadin.terminal.gwt.client.ui.VGridLayoutPaintable; /** * <p> @@ -41,7 +41,7 @@ import com.vaadin.terminal.gwt.client.ui.VGridLayout; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(VGridLayout.class) +@ClientWidget(VGridLayoutPaintable.class) public class GridLayout extends AbstractLayout implements Layout.AlignmentHandler, Layout.SpacingHandler, LayoutClickNotifier { diff --git a/src/com/vaadin/ui/HorizontalLayout.java b/src/com/vaadin/ui/HorizontalLayout.java index ed1cad8184..ba685ec410 100644 --- a/src/com/vaadin/ui/HorizontalLayout.java +++ b/src/com/vaadin/ui/HorizontalLayout.java @@ -3,7 +3,7 @@ */ package com.vaadin.ui; -import com.vaadin.terminal.gwt.client.ui.VHorizontalLayout; +import com.vaadin.terminal.gwt.client.ui.VHorizontalLayoutPaintable; import com.vaadin.ui.ClientWidget.LoadStyle; /** @@ -18,7 +18,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; * @since 5.3 */ @SuppressWarnings("serial") -@ClientWidget(value = VHorizontalLayout.class, loadStyle = LoadStyle.EAGER) +@ClientWidget(value = VHorizontalLayoutPaintable.class, loadStyle = LoadStyle.EAGER) public class HorizontalLayout extends AbstractOrderedLayout { public HorizontalLayout() { diff --git a/src/com/vaadin/ui/HorizontalSplitPanel.java b/src/com/vaadin/ui/HorizontalSplitPanel.java index d9368635df..d4a1e7cc0e 100644 --- a/src/com/vaadin/ui/HorizontalSplitPanel.java +++ b/src/com/vaadin/ui/HorizontalSplitPanel.java @@ -3,7 +3,7 @@ */ package com.vaadin.ui; -import com.vaadin.terminal.gwt.client.ui.VSplitPanelHorizontal; +import com.vaadin.terminal.gwt.client.ui.VHorizontalSplitPanelPaintable; import com.vaadin.ui.ClientWidget.LoadStyle; /** @@ -29,7 +29,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; * @VERSION@ * @since 6.5 */ -@ClientWidget(value = VSplitPanelHorizontal.class, loadStyle = LoadStyle.EAGER) +@ClientWidget(value = VHorizontalSplitPanelPaintable.class, loadStyle = LoadStyle.EAGER) public class HorizontalSplitPanel extends AbstractSplitPanel { public HorizontalSplitPanel() { super(); diff --git a/src/com/vaadin/ui/InlineDateField.java b/src/com/vaadin/ui/InlineDateField.java index 0bf7924d34..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.VDateFieldCalendar;
-
-/**
- * <p>
- * A date entry component, which displays the actual date selector inline.
- *
- * </p>
- *
- * @see DateField
- * @see PopupDateField
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 5.0
- */
-@ClientWidget(VDateFieldCalendar.class)
-public class InlineDateField extends DateField {
-
- public InlineDateField() {
- super();
- }
-
- public InlineDateField(Property dataSource) throws IllegalArgumentException {
- super(dataSource);
- }
-
- public InlineDateField(String caption, Date value) {
- super(caption, value);
- }
-
- public InlineDateField(String caption, Property dataSource) {
- super(caption, dataSource);
- }
-
- public InlineDateField(String caption) {
- super(caption);
- }
-
-}
+/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.ui; + +import java.util.Date; + +import com.vaadin.data.Property; +import com.vaadin.terminal.gwt.client.ui.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/Link.java b/src/com/vaadin/ui/Link.java index 99d742ec17..0b11151be7 100644 --- a/src/com/vaadin/ui/Link.java +++ b/src/com/vaadin/ui/Link.java @@ -7,7 +7,7 @@ package com.vaadin.ui; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.client.ui.VLink; +import com.vaadin.terminal.gwt.client.ui.VLinkPaintable; /** * Link is used to create external or internal URL links. @@ -18,7 +18,7 @@ import com.vaadin.terminal.gwt.client.ui.VLink; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(VLink.class) +@ClientWidget(VLinkPaintable.class) public class Link extends AbstractComponent { /* Target window border type constant: No window border */ diff --git a/src/com/vaadin/ui/ListSelect.java b/src/com/vaadin/ui/ListSelect.java index 5c879f00f5..cf0e6773f2 100644 --- a/src/com/vaadin/ui/ListSelect.java +++ b/src/com/vaadin/ui/ListSelect.java @@ -9,14 +9,14 @@ 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.VListSelect; +import com.vaadin.terminal.gwt.client.ui.VListSelectPaintable; /** * This is a simple list select without, for instance, support for new items, * lazyloading, and other advanced features. */ @SuppressWarnings("serial") -@ClientWidget(VListSelect.class) +@ClientWidget(VListSelectPaintable.class) public class ListSelect extends AbstractSelect { private int columns = 0; diff --git a/src/com/vaadin/ui/NativeSelect.java b/src/com/vaadin/ui/NativeSelect.java index e701d212b4..b0070426ad 100644 --- a/src/com/vaadin/ui/NativeSelect.java +++ b/src/com/vaadin/ui/NativeSelect.java @@ -9,7 +9,7 @@ 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.VNativeSelect; +import com.vaadin.terminal.gwt.client.ui.VNativeSelectPaintable; /** * This is a simple drop-down select without, for instance, support for @@ -18,7 +18,7 @@ import com.vaadin.terminal.gwt.client.ui.VNativeSelect; * better choice. */ @SuppressWarnings("serial") -@ClientWidget(VNativeSelect.class) +@ClientWidget(VNativeSelectPaintable.class) public class NativeSelect extends AbstractSelect { // width in characters, mimics TextField diff --git a/src/com/vaadin/ui/OptionGroup.java b/src/com/vaadin/ui/OptionGroup.java index 884e58824a..ddacc31554 100644 --- a/src/com/vaadin/ui/OptionGroup.java +++ b/src/com/vaadin/ui/OptionGroup.java @@ -18,12 +18,13 @@ import com.vaadin.event.FieldEvents.FocusListener; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.gwt.client.ui.VOptionGroup; +import com.vaadin.terminal.gwt.client.ui.VOptionGroupPaintable; /** * Configures select to be used as an option group. */ @SuppressWarnings("serial") -@ClientWidget(VOptionGroup.class) +@ClientWidget(VOptionGroupPaintable.class) public class OptionGroup extends AbstractSelect implements FieldEvents.BlurNotifier, FieldEvents.FocusNotifier { diff --git a/src/com/vaadin/ui/Panel.java b/src/com/vaadin/ui/Panel.java index a69413c28b..390279a62f 100644 --- a/src/com/vaadin/ui/Panel.java +++ b/src/com/vaadin/ui/Panel.java @@ -16,7 +16,7 @@ import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Scrollable; import com.vaadin.terminal.gwt.client.MouseEventDetails; -import com.vaadin.terminal.gwt.client.ui.VPanel; +import com.vaadin.terminal.gwt.client.ui.VPanelPaintable; import com.vaadin.ui.Component.Focusable; import com.vaadin.ui.themes.Reindeer; import com.vaadin.ui.themes.Runo; @@ -30,12 +30,12 @@ import com.vaadin.ui.themes.Runo; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(VPanel.class) +@ClientWidget(VPanelPaintable.class) public class Panel extends AbstractComponentContainer implements Scrollable, ComponentContainer.ComponentAttachListener, ComponentContainer.ComponentDetachListener, Action.Notifier, Focusable { - private static final String CLICK_EVENT = VPanel.CLICK_EVENT_IDENTIFIER; + private static final String CLICK_EVENT = VPanelPaintable.CLICK_EVENT_IDENTIFIER; /** * Removes extra decorations from the Panel. @@ -559,6 +559,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable, /* * ACTIONS */ + @Override protected ActionManager getActionManager() { if (actionManager == null) { actionManager = new ActionManager(this); diff --git a/src/com/vaadin/ui/PasswordField.java b/src/com/vaadin/ui/PasswordField.java index 99874147d5..d5be4f378d 100644 --- a/src/com/vaadin/ui/PasswordField.java +++ b/src/com/vaadin/ui/PasswordField.java @@ -4,13 +4,13 @@ package com.vaadin.ui; import com.vaadin.data.Property; -import com.vaadin.terminal.gwt.client.ui.VPasswordField; +import com.vaadin.terminal.gwt.client.ui.VPasswordFieldPaintable; /** * A field that is used to enter secret text information like passwords. The * entered text is not displayed on the screen. */ -@ClientWidget(VPasswordField.class) +@ClientWidget(VPasswordFieldPaintable.class) public class PasswordField extends AbstractTextField { /** 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(); + } + +} diff --git a/src/com/vaadin/ui/PopupView.java b/src/com/vaadin/ui/PopupView.java index fcad727510..5637ef69d7 100644 --- a/src/com/vaadin/ui/PopupView.java +++ b/src/com/vaadin/ui/PopupView.java @@ -10,7 +10,7 @@ import java.util.Map; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.VPopupView; +import com.vaadin.terminal.gwt.client.ui.VPopupViewPaintable; /** * @@ -22,7 +22,7 @@ import com.vaadin.terminal.gwt.client.ui.VPopupView; * @author Vaadin Ltd. */ @SuppressWarnings("serial") -@ClientWidget(VPopupView.class) +@ClientWidget(VPopupViewPaintable.class) public class PopupView extends AbstractComponentContainer { private Content content; diff --git a/src/com/vaadin/ui/ProgressIndicator.java b/src/com/vaadin/ui/ProgressIndicator.java index cc17333cc4..9152a3adab 100644 --- a/src/com/vaadin/ui/ProgressIndicator.java +++ b/src/com/vaadin/ui/ProgressIndicator.java @@ -8,7 +8,7 @@ import com.vaadin.data.Property; import com.vaadin.data.util.ObjectProperty; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.VProgressIndicator; +import com.vaadin.terminal.gwt.client.ui.VProgressIndicatorPaintable; /** * <code>ProgressIndicator</code> is component that shows user state of a @@ -25,7 +25,7 @@ import com.vaadin.terminal.gwt.client.ui.VProgressIndicator; * @since 4 */ @SuppressWarnings("serial") -@ClientWidget(VProgressIndicator.class) +@ClientWidget(VProgressIndicatorPaintable.class) public class ProgressIndicator extends AbstractField<Number> implements Property.Viewer, Property.ValueChangeListener { diff --git a/src/com/vaadin/ui/RichTextArea.java b/src/com/vaadin/ui/RichTextArea.java index ea22a6b54b..240063caf3 100644 --- a/src/com/vaadin/ui/RichTextArea.java +++ b/src/com/vaadin/ui/RichTextArea.java @@ -10,7 +10,7 @@ import java.util.Map; import com.vaadin.data.Property; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.richtextarea.VRichTextArea; +import com.vaadin.terminal.gwt.client.ui.richtextarea.VRichTextAreaPaintable; import com.vaadin.ui.ClientWidget.LoadStyle; /** @@ -20,7 +20,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; * {@link RichTextArea} may produce unexpected results as formatting is counted * into length of field. */ -@ClientWidget(value = VRichTextArea.class, loadStyle = LoadStyle.LAZY) +@ClientWidget(value = VRichTextAreaPaintable.class, loadStyle = LoadStyle.LAZY) public class RichTextArea extends AbstractField<String> { /** diff --git a/src/com/vaadin/ui/Select.java b/src/com/vaadin/ui/Select.java index 0ea331dc40..38785f3ab9 100644 --- a/src/com/vaadin/ui/Select.java +++ b/src/com/vaadin/ui/Select.java @@ -23,7 +23,7 @@ import com.vaadin.event.FieldEvents.FocusListener; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.client.ui.VFilterSelect; +import com.vaadin.terminal.gwt.client.ui.VFilterSelectPaintable; /** * <p> @@ -44,7 +44,7 @@ import com.vaadin.terminal.gwt.client.ui.VFilterSelect; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(VFilterSelect.class) +@ClientWidget(VFilterSelectPaintable.class) public class Select extends AbstractSelect implements AbstractSelect.Filtering, FieldEvents.BlurNotifier, FieldEvents.FocusNotifier { diff --git a/src/com/vaadin/ui/SplitPanel.java b/src/com/vaadin/ui/SplitPanel.java deleted file mode 100644 index bae1bf7ce0..0000000000 --- a/src/com/vaadin/ui/SplitPanel.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.VSplitPanelHorizontal; -import com.vaadin.ui.ClientWidget.LoadStyle; - -/** - * SplitPanel. - * - * <code>SplitPanel</code> is a component container, that can contain two - * components (possibly containers) which are split by divider element. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 5.0 - * @deprecated in 6.5. Use {@link HorizontalSplitPanel} or - * {@link VerticalSplitPanel} instead. - */ -@Deprecated -@ClientWidget(value = VSplitPanelHorizontal.class, loadStyle = LoadStyle.EAGER) -public class SplitPanel extends AbstractSplitPanel { - - /* Predefined orientations */ - - /** - * Components are to be laid out vertically. - */ - public static final int ORIENTATION_VERTICAL = 0; - - /** - * Components are to be laid out horizontally. - */ - public static final int ORIENTATION_HORIZONTAL = 1; - - /** - * Orientation of the layout. - */ - private int orientation; - - /** - * Creates a new split panel. The orientation of the panels is - * <code>ORIENTATION_VERTICAL</code>. - */ - public SplitPanel() { - super(); - orientation = ORIENTATION_VERTICAL; - setSizeFull(); - } - - /** - * Create a new split panels. The orientation of the panel is given as - * parameters. - * - * @param orientation - * the Orientation of the layout. - */ - public SplitPanel(int orientation) { - this(); - setOrientation(orientation); - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - - if (orientation == ORIENTATION_VERTICAL) { - target.addAttribute("vertical", true); - } - - } - - /** - * Gets the orientation of the split panel. - * - * @return the Value of property orientation. - * - */ - public int getOrientation() { - return orientation; - } - - /** - * Sets the orientation of the split panel. - * - * @param orientation - * the New value of property orientation. - */ - public void setOrientation(int orientation) { - - // Checks the validity of the argument - if (orientation < ORIENTATION_VERTICAL - || orientation > ORIENTATION_HORIZONTAL) { - throw new IllegalArgumentException(); - } - - this.orientation = orientation; - requestRepaint(); - } - -} diff --git a/src/com/vaadin/ui/TabSheet.java b/src/com/vaadin/ui/TabSheet.java index a13c336943..e256c51cfd 100644 --- a/src/com/vaadin/ui/TabSheet.java +++ b/src/com/vaadin/ui/TabSheet.java @@ -20,6 +20,7 @@ import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; import com.vaadin.terminal.gwt.client.ui.VTabsheet; +import com.vaadin.terminal.gwt.client.ui.VTabsheetPaintable; import com.vaadin.terminal.gwt.server.CommunicationManager; import com.vaadin.ui.themes.Reindeer; import com.vaadin.ui.themes.Runo; @@ -53,8 +54,7 @@ import com.vaadin.ui.themes.Runo; * @VERSION@ * @since 3.0 */ -@SuppressWarnings("serial") -@ClientWidget(VTabsheet.class) +@ClientWidget(VTabsheetPaintable.class) public class TabSheet extends AbstractComponentContainer { /** diff --git a/src/com/vaadin/ui/TextArea.java b/src/com/vaadin/ui/TextArea.java index e1e5aeabd4..a5e6bb5630 100644 --- a/src/com/vaadin/ui/TextArea.java +++ b/src/com/vaadin/ui/TextArea.java @@ -7,12 +7,12 @@ package com.vaadin.ui; import com.vaadin.data.Property; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.VTextArea; +import com.vaadin.terminal.gwt.client.ui.VTextAreaPaintable; /** * A text field that supports multi line editing. */ -@ClientWidget(VTextArea.class) +@ClientWidget(VTextAreaPaintable.class) public class TextArea extends AbstractTextField { private static final int DEFAULT_ROWS = 5; diff --git a/src/com/vaadin/ui/TextField.java b/src/com/vaadin/ui/TextField.java index e154aaad17..a3d873336c 100644 --- a/src/com/vaadin/ui/TextField.java +++ b/src/com/vaadin/ui/TextField.java @@ -5,7 +5,7 @@ package com.vaadin.ui; import com.vaadin.data.Property; -import com.vaadin.terminal.gwt.client.ui.VTextField; +import com.vaadin.terminal.gwt.client.ui.VTextFieldPaintable; import com.vaadin.ui.ClientWidget.LoadStyle; /** @@ -29,7 +29,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(value = VTextField.class, loadStyle = LoadStyle.EAGER) +@ClientWidget(value = VTextFieldPaintable.class, loadStyle = LoadStyle.EAGER) public class TextField extends AbstractTextField { /** diff --git a/src/com/vaadin/ui/Tree.java b/src/com/vaadin/ui/Tree.java index 554afda97c..4ea66cc6bf 100644 --- a/src/com/vaadin/ui/Tree.java +++ b/src/com/vaadin/ui/Tree.java @@ -45,6 +45,7 @@ import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.ui.VTree; +import com.vaadin.terminal.gwt.client.ui.VTreePaintable; import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers; import com.vaadin.terminal.gwt.client.ui.dd.VTargetInSubtree; import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; @@ -60,7 +61,7 @@ import com.vaadin.tools.ReflectTools; * @since 3.0 */ @SuppressWarnings({ "serial", "deprecation" }) -@ClientWidget(VTree.class) +@ClientWidget(VTreePaintable.class) public class Tree extends AbstractSelect implements Container.Hierarchical, Action.Container, ItemClickSource, ItemClickNotifier, DragSource, DropTarget { diff --git a/src/com/vaadin/ui/TwinColSelect.java b/src/com/vaadin/ui/TwinColSelect.java index 1c1fe07a5c..fbdd825a66 100644 --- a/src/com/vaadin/ui/TwinColSelect.java +++ b/src/com/vaadin/ui/TwinColSelect.java @@ -10,13 +10,14 @@ import com.vaadin.data.Container; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.gwt.client.ui.VTwinColSelect; +import com.vaadin.terminal.gwt.client.ui.VTwinColSelectPaintable; /** * Multiselect component with two lists: left side for available items and right * side for selected items. */ @SuppressWarnings("serial") -@ClientWidget(VTwinColSelect.class) +@ClientWidget(VTwinColSelectPaintable.class) public class TwinColSelect extends AbstractSelect { private int columns = 0; diff --git a/src/com/vaadin/ui/Upload.java b/src/com/vaadin/ui/Upload.java index 9d684291a5..08a8023ad5 100644 --- a/src/com/vaadin/ui/Upload.java +++ b/src/com/vaadin/ui/Upload.java @@ -15,7 +15,7 @@ import java.util.Map; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.StreamVariable.StreamingProgressEvent; -import com.vaadin.terminal.gwt.client.ui.VUpload; +import com.vaadin.terminal.gwt.client.ui.VUploadPaintable; import com.vaadin.terminal.gwt.server.NoInputStreamException; import com.vaadin.terminal.gwt.server.NoOutputStreamException; import com.vaadin.ui.ClientWidget.LoadStyle; @@ -61,7 +61,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(value = VUpload.class, loadStyle = LoadStyle.LAZY) +@ClientWidget(value = VUploadPaintable.class, loadStyle = LoadStyle.LAZY) public class Upload extends AbstractComponent implements Component.Focusable { /** diff --git a/src/com/vaadin/ui/VerticalLayout.java b/src/com/vaadin/ui/VerticalLayout.java index c40aeaea30..0c5de43bbd 100644 --- a/src/com/vaadin/ui/VerticalLayout.java +++ b/src/com/vaadin/ui/VerticalLayout.java @@ -3,7 +3,7 @@ */ package com.vaadin.ui; -import com.vaadin.terminal.gwt.client.ui.VVerticalLayout; +import com.vaadin.terminal.gwt.client.ui.VVerticalLayoutPaintable; import com.vaadin.ui.ClientWidget.LoadStyle; /** @@ -19,7 +19,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; * @since 5.3 */ @SuppressWarnings("serial") -@ClientWidget(value = VVerticalLayout.class, loadStyle = LoadStyle.EAGER) +@ClientWidget(value = VVerticalLayoutPaintable.class, loadStyle = LoadStyle.EAGER) public class VerticalLayout extends AbstractOrderedLayout { public VerticalLayout() { diff --git a/src/com/vaadin/ui/VerticalSplitPanel.java b/src/com/vaadin/ui/VerticalSplitPanel.java index 699bd9287c..46e9d681e8 100644 --- a/src/com/vaadin/ui/VerticalSplitPanel.java +++ b/src/com/vaadin/ui/VerticalSplitPanel.java @@ -3,7 +3,7 @@ */ package com.vaadin.ui; -import com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical; +import com.vaadin.terminal.gwt.client.ui.VVerticalSplitPanelPaintable; import com.vaadin.ui.ClientWidget.LoadStyle; /** @@ -23,7 +23,7 @@ import com.vaadin.ui.ClientWidget.LoadStyle; * </pre> * */ -@ClientWidget(value = VSplitPanelVertical.class, loadStyle = LoadStyle.EAGER) +@ClientWidget(value = VVerticalSplitPanelPaintable.class, loadStyle = LoadStyle.EAGER) public class VerticalSplitPanel extends AbstractSplitPanel { public VerticalSplitPanel() { diff --git a/src/com/vaadin/ui/Window.java b/src/com/vaadin/ui/Window.java index a860d371b0..e6c8642b84 100644 --- a/src/com/vaadin/ui/Window.java +++ b/src/com/vaadin/ui/Window.java @@ -23,7 +23,7 @@ import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Sizeable; import com.vaadin.terminal.gwt.client.ui.VView; -import com.vaadin.terminal.gwt.client.ui.VWindow; +import com.vaadin.terminal.gwt.client.ui.VWindowPaintable; /** * A component that represents an application (browser native) window or a sub @@ -71,7 +71,7 @@ import com.vaadin.terminal.gwt.client.ui.VWindow; * @since 3.0 */ @SuppressWarnings("serial") -@ClientWidget(VWindow.class) +@ClientWidget(VWindowPaintable.class) public class Window extends Panel implements FocusNotifier, BlurNotifier { /** |