diff options
author | Marc Englund <marc.englund@itmill.com> | 2007-11-19 14:03:05 +0000 |
---|---|---|
committer | Marc Englund <marc.englund@itmill.com> | 2007-11-19 14:03:05 +0000 |
commit | f2e3722df9676436680afc0f1991e91e1696fb99 (patch) | |
tree | 6f255ff78abaf96f1e71a1f2c9ecd3b66647f4a2 /src/com/itmill/toolkit/ui/Form.java | |
parent | 93291f532db9d545cf2a8dd98e2671f27cd197b0 (diff) | |
download | vaadin-framework-f2e3722df9676436680afc0f1991e91e1696fb99.tar.gz vaadin-framework-f2e3722df9676436680afc0f1991e91e1696fb99.zip |
MASS REFORMAT.
According to http://toolkit.intra.itmill.com/trac/itmilltoolkit/wiki/CodingConventions
svn changeset:2864/svn branch:trunk
Diffstat (limited to 'src/com/itmill/toolkit/ui/Form.java')
-rw-r--r-- | src/com/itmill/toolkit/ui/Form.java | 1736 |
1 files changed, 888 insertions, 848 deletions
diff --git a/src/com/itmill/toolkit/ui/Form.java b/src/com/itmill/toolkit/ui/Form.java index 784b97e040..765fcc15b0 100644 --- a/src/com/itmill/toolkit/ui/Form.java +++ b/src/com/itmill/toolkit/ui/Form.java @@ -34,7 +34,11 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; -import com.itmill.toolkit.data.*; +import com.itmill.toolkit.data.Buffered; +import com.itmill.toolkit.data.Item; +import com.itmill.toolkit.data.Property; +import com.itmill.toolkit.data.Validatable; +import com.itmill.toolkit.data.Validator; import com.itmill.toolkit.data.Validator.InvalidValueException; import com.itmill.toolkit.data.util.BeanItem; import com.itmill.toolkit.terminal.PaintException; @@ -72,851 +76,887 @@ import com.itmill.toolkit.terminal.PaintTarget; * @since 3.0 */ public class Form extends AbstractField implements Item.Editor, Buffered, Item, - Validatable { - - private Object propertyValue; - - /** - * Layout of the form. - */ - private Layout layout; - - /** - * Item connected to this form as datasource. - */ - private Item itemDatasource; - - /** - * Ordered list of property ids in this editor. - */ - private LinkedList propertyIds = new LinkedList(); - - /** - * Current buffered source exception. - */ - private Buffered.SourceException currentBufferedSourceException = null; - - /** - * Is the form in write trough mode. - */ - private boolean writeThrough = true; - - /** - * Is the form in read trough mode. - */ - private boolean readThrough = true; - - /** - * Mapping from propertyName to corresponding field. - */ - private HashMap fields = new HashMap(); - - /** - * Field factory for this form. - */ - private FieldFactory fieldFactory; - - /** - * Registered Validators. - */ - private LinkedList validators; - - /** - * Visible item properties. - */ - private Collection visibleItemProperties; - - /** - * Contructs a new form with default layout. - * - * <p> - * By default the form uses <code>OrderedLayout</code> with - * <code>form</code>-style. - * </p> - * - * @param formLayout - * the layout of the form. - */ - public Form() { - this(null); - } - - /** - * Contructs a new form with given layout. - * - * @param formLayout - * the layout of the form. - */ - public Form(Layout formLayout) { - this(formLayout, new BaseFieldFactory()); - } - - /** - * Contructs a new form with given layout and FieldFactory. - * - * @param formLayout - * the layout of the form. - * @param fieldFactory - * the FieldFactory of the form. - */ - public Form(Layout formLayout, FieldFactory fieldFactory) { - super(); - setLayout(formLayout); - setFieldFactory(fieldFactory); - } - - /* Documented in interface */ - public String getTag() { - return "form"; - } - - /* Documented in interface */ - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - layout.paint(target); - } - - /* - * Commit changes to the data source Don't add a JavaDoc comment here, we - * use the default one from the interface. - */ - public void commit() throws Buffered.SourceException { - - LinkedList problems = null; - - // Try to commit all - for (Iterator i = propertyIds.iterator(); i.hasNext();) - try { - Field f = ((Field) fields.get(i.next())); - // Commit only non-readonly fields. - if (!f.isReadOnly()) { - f.commit(); - } - } catch (Buffered.SourceException e) { - if (problems == null) - problems = new LinkedList(); - problems.add(e); - } - - // No problems occurred - if (problems == null) { - if (currentBufferedSourceException != null) { - currentBufferedSourceException = null; - requestRepaint(); - } - return; - } - - // Commit problems - Throwable[] causes = new Throwable[problems.size()]; - int index = 0; - for (Iterator i = problems.iterator(); i.hasNext();) - causes[index++] = (Throwable) i.next(); - Buffered.SourceException e = new Buffered.SourceException(this, causes); - currentBufferedSourceException = e; - requestRepaint(); - throw e; - } - - /* - * Discards local changes and refresh values from the data source Don't add - * a JavaDoc comment here, we use the default one from the interface. - */ - public void discard() throws Buffered.SourceException { - - LinkedList problems = null; - - // Try to discard all changes - for (Iterator i = propertyIds.iterator(); i.hasNext();) - try { - ((Field) fields.get(i.next())).discard(); - } catch (Buffered.SourceException e) { - if (problems == null) - problems = new LinkedList(); - problems.add(e); - } - - // No problems occurred - if (problems == null) { - if (currentBufferedSourceException != null) { - currentBufferedSourceException = null; - requestRepaint(); - } - return; - } - - // Discards problems occurred - Throwable[] causes = new Throwable[problems.size()]; - int index = 0; - for (Iterator i = problems.iterator(); i.hasNext();) - causes[index++] = (Throwable) i.next(); - Buffered.SourceException e = new Buffered.SourceException(this, causes); - currentBufferedSourceException = e; - requestRepaint(); - throw e; - } - - /* - * Is the object modified but not committed? Don't add a JavaDoc comment - * here, we use the default one from the interface. - */ - public boolean isModified() { - for (Iterator i = propertyIds.iterator(); i.hasNext();) { - Field f = (Field) fields.get(i.next()); - if (f != null && f.isModified()) - return true; - - } - return false; - } - - /* - * Is the editor in a read-through mode? Don't add a JavaDoc comment here, - * we use the default one from the interface. - */ - public boolean isReadThrough() { - return readThrough; - } - - /* - * Is the editor in a write-through mode? Don't add a JavaDoc comment here, - * we use the default one from the interface. - */ - public boolean isWriteThrough() { - return writeThrough; - } - - /* - * Sets the editor's read-through mode to the specified status. Don't add a - * JavaDoc comment here, we use the default one from the interface. - */ - public void setReadThrough(boolean readThrough) { - if (readThrough != this.readThrough) { - this.readThrough = readThrough; - for (Iterator i = propertyIds.iterator(); i.hasNext();) - ((Field) fields.get(i.next())).setReadThrough(readThrough); - } - } - - /* - * Sets the editor's read-through mode to the specified status. Don't add a - * JavaDoc comment here, we use the default one from the interface. - */ - public void setWriteThrough(boolean writeThrough) { - if (writeThrough != this.writeThrough) { - this.writeThrough = writeThrough; - for (Iterator i = propertyIds.iterator(); i.hasNext();) - ((Field) fields.get(i.next())).setWriteThrough(writeThrough); - } - } - - /** - * Adds a new property to form and create corresponding field. - * - * @see com.itmill.toolkit.data.Item#addItemProperty(Object, Property) - */ - public boolean addItemProperty(Object id, Property property) { - - // Checks inputs - if (id == null || property == null) - throw new NullPointerException("Id and property must be non-null"); - - // Checks that the property id is not reserved - if (propertyIds.contains(id)) - return false; - - // Gets suitable field - Field field = this.fieldFactory.createField(property, this); - if (field == null) - return false; - - // Configures the field - try { - field.setPropertyDataSource(property); - String caption = id.toString(); - if (caption.length() > 50) - caption = caption.substring(0, 47) + "..."; - if (caption.length() > 0) - caption = "" + Character.toUpperCase(caption.charAt(0)) - + caption.substring(1, caption.length()); - field.setCaption(caption); - } catch (Throwable ignored) { - return false; - } - - addField(id, field); - - return true; - } - - /** - * Adds the field to form. - * - * <p> - * The property id must not be already used in the form. - * </p> - * - * <p> - * This field is added to the form layout in the default position (the - * position used by {@link Layout#addComponent(Component)} method. In the - * special case that the underlying layout is a custom layout, string - * representation of the property id is used instead of the default - * location. - * </p> - * - * @param propertyId - * the Property id the the field. - * @param field - * the New field added to the form. - */ - public void addField(Object propertyId, Field field) { - - if (propertyId != null && field != null) { - this.dependsOn(field); - field.dependsOn(this); - fields.put(propertyId, field); - propertyIds.addLast(propertyId); - field.setReadThrough(readThrough); - field.setWriteThrough(writeThrough); - - if (layout instanceof CustomLayout) - ((CustomLayout) layout).addComponent(field, propertyId - .toString()); - else - layout.addComponent(field); - - requestRepaint(); - } - } - - /** - * The property identified by the property id. - * - * <p> - * The property data source of the field specified with property id is - * returned. If there is a (with specified property id) having no data - * source, the field is returned instead of the data source. - * </p> - * - * @see com.itmill.toolkit.data.Item#getItemProperty(Object) - */ - public Property getItemProperty(Object id) { - Field field = (Field) fields.get(id); - if (field == null) - return null; - Property property = field.getPropertyDataSource(); - - if (property != null) - return property; - else - return field; - } - - /** - * Gets the field identified by the propertyid. - * - * @param propertyId - * the id of the property. - */ - public Field getField(Object propertyId) { - return (Field) fields.get(propertyId); - } - - /* Documented in interface */ - public Collection getItemPropertyIds() { - return Collections.unmodifiableCollection(propertyIds); - } - - /** - * Removes the property and corresponding field from the form. - * - * @see com.itmill.toolkit.data.Item#removeItemProperty(Object) - */ - public boolean removeItemProperty(Object id) { - - Field field = (Field) fields.get(id); - - if (field != null) { - propertyIds.remove(id); - fields.remove(id); - this.removeDirectDependency(field); - field.removeDirectDependency(this); - layout.removeComponent(field); - return true; - } - - return false; - } - - /** - * Removes all properties and fields from the form. - * - * @return the Success of the operation. Removal of all fields succeeded if - * (and only if) the return value is <code>true</code>. - */ - public boolean removeAllProperties() { - Object[] properties = propertyIds.toArray(); - boolean success = true; - - for (int i = 0; i < properties.length; i++) - if (!removeItemProperty(properties[i])) - success = false; - - return success; - } - - /* Documented in the interface */ - public Item getItemDataSource() { - return itemDatasource; - } - - /** - * Sets the item datasource for the form. - * - * <p> - * Setting item datasource clears any fields, the form might contain and - * adds all the properties as fields to the form. - * </p> - * - * @see com.itmill.toolkit.data.Item.Viewer#setItemDataSource(Item) - */ - public void setItemDataSource(Item newDataSource) { - setItemDataSource(newDataSource, newDataSource != null ? newDataSource - .getItemPropertyIds() : null); - } - - /** - * Set the item datasource for the form, but limit the form contents to - * specified properties of the item. - * - * <p> - * Setting item datasource clears any fields, the form might contain and - * adds the specified the properties as fields to the form, in the specified - * order. - * </p> - * - * @see com.itmill.toolkit.data.Item.Viewer#setItemDataSource(Item) - */ - public void setItemDataSource(Item newDataSource, Collection propertyIds) { - - // Removes all fields first from the form - removeAllProperties(); - - // Sets the datasource - itemDatasource = newDataSource; - - // If the new datasource is null, just set null datasource - if (itemDatasource == null) - return; - - // Adds all the properties to this form - for (Iterator i = propertyIds.iterator(); i.hasNext();) { - Object id = i.next(); - Property property = itemDatasource.getItemProperty(id); - if (id != null && property != null) { - Field f = this.fieldFactory.createField(itemDatasource, id, - this); - if (f != null) { - f.setPropertyDataSource(property); - addField(id, f); - } - } - } - } - - /** - * Gets the layout of the form. - * - * <p> - * By default form uses <code>OrderedLayout</code> with <code>form</code>-style. - * </p> - * - * @return the Layout of the form. - */ - public Layout getLayout() { - return layout; - } - - /** - * Sets the layout of the form. - * - * <p> - * By default form uses <code>OrderedLayout</code> with <code>form</code>-style. - * </p> - * - * @param newLayout - * the Layout of the form. - */ - public void setLayout(Layout newLayout) { - - // Use orderedlayout by default - if (newLayout == null) { - newLayout = new FormLayout(); - } - - // Move components from previous layout - if (this.layout != null) { - newLayout.moveComponentsFrom(this.layout); - this.layout.setParent(null); - } - - // Replace the previous layout - newLayout.setParent(this); - this.layout = newLayout; - } - - /** - * Sets the form field to be selectable from static list of changes. - * - * <p> - * The list values and descriptions are given as array. The value-array must - * contain the current value of the field and the lengths of the arrays must - * match. Null values are not supported. - * </p> - * - * @param propertyId - * the id of the property. - * @param values - * @param descriptions - * @return the select property generated - */ - public Select replaceWithSelect(Object propertyId, Object[] values, - Object[] descriptions) { - - // Checks the parameters - if (propertyId == null || values == null || descriptions == null) - throw new NullPointerException("All parameters must be non-null"); - if (values.length != descriptions.length) - throw new IllegalArgumentException( - "Value and description list are of different size"); - - // Gets the old field - Field oldField = (Field) fields.get(propertyId); - if (oldField == null) - throw new IllegalArgumentException("Field with given propertyid '" - + propertyId.toString() + "' can not be found."); - Object value = oldField.getValue(); - - // Checks that the value exists and check if the select should - // be forced in multiselect mode - boolean found = false; - boolean isMultiselect = false; - for (int i = 0; i < values.length && !found; i++) - if (values[i] == value - || (value != null && value.equals(values[i]))) - found = true; - if (value != null && !found) { - if (value instanceof Collection) { - for (Iterator it = ((Collection) value).iterator(); it - .hasNext();) { - Object val = it.next(); - found = false; - for (int i = 0; i < values.length && !found; i++) - if (values[i] == val - || (val != null && val.equals(values[i]))) - found = true; - if (!found) - throw new IllegalArgumentException( - "Currently selected value '" + val - + "' of property '" - + propertyId.toString() - + "' was not found"); - } - isMultiselect = true; - } else - throw new IllegalArgumentException("Current value '" + value - + "' of property '" + propertyId.toString() - + "' was not found"); - } - - // Creates the new field matching to old field parameters - Select newField = new Select(); - if (isMultiselect) - newField.setMultiSelect(true); - newField.setCaption(oldField.getCaption()); - newField.setReadOnly(oldField.isReadOnly()); - newField.setReadThrough(oldField.isReadThrough()); - newField.setWriteThrough(oldField.isWriteThrough()); - - // Creates the options list - newField.addContainerProperty("desc", String.class, ""); - newField.setItemCaptionPropertyId("desc"); - for (int i = 0; i < values.length; i++) { - Object id = values[i]; - if (id == null) { - id = new Object(); - newField.setNullSelectionItemId(id); - } - Item item = newField.addItem(id); - if (item != null) - item.getItemProperty("desc").setValue( - descriptions[i].toString()); - } - - // Sets the property data source - Property property = oldField.getPropertyDataSource(); - oldField.setPropertyDataSource(null); - newField.setPropertyDataSource(property); - - // Replaces the old field with new one - layout.replaceComponent(oldField, newField); - fields.put(propertyId, newField); - this.removeDirectDependency(oldField); - oldField.removeDirectDependency(this); - this.dependsOn(newField); - newField.dependsOn(this); - - return newField; - } - - /** - * Notifies the component that it is connected to an application - * - * @see com.itmill.toolkit.ui.Component#attach() - */ - public void attach() { - super.attach(); - layout.attach(); - } - - /** - * Notifies the component that it is detached from the application. - * - * @see com.itmill.toolkit.ui.Component#detach() - */ - public void detach() { - super.detach(); - layout.detach(); - } - - /** - * Adds a new validator for this object. - * - * @see com.itmill.toolkit.data.Validatable#addValidator(com.itmill.toolkit.data.Validator) - */ - public void addValidator(Validator validator) { - - if (this.validators == null) { - this.validators = new LinkedList(); - } - this.validators.add(validator); - } - - /** - * Removes a previously registered validator from the object. - * - * @see com.itmill.toolkit.data.Validatable#removeValidator(com.itmill.toolkit.data.Validator) - */ - public void removeValidator(Validator validator) { - if (this.validators != null) { - this.validators.remove(validator); - } - } - - /** - * Gets the Lists all validators currently registered for the object. - * - * @see com.itmill.toolkit.data.Validatable#getValidators() - */ - public Collection getValidators() { - if (this.validators == null) { - this.validators = new LinkedList(); - } - return this.validators; - } - - /** - * Tests the current value of the object against all registered validators - * - * @see com.itmill.toolkit.data.Validatable#isValid() - */ - public boolean isValid() { - boolean valid = true; - for (Iterator i = propertyIds.iterator(); i.hasNext();) - valid &= ((Field) fields.get(i.next())).isValid(); - return valid; - } - - /** - * Checks the validity of the validatable. - * - * @see com.itmill.toolkit.data.Validatable#validate() - */ - public void validate() throws InvalidValueException { - for (Iterator i = propertyIds.iterator(); i.hasNext();) - ((Field) fields.get(i.next())).validate(); - } - - /** - * Checks the validabtable object accept invalid values. - * - * @see com.itmill.toolkit.data.Validatable#isInvalidAllowed() - */ - public boolean isInvalidAllowed() { - return true; - } - - /** - * Should the validabtable object accept invalid values. - * - * @see com.itmill.toolkit.data.Validatable#setInvalidAllowed(boolean) - */ - public void setInvalidAllowed(boolean invalidValueAllowed) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Sets the component's to read-only mode to the specified state. - * - * @see com.itmill.toolkit.ui.Component#setReadOnly(boolean) - */ - public void setReadOnly(boolean readOnly) { - super.setReadOnly(readOnly); - for (Iterator i = propertyIds.iterator(); i.hasNext();) - ((Field) fields.get(i.next())).setReadOnly(readOnly); - } - - /** - * Sets the field factory of Form. - * - * <code>FieldFactory</code> is used to create fields for form properties. - * By default the form uses BaseFieldFactory to create Field instances. - * - * @param fieldFactory - * the New factory used to create the fields. - * @see Field - * @see FieldFactory - */ - public void setFieldFactory(FieldFactory fieldFactory) { - this.fieldFactory = fieldFactory; - } - - /** - * Get the field factory of the form. - * - * @return the FieldFactory Factory used to create the fields. - */ - public FieldFactory getFieldFactory() { - return this.fieldFactory; - } - - /** - * Gets the field type. - * - * @see com.itmill.toolkit.ui.AbstractField#getType() - */ - public Class getType() { - if (getPropertyDataSource() != null) - return getPropertyDataSource().getType(); - return Object.class; - } - - /** - * Sets the internal value. - * - * This is relevant when the Form is used as Field. - * - * @see com.itmill.toolkit.ui.AbstractField#setInternalValue(java.lang.Object) - */ - protected void setInternalValue(Object newValue) { - // Stores the old value - Object oldValue = this.propertyValue; - - // Sets the current Value - super.setInternalValue(newValue); - this.propertyValue = newValue; - - // Ignores form updating if data object has not changed. - if (oldValue != newValue) { - setFormDataSource(newValue, getVisibleItemProperties()); - } - } - - /** - * Gets the first field in form. - * - * @return the Field. - */ - private Field getFirstField() { - Object id = null; - if (this.getItemPropertyIds() != null) { - id = this.getItemPropertyIds().iterator().next(); - } - if (id != null) - return this.getField(id); - return null; - } - - /** - * Updates the internal form datasource. - * - * Method setFormDataSource. - * - * @param data - * @param properties - */ - protected void setFormDataSource(Object data, Collection properties) { - - // If data is an item use it. - Item item = null; - if (data instanceof Item) { - item = (Item) data; - } else if (data != null) { - item = new BeanItem(data); - } - - // Sets the datasource to form - if (item != null && properties != null) { - // Shows only given properties - this.setItemDataSource(item, properties); - } else { - // Shows all properties - this.setItemDataSource(item); - } - } - - /** - * Returns the visibleProperties. - * - * @return the Collection of visible Item properites. - */ - public Collection getVisibleItemProperties() { - return visibleItemProperties; - } - - /** - * Sets the visibleProperties. - * - * @param visibleProperties - * the visibleProperties to set. - */ - public void setVisibleItemProperties(Collection visibleProperties) { - this.visibleItemProperties = visibleProperties; - Object value = getValue(); - setFormDataSource(value, getVisibleItemProperties()); - } - - /** - * Focuses the first field in the form. - * - * @see com.itmill.toolkit.ui.Component.Focusable#focus() - */ - public void focus() { - Field f = getFirstField(); - if (f != null) { - f.focus(); - } - } - - /** - * Sets the Tabulator index of this Focusable component. - * - * @see com.itmill.toolkit.ui.Component.Focusable#setTabIndex(int) - */ - public void setTabIndex(int tabIndex) { - super.setTabIndex(tabIndex); - for (Iterator i = this.getItemPropertyIds().iterator(); i.hasNext();) - (this.getField(i.next())).setTabIndex(tabIndex); - } + Validatable { + + private Object propertyValue; + + /** + * Layout of the form. + */ + private Layout layout; + + /** + * Item connected to this form as datasource. + */ + private Item itemDatasource; + + /** + * Ordered list of property ids in this editor. + */ + private LinkedList propertyIds = new LinkedList(); + + /** + * Current buffered source exception. + */ + private Buffered.SourceException currentBufferedSourceException = null; + + /** + * Is the form in write trough mode. + */ + private boolean writeThrough = true; + + /** + * Is the form in read trough mode. + */ + private boolean readThrough = true; + + /** + * Mapping from propertyName to corresponding field. + */ + private HashMap fields = new HashMap(); + + /** + * Field factory for this form. + */ + private FieldFactory fieldFactory; + + /** + * Registered Validators. + */ + private LinkedList validators; + + /** + * Visible item properties. + */ + private Collection visibleItemProperties; + + /** + * Contructs a new form with default layout. + * + * <p> + * By default the form uses <code>OrderedLayout</code> with + * <code>form</code>-style. + * </p> + * + * @param formLayout + * the layout of the form. + */ + public Form() { + this(null); + } + + /** + * Contructs a new form with given layout. + * + * @param formLayout + * the layout of the form. + */ + public Form(Layout formLayout) { + this(formLayout, new BaseFieldFactory()); + } + + /** + * Contructs a new form with given layout and FieldFactory. + * + * @param formLayout + * the layout of the form. + * @param fieldFactory + * the FieldFactory of the form. + */ + public Form(Layout formLayout, FieldFactory fieldFactory) { + super(); + setLayout(formLayout); + setFieldFactory(fieldFactory); + } + + /* Documented in interface */ + public String getTag() { + return "form"; + } + + /* Documented in interface */ + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + layout.paint(target); + } + + /* + * Commit changes to the data source Don't add a JavaDoc comment here, we + * use the default one from the interface. + */ + public void commit() throws Buffered.SourceException { + + LinkedList problems = null; + + // Try to commit all + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + try { + Field f = ((Field) fields.get(i.next())); + // Commit only non-readonly fields. + if (!f.isReadOnly()) { + f.commit(); + } + } catch (Buffered.SourceException e) { + if (problems == null) { + problems = new LinkedList(); + } + problems.add(e); + } + } + + // No problems occurred + if (problems == null) { + if (currentBufferedSourceException != null) { + currentBufferedSourceException = null; + requestRepaint(); + } + return; + } + + // Commit problems + Throwable[] causes = new Throwable[problems.size()]; + int index = 0; + for (Iterator i = problems.iterator(); i.hasNext();) { + causes[index++] = (Throwable) i.next(); + } + Buffered.SourceException e = new Buffered.SourceException(this, causes); + currentBufferedSourceException = e; + requestRepaint(); + throw e; + } + + /* + * Discards local changes and refresh values from the data source Don't add + * a JavaDoc comment here, we use the default one from the interface. + */ + public void discard() throws Buffered.SourceException { + + LinkedList problems = null; + + // Try to discard all changes + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + try { + ((Field) fields.get(i.next())).discard(); + } catch (Buffered.SourceException e) { + if (problems == null) { + problems = new LinkedList(); + } + problems.add(e); + } + } + + // No problems occurred + if (problems == null) { + if (currentBufferedSourceException != null) { + currentBufferedSourceException = null; + requestRepaint(); + } + return; + } + + // Discards problems occurred + Throwable[] causes = new Throwable[problems.size()]; + int index = 0; + for (Iterator i = problems.iterator(); i.hasNext();) { + causes[index++] = (Throwable) i.next(); + } + Buffered.SourceException e = new Buffered.SourceException(this, causes); + currentBufferedSourceException = e; + requestRepaint(); + throw e; + } + + /* + * Is the object modified but not committed? Don't add a JavaDoc comment + * here, we use the default one from the interface. + */ + public boolean isModified() { + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + Field f = (Field) fields.get(i.next()); + if (f != null && f.isModified()) { + return true; + } + + } + return false; + } + + /* + * Is the editor in a read-through mode? Don't add a JavaDoc comment here, + * we use the default one from the interface. + */ + public boolean isReadThrough() { + return readThrough; + } + + /* + * Is the editor in a write-through mode? Don't add a JavaDoc comment here, + * we use the default one from the interface. + */ + public boolean isWriteThrough() { + return writeThrough; + } + + /* + * Sets the editor's read-through mode to the specified status. Don't add a + * JavaDoc comment here, we use the default one from the interface. + */ + public void setReadThrough(boolean readThrough) { + if (readThrough != this.readThrough) { + this.readThrough = readThrough; + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + ((Field) fields.get(i.next())).setReadThrough(readThrough); + } + } + } + + /* + * Sets the editor's read-through mode to the specified status. Don't add a + * JavaDoc comment here, we use the default one from the interface. + */ + public void setWriteThrough(boolean writeThrough) { + if (writeThrough != this.writeThrough) { + this.writeThrough = writeThrough; + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + ((Field) fields.get(i.next())).setWriteThrough(writeThrough); + } + } + } + + /** + * Adds a new property to form and create corresponding field. + * + * @see com.itmill.toolkit.data.Item#addItemProperty(Object, Property) + */ + public boolean addItemProperty(Object id, Property property) { + + // Checks inputs + if (id == null || property == null) { + throw new NullPointerException("Id and property must be non-null"); + } + + // Checks that the property id is not reserved + if (propertyIds.contains(id)) { + return false; + } + + // Gets suitable field + Field field = fieldFactory.createField(property, this); + if (field == null) { + return false; + } + + // Configures the field + try { + field.setPropertyDataSource(property); + String caption = id.toString(); + if (caption.length() > 50) { + caption = caption.substring(0, 47) + "..."; + } + if (caption.length() > 0) { + caption = "" + Character.toUpperCase(caption.charAt(0)) + + caption.substring(1, caption.length()); + } + field.setCaption(caption); + } catch (Throwable ignored) { + return false; + } + + addField(id, field); + + return true; + } + + /** + * Adds the field to form. + * + * <p> + * The property id must not be already used in the form. + * </p> + * + * <p> + * This field is added to the form layout in the default position (the + * position used by {@link Layout#addComponent(Component)} method. In the + * special case that the underlying layout is a custom layout, string + * representation of the property id is used instead of the default + * location. + * </p> + * + * @param propertyId + * the Property id the the field. + * @param field + * the New field added to the form. + */ + public void addField(Object propertyId, Field field) { + + if (propertyId != null && field != null) { + dependsOn(field); + field.dependsOn(this); + fields.put(propertyId, field); + propertyIds.addLast(propertyId); + field.setReadThrough(readThrough); + field.setWriteThrough(writeThrough); + + if (layout instanceof CustomLayout) { + ((CustomLayout) layout).addComponent(field, propertyId + .toString()); + } else { + layout.addComponent(field); + } + + requestRepaint(); + } + } + + /** + * The property identified by the property id. + * + * <p> + * The property data source of the field specified with property id is + * returned. If there is a (with specified property id) having no data + * source, the field is returned instead of the data source. + * </p> + * + * @see com.itmill.toolkit.data.Item#getItemProperty(Object) + */ + public Property getItemProperty(Object id) { + Field field = (Field) fields.get(id); + if (field == null) { + return null; + } + Property property = field.getPropertyDataSource(); + + if (property != null) { + return property; + } else { + return field; + } + } + + /** + * Gets the field identified by the propertyid. + * + * @param propertyId + * the id of the property. + */ + public Field getField(Object propertyId) { + return (Field) fields.get(propertyId); + } + + /* Documented in interface */ + public Collection getItemPropertyIds() { + return Collections.unmodifiableCollection(propertyIds); + } + + /** + * Removes the property and corresponding field from the form. + * + * @see com.itmill.toolkit.data.Item#removeItemProperty(Object) + */ + public boolean removeItemProperty(Object id) { + + Field field = (Field) fields.get(id); + + if (field != null) { + propertyIds.remove(id); + fields.remove(id); + removeDirectDependency(field); + field.removeDirectDependency(this); + layout.removeComponent(field); + return true; + } + + return false; + } + + /** + * Removes all properties and fields from the form. + * + * @return the Success of the operation. Removal of all fields succeeded if + * (and only if) the return value is <code>true</code>. + */ + public boolean removeAllProperties() { + Object[] properties = propertyIds.toArray(); + boolean success = true; + + for (int i = 0; i < properties.length; i++) { + if (!removeItemProperty(properties[i])) { + success = false; + } + } + + return success; + } + + /* Documented in the interface */ + public Item getItemDataSource() { + return itemDatasource; + } + + /** + * Sets the item datasource for the form. + * + * <p> + * Setting item datasource clears any fields, the form might contain and + * adds all the properties as fields to the form. + * </p> + * + * @see com.itmill.toolkit.data.Item.Viewer#setItemDataSource(Item) + */ + public void setItemDataSource(Item newDataSource) { + setItemDataSource(newDataSource, newDataSource != null ? newDataSource + .getItemPropertyIds() : null); + } + + /** + * Set the item datasource for the form, but limit the form contents to + * specified properties of the item. + * + * <p> + * Setting item datasource clears any fields, the form might contain and + * adds the specified the properties as fields to the form, in the specified + * order. + * </p> + * + * @see com.itmill.toolkit.data.Item.Viewer#setItemDataSource(Item) + */ + public void setItemDataSource(Item newDataSource, Collection propertyIds) { + + // Removes all fields first from the form + removeAllProperties(); + + // Sets the datasource + itemDatasource = newDataSource; + + // If the new datasource is null, just set null datasource + if (itemDatasource == null) { + return; + } + + // Adds all the properties to this form + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + Object id = i.next(); + Property property = itemDatasource.getItemProperty(id); + if (id != null && property != null) { + Field f = fieldFactory.createField(itemDatasource, id, this); + if (f != null) { + f.setPropertyDataSource(property); + addField(id, f); + } + } + } + } + + /** + * Gets the layout of the form. + * + * <p> + * By default form uses <code>OrderedLayout</code> with <code>form</code>-style. + * </p> + * + * @return the Layout of the form. + */ + public Layout getLayout() { + return layout; + } + + /** + * Sets the layout of the form. + * + * <p> + * By default form uses <code>OrderedLayout</code> with <code>form</code>-style. + * </p> + * + * @param newLayout + * the Layout of the form. + */ + public void setLayout(Layout newLayout) { + + // Use orderedlayout by default + if (newLayout == null) { + newLayout = new FormLayout(); + } + + // Move components from previous layout + if (layout != null) { + newLayout.moveComponentsFrom(layout); + layout.setParent(null); + } + + // Replace the previous layout + newLayout.setParent(this); + layout = newLayout; + } + + /** + * Sets the form field to be selectable from static list of changes. + * + * <p> + * The list values and descriptions are given as array. The value-array must + * contain the current value of the field and the lengths of the arrays must + * match. Null values are not supported. + * </p> + * + * @param propertyId + * the id of the property. + * @param values + * @param descriptions + * @return the select property generated + */ + public Select replaceWithSelect(Object propertyId, Object[] values, + Object[] descriptions) { + + // Checks the parameters + if (propertyId == null || values == null || descriptions == null) { + throw new NullPointerException("All parameters must be non-null"); + } + if (values.length != descriptions.length) { + throw new IllegalArgumentException( + "Value and description list are of different size"); + } + + // Gets the old field + Field oldField = (Field) fields.get(propertyId); + if (oldField == null) { + throw new IllegalArgumentException("Field with given propertyid '" + + propertyId.toString() + "' can not be found."); + } + Object value = oldField.getValue(); + + // Checks that the value exists and check if the select should + // be forced in multiselect mode + boolean found = false; + boolean isMultiselect = false; + for (int i = 0; i < values.length && !found; i++) { + if (values[i] == value + || (value != null && value.equals(values[i]))) { + found = true; + } + } + if (value != null && !found) { + if (value instanceof Collection) { + for (Iterator it = ((Collection) value).iterator(); it + .hasNext();) { + Object val = it.next(); + found = false; + for (int i = 0; i < values.length && !found; i++) { + if (values[i] == val + || (val != null && val.equals(values[i]))) { + found = true; + } + } + if (!found) { + throw new IllegalArgumentException( + "Currently selected value '" + val + + "' of property '" + + propertyId.toString() + + "' was not found"); + } + } + isMultiselect = true; + } else { + throw new IllegalArgumentException("Current value '" + value + + "' of property '" + propertyId.toString() + + "' was not found"); + } + } + + // Creates the new field matching to old field parameters + Select newField = new Select(); + if (isMultiselect) { + newField.setMultiSelect(true); + } + newField.setCaption(oldField.getCaption()); + newField.setReadOnly(oldField.isReadOnly()); + newField.setReadThrough(oldField.isReadThrough()); + newField.setWriteThrough(oldField.isWriteThrough()); + + // Creates the options list + newField.addContainerProperty("desc", String.class, ""); + newField.setItemCaptionPropertyId("desc"); + for (int i = 0; i < values.length; i++) { + Object id = values[i]; + if (id == null) { + id = new Object(); + newField.setNullSelectionItemId(id); + } + Item item = newField.addItem(id); + if (item != null) { + item.getItemProperty("desc").setValue( + descriptions[i].toString()); + } + } + + // Sets the property data source + Property property = oldField.getPropertyDataSource(); + oldField.setPropertyDataSource(null); + newField.setPropertyDataSource(property); + + // Replaces the old field with new one + layout.replaceComponent(oldField, newField); + fields.put(propertyId, newField); + removeDirectDependency(oldField); + oldField.removeDirectDependency(this); + dependsOn(newField); + newField.dependsOn(this); + + return newField; + } + + /** + * Notifies the component that it is connected to an application + * + * @see com.itmill.toolkit.ui.Component#attach() + */ + public void attach() { + super.attach(); + layout.attach(); + } + + /** + * Notifies the component that it is detached from the application. + * + * @see com.itmill.toolkit.ui.Component#detach() + */ + public void detach() { + super.detach(); + layout.detach(); + } + + /** + * Adds a new validator for this object. + * + * @see com.itmill.toolkit.data.Validatable#addValidator(com.itmill.toolkit.data.Validator) + */ + public void addValidator(Validator validator) { + + if (validators == null) { + validators = new LinkedList(); + } + validators.add(validator); + } + + /** + * Removes a previously registered validator from the object. + * + * @see com.itmill.toolkit.data.Validatable#removeValidator(com.itmill.toolkit.data.Validator) + */ + public void removeValidator(Validator validator) { + if (validators != null) { + validators.remove(validator); + } + } + + /** + * Gets the Lists all validators currently registered for the object. + * + * @see com.itmill.toolkit.data.Validatable#getValidators() + */ + public Collection getValidators() { + if (validators == null) { + validators = new LinkedList(); + } + return validators; + } + + /** + * Tests the current value of the object against all registered validators + * + * @see com.itmill.toolkit.data.Validatable#isValid() + */ + public boolean isValid() { + boolean valid = true; + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + valid &= ((Field) fields.get(i.next())).isValid(); + } + return valid; + } + + /** + * Checks the validity of the validatable. + * + * @see com.itmill.toolkit.data.Validatable#validate() + */ + public void validate() throws InvalidValueException { + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + ((Field) fields.get(i.next())).validate(); + } + } + + /** + * Checks the validabtable object accept invalid values. + * + * @see com.itmill.toolkit.data.Validatable#isInvalidAllowed() + */ + public boolean isInvalidAllowed() { + return true; + } + + /** + * Should the validabtable object accept invalid values. + * + * @see com.itmill.toolkit.data.Validatable#setInvalidAllowed(boolean) + */ + public void setInvalidAllowed(boolean invalidValueAllowed) + throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Sets the component's to read-only mode to the specified state. + * + * @see com.itmill.toolkit.ui.Component#setReadOnly(boolean) + */ + public void setReadOnly(boolean readOnly) { + super.setReadOnly(readOnly); + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + ((Field) fields.get(i.next())).setReadOnly(readOnly); + } + } + + /** + * Sets the field factory of Form. + * + * <code>FieldFactory</code> is used to create fields for form properties. + * By default the form uses BaseFieldFactory to create Field instances. + * + * @param fieldFactory + * the New factory used to create the fields. + * @see Field + * @see FieldFactory + */ + public void setFieldFactory(FieldFactory fieldFactory) { + this.fieldFactory = fieldFactory; + } + + /** + * Get the field factory of the form. + * + * @return the FieldFactory Factory used to create the fields. + */ + public FieldFactory getFieldFactory() { + return fieldFactory; + } + + /** + * Gets the field type. + * + * @see com.itmill.toolkit.ui.AbstractField#getType() + */ + public Class getType() { + if (getPropertyDataSource() != null) { + return getPropertyDataSource().getType(); + } + return Object.class; + } + + /** + * Sets the internal value. + * + * This is relevant when the Form is used as Field. + * + * @see com.itmill.toolkit.ui.AbstractField#setInternalValue(java.lang.Object) + */ + protected void setInternalValue(Object newValue) { + // Stores the old value + Object oldValue = propertyValue; + + // Sets the current Value + super.setInternalValue(newValue); + propertyValue = newValue; + + // Ignores form updating if data object has not changed. + if (oldValue != newValue) { + setFormDataSource(newValue, getVisibleItemProperties()); + } + } + + /** + * Gets the first field in form. + * + * @return the Field. + */ + private Field getFirstField() { + Object id = null; + if (getItemPropertyIds() != null) { + id = getItemPropertyIds().iterator().next(); + } + if (id != null) { + return getField(id); + } + return null; + } + + /** + * Updates the internal form datasource. + * + * Method setFormDataSource. + * + * @param data + * @param properties + */ + protected void setFormDataSource(Object data, Collection properties) { + + // If data is an item use it. + Item item = null; + if (data instanceof Item) { + item = (Item) data; + } else if (data != null) { + item = new BeanItem(data); + } + + // Sets the datasource to form + if (item != null && properties != null) { + // Shows only given properties + this.setItemDataSource(item, properties); + } else { + // Shows all properties + this.setItemDataSource(item); + } + } + + /** + * Returns the visibleProperties. + * + * @return the Collection of visible Item properites. + */ + public Collection getVisibleItemProperties() { + return visibleItemProperties; + } + + /** + * Sets the visibleProperties. + * + * @param visibleProperties + * the visibleProperties to set. + */ + public void setVisibleItemProperties(Collection visibleProperties) { + visibleItemProperties = visibleProperties; + Object value = getValue(); + setFormDataSource(value, getVisibleItemProperties()); + } + + /** + * Focuses the first field in the form. + * + * @see com.itmill.toolkit.ui.Component.Focusable#focus() + */ + public void focus() { + Field f = getFirstField(); + if (f != null) { + f.focus(); + } + } + + /** + * Sets the Tabulator index of this Focusable component. + * + * @see com.itmill.toolkit.ui.Component.Focusable#setTabIndex(int) + */ + public void setTabIndex(int tabIndex) { + super.setTabIndex(tabIndex); + for (Iterator i = getItemPropertyIds().iterator(); i.hasNext();) { + (getField(i.next())).setTabIndex(tabIndex); + } + } } |