From: Marc Englund Date: Wed, 30 Jan 2008 14:36:23 +0000 (+0000) Subject: Selects now listen for changes to item/property as appropriate. Version 1. Table... X-Git-Tag: 6.7.0.beta1~5143 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=597630487829207a5427d0a90cd78844dac2d862;p=vaadin-framework.git Selects now listen for changes to item/property as appropriate. Version 1. Table still needs work (might 'leak' listeners as it is now) svn changeset:3671/svn branch:trunk --- diff --git a/src/com/itmill/toolkit/ui/AbstractSelect.java b/src/com/itmill/toolkit/ui/AbstractSelect.java index 47d06104e7..a464b444f1 100644 --- a/src/com/itmill/toolkit/ui/AbstractSelect.java +++ b/src/com/itmill/toolkit/ui/AbstractSelect.java @@ -181,6 +181,9 @@ public abstract class AbstractSelect extends AbstractField implements private boolean nullSelectionAllowed = true; private NewItemHandler newItemHandler; + // Caption (Item / Property) change listeners + CaptionChangeListener captionChangeListener; + /* Constructors ********************************************************* */ /** @@ -273,7 +276,10 @@ public abstract class AbstractSelect extends AbstractField implements } // == + // first remove all previous item/property listeners + getCaptionChangeListener().clear(); // Paints the options and create array of selected id keys + target.startTag("options"); int keyIndex = 0; // Support for external null selection item id @@ -313,6 +319,8 @@ public abstract class AbstractSelect extends AbstractField implements } final String key = itemIdMapper.key(id); final String caption = getItemCaption(id); + // add listener for each item, to cause repaint if an item changes + getCaptionChangeListener().addNotifierForItem(id); final Resource icon = getItemIcon(id); // Paints the option target.startTag("so"); if (icon != null) { @@ -835,6 +843,8 @@ public abstract class AbstractSelect extends AbstractField implements newDataSource = new IndexedContainer(); } + getCaptionChangeListener().clear(); + if (items != newDataSource) { // Removes listeners from the old datasource @@ -1565,7 +1575,94 @@ public abstract class AbstractSelect extends AbstractField implements * @see com.itmill.toolkit.ui.AbstractComponent#detach() */ public void detach() { + getCaptionChangeListener().clear(); super.detach(); } + // Caption change listener + protected CaptionChangeListener getCaptionChangeListener() { + if (captionChangeListener == null) { + captionChangeListener = new CaptionChangeListener(); + } + return captionChangeListener; + } + + /** + * This is a listener helper for Item and Property changes that should cause + * a repaint. It should be attached to all items that are displayed, and the + * default implementation does this in paintContent(). Especially + * "lazyloading" components should take care to add and remove listeners as + * appropriate. Call addNotifierForItem() for each painted item (and + * remember to clear). + * + */ + protected class CaptionChangeListener implements + Item.PropertySetChangeListener, Property.ValueChangeListener { + + HashSet captionChangeNotifiers = new HashSet(); + + public void addNotifierForItem(Object itemId) { + switch (getItemCaptionMode()) { + case ITEM_CAPTION_MODE_ITEM: + final Item i = getItem(itemId); + if (i == null) { + return; + } + if (i instanceof Item.PropertySetChangeNotifier) { + ((Item.PropertySetChangeNotifier) i) + .addListener(getCaptionChangeListener()); + captionChangeNotifiers.add(i); + } + Collection pids = i.getItemPropertyIds(); + if (pids != null) { + for (Iterator it = pids.iterator(); it.hasNext();) { + Property p = i.getItemProperty(it.next()); + if (p != null + || p instanceof Property.ValueChangeNotifier) { + ((Property.ValueChangeNotifier) p) + .addListener(getCaptionChangeListener()); + captionChangeNotifiers.add(p); + } + } + + } + break; + case ITEM_CAPTION_MODE_PROPERTY: + final Property p = getContainerProperty(itemId, + getItemCaptionPropertyId()); + if (p != null || p instanceof Property.ValueChangeNotifier) { + ((Property.ValueChangeNotifier) p) + .addListener(getCaptionChangeListener()); + captionChangeNotifiers.add(p); + } + break; + + } + } + + public void clear() { + for (Iterator it = captionChangeNotifiers.iterator(); it.hasNext();) { + Object notifier = it.next(); + if (notifier instanceof Item.PropertySetChangeNotifier) { + ((Item.PropertySetChangeNotifier) notifier) + .removeListener(getCaptionChangeListener()); + } else { + ((Property.ValueChangeNotifier) notifier) + .removeListener(getCaptionChangeListener()); + } + } + } + + public void valueChange( + com.itmill.toolkit.data.Property.ValueChangeEvent event) { + requestRepaint(); + } + + public void itemPropertySetChange( + com.itmill.toolkit.data.Item.PropertySetChangeEvent event) { + requestRepaint(); + } + + } + } diff --git a/src/com/itmill/toolkit/ui/Select.java b/src/com/itmill/toolkit/ui/Select.java index 12f833bbb0..fdcba9e998 100644 --- a/src/com/itmill/toolkit/ui/Select.java +++ b/src/com/itmill/toolkit/ui/Select.java @@ -82,6 +82,9 @@ public class Select extends AbstractSelect implements AbstractSelect.Filtering { * if the paint operation failed. */ public void paintContent(PaintTarget target) throws PaintException { + // clear caption change listeners + getCaptionChangeListener().clear(); + // Focus control id if (getFocusableId() > 0) { target.addAttribute("focusid", getFocusableId()); @@ -178,6 +181,7 @@ public class Select extends AbstractSelect implements AbstractSelect.Filtering { final String key = itemIdMapper.key(id); final String caption = getItemCaption(id); final Resource icon = getItemIcon(id); + getCaptionChangeListener().addNotifierForItem(id); // Paints the option target.startTag("so"); diff --git a/src/com/itmill/toolkit/ui/Table.java b/src/com/itmill/toolkit/ui/Table.java index 12e24c3b1a..9539653b3c 100644 --- a/src/com/itmill/toolkit/ui/Table.java +++ b/src/com/itmill/toolkit/ui/Table.java @@ -1681,7 +1681,8 @@ public class Table extends AbstractSelect implements Action.Container, // Stops listening the old properties and initialise the list if (listenedProperties == null) { listenedProperties = new LinkedList(); - } else { + } else if (reqRowsToPaint < 0) { + // TODO the above if is not perfect - should be fixed properly for (final Iterator i = listenedProperties.iterator(); i.hasNext();) { ((Property.ValueChangeNotifier) i.next()).removeListener(this); } @@ -1690,7 +1691,8 @@ public class Table extends AbstractSelect implements Action.Container, // Detach old visible component from the table if (visibleComponents == null) { visibleComponents = new LinkedList(); - } else { + } else if (reqRowsToPaint < 0) { + // TODO the above if is not perfect - should be fixed properly for (final Iterator i = visibleComponents.iterator(); i.hasNext();) { ((Component) i.next()).setParent(null); } diff --git a/src/com/itmill/toolkit/ui/Tree.java b/src/com/itmill/toolkit/ui/Tree.java index 9ef41c1567..d617e3118d 100644 --- a/src/com/itmill/toolkit/ui/Tree.java +++ b/src/com/itmill/toolkit/ui/Tree.java @@ -396,6 +396,7 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, target.addAttribute("partialUpdate", true); target.addAttribute("rootKey", itemIdMapper.key(expandedItemId)); } else { + getCaptionChangeListener().clear(); // Focus control id if (getFocusableId() > 0) { @@ -495,6 +496,9 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, expandedKeys.add(key); } + // Add caption change listener + getCaptionChangeListener().addNotifierForItem(itemId); + // Actions if (actionHandlers != null) { final ArrayList keys = new ArrayList();