Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 122852 Details for
Bug 194734
[Databinding] Property-based observables
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
Possible change
clipboard.txt (text/plain), 287.20 KB, created by
Matthew Hall
on 2009-01-16 19:58:28 EST
(
hide
)
Description:
Possible change
Filename:
MIME Type:
Creator:
Matthew Hall
Created:
2009-01-16 19:58:28 EST
Size:
287.20 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.jface.databinding >Index: src/org/eclipse/jface/internal/databinding/viewers/ViewerInputProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/viewers/Attic/ViewerInputProperty.java,v >retrieving revision 1.1.2.6 >diff -u -r1.1.2.6 ViewerInputProperty.java >--- src/org/eclipse/jface/internal/databinding/viewers/ViewerInputProperty.java 6 Jan 2009 06:21:04 -0000 1.1.2.6 >+++ src/org/eclipse/jface/internal/databinding/viewers/ViewerInputProperty.java 17 Jan 2009 00:49:36 -0000 >@@ -13,7 +13,7 @@ > package org.eclipse.jface.internal.databinding.viewers; > > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > import org.eclipse.jface.viewers.Viewer; > > /** >@@ -33,8 +33,8 @@ > ((Viewer) source).setInput(value); > } > >- protected INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ public INativePropertyListener adaptListener( >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderSingleSelectionProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/viewers/Attic/SelectionProviderSingleSelectionProperty.java,v >retrieving revision 1.1.2.7 >diff -u -r1.1.2.7 SelectionProviderSingleSelectionProperty.java >--- src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderSingleSelectionProperty.java 14 Jan 2009 23:51:12 -0000 1.1.2.7 >+++ src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderSingleSelectionProperty.java 17 Jan 2009 00:49:36 -0000 >@@ -13,8 +13,8 @@ > package org.eclipse.jface.internal.databinding.viewers; > > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; > import org.eclipse.jface.viewers.ISelection; > import org.eclipse.jface.viewers.ISelectionChangedListener; > import org.eclipse.jface.viewers.ISelectionProvider; >@@ -47,7 +47,7 @@ > } > > public INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ ISimplePropertyListener listener) { > return new SelectionChangedListener(listener); > } > >@@ -65,14 +65,14 @@ > > private class SelectionChangedListener implements INativePropertyListener, > ISelectionChangedListener { >- private IPropertyChangeListener listener; >+ private ISimplePropertyListener listener; > >- private SelectionChangedListener(IPropertyChangeListener listener) { >+ private SelectionChangedListener(ISimplePropertyListener listener) { > this.listener = listener; > } > > public void selectionChanged(SelectionChangedEvent event) { >- listener.handlePropertyChange(new PropertyChangeEvent(event >+ listener.handlePropertyChange(new SimplePropertyEvent(event > .getSource(), > SelectionProviderSingleSelectionProperty.this, null)); > } >Index: src/org/eclipse/jface/internal/databinding/viewers/StructuredViewerFiltersProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/viewers/Attic/StructuredViewerFiltersProperty.java,v >retrieving revision 1.1.2.6 >diff -u -r1.1.2.6 StructuredViewerFiltersProperty.java >--- src/org/eclipse/jface/internal/databinding/viewers/StructuredViewerFiltersProperty.java 6 Jan 2009 06:21:04 -0000 1.1.2.6 >+++ src/org/eclipse/jface/internal/databinding/viewers/StructuredViewerFiltersProperty.java 17 Jan 2009 00:49:36 -0000 >@@ -18,7 +18,7 @@ > > import org.eclipse.core.databinding.observable.set.SetDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > import org.eclipse.jface.viewers.StructuredViewer; > import org.eclipse.jface.viewers.ViewerFilter; > >@@ -48,7 +48,7 @@ > } > > public INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/jface/internal/databinding/viewers/CheckableCheckedElementsProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/viewers/Attic/CheckableCheckedElementsProperty.java,v >retrieving revision 1.1.2.7 >diff -u -r1.1.2.7 CheckableCheckedElementsProperty.java >--- src/org/eclipse/jface/internal/databinding/viewers/CheckableCheckedElementsProperty.java 14 Jan 2009 23:51:12 -0000 1.1.2.7 >+++ src/org/eclipse/jface/internal/databinding/viewers/CheckableCheckedElementsProperty.java 17 Jan 2009 00:49:36 -0000 >@@ -20,8 +20,8 @@ > import org.eclipse.core.databinding.observable.Diffs; > import org.eclipse.core.databinding.observable.set.SetDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; > import org.eclipse.jface.viewers.CheckStateChangedEvent; > import org.eclipse.jface.viewers.ICheckStateListener; > import org.eclipse.jface.viewers.ICheckable; >@@ -74,7 +74,7 @@ > } > > public INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ ISimplePropertyListener listener) { > return new CheckStateListener(listener); > } > >@@ -90,9 +90,9 @@ > > private class CheckStateListener implements INativePropertyListener, > ICheckStateListener { >- private IPropertyChangeListener listener; >+ private ISimplePropertyListener listener; > >- private CheckStateListener(IPropertyChangeListener listener) { >+ private CheckStateListener(ISimplePropertyListener listener) { > this.listener = listener; > } > >@@ -103,7 +103,7 @@ > Set additions = checked ? elementSet : Collections.EMPTY_SET; > Set removals = checked ? Collections.EMPTY_SET : elementSet; > SetDiff diff = Diffs.createSetDiff(additions, removals); >- listener.handlePropertyChange(new PropertyChangeEvent(event >+ listener.handlePropertyChange(new SimplePropertyEvent(event > .getSource(), CheckableCheckedElementsProperty.this, diff)); > } > } >Index: src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderMultipleSelectionProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/viewers/Attic/SelectionProviderMultipleSelectionProperty.java,v >retrieving revision 1.1.2.7 >diff -u -r1.1.2.7 SelectionProviderMultipleSelectionProperty.java >--- src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderMultipleSelectionProperty.java 14 Jan 2009 23:51:12 -0000 1.1.2.7 >+++ src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderMultipleSelectionProperty.java 17 Jan 2009 00:49:36 -0000 >@@ -17,8 +17,8 @@ > > import org.eclipse.core.databinding.observable.list.ListDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; > import org.eclipse.jface.viewers.ISelection; > import org.eclipse.jface.viewers.ISelectionChangedListener; > import org.eclipse.jface.viewers.ISelectionProvider; >@@ -50,7 +50,7 @@ > } > > public INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ ISimplePropertyListener listener) { > return new SelectionChangedListener(listener); > } > >@@ -67,14 +67,14 @@ > > private class SelectionChangedListener implements INativePropertyListener, > ISelectionChangedListener { >- private IPropertyChangeListener listener; >+ private ISimplePropertyListener listener; > >- private SelectionChangedListener(IPropertyChangeListener listener) { >+ private SelectionChangedListener(ISimplePropertyListener listener) { > this.listener = listener; > } > > public void selectionChanged(SelectionChangedEvent event) { >- listener.handlePropertyChange(new PropertyChangeEvent(event >+ listener.handlePropertyChange(new SimplePropertyEvent(event > .getSource(), > SelectionProviderMultipleSelectionProperty.this, null)); > } >Index: src/org/eclipse/jface/internal/databinding/swt/ControlStringListProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/swt/Attic/ControlStringListProperty.java,v >retrieving revision 1.1.2.6 >diff -u -r1.1.2.6 ControlStringListProperty.java >--- src/org/eclipse/jface/internal/databinding/swt/ControlStringListProperty.java 6 Jan 2009 06:21:04 -0000 1.1.2.6 >+++ src/org/eclipse/jface/internal/databinding/swt/ControlStringListProperty.java 17 Jan 2009 00:49:36 -0000 >@@ -17,7 +17,7 @@ > > import org.eclipse.core.databinding.observable.list.ListDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > import org.eclipse.swt.widgets.Control; > > /** >@@ -44,7 +44,7 @@ > abstract String[] doGetStringList(Control control); > > public INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/jface/internal/databinding/swt/WidgetValueProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/swt/Attic/WidgetValueProperty.java,v >retrieving revision 1.1.2.8 >diff -u -r1.1.2.8 WidgetValueProperty.java >--- src/org/eclipse/jface/internal/databinding/swt/WidgetValueProperty.java 14 Jan 2009 23:51:12 -0000 1.1.2.8 >+++ src/org/eclipse/jface/internal/databinding/swt/WidgetValueProperty.java 17 Jan 2009 00:49:36 -0000 >@@ -14,8 +14,8 @@ > import org.eclipse.core.databinding.observable.Realm; > import org.eclipse.core.databinding.observable.value.IObservableValue; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; > import org.eclipse.core.databinding.property.value.SimpleValueProperty; > import org.eclipse.jface.databinding.swt.ISWTObservableValue; > import org.eclipse.jface.databinding.swt.SWTObservables; >@@ -39,8 +39,8 @@ > this.events = events; > } > >- protected INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ public INativePropertyListener adaptListener( >+ ISimplePropertyListener listener) { > return new WidgetListener(listener); > } > >@@ -70,14 +70,14 @@ > } > > private class WidgetListener implements INativePropertyListener, Listener { >- private final IPropertyChangeListener listener; >+ private final ISimplePropertyListener listener; > >- protected WidgetListener(IPropertyChangeListener listener) { >+ protected WidgetListener(ISimplePropertyListener listener) { > this.listener = listener; > } > > public void handleEvent(Event event) { >- listener.handlePropertyChange(new PropertyChangeEvent(event.widget, >+ listener.handlePropertyChange(new SimplePropertyEvent(event.widget, > WidgetValueProperty.this, null)); > } > } >#P org.eclipse.core.databinding >Index: src/org/eclipse/core/databinding/property/map/SimpleMapProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/property/map/Attic/SimpleMapProperty.java,v >retrieving revision 1.1.2.8 >diff -u -r1.1.2.8 SimpleMapProperty.java >--- src/org/eclipse/core/databinding/property/map/SimpleMapProperty.java 8 Jan 2009 01:24:50 -0000 1.1.2.8 >+++ src/org/eclipse/core/databinding/property/map/SimpleMapProperty.java 17 Jan 2009 00:49:38 -0000 >@@ -19,7 +19,8 @@ > import org.eclipse.core.databinding.observable.map.IObservableMap; > import org.eclipse.core.databinding.observable.map.MapDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.internal.databinding.property.map.SimpleMapPropertyObservableMap; > > /** > * Simplified abstract implementation of IMapProperty. This class takes care of >@@ -32,7 +33,7 @@ > * <li> {@link #getValueType()} > * <li> {@link #doGetMap(Object)} > * <li> {@link #doSetMap(Object, Map, MapDiff)} >- * <li> {@link #adaptListener(IPropertyChangeListener)} >+ * <li> {@link #adaptListener(ISimplePropertyListener)} > * <li> {@link #doAddListener(Object, INativePropertyListener)} > * <li> {@link #doRemoveListener(Object, INativePropertyListener)} > * </ul> >@@ -43,23 +44,14 @@ > * @since 1.2 > */ > public abstract class SimpleMapProperty extends MapProperty implements >- IMapProperty { >+ ISimpleMapProperty { > public IObservableMap observe(Realm realm, Object source) { > return new SimpleMapPropertyObservableMap(realm, source, this); > } > > // Accessors > >- /** >- * Returns an unmodifiable Map with the current contents of the source's map >- * property. >- * >- * @param source >- * the property source >- * @return a Map with the current contents of the source's map property >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final Map getMap(Object source) { >+ public final Map getMap(Object source) { > if (source == null) > return Collections.EMPTY_MAP; > return Collections.unmodifiableMap(doGetMap(source)); >@@ -77,18 +69,7 @@ > > // Mutators > >- /** >- * Updates the property on the source with the specified change. >- * >- * @param source >- * the property source >- * @param map >- * the new map >- * @param diff >- * a diff describing the change >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void setMap(Object source, Map map, MapDiff diff) { >+ public final void setMap(Object source, Map map, MapDiff diff) { > if (source != null && !diff.isEmpty()) > doSetMap(source, map, diff); > } >@@ -124,23 +105,23 @@ > * ISetProperty or IMapProperty) depending on the property. > * @noreference This method is not intended to be referenced by clients. > */ >- protected abstract INativePropertyListener adaptListener( >- IPropertyChangeListener listener); >+ public abstract INativePropertyListener adaptListener( >+ ISimplePropertyListener listener); > > /** > * Adds the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)} . >+ * {@link #adaptListener(ISimplePropertyListener)} . > * @noreference This method is not intended to be referenced by clients. > */ >- protected final void addListener(Object source, >+ public final void addListener(Object source, > INativePropertyListener listener) { > if (source != null) > doAddListener(source, listener); >@@ -149,14 +130,14 @@ > /** > * Adds the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)} . >+ * {@link #adaptListener(ISimplePropertyListener)} . > * @noreference This method is not intended to be referenced by clients. > */ > protected abstract void doAddListener(Object source, >@@ -165,17 +146,17 @@ > /** > * Removes the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)} . >+ * {@link #adaptListener(ISimplePropertyListener)} . > * @noreference This method is not intended to be referenced by clients. > */ >- protected final void removeListener(Object source, >+ public final void removeListener(Object source, > INativePropertyListener listener) { > if (source != null) > doRemoveListener(source, listener); >@@ -184,14 +165,14 @@ > /** > * Removes the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)} . >+ * {@link #adaptListener(ISimplePropertyListener)} . > * @noreference This method is not intended to be referenced by clients. > */ > protected abstract void doRemoveListener(Object source, >Index: src/org/eclipse/core/databinding/property/map/DelegatingMapProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/property/map/Attic/DelegatingMapProperty.java,v >retrieving revision 1.1.2.2 >diff -u -r1.1.2.2 DelegatingMapProperty.java >--- src/org/eclipse/core/databinding/property/map/DelegatingMapProperty.java 14 Jan 2009 23:51:11 -0000 1.1.2.2 >+++ src/org/eclipse/core/databinding/property/map/DelegatingMapProperty.java 17 Jan 2009 00:49:38 -0000 >@@ -18,7 +18,7 @@ > import org.eclipse.core.databinding.observable.map.IObservableMap; > import org.eclipse.core.databinding.observable.map.MapDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > > /** > * @since 1.2 >@@ -38,7 +38,16 @@ > this.valueType = valueType; > } > >- protected final IMapProperty getDelegate(Object source) { >+ /** >+ * Returns the property to delegate to for the specified source object. >+ * Repeated calls to this method with the same source object returns the >+ * same delegate instance. >+ * >+ * @param source >+ * the property source (may be null) >+ * @return the property to delegate to for the specified source object. >+ */ >+ public final IMapProperty getDelegate(Object source) { > if (source == null) > return null; > IMapProperty delegate = doGetDelegate(source); >@@ -47,6 +56,15 @@ > return delegate; > } > >+ /** >+ * Returns the property to delegate to for the specified source object. >+ * Implementers must ensure that repeated calls to this method with the same >+ * source object returns the same delegate instance. >+ * >+ * @param source >+ * the property source >+ * @return the property to delegate to for the specified source object. >+ */ > protected abstract IMapProperty doGetDelegate(Object source); > > public Object getKeyType() { >@@ -69,8 +87,8 @@ > protected void doSetMap(Object source, Map map, MapDiff diff) { > } > >- protected INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ public INativePropertyListener adaptListener( >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/core/databinding/property/map/SimpleMapPropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/map/SimpleMapPropertyObservableMap.java >diff -N src/org/eclipse/core/databinding/property/map/SimpleMapPropertyObservableMap.java >--- src/org/eclipse/core/databinding/property/map/SimpleMapPropertyObservableMap.java 14 Jan 2009 23:51:11 -0000 1.1.2.5 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,296 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.map; >- >-import java.util.AbstractSet; >-import java.util.Collection; >-import java.util.Collections; >-import java.util.ConcurrentModificationException; >-import java.util.HashMap; >-import java.util.HashSet; >-import java.util.Iterator; >-import java.util.Map; >-import java.util.Set; >- >-import org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.ObservableTracker; >-import org.eclipse.core.databinding.observable.Realm; >-import org.eclipse.core.databinding.observable.map.AbstractObservableMap; >-import org.eclipse.core.databinding.observable.map.MapDiff; >-import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IProperty; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.IPropertyObservable; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >- >-/** >- * @since 1.2 >- */ >-class SimpleMapPropertyObservableMap extends AbstractObservableMap implements >- IPropertyObservable { >- private Object source; >- private SimpleMapProperty property; >- >- private volatile boolean updating = false; >- >- private volatile int modCount = 0; >- >- private INativePropertyListener listener; >- >- private Map cachedMap; >- >- /** >- * @param realm >- * @param source >- * @param property >- */ >- public SimpleMapPropertyObservableMap(Realm realm, Object source, >- SimpleMapProperty property) { >- super(realm); >- this.source = source; >- this.property = property; >- } >- >- public Object getKeyType() { >- return property.getKeyType(); >- } >- >- public Object getValueType() { >- return property.getValueType(); >- } >- >- private void getterCalled() { >- ObservableTracker.getterCalled(this); >- } >- >- protected void firstListenerAdded() { >- if (!isDisposed()) { >- cachedMap = new HashMap(this); >- >- if (listener == null) { >- listener = property >- .adaptListener(new IPropertyChangeListener() { >- public void handlePropertyChange( >- final PropertyChangeEvent event) { >- modCount++; >- if (!isDisposed() && !updating) { >- getRealm().exec(new Runnable() { >- public void run() { >- notifyIfChanged((MapDiff) event.diff); >- } >- }); >- } >- } >- }); >- } >- property.addListener(source, listener); >- } >- } >- >- protected void lastListenerRemoved() { >- if (listener != null) { >- property.removeListener(source, listener); >- } >- >- cachedMap.clear(); >- cachedMap = null; >- } >- >- // Queries >- >- private Map getMap() { >- return property.getMap(source); >- } >- >- // Single change operations >- >- private EntrySet es = new EntrySet(); >- >- public Set entrySet() { >- getterCalled(); >- return es; >- } >- >- private class EntrySet extends AbstractSet { >- public Iterator iterator() { >- return new EntrySetIterator(); >- } >- >- public int size() { >- return getMap().size(); >- } >- } >- >- private class EntrySetIterator implements Iterator { >- private volatile int expectedModCount = modCount; >- Map map = new HashMap(getMap()); >- Iterator iterator = map.entrySet().iterator(); >- Map.Entry last = null; >- >- public boolean hasNext() { >- getterCalled(); >- checkForComodification(); >- return iterator.hasNext(); >- } >- >- public Object next() { >- getterCalled(); >- checkForComodification(); >- last = (Map.Entry) iterator.next(); >- return last; >- } >- >- public void remove() { >- getterCalled(); >- checkForComodification(); >- >- iterator.remove(); // stay in sync >- MapDiff diff = Diffs.createMapDiffSingleRemove(last.getKey(), last >- .getValue()); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setMap(source, map, diff); >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- last = null; >- expectedModCount = modCount; >- } >- >- private void checkForComodification() { >- if (expectedModCount != modCount) >- throw new ConcurrentModificationException(); >- } >- } >- >- public Set keySet() { >- getterCalled(); >- // AbstractMap depends on entrySet() to fulfil keySet() API, so all >- // getterCalled() and comodification checks will still be handled >- return super.keySet(); >- } >- >- public Object put(Object key, Object value) { >- checkRealm(); >- >- Map map = new HashMap(getMap()); >- >- boolean add = !map.containsKey(key); >- >- Object oldValue = map.put(key, value); >- >- MapDiff diff; >- if (add) >- diff = Diffs.createMapDiffSingleAdd(key, value); >- else >- diff = Diffs.createMapDiffSingleChange(key, oldValue, value); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setMap(source, map, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return oldValue; >- } >- >- public void putAll(Map m) { >- checkRealm(); >- >- Map map = new HashMap(getMap()); >- >- Map oldValues = new HashMap(); >- Map newValues = new HashMap(); >- Set changedKeys = new HashSet(); >- Set addedKeys = new HashSet(); >- for (Iterator it = m.entrySet().iterator(); it.hasNext();) { >- Map.Entry entry = (Entry) it.next(); >- Object key = entry.getKey(); >- Object newValue = entry.getValue(); >- if (map.containsKey(key)) { >- changedKeys.add(key); >- oldValues.put(key, map.get(key)); >- } else { >- addedKeys.add(key); >- } >- map.put(key, newValue); >- >- newValues.put(key, newValue); >- } >- >- MapDiff diff = Diffs.createMapDiff(addedKeys, Collections.EMPTY_SET, >- changedKeys, oldValues, newValues); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setMap(source, map, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- } >- >- public Object remove(Object key) { >- checkRealm(); >- return super.remove(key); >- } >- >- public Collection values() { >- getterCalled(); >- // AbstractMap depends on entrySet() to fulfil values() API, so all >- // getterCalled() and comodification checks will still be handled >- return super.values(); >- } >- >- private void notifyIfChanged(MapDiff diff) { >- if (hasListeners()) { >- Map oldMap = cachedMap; >- Map newMap = cachedMap = property.getMap(source); >- if (diff == null) >- diff = Diffs.computeMapDiff(oldMap, newMap); >- if (!diff.isEmpty()) >- fireMapChange(diff); >- } >- } >- >- public Object getObserved() { >- return source; >- } >- >- public IProperty getProperty() { >- return property; >- } >- >- public synchronized void dispose() { >- if (!isDisposed()) { >- if (listener != null) >- property.removeListener(source, listener); >- property = null; >- source = null; >- listener = null; >- } >- super.dispose(); >- } >-} >Index: src/org/eclipse/core/databinding/property/value/ObservableSetDelegatingValuePropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/value/ObservableSetDelegatingValuePropertyObservableMap.java >diff -N src/org/eclipse/core/databinding/property/value/ObservableSetDelegatingValuePropertyObservableMap.java >--- src/org/eclipse/core/databinding/property/value/ObservableSetDelegatingValuePropertyObservableMap.java 8 Jan 2009 01:24:49 -0000 1.1.2.1 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,235 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.value; >- >-import java.util.AbstractSet; >-import java.util.Collections; >-import java.util.HashMap; >-import java.util.Iterator; >-import java.util.Map; >-import java.util.Set; >- >-import org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.IObserving; >-import org.eclipse.core.databinding.observable.IStaleListener; >-import org.eclipse.core.databinding.observable.ObservableTracker; >-import org.eclipse.core.databinding.observable.StaleEvent; >-import org.eclipse.core.databinding.observable.map.AbstractObservableMap; >-import org.eclipse.core.databinding.observable.map.MapDiff; >-import org.eclipse.core.databinding.observable.set.IObservableSet; >-import org.eclipse.core.databinding.observable.set.ISetChangeListener; >-import org.eclipse.core.databinding.observable.set.SetChangeEvent; >-import org.eclipse.core.databinding.observable.set.SetDiff; >-import org.eclipse.core.internal.databinding.Util; >- >-/** >- * @since 1.2 >- */ >-class ObservableSetDelegatingValuePropertyObservableMap extends >- AbstractObservableMap implements IObserving { >- private IObservableSet masterSet; >- private DelegatingValueProperty detailProperty; >- private DelegatingCache cache; >- >- private Set entrySet; >- >- class EntrySet extends AbstractSet { >- public Iterator iterator() { >- return new Iterator() { >- final Iterator it = masterSet.iterator(); >- >- public boolean hasNext() { >- return it.hasNext(); >- } >- >- public Object next() { >- return new MapEntry(it.next()); >- } >- >- public void remove() { >- it.remove(); >- } >- }; >- } >- >- public int size() { >- return masterSet.size(); >- } >- } >- >- class MapEntry implements Map.Entry { >- private final Object key; >- >- MapEntry(Object key) { >- this.key = key; >- } >- >- public Object getKey() { >- getterCalled(); >- return key; >- } >- >- public Object getValue() { >- getterCalled(); >- >- if (!masterSet.contains(key)) >- return null; >- >- return cache.get(key); >- } >- >- public Object setValue(Object value) { >- checkRealm(); >- >- if (!masterSet.contains(key)) >- return null; >- >- return cache.put(key, value); >- } >- >- public boolean equals(Object o) { >- getterCalled(); >- if (o == this) >- return true; >- if (o == null) >- return false; >- if (!(o instanceof Map.Entry)) >- return false; >- Map.Entry that = (Map.Entry) o; >- return Util.equals(this.getKey(), that.getKey()) >- && Util.equals(this.getValue(), that.getValue()); >- } >- >- public int hashCode() { >- getterCalled(); >- Object value = getValue(); >- return (key == null ? 0 : key.hashCode()) >- ^ (value == null ? 0 : value.hashCode()); >- } >- } >- >- private ISetChangeListener masterListener = new ISetChangeListener() { >- public void handleSetChange(SetChangeEvent event) { >- if (isDisposed()) >- return; >- >- cache.addAll(masterSet); >- >- // Need both obsolete and new elements to convert diff >- MapDiff diff = convertDiff(event.diff); >- >- cache.retainAll(masterSet); >- >- fireMapChange(diff); >- } >- >- private MapDiff convertDiff(SetDiff diff) { >- // Convert diff to detail value >- Map oldValues = new HashMap(); >- Map newValues = new HashMap(); >- >- for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) { >- Object masterElement = it.next(); >- oldValues.put(masterElement, cache.get(masterElement)); >- } >- for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) { >- Object masterElement = it.next(); >- newValues.put(masterElement, cache.get(masterElement)); >- } >- return Diffs.createMapDiff(diff.getAdditions(), diff.getRemovals(), >- Collections.EMPTY_SET, oldValues, newValues); >- } >- }; >- >- private IStaleListener staleListener = new IStaleListener() { >- public void handleStale(StaleEvent staleEvent) { >- fireStale(); >- } >- }; >- >- /** >- * @param keySet >- * @param valueProperty >- */ >- public ObservableSetDelegatingValuePropertyObservableMap( >- IObservableSet keySet, DelegatingValueProperty valueProperty) { >- super(keySet.getRealm()); >- this.masterSet = keySet; >- this.detailProperty = valueProperty; >- this.cache = new DelegatingCache(getRealm(), valueProperty) { >- void handleValueChange(Object masterElement, Object oldValue, >- Object newValue) { >- fireMapChange(Diffs.createMapDiffSingleChange(masterElement, >- oldValue, newValue)); >- } >- }; >- cache.addAll(masterSet); >- >- masterSet.addSetChangeListener(masterListener); >- masterSet.addStaleListener(staleListener); >- } >- >- public Set entrySet() { >- getterCalled(); >- if (entrySet == null) >- entrySet = new EntrySet(); >- return entrySet; >- } >- >- private void getterCalled() { >- ObservableTracker.getterCalled(this); >- } >- >- public Object get(Object key) { >- getterCalled(); >- return cache.get(key); >- } >- >- public Object put(Object key, Object value) { >- checkRealm(); >- return cache.put(key, value); >- } >- >- public boolean isStale() { >- return masterSet.isStale(); >- } >- >- public Object getObserved() { >- return masterSet; >- } >- >- public Object getKeyType() { >- return masterSet.getElementType(); >- } >- >- public Object getValueType() { >- return detailProperty.getValueType(); >- } >- >- public synchronized void dispose() { >- if (masterSet != null) { >- masterSet.removeSetChangeListener(masterListener); >- masterSet.removeStaleListener(staleListener); >- masterSet = null; >- } >- >- if (cache != null) { >- cache.dispose(); >- cache = null; >- } >- >- masterListener = null; >- detailProperty = null; >- >- super.dispose(); >- } >-} >Index: src/org/eclipse/core/databinding/property/value/DelegatingCache.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/value/DelegatingCache.java >diff -N src/org/eclipse/core/databinding/property/value/DelegatingCache.java >--- src/org/eclipse/core/databinding/property/value/DelegatingCache.java 8 Jan 2009 01:24:49 -0000 1.1.2.1 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,208 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2009 IBM Corporation and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * IBM Corporation - initial API and implementation >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.value; >- >-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 org.eclipse.core.databinding.observable.Realm; >-import org.eclipse.core.databinding.observable.map.IMapChangeListener; >-import org.eclipse.core.databinding.observable.map.IObservableMap; >-import org.eclipse.core.databinding.observable.map.MapChangeEvent; >-import org.eclipse.core.databinding.observable.set.IObservableSet; >-import org.eclipse.core.databinding.observable.set.ISetChangeListener; >-import org.eclipse.core.databinding.observable.set.SetChangeEvent; >-import org.eclipse.core.databinding.observable.set.WritableSet; >-import org.eclipse.core.internal.databinding.IdentityWrapper; >-import org.eclipse.core.internal.databinding.Util; >- >-/** >- * @since 3.3 >- * >- */ >-abstract class DelegatingCache { >- private Realm realm; >- private DelegatingValueProperty detailProperty; >- private IObservableSet elements; >- private Map delegateCaches; >- >- private class DelegateCache implements IMapChangeListener { >- private final IValueProperty delegate; >- private final IObservableSet masterElements; >- private final IObservableMap masterElementValues; >- private final Map cachedValues; >- >- DelegateCache(IValueProperty delegate) { >- this.delegate = delegate; >- this.masterElements = new WritableSet(realm, Collections.EMPTY_SET, >- elements.getElementType()); >- this.masterElementValues = delegate.observeDetail(masterElements); >- this.cachedValues = new HashMap(); >- >- masterElementValues.addMapChangeListener(this); >- } >- >- void add(Object masterElement) { >- boolean wasEmpty = masterElements.isEmpty(); >- >- masterElements.add(masterElement); >- cachedValues.put(new IdentityWrapper(masterElement), >- masterElementValues.get(masterElement)); >- >- if (wasEmpty) >- delegateCaches.put(delegate, this); >- } >- >- void remove(Object masterElement) { >- cachedValues.remove(new IdentityWrapper(masterElement)); >- masterElements.remove(masterElement); >- if (cachedValues.isEmpty()) >- dispose(); >- } >- >- Object get(Object masterElement) { >- return cachedValues.get(new IdentityWrapper(masterElement)); >- } >- >- Object put(Object masterElement, Object detailValue) { >- Object oldValue = masterElementValues.put(masterElement, >- detailValue); >- notifyIfChanged(masterElement); >- return oldValue; >- } >- >- boolean containsValue(Object detailValue) { >- return cachedValues.containsValue(detailValue); >- } >- >- public void handleMapChange(MapChangeEvent event) { >- Set changedKeys = event.diff.getChangedKeys(); >- for (Iterator it = changedKeys.iterator(); it.hasNext();) >- notifyIfChanged(it.next()); >- } >- >- private void notifyIfChanged(Object masterElement) { >- Object oldValue = cachedValues.get(new IdentityWrapper( >- masterElement)); >- Object newValue = masterElementValues.get(masterElement); >- if (!Util.equals(oldValue, newValue)) { >- cachedValues.put(new IdentityWrapper(masterElement), newValue); >- handleValueChange(masterElement, oldValue, newValue); >- } >- } >- >- void handleValueChange(Object masterElement, Object oldValue, >- Object newValue) { >- DelegatingCache.this.handleValueChange(masterElement, oldValue, >- newValue); >- } >- >- void dispose() { >- delegateCaches.remove(delegate); >- masterElementValues.dispose(); >- masterElements.dispose(); >- cachedValues.clear(); >- } >- } >- >- DelegatingCache(Realm realm, DelegatingValueProperty detailProperty) { >- this.realm = realm; >- this.detailProperty = detailProperty; >- >- this.elements = new WritableSet(realm); >- this.delegateCaches = new HashMap(); >- >- elements.addSetChangeListener(new ISetChangeListener() { >- public void handleSetChange(SetChangeEvent event) { >- for (Iterator it = event.diff.getRemovals().iterator(); it >- .hasNext();) { >- IdentityWrapper wrapper = (IdentityWrapper) it.next(); >- Object element = wrapper.unwrap(); >- getCache(element).remove(element); >- >- } >- for (Iterator it = event.diff.getAdditions().iterator(); it >- .hasNext();) { >- IdentityWrapper wrapper = (IdentityWrapper) it.next(); >- Object element = wrapper.unwrap(); >- getCache(element).add(element); >- } >- } >- }); >- } >- >- private DelegateCache getCache(Object masterElement) { >- IValueProperty delegate = detailProperty.getDelegate(masterElement); >- if (delegateCaches.containsKey(delegate)) { >- return (DelegateCache) delegateCaches.get(delegate); >- } >- return new DelegateCache(delegate); >- } >- >- Object get(Object element) { >- return getCache(element).get(element); >- } >- >- Object put(Object element, Object value) { >- return getCache(element).put(element, value); >- } >- >- boolean contains(Object value) { >- for (Iterator it = delegateCaches.values().iterator(); it.hasNext();) { >- DelegateCache cache = (DelegateCache) it.next(); >- if (cache.containsValue(value)) >- return true; >- } >- return false; >- } >- >- private Set identitySet(Collection elements) { >- Set result = new HashSet(); >- for (Iterator it = elements.iterator(); it.hasNext();) { >- result.add(new IdentityWrapper(it.next())); >- } >- return result; >- } >- >- void addAll(Collection elements) { >- this.elements.addAll(identitySet(elements)); >- } >- >- void retainAll(Collection elements) { >- this.elements.retainAll(identitySet(elements)); >- } >- >- abstract void handleValueChange(Object masterElement, Object oldValue, >- Object newValue); >- >- void dispose() { >- if (elements != null) { >- elements.clear(); // clears caches >- elements.dispose(); >- elements = null; >- } >- >- if (delegateCaches != null) { >- for (Iterator it = delegateCaches.values().iterator(); it.hasNext();) { >- DelegateCache cache = (DelegateCache) it.next(); >- cache.dispose(); >- } >- delegateCaches.clear(); >- delegateCaches = null; >- } >- } >-} >Index: src/org/eclipse/core/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java >diff -N src/org/eclipse/core/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java >--- src/org/eclipse/core/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java 23 Dec 2008 18:24:44 -0000 1.1.2.4 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,443 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.value; >- >-import java.lang.reflect.Array; >-import java.util.ArrayList; >-import java.util.Collection; >-import java.util.HashMap; >-import java.util.HashSet; >-import java.util.Iterator; >-import java.util.List; >-import java.util.ListIterator; >-import java.util.Map; >-import java.util.Set; >- >-import org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.IObserving; >-import org.eclipse.core.databinding.observable.IStaleListener; >-import org.eclipse.core.databinding.observable.ObservableTracker; >-import org.eclipse.core.databinding.observable.StaleEvent; >-import org.eclipse.core.databinding.observable.list.AbstractObservableList; >-import org.eclipse.core.databinding.observable.list.IListChangeListener; >-import org.eclipse.core.databinding.observable.list.IObservableList; >-import org.eclipse.core.databinding.observable.list.ListChangeEvent; >-import org.eclipse.core.databinding.observable.list.ListDiff; >-import org.eclipse.core.databinding.observable.list.ListDiffEntry; >-import org.eclipse.core.databinding.observable.set.IObservableSet; >-import org.eclipse.core.databinding.observable.set.ISetChangeListener; >-import org.eclipse.core.databinding.observable.set.SetChangeEvent; >-import org.eclipse.core.databinding.observable.set.WritableSet; >-import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >-import org.eclipse.core.internal.databinding.IdentityWrapper; >-import org.eclipse.core.internal.databinding.Util; >- >-/** >- * @since 1.2 >- */ >-class ObservableListSimpleValuePropertyObservableList extends >- AbstractObservableList implements IObserving { >- private IObservableList masterList; >- private SimpleValueProperty detailProperty; >- >- private IObservableSet knownMasterElements; >- private Map cachedValues; >- >- private boolean updating; >- >- private IListChangeListener masterListener = new IListChangeListener() { >- public void handleListChange(ListChangeEvent event) { >- if (!isDisposed()) { >- updateKnownElements(); >- fireListChange(convertDiff(event.diff)); >- } >- } >- >- private void updateKnownElements() { >- Set identityKnownElements = new HashSet(); >- for (Iterator it = masterList.iterator(); it.hasNext();) { >- identityKnownElements.add(new IdentityWrapper(it.next())); >- } >- >- knownMasterElements.retainAll(identityKnownElements); >- knownMasterElements.addAll(identityKnownElements); >- } >- >- private ListDiff convertDiff(ListDiff diff) { >- // Convert diff to detail value >- ListDiffEntry[] masterEntries = diff.getDifferences(); >- ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length]; >- for (int i = 0; i < masterEntries.length; i++) { >- ListDiffEntry masterDifference = masterEntries[i]; >- int index = masterDifference.getPosition(); >- boolean addition = masterDifference.isAddition(); >- Object masterElement = masterDifference.getElement(); >- Object elementDetailValue = detailProperty >- .getValue(masterElement); >- detailEntries[i] = Diffs.createListDiffEntry(index, addition, >- elementDetailValue); >- } >- return Diffs.createListDiff(detailEntries); >- } >- }; >- >- private IStaleListener staleListener = new IStaleListener() { >- public void handleStale(StaleEvent staleEvent) { >- fireStale(); >- } >- }; >- >- private INativePropertyListener detailListener; >- >- /** >- * @param masterList >- * @param valueProperty >- */ >- public ObservableListSimpleValuePropertyObservableList( >- IObservableList masterList, SimpleValueProperty valueProperty) { >- super(masterList.getRealm()); >- this.masterList = masterList; >- this.detailProperty = valueProperty; >- >- IPropertyChangeListener listener = new IPropertyChangeListener() { >- public void handlePropertyChange(PropertyChangeEvent event) { >- if (!isDisposed() && !updating) { >- notifyIfChanged(event.getSource()); >- } >- } >- }; >- this.detailListener = detailProperty.adaptListener(listener); >- } >- >- protected void firstListenerAdded() { >- knownMasterElements = new WritableSet(getRealm()); >- cachedValues = new HashMap(); >- knownMasterElements.addSetChangeListener(new ISetChangeListener() { >- public void handleSetChange(SetChangeEvent event) { >- for (Iterator it = event.diff.getRemovals().iterator(); it >- .hasNext();) { >- IdentityWrapper wrapper = (IdentityWrapper) it.next(); >- Object key = wrapper.unwrap(); >- detailProperty.removeListener(key, detailListener); >- cachedValues.remove(wrapper); >- } >- for (Iterator it = event.diff.getAdditions().iterator(); it >- .hasNext();) { >- IdentityWrapper wrapper = (IdentityWrapper) it.next(); >- Object key = wrapper.unwrap(); >- cachedValues.put(wrapper, detailProperty.getValue(key)); >- detailProperty.addListener(key, detailListener); >- } >- } >- }); >- for (Iterator it = masterList.iterator(); it.hasNext();) { >- knownMasterElements.add(new IdentityWrapper(it.next())); >- } >- >- masterList.addListChangeListener(masterListener); >- masterList.addStaleListener(staleListener); >- } >- >- protected void lastListenerRemoved() { >- masterList.removeListChangeListener(masterListener); >- masterList.removeStaleListener(staleListener); >- if (knownMasterElements != null) { >- knownMasterElements.clear(); // clears cachedValues >- knownMasterElements.dispose(); >- knownMasterElements = null; >- } >- cachedValues.clear(); >- cachedValues = null; >- } >- >- protected int doGetSize() { >- getterCalled(); >- return masterList.size(); >- } >- >- private void getterCalled() { >- ObservableTracker.getterCalled(this); >- } >- >- public Object getElementType() { >- return detailProperty.getValueType(); >- } >- >- public Object get(int index) { >- getterCalled(); >- Object masterElement = masterList.get(index); >- return detailProperty.getValue(masterElement); >- } >- >- public boolean add(Object o) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean addAll(Collection c) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean addAll(int index, Collection c) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean contains(Object o) { >- getterCalled(); >- >- for (Iterator it = masterList.iterator(); it.hasNext();) { >- if (Util.equals(detailProperty.getValue(it.next()), o)) >- return true; >- } >- return false; >- } >- >- public boolean isEmpty() { >- getterCalled(); >- return masterList.isEmpty(); >- } >- >- public boolean isStale() { >- getterCalled(); >- return masterList.isStale(); >- } >- >- public Iterator iterator() { >- getterCalled(); >- return new Iterator() { >- Iterator it = masterList.iterator(); >- >- public boolean hasNext() { >- getterCalled(); >- return it.hasNext(); >- } >- >- public Object next() { >- getterCalled(); >- Object masterElement = it.next(); >- return detailProperty.getValue(masterElement); >- } >- >- public void remove() { >- throw new UnsupportedOperationException(); >- } >- }; >- } >- >- public Object move(int oldIndex, int newIndex) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean remove(Object o) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean removeAll(Collection c) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean retainAll(Collection c) { >- throw new UnsupportedOperationException(); >- } >- >- public Object[] toArray() { >- getterCalled(); >- Object[] masterElements = masterList.toArray(); >- Object[] result = new Object[masterElements.length]; >- for (int i = 0; i < result.length; i++) { >- result[i] = detailProperty.getValue(masterElements[i]); >- } >- return result; >- } >- >- public Object[] toArray(Object[] a) { >- getterCalled(); >- Object[] masterElements = masterList.toArray(); >- if (a.length < masterElements.length) >- a = (Object[]) Array.newInstance(a.getClass().getComponentType(), >- masterElements.length); >- for (int i = 0; i < masterElements.length; i++) { >- a[i] = detailProperty.getValue(masterElements[i]); >- } >- return a; >- } >- >- public void add(int index, Object o) { >- throw new UnsupportedOperationException(); >- } >- >- public void clear() { >- throw new UnsupportedOperationException(); >- } >- >- public ListIterator listIterator() { >- return listIterator(0); >- } >- >- public ListIterator listIterator(final int index) { >- getterCalled(); >- return new ListIterator() { >- ListIterator it = masterList.listIterator(index); >- Object lastMasterElement; >- Object lastElement; >- boolean haveIterated = false; >- >- public void add(Object arg0) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean hasNext() { >- getterCalled(); >- return it.hasNext(); >- } >- >- public boolean hasPrevious() { >- getterCalled(); >- return it.hasPrevious(); >- } >- >- public Object next() { >- getterCalled(); >- lastMasterElement = it.next(); >- lastElement = detailProperty.getValue(lastMasterElement); >- haveIterated = true; >- return lastElement; >- } >- >- public int nextIndex() { >- getterCalled(); >- return it.nextIndex(); >- } >- >- public Object previous() { >- getterCalled(); >- lastMasterElement = it.previous(); >- lastElement = detailProperty.getValue(lastMasterElement); >- haveIterated = true; >- return lastElement; >- } >- >- public int previousIndex() { >- getterCalled(); >- return it.previousIndex(); >- } >- >- public void remove() { >- throw new UnsupportedOperationException(); >- } >- >- public void set(Object o) { >- checkRealm(); >- if (!haveIterated) >- throw new IllegalStateException(); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- detailProperty.setValue(lastElement, o); >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(lastMasterElement); >- >- lastElement = o; >- } >- }; >- } >- >- private void notifyIfChanged(Object masterElement) { >- if (cachedValues != null) { >- Object oldValue = cachedValues.get(new IdentityWrapper( >- masterElement)); >- Object newValue = detailProperty.getValue(masterElement); >- if (!Util.equals(oldValue, newValue)) { >- cachedValues.put(new IdentityWrapper(masterElement), newValue); >- fireListChange(indicesOf(masterElement), oldValue, newValue); >- } >- } >- } >- >- private int[] indicesOf(Object masterElement) { >- List indices = new ArrayList(); >- >- for (ListIterator it = ObservableListSimpleValuePropertyObservableList.this.masterList >- .listIterator(); it.hasNext();) { >- if (masterElement == it.next()) >- indices.add(new Integer(it.previousIndex())); >- } >- >- int[] result = new int[indices.size()]; >- for (int i = 0; i < result.length; i++) { >- result[i] = ((Integer) indices.get(i)).intValue(); >- } >- return result; >- } >- >- private void fireListChange(int[] indices, Object oldValue, Object newValue) { >- ListDiffEntry[] differences = new ListDiffEntry[indices.length * 2]; >- for (int i = 0; i < indices.length; i++) { >- int index = indices[i]; >- differences[i * 2] = Diffs.createListDiffEntry(index, false, >- oldValue); >- differences[i * 2 + 1] = Diffs.createListDiffEntry(index, true, >- newValue); >- } >- fireListChange(Diffs.createListDiff(differences)); >- } >- >- public Object remove(int index) { >- throw new UnsupportedOperationException(); >- } >- >- public Object set(int index, Object o) { >- checkRealm(); >- Object masterElement = masterList.get(index); >- Object oldValue = detailProperty.getValue(masterElement); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- detailProperty.setValue(masterElement, o); >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(masterElement); >- >- return oldValue; >- } >- >- public Object getObserved() { >- return masterList; >- } >- >- public synchronized void dispose() { >- if (masterList != null) { >- masterList.removeListChangeListener(masterListener); >- masterList = null; >- } >- if (knownMasterElements != null) { >- knownMasterElements.clear(); // detaches listeners >- knownMasterElements.dispose(); >- knownMasterElements = null; >- } >- >- masterListener = null; >- detailListener = null; >- detailProperty = null; >- cachedValues = null; >- >- super.dispose(); >- } >-} >\ No newline at end of file >Index: src/org/eclipse/core/databinding/property/value/ObservableMapDelegatingValuePropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/value/ObservableMapDelegatingValuePropertyObservableMap.java >diff -N src/org/eclipse/core/databinding/property/value/ObservableMapDelegatingValuePropertyObservableMap.java >--- src/org/eclipse/core/databinding/property/value/ObservableMapDelegatingValuePropertyObservableMap.java 8 Jan 2009 01:24:49 -0000 1.1.2.1 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,310 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.value; >- >-import java.util.AbstractSet; >-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 org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.IObserving; >-import org.eclipse.core.databinding.observable.IStaleListener; >-import org.eclipse.core.databinding.observable.ObservableTracker; >-import org.eclipse.core.databinding.observable.StaleEvent; >-import org.eclipse.core.databinding.observable.map.AbstractObservableMap; >-import org.eclipse.core.databinding.observable.map.IMapChangeListener; >-import org.eclipse.core.databinding.observable.map.IObservableMap; >-import org.eclipse.core.databinding.observable.map.MapChangeEvent; >-import org.eclipse.core.databinding.observable.map.MapDiff; >-import org.eclipse.core.internal.databinding.Util; >- >-/** >- * @since 1.2 >- */ >-class ObservableMapDelegatingValuePropertyObservableMap extends >- AbstractObservableMap implements IObserving { >- private IObservableMap masterMap; >- private DelegatingValueProperty detailProperty; >- private DelegatingCache cache; >- >- private Set entrySet; >- >- class EntrySet extends AbstractSet { >- public Iterator iterator() { >- return new Iterator() { >- Iterator it = masterMap.entrySet().iterator(); >- >- public boolean hasNext() { >- getterCalled(); >- return it.hasNext(); >- } >- >- public Object next() { >- getterCalled(); >- Map.Entry next = (Map.Entry) it.next(); >- return new MapEntry(next.getKey()); >- } >- >- public void remove() { >- it.remove(); >- } >- }; >- } >- >- public int size() { >- return masterMap.size(); >- } >- } >- >- class MapEntry implements Map.Entry { >- private Object key; >- >- MapEntry(Object key) { >- this.key = key; >- } >- >- public Object getKey() { >- getterCalled(); >- return key; >- } >- >- public Object getValue() { >- getterCalled(); >- >- if (!masterMap.containsKey(key)) >- return null; >- >- Object masterValue = masterMap.get(key); >- return cache.get(masterValue); >- } >- >- public Object setValue(Object value) { >- checkRealm(); >- >- if (!masterMap.containsKey(key)) >- return null; >- >- Object masterValue = masterMap.get(key); >- return cache.put(masterValue, value); >- } >- >- public boolean equals(Object o) { >- getterCalled(); >- if (o == this) >- return true; >- if (o == null) >- return false; >- if (!(o instanceof Map.Entry)) >- return false; >- Map.Entry that = (Map.Entry) o; >- return Util.equals(this.getKey(), that.getKey()) >- && Util.equals(this.getValue(), that.getValue()); >- } >- >- public int hashCode() { >- getterCalled(); >- Object value = getValue(); >- return (key == null ? 0 : key.hashCode()) >- ^ (value == null ? 0 : value.hashCode()); >- } >- } >- >- private IMapChangeListener masterListener = new IMapChangeListener() { >- public void handleMapChange(final MapChangeEvent event) { >- if (isDisposed()) >- return; >- >- cache.addAll(masterMap.values()); >- >- // Need both obsolete and new master values to convert diff >- MapDiff diff = convertDiff(event.diff); >- >- cache.retainAll(masterMap.values()); >- >- fireMapChange(diff); >- } >- >- private MapDiff convertDiff(MapDiff diff) { >- Map oldValues = new HashMap(); >- Map newValues = new HashMap(); >- >- Set addedKeys = diff.getAddedKeys(); >- for (Iterator it = addedKeys.iterator(); it.hasNext();) { >- Object key = it.next(); >- Object masterValue = diff.getNewValue(key); >- Object newValue = cache.get(masterValue); >- newValues.put(key, newValue); >- } >- >- Set removedKeys = diff.getRemovedKeys(); >- for (Iterator it = removedKeys.iterator(); it.hasNext();) { >- Object key = it.next(); >- Object masterValue = diff.getOldValue(key); >- Object oldValue = cache.get(masterValue); >- oldValues.put(key, oldValue); >- } >- >- Set changedKeys = new HashSet(diff.getChangedKeys()); >- for (Iterator it = changedKeys.iterator(); it.hasNext();) { >- Object key = it.next(); >- >- Object oldMasterValue = diff.getOldValue(key); >- Object newMasterValue = diff.getNewValue(key); >- >- Object oldValue = cache.get(oldMasterValue); >- Object newValue = cache.get(newMasterValue); >- >- if (Util.equals(oldValue, newValue)) { >- it.remove(); >- } else { >- oldValues.put(key, oldValue); >- newValues.put(key, newValue); >- } >- } >- >- return Diffs.createMapDiff(addedKeys, removedKeys, changedKeys, >- oldValues, newValues); >- } >- }; >- >- private IStaleListener staleListener = new IStaleListener() { >- public void handleStale(StaleEvent staleEvent) { >- fireStale(); >- } >- }; >- >- /** >- * @param map >- * @param valueProperty >- */ >- public ObservableMapDelegatingValuePropertyObservableMap( >- IObservableMap map, DelegatingValueProperty valueProperty) { >- super(map.getRealm()); >- this.masterMap = map; >- this.detailProperty = valueProperty; >- this.cache = new DelegatingCache(getRealm(), valueProperty) { >- void handleValueChange(Object masterElement, Object oldValue, >- Object newValue) { >- fireMapChange(keysFor(masterElement), oldValue, newValue); >- } >- }; >- cache.addAll(masterMap.values()); >- >- masterMap.addMapChangeListener(masterListener); >- masterMap.addStaleListener(staleListener); >- } >- >- public Set entrySet() { >- getterCalled(); >- if (entrySet == null) >- entrySet = new EntrySet(); >- return entrySet; >- } >- >- private void getterCalled() { >- ObservableTracker.getterCalled(this); >- } >- >- public Object get(Object key) { >- getterCalled(); >- Object masterValue = masterMap.get(key); >- return cache.get(masterValue); >- } >- >- public Object put(Object key, Object value) { >- if (!masterMap.containsKey(key)) >- return null; >- Object masterValue = masterMap.get(key); >- return cache.put(masterValue, value); >- } >- >- public boolean isStale() { >- getterCalled(); >- return masterMap.isStale(); >- } >- >- public Object getObserved() { >- return masterMap; >- } >- >- public Object getKeyType() { >- return masterMap.getKeyType(); >- } >- >- public Object getValueType() { >- return detailProperty.getValueType(); >- } >- >- private Set keysFor(Object masterValue) { >- Set keys = new HashSet(); >- >- for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) { >- Map.Entry entry = (Entry) it.next(); >- if (entry.getValue() == masterValue) { >- keys.add(entry.getKey()); >- } >- } >- >- return keys; >- } >- >- private void fireMapChange(final Set changedKeys, final Object oldValue, >- final Object newValue) { >- fireMapChange(new MapDiff() { >- public Set getAddedKeys() { >- return Collections.EMPTY_SET; >- } >- >- public Set getRemovedKeys() { >- return Collections.EMPTY_SET; >- } >- >- public Set getChangedKeys() { >- return Collections.unmodifiableSet(changedKeys); >- } >- >- public Object getOldValue(Object key) { >- if (changedKeys.contains(key)) >- return oldValue; >- return null; >- } >- >- public Object getNewValue(Object key) { >- if (changedKeys.contains(key)) >- return newValue; >- return null; >- } >- }); >- } >- >- public synchronized void dispose() { >- if (masterMap != null) { >- masterMap.removeMapChangeListener(masterListener); >- masterMap.removeStaleListener(staleListener); >- masterMap = null; >- } >- >- if (cache != null) { >- cache.dispose(); >- cache = null; >- } >- >- masterListener = null; >- detailProperty = null; >- >- super.dispose(); >- } >-} >Index: src/org/eclipse/core/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java >diff -N src/org/eclipse/core/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java >--- src/org/eclipse/core/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java 23 Dec 2008 18:30:30 -0000 1.1.2.5 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,138 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.value; >- >-import java.util.HashMap; >-import java.util.Iterator; >-import java.util.Map; >- >-import org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.IObserving; >-import org.eclipse.core.databinding.observable.map.ComputedObservableMap; >-import org.eclipse.core.databinding.observable.set.IObservableSet; >-import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >-import org.eclipse.core.internal.databinding.Util; >- >-/** >- * @since 1.2 >- */ >-class ObservableSetSimpleValuePropertyObservableMap extends >- ComputedObservableMap implements IObserving { >- private SimpleValueProperty detailProperty; >- >- private INativePropertyListener listener; >- >- private Map cachedValues; >- >- private boolean updating; >- >- /** >- * @param keySet >- * @param valueProperty >- */ >- public ObservableSetSimpleValuePropertyObservableMap(IObservableSet keySet, >- SimpleValueProperty valueProperty) { >- super(keySet); >- this.detailProperty = valueProperty; >- } >- >- protected void firstListenerAdded() { >- cachedValues = new HashMap(this); >- if (listener == null) { >- listener = detailProperty >- .adaptListener(new IPropertyChangeListener() { >- public void handlePropertyChange( >- final PropertyChangeEvent event) { >- if (!isDisposed() && !updating) { >- getRealm().exec(new Runnable() { >- public void run() { >- notifyIfChanged(event.getSource()); >- } >- }); >- } >- } >- }); >- } >- super.firstListenerAdded(); >- } >- >- protected void lastListenerRemoved() { >- super.lastListenerRemoved(); >- cachedValues.clear(); >- cachedValues = null; >- } >- >- protected void hookListener(Object addedKey) { >- if (listener != null) { >- cachedValues.put(addedKey, detailProperty.getValue(addedKey)); >- detailProperty.addListener(addedKey, listener); >- } >- } >- >- protected void unhookListener(Object removedKey) { >- if (listener != null) { >- detailProperty.removeListener(removedKey, listener); >- cachedValues.remove(removedKey); >- } >- } >- >- protected Object doGet(Object key) { >- return detailProperty.getValue(key); >- } >- >- protected Object doPut(Object key, Object value) { >- Object oldValue = detailProperty.getValue(key); >- >- updating = true; >- try { >- detailProperty.setValue(key, value); >- } finally { >- updating = false; >- } >- >- notifyIfChanged(key); >- >- return oldValue; >- } >- >- private void notifyIfChanged(Object key) { >- if (cachedValues != null) { >- Object oldValue = cachedValues.get(key); >- Object newValue = detailProperty.getValue(key); >- if (!Util.equals(oldValue, newValue)) { >- cachedValues.put(key, newValue); >- fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue, >- newValue)); >- } >- } >- } >- >- public Object getObserved() { >- return keySet(); >- } >- >- public synchronized void dispose() { >- if (!isDisposed()) { >- if (listener != null) { >- for (Iterator it = values().iterator(); it.hasNext();) { >- unhookListener(it.next()); >- } >- listener = null; >- } >- detailProperty = null; >- } >- >- super.dispose(); >- } >-} >Index: src/org/eclipse/core/databinding/property/value/ObservableListDelegatingValuePropertyObservableList.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/value/ObservableListDelegatingValuePropertyObservableList.java >diff -N src/org/eclipse/core/databinding/property/value/ObservableListDelegatingValuePropertyObservableList.java >--- src/org/eclipse/core/databinding/property/value/ObservableListDelegatingValuePropertyObservableList.java 8 Jan 2009 01:24:49 -0000 1.1.2.1 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,341 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.value; >- >-import java.lang.reflect.Array; >-import java.util.ArrayList; >-import java.util.Collection; >-import java.util.Iterator; >-import java.util.List; >-import java.util.ListIterator; >- >-import org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.IStaleListener; >-import org.eclipse.core.databinding.observable.ObservableTracker; >-import org.eclipse.core.databinding.observable.StaleEvent; >-import org.eclipse.core.databinding.observable.list.AbstractObservableList; >-import org.eclipse.core.databinding.observable.list.IListChangeListener; >-import org.eclipse.core.databinding.observable.list.IObservableList; >-import org.eclipse.core.databinding.observable.list.ListChangeEvent; >-import org.eclipse.core.databinding.observable.list.ListDiff; >-import org.eclipse.core.databinding.observable.list.ListDiffEntry; >- >-/** >- * @since 1.2 >- */ >-class ObservableListDelegatingValuePropertyObservableList extends >- AbstractObservableList { >- private IObservableList masterList; >- private DelegatingValueProperty detailProperty; >- private DelegatingCache cache; >- >- private IListChangeListener masterListener = new IListChangeListener() { >- public void handleListChange(ListChangeEvent event) { >- if (isDisposed()) >- return; >- >- cache.addAll(masterList); >- >- // Need both obsolete and new elements to convert diff >- ListDiff diff = convertDiff(event.diff); >- >- cache.retainAll(masterList); >- >- fireListChange(diff); >- } >- >- private ListDiff convertDiff(ListDiff diff) { >- // Convert diff to detail value >- ListDiffEntry[] masterEntries = diff.getDifferences(); >- ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length]; >- for (int i = 0; i < masterEntries.length; i++) { >- ListDiffEntry masterDifference = masterEntries[i]; >- int index = masterDifference.getPosition(); >- boolean addition = masterDifference.isAddition(); >- Object masterElement = masterDifference.getElement(); >- Object detailValue = cache.get(masterElement); >- >- detailEntries[i] = Diffs.createListDiffEntry(index, addition, >- detailValue); >- } >- return Diffs.createListDiff(detailEntries); >- } >- }; >- >- private IStaleListener staleListener = new IStaleListener() { >- public void handleStale(StaleEvent staleEvent) { >- fireStale(); >- } >- }; >- >- /** >- * @param masterList >- * @param valueProperty >- */ >- public ObservableListDelegatingValuePropertyObservableList( >- IObservableList masterList, DelegatingValueProperty valueProperty) { >- super(masterList.getRealm()); >- this.masterList = masterList; >- this.detailProperty = valueProperty; >- this.cache = new DelegatingCache(getRealm(), valueProperty) { >- void handleValueChange(Object masterElement, Object oldValue, >- Object newValue) { >- fireListChange(indicesOf(masterElement), oldValue, newValue); >- } >- }; >- cache.addAll(masterList); >- >- masterList.addListChangeListener(masterListener); >- masterList.addStaleListener(staleListener); >- } >- >- protected int doGetSize() { >- getterCalled(); >- return masterList.size(); >- } >- >- private void getterCalled() { >- ObservableTracker.getterCalled(this); >- } >- >- public Object get(int index) { >- getterCalled(); >- Object masterElement = masterList.get(index); >- return cache.get(masterElement); >- } >- >- public boolean add(Object o) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean addAll(Collection c) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean addAll(int index, Collection c) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean contains(Object o) { >- getterCalled(); >- return cache.contains(o); >- } >- >- public boolean isEmpty() { >- getterCalled(); >- return masterList.isEmpty(); >- } >- >- public boolean isStale() { >- getterCalled(); >- return masterList.isStale(); >- } >- >- public Iterator iterator() { >- getterCalled(); >- return new Iterator() { >- Iterator it = masterList.iterator(); >- >- public boolean hasNext() { >- getterCalled(); >- return it.hasNext(); >- } >- >- public Object next() { >- getterCalled(); >- Object masterElement = it.next(); >- return cache.get(masterElement); >- } >- >- public void remove() { >- throw new UnsupportedOperationException(); >- } >- }; >- } >- >- public Object move(int oldIndex, int newIndex) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean remove(Object o) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean removeAll(Collection c) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean retainAll(Collection c) { >- throw new UnsupportedOperationException(); >- } >- >- public Object[] toArray() { >- getterCalled(); >- Object[] masterElements = masterList.toArray(); >- Object[] result = new Object[masterElements.length]; >- for (int i = 0; i < result.length; i++) { >- result[i] = cache.get(masterElements[i]); >- } >- return result; >- } >- >- public Object[] toArray(Object[] a) { >- getterCalled(); >- Object[] masterElements = masterList.toArray(); >- if (a.length < masterElements.length) >- a = (Object[]) Array.newInstance(a.getClass().getComponentType(), >- masterElements.length); >- for (int i = 0; i < masterElements.length; i++) { >- a[i] = cache.get(masterElements[i]); >- } >- return a; >- } >- >- public void add(int index, Object o) { >- throw new UnsupportedOperationException(); >- } >- >- public void clear() { >- throw new UnsupportedOperationException(); >- } >- >- public ListIterator listIterator() { >- return listIterator(0); >- } >- >- public ListIterator listIterator(final int index) { >- getterCalled(); >- return new ListIterator() { >- ListIterator it = masterList.listIterator(index); >- Object lastMasterElement; >- Object lastElement; >- boolean haveIterated = false; >- >- public void add(Object arg0) { >- throw new UnsupportedOperationException(); >- } >- >- public boolean hasNext() { >- getterCalled(); >- return it.hasNext(); >- } >- >- public boolean hasPrevious() { >- getterCalled(); >- return it.hasPrevious(); >- } >- >- public Object next() { >- getterCalled(); >- lastMasterElement = it.next(); >- lastElement = cache.get(lastMasterElement); >- haveIterated = true; >- return lastElement; >- } >- >- public int nextIndex() { >- getterCalled(); >- return it.nextIndex(); >- } >- >- public Object previous() { >- getterCalled(); >- lastMasterElement = it.previous(); >- lastElement = cache.get(lastMasterElement); >- haveIterated = true; >- return lastElement; >- } >- >- public int previousIndex() { >- getterCalled(); >- return it.previousIndex(); >- } >- >- public void remove() { >- throw new UnsupportedOperationException(); >- } >- >- public void set(Object o) { >- checkRealm(); >- if (!haveIterated) >- throw new IllegalStateException(); >- >- cache.put(lastMasterElement, o); >- >- lastElement = o; >- } >- }; >- } >- >- private int[] indicesOf(Object masterElement) { >- List indices = new ArrayList(); >- >- for (ListIterator it = masterList.listIterator(); it.hasNext();) { >- if (masterElement == it.next()) >- indices.add(new Integer(it.previousIndex())); >- } >- >- int[] result = new int[indices.size()]; >- for (int i = 0; i < result.length; i++) { >- result[i] = ((Integer) indices.get(i)).intValue(); >- } >- return result; >- } >- >- private void fireListChange(int[] indices, Object oldValue, Object newValue) { >- ListDiffEntry[] differences = new ListDiffEntry[indices.length * 2]; >- for (int i = 0; i < indices.length; i++) { >- int index = indices[i]; >- differences[i * 2] = Diffs.createListDiffEntry(index, false, >- oldValue); >- differences[i * 2 + 1] = Diffs.createListDiffEntry(index, true, >- newValue); >- } >- fireListChange(Diffs.createListDiff(differences)); >- } >- >- public Object remove(int index) { >- throw new UnsupportedOperationException(); >- } >- >- public Object set(int index, Object o) { >- checkRealm(); >- Object masterElement = masterList.get(index); >- return cache.put(masterElement, o); >- } >- >- public Object getObserved() { >- return masterList; >- } >- >- public Object getElementType() { >- return detailProperty.getValueType(); >- } >- >- public synchronized void dispose() { >- if (masterList != null) { >- masterList.removeListChangeListener(masterListener); >- masterList.removeStaleListener(staleListener); >- masterList = null; >- } >- >- if (cache != null) { >- cache.dispose(); >- cache = null; >- } >- >- masterListener = null; >- detailProperty = null; >- >- super.dispose(); >- } >-} >Index: src/org/eclipse/core/databinding/property/value/SimpleValueProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/property/value/Attic/SimpleValueProperty.java,v >retrieving revision 1.1.2.8 >diff -u -r1.1.2.8 SimpleValueProperty.java >--- src/org/eclipse/core/databinding/property/value/SimpleValueProperty.java 8 Jan 2009 01:24:49 -0000 1.1.2.8 >+++ src/org/eclipse/core/databinding/property/value/SimpleValueProperty.java 17 Jan 2009 00:49:38 -0000 >@@ -18,7 +18,11 @@ > import org.eclipse.core.databinding.observable.set.IObservableSet; > import org.eclipse.core.databinding.observable.value.IObservableValue; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.internal.databinding.property.value.ObservableListSimpleValuePropertyObservableList; >+import org.eclipse.core.internal.databinding.property.value.ObservableMapSimpleValuePropertyObservableMap; >+import org.eclipse.core.internal.databinding.property.value.ObservableSetSimpleValuePropertyObservableMap; >+import org.eclipse.core.internal.databinding.property.value.SimpleValuePropertyObservableValue; > > /** > * Simplified abstract implementation of IValueProperty. This class takes care >@@ -30,7 +34,7 @@ > * <li> {@link #getValueType()} > * <li> {@link #doGetValue(Object)} > * <li> {@link #doSetValue(Object, Object)} >- * <li> {@link #adaptListener(IPropertyChangeListener)} >+ * <li> {@link #adaptListener(ISimplePropertyListener)} > * <li> {@link #doAddListener(Object, INativePropertyListener)} > * <li> {@link #doRemoveListener(Object, INativePropertyListener)} > * </ul> >@@ -40,16 +44,9 @@ > * > * @since 1.2 > */ >-public abstract class SimpleValueProperty extends ValueProperty { >- /** >- * Returns the value of the property on the specified source object >- * >- * @param source >- * the property source (may be null) >- * @return the current value of the source's value property >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final Object getValue(Object source) { >+public abstract class SimpleValueProperty extends ValueProperty implements >+ ISimpleValueProperty { >+ public final Object getValue(Object source) { > return source == null ? null : doGetValue(source); > } > >@@ -63,55 +60,17 @@ > */ > protected abstract Object doGetValue(Object source); > >- /** >- * Sets the source's value property to the specified value >- * >- * @param source >- * the property source >- * @param value >- * the new value >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void setValue(Object source, Object value) { >+ public final void setValue(Object source, Object value) { > if (source != null) > doSetValue(source, value); > } > > protected abstract void doSetValue(Object source, Object value); > >- /** >- * Returns a listener which implements the correct listener interface for >- * the expected source object, and which parlays property change events from >- * the source object to the given listener. If there is no listener API for >- * this property, this method returns null. >- * >- * @param listener >- * the property listener to receive events >- * @return a native listener which parlays property change events to the >- * specified listener. >- * @throws ClassCastException >- * if the provided listener does not implement the correct >- * listener interface (IValueProperty, IListProperty, >- * ISetProperty or IMapProperty) depending on the property. >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected abstract INativePropertyListener adaptListener( >- IPropertyChangeListener listener); >+ public abstract INativePropertyListener adaptListener( >+ ISimplePropertyListener listener); > >- /** >- * Adds the specified listener as a listener for this property on the >- * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >- * returns null), this method does nothing. >- * >- * @param source >- * the property source >- * @param listener >- * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void addListener(Object source, >+ public final void addListener(Object source, > INativePropertyListener listener) { > if (source != null) > doAddListener(source, listener); >@@ -120,33 +79,20 @@ > /** > * Adds the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >+ * {@link #adaptListener(ISimplePropertyListener)}. > * @noreference This method is not intended to be referenced by clients. > */ > protected abstract void doAddListener(Object source, > INativePropertyListener listener); > >- /** >- * Removes the specified listener as a listener for this property on the >- * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >- * returns null), this method does nothing. >- * >- * @param source >- * the property source >- * @param listener >- * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void removeListener(Object source, >+ public final void removeListener(Object source, > INativePropertyListener listener) { > if (source != null) > doRemoveListener(source, listener); >@@ -155,14 +101,14 @@ > /** > * Removes the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >+ * {@link #adaptListener(ISimplePropertyListener)}. > * @noreference This method is not intended to be referenced by clients. > */ > protected abstract void doRemoveListener(Object source, >Index: src/org/eclipse/core/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java >diff -N src/org/eclipse/core/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java >--- src/org/eclipse/core/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java 23 Dec 2008 18:24:44 -0000 1.1.2.4 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,369 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.value; >- >-import java.util.AbstractSet; >-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 org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.IObserving; >-import org.eclipse.core.databinding.observable.IStaleListener; >-import org.eclipse.core.databinding.observable.ObservableTracker; >-import org.eclipse.core.databinding.observable.StaleEvent; >-import org.eclipse.core.databinding.observable.map.AbstractObservableMap; >-import org.eclipse.core.databinding.observable.map.IMapChangeListener; >-import org.eclipse.core.databinding.observable.map.IObservableMap; >-import org.eclipse.core.databinding.observable.map.MapChangeEvent; >-import org.eclipse.core.databinding.observable.map.MapDiff; >-import org.eclipse.core.databinding.observable.set.IObservableSet; >-import org.eclipse.core.databinding.observable.set.ISetChangeListener; >-import org.eclipse.core.databinding.observable.set.SetChangeEvent; >-import org.eclipse.core.databinding.observable.set.WritableSet; >-import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >-import org.eclipse.core.internal.databinding.IdentityWrapper; >-import org.eclipse.core.internal.databinding.Util; >- >-/** >- * @since 1.2 >- * >- */ >-class ObservableMapSimpleValuePropertyObservableMap extends >- AbstractObservableMap implements IObserving { >- private IObservableMap masterMap; >- private SimpleValueProperty detailProperty; >- >- private IObservableSet knownMasterValues; >- private Map cachedValues; >- >- private boolean updating = false; >- >- private IMapChangeListener masterListener = new IMapChangeListener() { >- public void handleMapChange(final MapChangeEvent event) { >- if (!isDisposed()) { >- updateKnownValues(); >- if (!updating) >- fireMapChange(convertDiff(event.diff)); >- } >- } >- >- private void updateKnownValues() { >- Set identityKnownValues = new HashSet(); >- for (Iterator it = masterMap.values().iterator(); it.hasNext();) { >- identityKnownValues.add(new IdentityWrapper(it.next())); >- } >- >- knownMasterValues.retainAll(identityKnownValues); >- knownMasterValues.addAll(identityKnownValues); >- } >- >- private MapDiff convertDiff(MapDiff diff) { >- Map oldValues = new HashMap(); >- Map newValues = new HashMap(); >- >- Set addedKeys = diff.getAddedKeys(); >- for (Iterator it = addedKeys.iterator(); it.hasNext();) { >- Object key = it.next(); >- Object newSource = diff.getNewValue(key); >- Object newValue = detailProperty.getValue(newSource); >- newValues.put(key, newValue); >- } >- >- Set removedKeys = diff.getRemovedKeys(); >- for (Iterator it = removedKeys.iterator(); it.hasNext();) { >- Object key = it.next(); >- Object oldSource = diff.getOldValue(key); >- Object oldValue = detailProperty.getValue(oldSource); >- oldValues.put(key, oldValue); >- } >- >- Set changedKeys = new HashSet(diff.getChangedKeys()); >- for (Iterator it = changedKeys.iterator(); it.hasNext();) { >- Object key = it.next(); >- >- Object oldSource = diff.getOldValue(key); >- Object newSource = diff.getNewValue(key); >- >- Object oldValue = detailProperty.getValue(oldSource); >- Object newValue = detailProperty.getValue(newSource); >- >- if (Util.equals(oldValue, newValue)) { >- it.remove(); >- } else { >- oldValues.put(key, oldValue); >- newValues.put(key, newValue); >- } >- } >- >- return Diffs.createMapDiff(addedKeys, removedKeys, changedKeys, >- oldValues, newValues); >- } >- }; >- >- private IStaleListener staleListener = new IStaleListener() { >- public void handleStale(StaleEvent staleEvent) { >- fireStale(); >- } >- }; >- >- private INativePropertyListener detailListener; >- >- /** >- * @param map >- * @param valueProperty >- */ >- public ObservableMapSimpleValuePropertyObservableMap(IObservableMap map, >- SimpleValueProperty valueProperty) { >- super(map.getRealm()); >- this.masterMap = map; >- this.detailProperty = valueProperty; >- >- IPropertyChangeListener listener = new IPropertyChangeListener() { >- public void handlePropertyChange(PropertyChangeEvent event) { >- notifyIfChanged(event.getSource()); >- } >- }; >- this.detailListener = detailProperty.adaptListener(listener); >- } >- >- protected void firstListenerAdded() { >- knownMasterValues = new WritableSet(getRealm()); >- cachedValues = new HashMap(); >- knownMasterValues.addSetChangeListener(new ISetChangeListener() { >- public void handleSetChange(SetChangeEvent event) { >- for (Iterator it = event.diff.getRemovals().iterator(); it >- .hasNext();) { >- IdentityWrapper wrapper = (IdentityWrapper) it.next(); >- Object key = wrapper.unwrap(); >- detailProperty.removeListener(key, detailListener); >- cachedValues.remove(wrapper); >- } >- for (Iterator it = event.diff.getAdditions().iterator(); it >- .hasNext();) { >- IdentityWrapper wrapper = (IdentityWrapper) it.next(); >- Object key = wrapper.unwrap(); >- cachedValues.put(wrapper, detailProperty.getValue(key)); >- detailProperty.addListener(key, detailListener); >- } >- } >- }); >- for (Iterator it = masterMap.values().iterator(); it.hasNext();) { >- knownMasterValues.add(new IdentityWrapper(it.next())); >- } >- >- masterMap.addMapChangeListener(masterListener); >- masterMap.addStaleListener(staleListener); >- } >- >- protected void lastListenerRemoved() { >- masterMap.removeMapChangeListener(masterListener); >- masterMap.removeStaleListener(staleListener); >- if (knownMasterValues != null) { >- knownMasterValues.clear(); // removes attached listeners >- knownMasterValues.dispose(); >- knownMasterValues = null; >- } >- cachedValues.clear(); >- cachedValues = null; >- } >- >- private Set entrySet; >- >- public Set entrySet() { >- getterCalled(); >- if (entrySet == null) >- entrySet = new EntrySet(); >- return entrySet; >- } >- >- class EntrySet extends AbstractSet { >- public Iterator iterator() { >- return new Iterator() { >- Iterator it = masterMap.entrySet().iterator(); >- >- public boolean hasNext() { >- getterCalled(); >- return it.hasNext(); >- } >- >- public Object next() { >- getterCalled(); >- Map.Entry next = (Map.Entry) it.next(); >- return new MapEntry(next.getKey()); >- } >- >- public void remove() { >- it.remove(); >- } >- }; >- } >- >- public int size() { >- return masterMap.size(); >- } >- } >- >- class MapEntry implements Map.Entry { >- private Object key; >- >- MapEntry(Object key) { >- this.key = key; >- } >- >- public Object getKey() { >- getterCalled(); >- return key; >- } >- >- public Object getValue() { >- getterCalled(); >- if (!masterMap.containsKey(key)) >- return null; >- return detailProperty.getValue(masterMap.get(key)); >- } >- >- public Object setValue(Object value) { >- if (!masterMap.containsKey(key)) >- return null; >- Object source = masterMap.get(key); >- >- Object oldValue = detailProperty.getValue(source); >- >- updating = true; >- try { >- detailProperty.setValue(source, value); >- } finally { >- updating = false; >- } >- >- notifyIfChanged(source); >- >- return oldValue; >- } >- >- public boolean equals(Object o) { >- getterCalled(); >- if (o == this) >- return true; >- if (o == null) >- return false; >- if (!(o instanceof Map.Entry)) >- return false; >- Map.Entry that = (Map.Entry) o; >- return Util.equals(this.getKey(), that.getKey()) >- && Util.equals(this.getValue(), that.getValue()); >- } >- >- public int hashCode() { >- getterCalled(); >- Object value = getValue(); >- return (key == null ? 0 : key.hashCode()) >- ^ (value == null ? 0 : value.hashCode()); >- } >- } >- >- public Object put(Object key, Object value) { >- if (!masterMap.containsKey(key)) >- return null; >- Object masterValue = masterMap.get(key); >- Object oldValue = detailProperty.getValue(key); >- detailProperty.setValue(masterValue, value); >- notifyIfChanged(masterValue); >- return oldValue; >- } >- >- private void notifyIfChanged(Object masterValue) { >- if (cachedValues != null) { >- final Set keys = keysFor(masterValue); >- >- final Object oldValue = cachedValues.get(new IdentityWrapper( >- masterValue)); >- final Object newValue = detailProperty.getValue(masterValue); >- >- if (!Util.equals(oldValue, newValue)) { >- cachedValues.put(new IdentityWrapper(masterValue), newValue); >- fireMapChange(new MapDiff() { >- public Set getAddedKeys() { >- return Collections.EMPTY_SET; >- } >- >- public Set getChangedKeys() { >- return keys; >- } >- >- public Set getRemovedKeys() { >- return Collections.EMPTY_SET; >- } >- >- public Object getNewValue(Object key) { >- return newValue; >- } >- >- public Object getOldValue(Object key) { >- return oldValue; >- } >- }); >- } >- } >- } >- >- private Set keysFor(Object value) { >- Set keys = new HashSet(); >- >- for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) { >- Map.Entry entry = (Entry) it.next(); >- if (entry.getValue() == value) { >- keys.add(entry.getKey()); >- } >- } >- >- return keys; >- } >- >- public boolean isStale() { >- getterCalled(); >- return masterMap.isStale(); >- } >- >- private void getterCalled() { >- ObservableTracker.getterCalled(this); >- } >- >- public Object getObserved() { >- return masterMap; >- } >- >- public synchronized void dispose() { >- if (masterMap != null) { >- masterMap.removeMapChangeListener(masterListener); >- masterMap = null; >- } >- if (knownMasterValues != null) { >- knownMasterValues.clear(); // detaches listeners >- knownMasterValues.dispose(); >- knownMasterValues = null; >- } >- >- masterListener = null; >- detailListener = null; >- detailProperty = null; >- cachedValues = null; >- >- super.dispose(); >- } >-} >Index: src/org/eclipse/core/databinding/property/value/SimpleValuePropertyObservableValue.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/value/SimpleValuePropertyObservableValue.java >diff -N src/org/eclipse/core/databinding/property/value/SimpleValuePropertyObservableValue.java >--- src/org/eclipse/core/databinding/property/value/SimpleValuePropertyObservableValue.java 14 Jan 2009 23:51:10 -0000 1.1.2.5 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,130 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.value; >- >-import org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.Realm; >-import org.eclipse.core.databinding.observable.value.AbstractObservableValue; >-import org.eclipse.core.databinding.observable.value.ValueDiff; >-import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IProperty; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.IPropertyObservable; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >-import org.eclipse.core.internal.databinding.Util; >- >-/** >- * @since 1.2 >- * >- */ >-class SimpleValuePropertyObservableValue extends AbstractObservableValue >- implements IPropertyObservable { >- private Object source; >- private SimpleValueProperty property; >- >- private boolean updating = false; >- private Object cachedValue; >- >- private INativePropertyListener listener; >- >- /** >- * @param realm >- * @param source >- * @param property >- */ >- public SimpleValuePropertyObservableValue(Realm realm, Object source, >- SimpleValueProperty property) { >- super(realm); >- this.source = source; >- this.property = property; >- } >- >- protected void firstListenerAdded() { >- if (!isDisposed()) { >- cachedValue = property.getValue(source); >- if (listener == null) { >- listener = property >- .adaptListener(new IPropertyChangeListener() { >- public void handlePropertyChange( >- final PropertyChangeEvent event) { >- if (!isDisposed() && !updating) { >- getRealm().exec(new Runnable() { >- public void run() { >- notifyIfChanged((ValueDiff) event.diff); >- } >- }); >- } >- } >- }); >- } >- property.addListener(source, listener); >- } >- } >- >- protected void lastListenerRemoved() { >- if (listener != null) { >- property.removeListener(source, listener); >- } >- cachedValue = null; >- } >- >- protected Object doGetValue() { >- notifyIfChanged(null); >- return property.getValue(source); >- } >- >- protected void doSetValue(Object value) { >- updating = true; >- try { >- property.setValue(source, value); >- } finally { >- updating = false; >- } >- >- notifyIfChanged(null); >- } >- >- private void notifyIfChanged(ValueDiff diff) { >- if (hasListeners()) { >- Object oldValue = cachedValue; >- Object newValue = cachedValue = property.getValue(source); >- if (diff == null) >- diff = Diffs.createValueDiff(oldValue, newValue); >- if (hasListeners() && !Util.equals(oldValue, newValue)) { >- fireValueChange(diff); >- } >- } >- } >- >- public Object getValueType() { >- return property.getValueType(); >- } >- >- public Object getObserved() { >- return source; >- } >- >- public IProperty getProperty() { >- return property; >- } >- >- public synchronized void dispose() { >- if (!isDisposed()) { >- if (listener != null) >- property.removeListener(source, listener); >- source = null; >- property = null; >- listener = null; >- } >- super.dispose(); >- } >-} >Index: src/org/eclipse/core/databinding/property/value/DelegatingValueProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/property/value/Attic/DelegatingValueProperty.java,v >retrieving revision 1.1.2.2 >diff -u -r1.1.2.2 DelegatingValueProperty.java >--- src/org/eclipse/core/databinding/property/value/DelegatingValueProperty.java 14 Jan 2009 23:51:10 -0000 1.1.2.2 >+++ src/org/eclipse/core/databinding/property/value/DelegatingValueProperty.java 17 Jan 2009 00:49:38 -0000 >@@ -17,7 +17,10 @@ > import org.eclipse.core.databinding.observable.set.IObservableSet; > import org.eclipse.core.databinding.observable.value.IObservableValue; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.internal.databinding.property.value.ObservableListDelegatingValuePropertyObservableList; >+import org.eclipse.core.internal.databinding.property.value.ObservableMapDelegatingValuePropertyObservableMap; >+import org.eclipse.core.internal.databinding.property.value.ObservableSetDelegatingValuePropertyObservableMap; > > /** > * @since 1.2 >@@ -35,7 +38,16 @@ > this.valueType = valueType; > } > >- protected final IValueProperty getDelegate(Object source) { >+ /** >+ * Returns the property to delegate to for the specified source object. >+ * Repeated calls to this method with the same source object returns the >+ * same delegate instance. >+ * >+ * @param source >+ * the property source (may be null) >+ * @return the property to delegate to for the specified source object. >+ */ >+ public final IValueProperty getDelegate(Object source) { > if (source == null) > return null; > IValueProperty delegate = doGetDelegate(source); >@@ -90,8 +102,8 @@ > protected void doSetValue(Object source, Object value) { > } > >- protected INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ public INativePropertyListener adaptListener( >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/core/databinding/property/INativePropertyListener.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/property/Attic/INativePropertyListener.java,v >retrieving revision 1.1.2.1 >diff -u -r1.1.2.1 INativePropertyListener.java >--- src/org/eclipse/core/databinding/property/INativePropertyListener.java 17 Dec 2008 18:40:05 -0000 1.1.2.1 >+++ src/org/eclipse/core/databinding/property/INativePropertyListener.java 17 Jan 2009 00:49:38 -0000 >@@ -18,6 +18,7 @@ > * provided when the native listener was constructed. > * > * @since 1.2 >+ * @see ISimpleProperty#adaptListener(ISimplePropertyListener) > */ > public interface INativePropertyListener { > } >Index: src/org/eclipse/core/databinding/property/IPropertyChangeListener.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/IPropertyChangeListener.java >diff -N src/org/eclipse/core/databinding/property/IPropertyChangeListener.java >--- src/org/eclipse/core/databinding/property/IPropertyChangeListener.java 23 Dec 2008 18:24:44 -0000 1.1.2.3 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,30 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- * Matthew Hall - but 194734 >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property; >- >-/** >- * Listener for changes to properties on a particular source object >- * >- * @noextend This interface is not intended to be extended by clients. >- * >- * @since 1.2 >- */ >-public interface IPropertyChangeListener { >- /** >- * Handle the property change described in the event. >- * >- * @param event >- * an event describing the list change that occured. >- */ >- public void handlePropertyChange(PropertyChangeEvent event); >-} >Index: src/org/eclipse/core/databinding/property/PropertyChangeEvent.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/PropertyChangeEvent.java >diff -N src/org/eclipse/core/databinding/property/PropertyChangeEvent.java >--- src/org/eclipse/core/databinding/property/PropertyChangeEvent.java 14 Jan 2009 23:51:10 -0000 1.1.2.3 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,76 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property; >- >-import java.util.EventObject; >- >-import org.eclipse.core.databinding.observable.IDiff; >-import org.eclipse.core.internal.databinding.Util; >- >-/** >- * Base class for change events in the properties API >- * >- * @since 1.2 >- */ >-public final class PropertyChangeEvent extends EventObject { >- private static final long serialVersionUID = 1L; >- >- /** >- * The property that changed >- */ >- public final IProperty property; >- >- /** >- * A diff object describing the change in state, or null for an unknown >- * change. >- */ >- public final IDiff diff; >- >- /** >- * Constructs a PropertyChangeEvent with the given attributes >- * >- * @param source >- * the property source >- * @param property >- * the property that changed on the source >- * @param diff >- * a diff describing the change in state, or null if the change >- * is unknown. >- */ >- public PropertyChangeEvent(Object source, IProperty property, IDiff diff) { >- super(source); >- this.property = property; >- this.diff = diff; >- } >- >- public boolean equals(Object obj) { >- if (obj == this) >- return true; >- if (obj == null) >- return false; >- if (getClass() != obj.getClass()) >- return false; >- >- PropertyChangeEvent that = (PropertyChangeEvent) obj; >- return Util.equals(getSource(), that.getSource()) >- && Util.equals(this.property, that.property) >- && Util.equals(this.diff, that.diff); >- } >- >- public int hashCode() { >- int hash = 17; >- hash = hash * 37 + getSource().hashCode(); >- hash = hash * 37 + property.hashCode(); >- hash = hash * 37 + (diff == null ? 0 : diff.hashCode()); >- return hash; >- } >-} >Index: src/org/eclipse/core/databinding/property/list/DelegatingListProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/property/list/Attic/DelegatingListProperty.java,v >retrieving revision 1.1.2.2 >diff -u -r1.1.2.2 DelegatingListProperty.java >--- src/org/eclipse/core/databinding/property/list/DelegatingListProperty.java 14 Jan 2009 23:51:10 -0000 1.1.2.2 >+++ src/org/eclipse/core/databinding/property/list/DelegatingListProperty.java 17 Jan 2009 00:49:38 -0000 >@@ -18,7 +18,7 @@ > import org.eclipse.core.databinding.observable.list.IObservableList; > import org.eclipse.core.databinding.observable.list.ListDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > > /** > * @since 1.2 >@@ -37,7 +37,16 @@ > this.nullProperty = new NullListProperty(); > } > >- protected final IListProperty getDelegate(Object source) { >+ /** >+ * Returns the property to delegate to for the specified source object. >+ * Repeated calls to this method with the same source object returns the >+ * same delegate instance. >+ * >+ * @param source >+ * the property source (may be null) >+ * @return the property to delegate to for the specified source object. >+ */ >+ public final IListProperty getDelegate(Object source) { > if (source == null) > return null; > IListProperty delegate = doGetDelegate(source); >@@ -46,6 +55,15 @@ > return delegate; > } > >+ /** >+ * Returns the property to delegate to for the specified source object. >+ * Implementers must ensure that repeated calls to this method with the same >+ * source object returns the same delegate instance. >+ * >+ * @param source >+ * the property source >+ * @return the property to delegate to for the specified source object. >+ */ > protected abstract IListProperty doGetDelegate(Object source); > > public Object getElementType() { >@@ -68,8 +86,8 @@ > protected void doSetList(Object source, List list, ListDiff diff) { > } > >- protected INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ public INativePropertyListener adaptListener( >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/core/databinding/property/list/SimpleListPropertyObservableList.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/list/SimpleListPropertyObservableList.java >diff -N src/org/eclipse/core/databinding/property/list/SimpleListPropertyObservableList.java >--- src/org/eclipse/core/databinding/property/list/SimpleListPropertyObservableList.java 14 Jan 2009 23:51:10 -0000 1.1.2.5 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,666 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.list; >- >-import java.util.ArrayList; >-import java.util.Collection; >-import java.util.Collections; >-import java.util.ConcurrentModificationException; >-import java.util.Iterator; >-import java.util.List; >-import java.util.ListIterator; >- >-import org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.ObservableTracker; >-import org.eclipse.core.databinding.observable.Realm; >-import org.eclipse.core.databinding.observable.list.AbstractObservableList; >-import org.eclipse.core.databinding.observable.list.ListDiff; >-import org.eclipse.core.databinding.observable.list.ListDiffEntry; >-import org.eclipse.core.databinding.property.IProperty; >-import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.IPropertyObservable; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >- >-/** >- * @since 1.2 >- * >- */ >-class SimpleListPropertyObservableList extends AbstractObservableList implements >- IPropertyObservable { >- private Object source; >- private SimpleListProperty property; >- >- private volatile boolean updating = false; >- >- private volatile int modCount = 0; >- >- private INativePropertyListener listener; >- >- private List cachedList; >- >- /** >- * @param realm >- * @param source >- * @param property >- */ >- public SimpleListPropertyObservableList(Realm realm, Object source, >- SimpleListProperty property) { >- super(realm); >- this.source = source; >- this.property = property; >- } >- >- protected void firstListenerAdded() { >- if (!isDisposed()) { >- cachedList = getList(); >- >- if (listener == null) { >- listener = property >- .adaptListener(new IPropertyChangeListener() { >- public void handlePropertyChange( >- final PropertyChangeEvent event) { >- modCount++; >- if (!isDisposed() && !updating) { >- getRealm().exec(new Runnable() { >- public void run() { >- notifyIfChanged((ListDiff) event.diff); >- } >- }); >- } >- } >- }); >- } >- property.addListener(source, listener); >- } >- } >- >- protected void lastListenerRemoved() { >- if (listener != null) { >- property.removeListener(source, listener); >- } >- >- cachedList = null; >- } >- >- private void getterCalled() { >- ObservableTracker.getterCalled(this); >- } >- >- public Object getElementType() { >- return property.getElementType(); >- } >- >- // Queries >- >- private List getList() { >- return property.getList(source); >- } >- >- protected int doGetSize() { >- return getList().size(); >- } >- >- public boolean contains(Object o) { >- getterCalled(); >- return getList().contains(o); >- } >- >- public boolean containsAll(Collection c) { >- getterCalled(); >- return getList().containsAll(c); >- } >- >- public Object get(int index) { >- getterCalled(); >- return getList().get(index); >- } >- >- public int indexOf(Object o) { >- getterCalled(); >- return getList().indexOf(o); >- } >- >- public boolean isEmpty() { >- getterCalled(); >- return getList().isEmpty(); >- } >- >- public int lastIndexOf(Object o) { >- getterCalled(); >- return getList().lastIndexOf(o); >- } >- >- public Object[] toArray() { >- getterCalled(); >- return getList().toArray(); >- } >- >- public Object[] toArray(Object[] a) { >- getterCalled(); >- return getList().toArray(a); >- } >- >- // Single change operations >- >- public boolean add(Object o) { >- checkRealm(); >- add(getList().size(), o); >- return true; >- } >- >- public void add(int index, Object o) { >- checkRealm(); >- boolean wasUpdating = updating; >- updating = true; >- List list = new ArrayList(getList()); >- list.add(index, o); >- ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, >- true, o)); >- try { >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- } >- >- public Iterator iterator() { >- getterCalled(); >- return new Iterator() { >- int expectedModCount = modCount; >- List list = new ArrayList(getList()); >- ListIterator iterator = list.listIterator(); >- >- Object lastElement = null; >- int lastIndex = -1; >- >- public boolean hasNext() { >- getterCalled(); >- checkForComodification(); >- return iterator.hasNext(); >- } >- >- public Object next() { >- getterCalled(); >- checkForComodification(); >- Object next = lastElement = iterator.next(); >- lastIndex = iterator.previousIndex(); >- return next; >- } >- >- public void remove() { >- checkRealm(); >- checkForComodification(); >- if (lastIndex == -1) >- throw new IllegalStateException(); >- >- iterator.remove(); // stay in sync >- ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >- lastIndex, false, lastElement)); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- lastElement = null; >- lastIndex = -1; >- >- expectedModCount = modCount; >- } >- >- private void checkForComodification() { >- if (expectedModCount != modCount) >- throw new ConcurrentModificationException(); >- } >- }; >- } >- >- public Object move(int oldIndex, int newIndex) { >- checkRealm(); >- >- List list = getList(); >- int size = list.size(); >- if (oldIndex < 0 || oldIndex >= size || newIndex < 0 >- || newIndex >= size) >- throw new IndexOutOfBoundsException(); >- >- if (oldIndex == newIndex) >- return list.get(oldIndex); >- >- list = new ArrayList(list); >- Object element = list.remove(oldIndex); >- list.add(newIndex, element); >- >- ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >- oldIndex, false, element), Diffs.createListDiffEntry(newIndex, >- true, element)); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return element; >- } >- >- public boolean remove(Object o) { >- checkRealm(); >- >- int index = getList().indexOf(o); >- if (index == -1) >- return false; >- >- remove(index); >- >- return true; >- } >- >- public ListIterator listIterator() { >- return listIterator(0); >- } >- >- public ListIterator listIterator(final int index) { >- getterCalled(); >- return new ListIterator() { >- int expectedModCount = modCount; >- List list = new ArrayList(getList()); >- ListIterator iterator = list.listIterator(index); >- >- Object lastElement = null; >- int lastIndex = -1; >- >- public boolean hasNext() { >- getterCalled(); >- checkForComodification(); >- return iterator.hasNext(); >- } >- >- public int nextIndex() { >- getterCalled(); >- checkForComodification(); >- return iterator.nextIndex(); >- } >- >- public Object next() { >- getterCalled(); >- checkForComodification(); >- lastElement = iterator.next(); >- lastIndex = iterator.previousIndex(); >- return lastElement; >- } >- >- public boolean hasPrevious() { >- getterCalled(); >- checkForComodification(); >- return iterator.hasPrevious(); >- } >- >- public int previousIndex() { >- getterCalled(); >- checkForComodification(); >- return iterator.previousIndex(); >- } >- >- public Object previous() { >- getterCalled(); >- checkForComodification(); >- lastElement = iterator.previous(); >- lastIndex = iterator.nextIndex(); >- return lastElement; >- } >- >- public void add(Object o) { >- checkRealm(); >- checkForComodification(); >- int index = iterator.nextIndex(); >- >- iterator.add(o); // keep in sync >- >- List list = getList(); >- list.add(index, o); >- ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >- index, true, o)); >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- lastElement = null; >- lastIndex = -1; >- expectedModCount = modCount; >- } >- >- public void set(Object o) { >- checkRealm(); >- checkForComodification(); >- >- iterator.set(o); >- ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >- lastIndex, false, lastElement), Diffs >- .createListDiffEntry(lastIndex, true, o)); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- lastElement = o; >- expectedModCount = modCount; >- } >- >- public void remove() { >- checkRealm(); >- checkForComodification(); >- if (lastIndex == -1) >- throw new IllegalStateException(); >- >- iterator.remove(); // keep in sync >- ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >- lastIndex, false, lastElement)); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- lastElement = null; >- lastIndex = -1; >- expectedModCount = modCount; >- } >- >- private void checkForComodification() { >- if (expectedModCount != modCount) >- throw new ConcurrentModificationException(); >- } >- }; >- } >- >- public Object remove(int index) { >- checkRealm(); >- >- List list = new ArrayList(getList()); >- Object element = list.remove(index); >- ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, >- false, element)); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return element; >- } >- >- public Object set(int index, Object o) { >- checkRealm(); >- >- List list = new ArrayList(getList()); >- Object oldElement = list.set(index, o); >- >- ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, >- false, oldElement), Diffs.createListDiffEntry(index, true, o)); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return oldElement; >- } >- >- public List subList(int fromIndex, int toIndex) { >- getterCalled(); >- return Collections.unmodifiableList(getList().subList(fromIndex, >- toIndex)); >- } >- >- // Bulk change operations >- >- public boolean addAll(Collection c) { >- checkRealm(); >- >- return addAll(getList().size(), c); >- } >- >- public boolean addAll(int index, Collection c) { >- checkRealm(); >- >- if (c.isEmpty()) >- return false; >- >- List list = new ArrayList(getList()); >- list.addAll(index, c); >- >- ListDiffEntry[] entries = new ListDiffEntry[c.size()]; >- int offsetIndex = 0; >- for (Iterator it = c.iterator(); it.hasNext();) { >- Object element = it.next(); >- entries[offsetIndex] = Diffs.createListDiffEntry(index >- + offsetIndex, true, element); >- offsetIndex++; >- } >- ListDiff diff = Diffs.createListDiff(entries); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return true; >- } >- >- public boolean removeAll(Collection c) { >- checkRealm(); >- >- if (c.isEmpty()) >- return false; >- >- List list = getList(); >- if (list.isEmpty()) >- return false; >- >- list = new ArrayList(list); >- List entries = new ArrayList(); >- ListDiff diff; >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- for (ListIterator it = list.listIterator(); it.hasNext();) { >- Object element = it.next(); >- int index = it.previousIndex(); >- if (c.contains(element)) { >- it.remove(); >- entries.add(Diffs >- .createListDiffEntry(index, false, element)); >- } >- } >- if (entries.isEmpty()) >- return false; >- >- diff = Diffs.createListDiff((ListDiffEntry[]) entries >- .toArray(new ListDiffEntry[entries.size()])); >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return !diff.isEmpty(); >- } >- >- public boolean retainAll(Collection c) { >- checkRealm(); >- >- List list = getList(); >- if (list.isEmpty()) >- return false; >- >- if (c.isEmpty()) { >- clear(); >- return true; >- } >- >- list = new ArrayList(list); >- List entries = new ArrayList(); >- ListDiff diff; >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- for (ListIterator it = list.listIterator(); it.hasNext();) { >- Object element = it.next(); >- int index = it.previousIndex(); >- if (!c.contains(element)) { >- it.remove(); >- entries.add(Diffs >- .createListDiffEntry(index, false, element)); >- } >- } >- if (entries.isEmpty()) >- return false; >- >- diff = Diffs.createListDiff((ListDiffEntry[]) entries >- .toArray(new ListDiffEntry[entries.size()])); >- property.setList(source, list, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return !diff.isEmpty(); >- } >- >- public void clear() { >- checkRealm(); >- >- List list = getList(); >- if (list.isEmpty()) >- return; >- >- List entries = new ArrayList(); >- for (Iterator it = list.iterator(); it.hasNext();) { >- // always report 0 as the remove index >- entries.add(Diffs.createListDiffEntry(0, false, it.next())); >- } >- >- ListDiff diff = Diffs.createListDiff((ListDiffEntry[]) entries >- .toArray(new ListDiffEntry[entries.size()])); >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setList(source, Collections.EMPTY_LIST, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- } >- >- private void notifyIfChanged(ListDiff diff) { >- if (hasListeners()) { >- List oldList = cachedList; >- List newList = cachedList = property.getList(source); >- if (diff == null) >- diff = Diffs.computeListDiff(oldList, newList); >- if (!diff.isEmpty()) { >- fireListChange(diff); >- } >- } >- } >- >- public boolean equals(Object o) { >- getterCalled(); >- return getList().equals(o); >- } >- >- public int hashCode() { >- getterCalled(); >- return getList().hashCode(); >- } >- >- public Object getObserved() { >- return source; >- } >- >- public IProperty getProperty() { >- return property; >- } >- >- public synchronized void dispose() { >- if (!isDisposed()) { >- if (listener != null) >- property.removeListener(source, listener); >- property = null; >- source = null; >- listener = null; >- } >- super.dispose(); >- } >-} >Index: src/org/eclipse/core/databinding/property/list/SimpleListProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/property/list/Attic/SimpleListProperty.java,v >retrieving revision 1.1.2.8 >diff -u -r1.1.2.8 SimpleListProperty.java >--- src/org/eclipse/core/databinding/property/list/SimpleListProperty.java 8 Jan 2009 01:24:50 -0000 1.1.2.8 >+++ src/org/eclipse/core/databinding/property/list/SimpleListProperty.java 17 Jan 2009 00:49:38 -0000 >@@ -19,7 +19,8 @@ > import org.eclipse.core.databinding.observable.list.IObservableList; > import org.eclipse.core.databinding.observable.list.ListDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.internal.databinding.property.list.SimpleListPropertyObservableList; > > /** > * Simplified abstract implementation of IListProperty. This class takes care of >@@ -31,7 +32,7 @@ > * <li> {@link #getElementType()} > * <li> {@link #doGetList(Object)} > * <li> {@link #doSetList(Object, List, ListDiff)} >- * <li> {@link #adaptListener(IPropertyChangeListener)} >+ * <li> {@link #adaptListener(ISimplePropertyListener)} > * <li> {@link #doAddListener(Object, INativePropertyListener)} > * <li> {@link #doRemoveListener(Object, INativePropertyListener)} > * </ul> >@@ -41,24 +42,15 @@ > * > * @since 1.2 > */ >-public abstract class SimpleListProperty extends ListProperty { >+public abstract class SimpleListProperty extends ListProperty implements >+ ISimpleListProperty { > public IObservableList observe(Realm realm, Object source) { > return new SimpleListPropertyObservableList(realm, source, this); > } > > // Accessors > >- /** >- * Returns an unmodifiable List with the current contents of the source's >- * list property >- * >- * @param source >- * the property source >- * @return an unmodifiable List with the current contents of the source's >- * list property >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final List getList(Object source) { >+ public final List getList(Object source) { > if (source == null) > return Collections.EMPTY_LIST; > return Collections.unmodifiableList(doGetList(source)); >@@ -76,18 +68,7 @@ > > // Mutators > >- /** >- * Updates the property on the source with the specified change. >- * >- * @param source >- * the property source >- * @param list >- * the new list >- * @param diff >- * a diff describing the change >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void setList(Object source, List list, ListDiff diff) { >+ public final void setList(Object source, List list, ListDiff diff) { > if (source != null && !diff.isEmpty()) > doSetList(source, list, diff); > } >@@ -105,40 +86,10 @@ > */ > protected abstract void doSetList(Object source, List list, ListDiff diff); > >- /** >- * Returns a listener which implements the correct listener interface for >- * the expected source object, and which parlays property change events from >- * the source object to the given listener. If there is no listener API for >- * this property, this method returns null. >- * >- * @param listener >- * the property listener to receive events >- * @return a native listener which parlays property change events to the >- * specified listener. >- * @throws ClassCastException >- * if the provided listener does not implement the correct >- * listener interface (IValueProperty, IListProperty, >- * ISetProperty or IMapProperty) depending on the property. >- * @noreference This method is not intended to be referenced by clients. >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected abstract INativePropertyListener adaptListener( >- IPropertyChangeListener listener); >+ public abstract INativePropertyListener adaptListener( >+ ISimplePropertyListener listener); > >- /** >- * Adds the specified listener as a listener for this property on the >- * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >- * returns null), this method does nothing. >- * >- * @param source >- * the property source >- * @param listener >- * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void addListener(Object source, >+ public final void addListener(Object source, > INativePropertyListener listener) { > if (source != null) > doAddListener(source, listener); >@@ -147,33 +98,20 @@ > /** > * Adds the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >+ * {@link #adaptListener(ISimplePropertyListener)}. > * @noreference This method is not intended to be referenced by clients. > */ > protected abstract void doAddListener(Object source, > INativePropertyListener listener); > >- /** >- * Removes the specified listener as a listener for this property on the >- * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >- * returns null), this method does nothing. >- * >- * @param source >- * the property source >- * @param listener >- * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void removeListener(Object source, >+ public final void removeListener(Object source, > INativePropertyListener listener) { > if (source != null) > doRemoveListener(source, listener); >@@ -182,14 +120,14 @@ > /** > * Removes the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >+ * {@link #adaptListener(ISimplePropertyListener)}. > * @noreference This method is not intended to be referenced by clients. > */ > protected abstract void doRemoveListener(Object source, >Index: src/org/eclipse/core/databinding/property/set/SimpleSetPropertyObservableSet.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/set/SimpleSetPropertyObservableSet.java >diff -N src/org/eclipse/core/databinding/property/set/SimpleSetPropertyObservableSet.java >--- src/org/eclipse/core/databinding/property/set/SimpleSetPropertyObservableSet.java 14 Jan 2009 23:51:10 -0000 1.1.2.5 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,407 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2008 Matthew Hall and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * Matthew Hall - initial API and implementation (bug 194734) >- ******************************************************************************/ >- >-package org.eclipse.core.databinding.property.set; >- >-import java.util.Collection; >-import java.util.Collections; >-import java.util.ConcurrentModificationException; >-import java.util.HashSet; >-import java.util.Iterator; >-import java.util.Set; >- >-import org.eclipse.core.databinding.observable.Diffs; >-import org.eclipse.core.databinding.observable.Realm; >-import org.eclipse.core.databinding.observable.set.AbstractObservableSet; >-import org.eclipse.core.databinding.observable.set.SetDiff; >-import org.eclipse.core.databinding.property.IProperty; >-import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.IPropertyObservable; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >- >-/** >- * @since 1.2 >- * >- */ >-class SimpleSetPropertyObservableSet extends AbstractObservableSet implements >- IPropertyObservable { >- private Object source; >- private SimpleSetProperty property; >- >- private volatile boolean updating = false; >- >- private volatile int modCount = 0; >- >- private INativePropertyListener listener; >- >- private Set cachedSet; >- >- /** >- * @param realm >- * @param source >- * @param property >- */ >- public SimpleSetPropertyObservableSet(Realm realm, Object source, >- SimpleSetProperty property) { >- super(realm); >- this.source = source; >- this.property = property; >- } >- >- protected void firstListenerAdded() { >- if (!isDisposed()) { >- cachedSet = getSet(); >- >- if (listener == null) { >- listener = property >- .adaptListener(new IPropertyChangeListener() { >- public void handlePropertyChange( >- final PropertyChangeEvent event) { >- modCount++; >- if (!isDisposed() && !updating) { >- getRealm().exec(new Runnable() { >- public void run() { >- notifyIfChanged((SetDiff) event.diff); >- } >- }); >- } >- } >- }); >- } >- property.addListener(source, listener); >- } >- } >- >- protected void lastListenerRemoved() { >- if (listener != null) { >- property.removeListener(source, listener); >- } >- >- cachedSet = null; >- } >- >- protected Set getWrappedSet() { >- return getSet(); >- } >- >- public Object getElementType() { >- return property.getElementType(); >- } >- >- // Queries >- >- private Set getSet() { >- return property.getSet(source); >- } >- >- public boolean contains(Object o) { >- getterCalled(); >- return getSet().contains(o); >- } >- >- public boolean containsAll(Collection c) { >- getterCalled(); >- return getSet().containsAll(c); >- } >- >- public boolean isEmpty() { >- getterCalled(); >- return getSet().isEmpty(); >- } >- >- public Object[] toArray() { >- getterCalled(); >- return getSet().toArray(); >- } >- >- public Object[] toArray(Object[] a) { >- getterCalled(); >- return getSet().toArray(a); >- } >- >- // Single change operations >- >- public boolean add(Object o) { >- checkRealm(); >- >- Set set = new HashSet(getSet()); >- if (!set.add(o)) >- return false; >- >- SetDiff diff = Diffs.createSetDiff(Collections.singleton(o), >- Collections.EMPTY_SET); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setSet(source, set, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return true; >- } >- >- public Iterator iterator() { >- getterCalled(); >- return new Iterator() { >- int expectedModCount = modCount; >- Set set = new HashSet(getSet()); >- Iterator iterator = set.iterator(); >- Object last = null; >- >- public boolean hasNext() { >- getterCalled(); >- checkForComodification(); >- return iterator.hasNext(); >- } >- >- public Object next() { >- getterCalled(); >- checkForComodification(); >- last = iterator.next(); >- return last; >- } >- >- public void remove() { >- checkRealm(); >- checkForComodification(); >- >- iterator.remove(); // stay in sync >- SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, >- Collections.singleton(last)); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setSet(source, set, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- last = null; >- expectedModCount = modCount; >- } >- >- private void checkForComodification() { >- if (expectedModCount != modCount) >- throw new ConcurrentModificationException(); >- } >- }; >- } >- >- public boolean remove(Object o) { >- getterCalled(); >- >- Set set = new HashSet(getSet()); >- if (!set.remove(o)) >- return false; >- >- SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, Collections >- .singleton(o)); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setSet(source, set, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return true; >- } >- >- // Bulk change operations >- >- public boolean addAll(Collection c) { >- getterCalled(); >- >- if (c.isEmpty()) >- return false; >- >- Set set = new HashSet(getSet()); >- >- Set additions = new HashSet(c); >- for (Iterator it = c.iterator(); it.hasNext();) { >- Object element = it.next(); >- if (set.add(element)) >- additions.add(element); >- } >- >- if (additions.isEmpty()) >- return false; >- >- SetDiff diff = Diffs.createSetDiff(additions, Collections.EMPTY_SET); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setSet(source, set, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return true; >- } >- >- public boolean removeAll(Collection c) { >- getterCalled(); >- >- Set set = getSet(); >- if (set.isEmpty()) >- return false; >- if (c.isEmpty()) >- return false; >- >- set = new HashSet(set); >- >- Set removals = new HashSet(c); >- for (Iterator it = c.iterator(); it.hasNext();) { >- Object element = it.next(); >- if (set.remove(element)) >- removals.add(element); >- } >- >- if (removals.isEmpty()) >- return false; >- >- SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setSet(source, set, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return true; >- } >- >- public boolean retainAll(Collection c) { >- getterCalled(); >- >- Set set = getSet(); >- if (set.isEmpty()) >- return false; >- >- if (c.isEmpty()) { >- clear(); >- return true; >- } >- >- set = new HashSet(set); >- >- Set removals = new HashSet(); >- for (Iterator it = set.iterator(); it.hasNext();) { >- Object element = it.next(); >- if (!c.contains(element)) { >- it.remove(); >- removals.add(element); >- } >- } >- >- if (removals.isEmpty()) >- return false; >- >- SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setSet(source, set, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- >- return true; >- } >- >- public void clear() { >- getterCalled(); >- >- Set set = getSet(); >- if (set.isEmpty()) >- return; >- >- SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, set); >- >- boolean wasUpdating = updating; >- updating = true; >- try { >- property.setSet(source, Collections.EMPTY_SET, diff); >- modCount++; >- } finally { >- updating = wasUpdating; >- } >- >- notifyIfChanged(null); >- } >- >- private void notifyIfChanged(SetDiff diff) { >- if (hasListeners()) { >- Set oldSet = cachedSet; >- Set newSet = cachedSet = property.getSet(source); >- if (diff == null) >- diff = Diffs.computeSetDiff(oldSet, newSet); >- if (!diff.isEmpty()) >- fireSetChange(diff); >- } >- } >- >- public boolean equals(Object o) { >- getterCalled(); >- return getSet().equals(o); >- } >- >- public int hashCode() { >- getterCalled(); >- return getSet().hashCode(); >- } >- >- public Object getObserved() { >- return source; >- } >- >- public IProperty getProperty() { >- return property; >- } >- >- public synchronized void dispose() { >- if (!isDisposed()) { >- if (listener != null) >- property.removeListener(source, listener); >- property = null; >- source = null; >- listener = null; >- } >- super.dispose(); >- } >-} >Index: src/org/eclipse/core/databinding/property/set/DelegatingSetProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/property/set/Attic/DelegatingSetProperty.java,v >retrieving revision 1.1.2.2 >diff -u -r1.1.2.2 DelegatingSetProperty.java >--- src/org/eclipse/core/databinding/property/set/DelegatingSetProperty.java 14 Jan 2009 23:51:11 -0000 1.1.2.2 >+++ src/org/eclipse/core/databinding/property/set/DelegatingSetProperty.java 17 Jan 2009 00:49:38 -0000 >@@ -18,7 +18,7 @@ > import org.eclipse.core.databinding.observable.set.IObservableSet; > import org.eclipse.core.databinding.observable.set.SetDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > > /** > * @since 1.2 >@@ -36,6 +36,15 @@ > this.elementType = elementType; > } > >+ /** >+ * Returns the property to delegate to for the specified source object. >+ * Repeated calls to this method with the same source object returns the >+ * same delegate instance. >+ * >+ * @param source >+ * the property source (may be null) >+ * @return the property to delegate to for the specified source object. >+ */ > protected final ISetProperty getDelegate(Object source) { > if (source == null) > return null; >@@ -45,6 +54,15 @@ > return delegate; > } > >+ /** >+ * Returns the property to delegate to for the specified source object. >+ * Implementers must ensure that repeated calls to this method with the same >+ * source object returns the same delegate instance. >+ * >+ * @param source >+ * the property source >+ * @return the property to delegate to for the specified source object. >+ */ > protected abstract ISetProperty doGetDelegate(Object source); > > public Object getElementType() { >@@ -67,8 +85,8 @@ > protected void doSetSet(Object source, Set set, SetDiff diff) { > } > >- protected INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ public INativePropertyListener adaptListener( >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/core/databinding/property/set/SimpleSetProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/property/set/Attic/SimpleSetProperty.java,v >retrieving revision 1.1.2.7 >diff -u -r1.1.2.7 SimpleSetProperty.java >--- src/org/eclipse/core/databinding/property/set/SimpleSetProperty.java 8 Jan 2009 01:24:50 -0000 1.1.2.7 >+++ src/org/eclipse/core/databinding/property/set/SimpleSetProperty.java 17 Jan 2009 00:49:38 -0000 >@@ -19,7 +19,8 @@ > import org.eclipse.core.databinding.observable.set.IObservableSet; > import org.eclipse.core.databinding.observable.set.SetDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.internal.databinding.property.set.SimpleSetPropertyObservableSet; > > /** > * Simplified abstract implementation of ISetProperty. This class takes care of >@@ -31,7 +32,7 @@ > * <li> {@link #getElementType()} > * <li> {@link #doGetSet(Object)} > * <li> {@link #doSetSet(Object, Set, SetDiff)} >- * <li> {@link #adaptListener(IPropertyChangeListener)} >+ * <li> {@link #adaptListener(ISimplePropertyListener)} > * <li> {@link #doAddListener(Object, INativePropertyListener)} > * <li> {@link #doRemoveListener(Object, INativePropertyListener)} > * </ul> >@@ -41,22 +42,15 @@ > * > * @since 1.2 > */ >-public abstract class SimpleSetProperty extends SetProperty { >+public abstract class SimpleSetProperty extends SetProperty implements >+ ISimpleSetProperty { > public IObservableSet observe(Realm realm, Object source) { > return new SimpleSetPropertyObservableSet(realm, source, this); > } > > // Accessors > >- /** >- * Returns a Set with the current contents of the source's set property >- * >- * @param source >- * the property source >- * @return a Set with the current contents of the source's set property >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final Set getSet(Object source) { >+ public final Set getSet(Object source) { > if (source == null) > return Collections.EMPTY_SET; > return Collections.unmodifiableSet(doGetSet(source)); >@@ -76,18 +70,7 @@ > > // Mutators > >- /** >- * Updates the property on the source with the specified change. >- * >- * @param source >- * the property source >- * @param set >- * the new set >- * @param diff >- * a diff describing the change >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void setSet(Object source, Set set, SetDiff diff) { >+ public final void setSet(Object source, Set set, SetDiff diff) { > if (source != null && !diff.isEmpty()) > doSetSet(source, set, diff); > } >@@ -107,40 +90,10 @@ > > // Listeners > >- /** >- * Returns a listener which implements the correct listener interface for >- * the expected source object, and which parlays property change events from >- * the source object to the given listener. If there is no listener API for >- * this property, this method returns null. >- * >- * @param listener >- * the property listener to receive events >- * @return a native listener which parlays property change events to the >- * specified listener. >- * @throws ClassCastException >- * if the provided listener does not implement the correct >- * listener interface (IValueProperty, IListProperty, >- * ISetProperty or IMapProperty) depending on the property. >- * @noreference This method is not intended to be referenced by clients. >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected abstract INativePropertyListener adaptListener( >- IPropertyChangeListener listener); >+ public abstract INativePropertyListener adaptListener( >+ ISimplePropertyListener listener); > >- /** >- * Adds the specified listener as a listener for this property on the >- * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >- * returns null), this method does nothing. >- * >- * @param source >- * the property source >- * @param listener >- * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void addListener(Object source, >+ public final void addListener(Object source, > INativePropertyListener listener) { > if (source != null) > doAddListener(source, listener); >@@ -149,33 +102,20 @@ > /** > * Adds the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)}. >+ * {@link #adaptListener(ISimplePropertyListener)}. > * @noreference This method is not intended to be referenced by clients. > */ > protected abstract void doAddListener(Object source, > INativePropertyListener listener); > >- /** >- * Removes the specified listener as a listener for this property on the >- * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >- * returns null), this method does nothing. >- * >- * @param source >- * the property source >- * @param listener >- * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)} . >- * @noreference This method is not intended to be referenced by clients. >- */ >- protected final void removeListener(Object source, >+ public final void removeListener(Object source, > INativePropertyListener listener) { > if (source != null) > doRemoveListener(source, listener); >@@ -184,14 +124,14 @@ > /** > * Removes the specified listener as a listener for this property on the > * specified property source. If the source object has no listener API for >- * this property (i.e. {@link #adaptListener(IPropertyChangeListener)} >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} > * returns null), this method does nothing. > * > * @param source > * the property source > * @param listener > * a listener obtained from calling >- * {@link #adaptListener(IPropertyChangeListener)} . >+ * {@link #adaptListener(ISimplePropertyListener)} . > * @noreference This method is not intended to be referenced by clients. > */ > protected abstract void doRemoveListener(Object source, >Index: src/org/eclipse/core/internal/databinding/property/map/SimpleMapPropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/map/SimpleMapPropertyObservableMap.java >diff -N src/org/eclipse/core/internal/databinding/property/map/SimpleMapPropertyObservableMap.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/map/SimpleMapPropertyObservableMap.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,297 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.map; >+ >+import java.util.AbstractSet; >+import java.util.Collection; >+import java.util.Collections; >+import java.util.ConcurrentModificationException; >+import java.util.HashMap; >+import java.util.HashSet; >+import java.util.Iterator; >+import java.util.Map; >+import java.util.Set; >+ >+import org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.ObservableTracker; >+import org.eclipse.core.databinding.observable.Realm; >+import org.eclipse.core.databinding.observable.map.AbstractObservableMap; >+import org.eclipse.core.databinding.observable.map.MapDiff; >+import org.eclipse.core.databinding.property.INativePropertyListener; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; >+import org.eclipse.core.databinding.property.map.ISimpleMapProperty; >+ >+/** >+ * @since 1.2 >+ */ >+public class SimpleMapPropertyObservableMap extends AbstractObservableMap >+ implements IPropertyObservable { >+ private Object source; >+ private ISimpleMapProperty property; >+ >+ private volatile boolean updating = false; >+ >+ private volatile int modCount = 0; >+ >+ private INativePropertyListener listener; >+ >+ private Map cachedMap; >+ >+ /** >+ * @param realm >+ * @param source >+ * @param property >+ */ >+ public SimpleMapPropertyObservableMap(Realm realm, Object source, >+ ISimpleMapProperty property) { >+ super(realm); >+ this.source = source; >+ this.property = property; >+ } >+ >+ public Object getKeyType() { >+ return property.getKeyType(); >+ } >+ >+ public Object getValueType() { >+ return property.getValueType(); >+ } >+ >+ private void getterCalled() { >+ ObservableTracker.getterCalled(this); >+ } >+ >+ protected void firstListenerAdded() { >+ if (!isDisposed()) { >+ cachedMap = new HashMap(this); >+ >+ if (listener == null) { >+ listener = property >+ .adaptListener(new ISimplePropertyListener() { >+ public void handlePropertyChange( >+ final SimplePropertyEvent event) { >+ modCount++; >+ if (!isDisposed() && !updating) { >+ getRealm().exec(new Runnable() { >+ public void run() { >+ notifyIfChanged((MapDiff) event.diff); >+ } >+ }); >+ } >+ } >+ }); >+ } >+ property.addListener(source, listener); >+ } >+ } >+ >+ protected void lastListenerRemoved() { >+ if (listener != null) { >+ property.removeListener(source, listener); >+ } >+ >+ cachedMap.clear(); >+ cachedMap = null; >+ } >+ >+ // Queries >+ >+ private Map getMap() { >+ return property.getMap(source); >+ } >+ >+ // Single change operations >+ >+ private EntrySet es = new EntrySet(); >+ >+ public Set entrySet() { >+ getterCalled(); >+ return es; >+ } >+ >+ private class EntrySet extends AbstractSet { >+ public Iterator iterator() { >+ return new EntrySetIterator(); >+ } >+ >+ public int size() { >+ return getMap().size(); >+ } >+ } >+ >+ private class EntrySetIterator implements Iterator { >+ private volatile int expectedModCount = modCount; >+ Map map = new HashMap(getMap()); >+ Iterator iterator = map.entrySet().iterator(); >+ Map.Entry last = null; >+ >+ public boolean hasNext() { >+ getterCalled(); >+ checkForComodification(); >+ return iterator.hasNext(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ checkForComodification(); >+ last = (Map.Entry) iterator.next(); >+ return last; >+ } >+ >+ public void remove() { >+ getterCalled(); >+ checkForComodification(); >+ >+ iterator.remove(); // stay in sync >+ MapDiff diff = Diffs.createMapDiffSingleRemove(last.getKey(), last >+ .getValue()); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setMap(source, map, diff); >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ last = null; >+ expectedModCount = modCount; >+ } >+ >+ private void checkForComodification() { >+ if (expectedModCount != modCount) >+ throw new ConcurrentModificationException(); >+ } >+ } >+ >+ public Set keySet() { >+ getterCalled(); >+ // AbstractMap depends on entrySet() to fulfil keySet() API, so all >+ // getterCalled() and comodification checks will still be handled >+ return super.keySet(); >+ } >+ >+ public Object put(Object key, Object value) { >+ checkRealm(); >+ >+ Map map = new HashMap(getMap()); >+ >+ boolean add = !map.containsKey(key); >+ >+ Object oldValue = map.put(key, value); >+ >+ MapDiff diff; >+ if (add) >+ diff = Diffs.createMapDiffSingleAdd(key, value); >+ else >+ diff = Diffs.createMapDiffSingleChange(key, oldValue, value); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setMap(source, map, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return oldValue; >+ } >+ >+ public void putAll(Map m) { >+ checkRealm(); >+ >+ Map map = new HashMap(getMap()); >+ >+ Map oldValues = new HashMap(); >+ Map newValues = new HashMap(); >+ Set changedKeys = new HashSet(); >+ Set addedKeys = new HashSet(); >+ for (Iterator it = m.entrySet().iterator(); it.hasNext();) { >+ Map.Entry entry = (Entry) it.next(); >+ Object key = entry.getKey(); >+ Object newValue = entry.getValue(); >+ if (map.containsKey(key)) { >+ changedKeys.add(key); >+ oldValues.put(key, map.get(key)); >+ } else { >+ addedKeys.add(key); >+ } >+ map.put(key, newValue); >+ >+ newValues.put(key, newValue); >+ } >+ >+ MapDiff diff = Diffs.createMapDiff(addedKeys, Collections.EMPTY_SET, >+ changedKeys, oldValues, newValues); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setMap(source, map, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ } >+ >+ public Object remove(Object key) { >+ checkRealm(); >+ return super.remove(key); >+ } >+ >+ public Collection values() { >+ getterCalled(); >+ // AbstractMap depends on entrySet() to fulfil values() API, so all >+ // getterCalled() and comodification checks will still be handled >+ return super.values(); >+ } >+ >+ private void notifyIfChanged(MapDiff diff) { >+ if (hasListeners()) { >+ Map oldMap = cachedMap; >+ Map newMap = cachedMap = property.getMap(source); >+ if (diff == null) >+ diff = Diffs.computeMapDiff(oldMap, newMap); >+ if (!diff.isEmpty()) >+ fireMapChange(diff); >+ } >+ } >+ >+ public Object getObserved() { >+ return source; >+ } >+ >+ public IProperty getProperty() { >+ return property; >+ } >+ >+ public synchronized void dispose() { >+ if (!isDisposed()) { >+ if (listener != null) >+ property.removeListener(source, listener); >+ property = null; >+ source = null; >+ listener = null; >+ } >+ super.dispose(); >+ } >+} >Index: src/org/eclipse/core/internal/databinding/property/set/SimpleSetPropertyObservableSet.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/set/SimpleSetPropertyObservableSet.java >diff -N src/org/eclipse/core/internal/databinding/property/set/SimpleSetPropertyObservableSet.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/set/SimpleSetPropertyObservableSet.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,408 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.set; >+ >+import java.util.Collection; >+import java.util.Collections; >+import java.util.ConcurrentModificationException; >+import java.util.HashSet; >+import java.util.Iterator; >+import java.util.Set; >+ >+import org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.Realm; >+import org.eclipse.core.databinding.observable.set.AbstractObservableSet; >+import org.eclipse.core.databinding.observable.set.SetDiff; >+import org.eclipse.core.databinding.property.INativePropertyListener; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; >+import org.eclipse.core.databinding.property.set.ISimpleSetProperty; >+ >+/** >+ * @since 1.2 >+ * >+ */ >+public class SimpleSetPropertyObservableSet extends AbstractObservableSet >+ implements IPropertyObservable { >+ private Object source; >+ private ISimpleSetProperty property; >+ >+ private volatile boolean updating = false; >+ >+ private volatile int modCount = 0; >+ >+ private INativePropertyListener listener; >+ >+ private Set cachedSet; >+ >+ /** >+ * @param realm >+ * @param source >+ * @param property >+ */ >+ public SimpleSetPropertyObservableSet(Realm realm, Object source, >+ ISimpleSetProperty property) { >+ super(realm); >+ this.source = source; >+ this.property = property; >+ } >+ >+ protected void firstListenerAdded() { >+ if (!isDisposed()) { >+ cachedSet = getSet(); >+ >+ if (listener == null) { >+ listener = property >+ .adaptListener(new ISimplePropertyListener() { >+ public void handlePropertyChange( >+ final SimplePropertyEvent event) { >+ modCount++; >+ if (!isDisposed() && !updating) { >+ getRealm().exec(new Runnable() { >+ public void run() { >+ notifyIfChanged((SetDiff) event.diff); >+ } >+ }); >+ } >+ } >+ }); >+ } >+ property.addListener(source, listener); >+ } >+ } >+ >+ protected void lastListenerRemoved() { >+ if (listener != null) { >+ property.removeListener(source, listener); >+ } >+ >+ cachedSet = null; >+ } >+ >+ protected Set getWrappedSet() { >+ return getSet(); >+ } >+ >+ public Object getElementType() { >+ return property.getElementType(); >+ } >+ >+ // Queries >+ >+ private Set getSet() { >+ return property.getSet(source); >+ } >+ >+ public boolean contains(Object o) { >+ getterCalled(); >+ return getSet().contains(o); >+ } >+ >+ public boolean containsAll(Collection c) { >+ getterCalled(); >+ return getSet().containsAll(c); >+ } >+ >+ public boolean isEmpty() { >+ getterCalled(); >+ return getSet().isEmpty(); >+ } >+ >+ public Object[] toArray() { >+ getterCalled(); >+ return getSet().toArray(); >+ } >+ >+ public Object[] toArray(Object[] a) { >+ getterCalled(); >+ return getSet().toArray(a); >+ } >+ >+ // Single change operations >+ >+ public boolean add(Object o) { >+ checkRealm(); >+ >+ Set set = new HashSet(getSet()); >+ if (!set.add(o)) >+ return false; >+ >+ SetDiff diff = Diffs.createSetDiff(Collections.singleton(o), >+ Collections.EMPTY_SET); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setSet(source, set, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return true; >+ } >+ >+ public Iterator iterator() { >+ getterCalled(); >+ return new Iterator() { >+ int expectedModCount = modCount; >+ Set set = new HashSet(getSet()); >+ Iterator iterator = set.iterator(); >+ Object last = null; >+ >+ public boolean hasNext() { >+ getterCalled(); >+ checkForComodification(); >+ return iterator.hasNext(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ checkForComodification(); >+ last = iterator.next(); >+ return last; >+ } >+ >+ public void remove() { >+ checkRealm(); >+ checkForComodification(); >+ >+ iterator.remove(); // stay in sync >+ SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, >+ Collections.singleton(last)); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setSet(source, set, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ last = null; >+ expectedModCount = modCount; >+ } >+ >+ private void checkForComodification() { >+ if (expectedModCount != modCount) >+ throw new ConcurrentModificationException(); >+ } >+ }; >+ } >+ >+ public boolean remove(Object o) { >+ getterCalled(); >+ >+ Set set = new HashSet(getSet()); >+ if (!set.remove(o)) >+ return false; >+ >+ SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, Collections >+ .singleton(o)); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setSet(source, set, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return true; >+ } >+ >+ // Bulk change operations >+ >+ public boolean addAll(Collection c) { >+ getterCalled(); >+ >+ if (c.isEmpty()) >+ return false; >+ >+ Set set = new HashSet(getSet()); >+ >+ Set additions = new HashSet(c); >+ for (Iterator it = c.iterator(); it.hasNext();) { >+ Object element = it.next(); >+ if (set.add(element)) >+ additions.add(element); >+ } >+ >+ if (additions.isEmpty()) >+ return false; >+ >+ SetDiff diff = Diffs.createSetDiff(additions, Collections.EMPTY_SET); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setSet(source, set, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return true; >+ } >+ >+ public boolean removeAll(Collection c) { >+ getterCalled(); >+ >+ Set set = getSet(); >+ if (set.isEmpty()) >+ return false; >+ if (c.isEmpty()) >+ return false; >+ >+ set = new HashSet(set); >+ >+ Set removals = new HashSet(c); >+ for (Iterator it = c.iterator(); it.hasNext();) { >+ Object element = it.next(); >+ if (set.remove(element)) >+ removals.add(element); >+ } >+ >+ if (removals.isEmpty()) >+ return false; >+ >+ SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setSet(source, set, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return true; >+ } >+ >+ public boolean retainAll(Collection c) { >+ getterCalled(); >+ >+ Set set = getSet(); >+ if (set.isEmpty()) >+ return false; >+ >+ if (c.isEmpty()) { >+ clear(); >+ return true; >+ } >+ >+ set = new HashSet(set); >+ >+ Set removals = new HashSet(); >+ for (Iterator it = set.iterator(); it.hasNext();) { >+ Object element = it.next(); >+ if (!c.contains(element)) { >+ it.remove(); >+ removals.add(element); >+ } >+ } >+ >+ if (removals.isEmpty()) >+ return false; >+ >+ SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setSet(source, set, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return true; >+ } >+ >+ public void clear() { >+ getterCalled(); >+ >+ Set set = getSet(); >+ if (set.isEmpty()) >+ return; >+ >+ SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, set); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setSet(source, Collections.EMPTY_SET, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ } >+ >+ private void notifyIfChanged(SetDiff diff) { >+ if (hasListeners()) { >+ Set oldSet = cachedSet; >+ Set newSet = cachedSet = property.getSet(source); >+ if (diff == null) >+ diff = Diffs.computeSetDiff(oldSet, newSet); >+ if (!diff.isEmpty()) >+ fireSetChange(diff); >+ } >+ } >+ >+ public boolean equals(Object o) { >+ getterCalled(); >+ return getSet().equals(o); >+ } >+ >+ public int hashCode() { >+ getterCalled(); >+ return getSet().hashCode(); >+ } >+ >+ public Object getObserved() { >+ return source; >+ } >+ >+ public IProperty getProperty() { >+ return property; >+ } >+ >+ public synchronized void dispose() { >+ if (!isDisposed()) { >+ if (listener != null) >+ property.removeListener(source, listener); >+ property = null; >+ source = null; >+ listener = null; >+ } >+ super.dispose(); >+ } >+} >Index: src/org/eclipse/core/internal/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java >diff -N src/org/eclipse/core/internal/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,144 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.value; >+ >+import java.util.HashMap; >+import java.util.Iterator; >+import java.util.Map; >+ >+import org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.map.ComputedObservableMap; >+import org.eclipse.core.databinding.observable.set.IObservableSet; >+import org.eclipse.core.databinding.property.INativePropertyListener; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; >+import org.eclipse.core.databinding.property.value.ISimpleValueProperty; >+import org.eclipse.core.internal.databinding.Util; >+ >+/** >+ * @since 1.2 >+ */ >+public class ObservableSetSimpleValuePropertyObservableMap extends >+ ComputedObservableMap implements IPropertyObservable { >+ private ISimpleValueProperty detailProperty; >+ >+ private INativePropertyListener listener; >+ >+ private Map cachedValues; >+ >+ private boolean updating; >+ >+ /** >+ * @param keySet >+ * @param valueProperty >+ */ >+ public ObservableSetSimpleValuePropertyObservableMap(IObservableSet keySet, >+ ISimpleValueProperty valueProperty) { >+ super(keySet); >+ this.detailProperty = valueProperty; >+ } >+ >+ protected void firstListenerAdded() { >+ cachedValues = new HashMap(this); >+ if (listener == null) { >+ listener = detailProperty >+ .adaptListener(new ISimplePropertyListener() { >+ public void handlePropertyChange( >+ final SimplePropertyEvent event) { >+ if (!isDisposed() && !updating) { >+ getRealm().exec(new Runnable() { >+ public void run() { >+ notifyIfChanged(event.getSource()); >+ } >+ }); >+ } >+ } >+ }); >+ } >+ super.firstListenerAdded(); >+ } >+ >+ protected void lastListenerRemoved() { >+ super.lastListenerRemoved(); >+ cachedValues.clear(); >+ cachedValues = null; >+ } >+ >+ protected void hookListener(Object addedKey) { >+ if (listener != null) { >+ cachedValues.put(addedKey, detailProperty.getValue(addedKey)); >+ detailProperty.addListener(addedKey, listener); >+ } >+ } >+ >+ protected void unhookListener(Object removedKey) { >+ if (listener != null) { >+ detailProperty.removeListener(removedKey, listener); >+ cachedValues.remove(removedKey); >+ } >+ } >+ >+ protected Object doGet(Object key) { >+ return detailProperty.getValue(key); >+ } >+ >+ protected Object doPut(Object key, Object value) { >+ Object oldValue = detailProperty.getValue(key); >+ >+ updating = true; >+ try { >+ detailProperty.setValue(key, value); >+ } finally { >+ updating = false; >+ } >+ >+ notifyIfChanged(key); >+ >+ return oldValue; >+ } >+ >+ private void notifyIfChanged(Object key) { >+ if (cachedValues != null) { >+ Object oldValue = cachedValues.get(key); >+ Object newValue = detailProperty.getValue(key); >+ if (!Util.equals(oldValue, newValue)) { >+ cachedValues.put(key, newValue); >+ fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue, >+ newValue)); >+ } >+ } >+ } >+ >+ public Object getObserved() { >+ return keySet(); >+ } >+ >+ public IProperty getProperty() { >+ return detailProperty; >+ } >+ >+ public synchronized void dispose() { >+ if (!isDisposed()) { >+ if (listener != null) { >+ for (Iterator it = values().iterator(); it.hasNext();) { >+ unhookListener(it.next()); >+ } >+ listener = null; >+ } >+ detailProperty = null; >+ } >+ >+ super.dispose(); >+ } >+} >Index: src/org/eclipse/core/internal/databinding/property/value/ObservableSetDelegatingValuePropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/value/ObservableSetDelegatingValuePropertyObservableMap.java >diff -N src/org/eclipse/core/internal/databinding/property/value/ObservableSetDelegatingValuePropertyObservableMap.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/value/ObservableSetDelegatingValuePropertyObservableMap.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,241 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.value; >+ >+import java.util.AbstractSet; >+import java.util.Collections; >+import java.util.HashMap; >+import java.util.Iterator; >+import java.util.Map; >+import java.util.Set; >+ >+import org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.IStaleListener; >+import org.eclipse.core.databinding.observable.ObservableTracker; >+import org.eclipse.core.databinding.observable.StaleEvent; >+import org.eclipse.core.databinding.observable.map.AbstractObservableMap; >+import org.eclipse.core.databinding.observable.map.MapDiff; >+import org.eclipse.core.databinding.observable.set.IObservableSet; >+import org.eclipse.core.databinding.observable.set.ISetChangeListener; >+import org.eclipse.core.databinding.observable.set.SetChangeEvent; >+import org.eclipse.core.databinding.observable.set.SetDiff; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.value.DelegatingValueProperty; >+import org.eclipse.core.internal.databinding.Util; >+ >+/** >+ * @since 1.2 >+ */ >+public class ObservableSetDelegatingValuePropertyObservableMap extends >+ AbstractObservableMap implements IPropertyObservable { >+ private IObservableSet masterSet; >+ private DelegatingValueProperty detailProperty; >+ private DelegatingCache cache; >+ >+ private Set entrySet; >+ >+ class EntrySet extends AbstractSet { >+ public Iterator iterator() { >+ return new Iterator() { >+ final Iterator it = masterSet.iterator(); >+ >+ public boolean hasNext() { >+ return it.hasNext(); >+ } >+ >+ public Object next() { >+ return new MapEntry(it.next()); >+ } >+ >+ public void remove() { >+ it.remove(); >+ } >+ }; >+ } >+ >+ public int size() { >+ return masterSet.size(); >+ } >+ } >+ >+ class MapEntry implements Map.Entry { >+ private final Object key; >+ >+ MapEntry(Object key) { >+ this.key = key; >+ } >+ >+ public Object getKey() { >+ getterCalled(); >+ return key; >+ } >+ >+ public Object getValue() { >+ getterCalled(); >+ >+ if (!masterSet.contains(key)) >+ return null; >+ >+ return cache.get(key); >+ } >+ >+ public Object setValue(Object value) { >+ checkRealm(); >+ >+ if (!masterSet.contains(key)) >+ return null; >+ >+ return cache.put(key, value); >+ } >+ >+ public boolean equals(Object o) { >+ getterCalled(); >+ if (o == this) >+ return true; >+ if (o == null) >+ return false; >+ if (!(o instanceof Map.Entry)) >+ return false; >+ Map.Entry that = (Map.Entry) o; >+ return Util.equals(this.getKey(), that.getKey()) >+ && Util.equals(this.getValue(), that.getValue()); >+ } >+ >+ public int hashCode() { >+ getterCalled(); >+ Object value = getValue(); >+ return (key == null ? 0 : key.hashCode()) >+ ^ (value == null ? 0 : value.hashCode()); >+ } >+ } >+ >+ private ISetChangeListener masterListener = new ISetChangeListener() { >+ public void handleSetChange(SetChangeEvent event) { >+ if (isDisposed()) >+ return; >+ >+ cache.addAll(masterSet); >+ >+ // Need both obsolete and new elements to convert diff >+ MapDiff diff = convertDiff(event.diff); >+ >+ cache.retainAll(masterSet); >+ >+ fireMapChange(diff); >+ } >+ >+ private MapDiff convertDiff(SetDiff diff) { >+ // Convert diff to detail value >+ Map oldValues = new HashMap(); >+ Map newValues = new HashMap(); >+ >+ for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) { >+ Object masterElement = it.next(); >+ oldValues.put(masterElement, cache.get(masterElement)); >+ } >+ for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) { >+ Object masterElement = it.next(); >+ newValues.put(masterElement, cache.get(masterElement)); >+ } >+ return Diffs.createMapDiff(diff.getAdditions(), diff.getRemovals(), >+ Collections.EMPTY_SET, oldValues, newValues); >+ } >+ }; >+ >+ private IStaleListener staleListener = new IStaleListener() { >+ public void handleStale(StaleEvent staleEvent) { >+ fireStale(); >+ } >+ }; >+ >+ /** >+ * @param keySet >+ * @param valueProperty >+ */ >+ public ObservableSetDelegatingValuePropertyObservableMap( >+ IObservableSet keySet, DelegatingValueProperty valueProperty) { >+ super(keySet.getRealm()); >+ this.masterSet = keySet; >+ this.detailProperty = valueProperty; >+ this.cache = new DelegatingCache(getRealm(), valueProperty) { >+ void handleValueChange(Object masterElement, Object oldValue, >+ Object newValue) { >+ fireMapChange(Diffs.createMapDiffSingleChange(masterElement, >+ oldValue, newValue)); >+ } >+ }; >+ cache.addAll(masterSet); >+ >+ masterSet.addSetChangeListener(masterListener); >+ masterSet.addStaleListener(staleListener); >+ } >+ >+ public Set entrySet() { >+ getterCalled(); >+ if (entrySet == null) >+ entrySet = new EntrySet(); >+ return entrySet; >+ } >+ >+ private void getterCalled() { >+ ObservableTracker.getterCalled(this); >+ } >+ >+ public Object get(Object key) { >+ getterCalled(); >+ return cache.get(key); >+ } >+ >+ public Object put(Object key, Object value) { >+ checkRealm(); >+ return cache.put(key, value); >+ } >+ >+ public boolean isStale() { >+ return masterSet.isStale(); >+ } >+ >+ public Object getObserved() { >+ return masterSet; >+ } >+ >+ public IProperty getProperty() { >+ return detailProperty; >+ } >+ >+ public Object getKeyType() { >+ return masterSet.getElementType(); >+ } >+ >+ public Object getValueType() { >+ return detailProperty.getValueType(); >+ } >+ >+ public synchronized void dispose() { >+ if (masterSet != null) { >+ masterSet.removeSetChangeListener(masterListener); >+ masterSet.removeStaleListener(staleListener); >+ masterSet = null; >+ } >+ >+ if (cache != null) { >+ cache.dispose(); >+ cache = null; >+ } >+ >+ masterListener = null; >+ detailProperty = null; >+ >+ super.dispose(); >+ } >+} >Index: src/org/eclipse/core/databinding/property/ISimplePropertyListener.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/ISimplePropertyListener.java >diff -N src/org/eclipse/core/databinding/property/ISimplePropertyListener.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/property/ISimplePropertyListener.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,30 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ * Matthew Hall - but 194734 >+ ******************************************************************************/ >+ >+package org.eclipse.core.databinding.property; >+ >+/** >+ * Listener for changes to properties on a particular source object >+ * >+ * @noextend This interface is not intended to be extended by clients. >+ * >+ * @since 1.2 >+ */ >+public interface ISimplePropertyListener { >+ /** >+ * Handle the property change described in the event. >+ * >+ * @param event >+ * an event describing the property change that occured. >+ */ >+ public void handlePropertyChange(SimplePropertyEvent event); >+} >Index: src/org/eclipse/core/databinding/property/list/ISimpleListProperty.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/list/ISimpleListProperty.java >diff -N src/org/eclipse/core/databinding/property/list/ISimpleListProperty.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/property/list/ISimpleListProperty.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,48 @@ >+/******************************************************************************* >+ * Copyright (c) 2009 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.databinding.property.list; >+ >+import java.util.List; >+ >+import org.eclipse.core.databinding.observable.list.ListDiff; >+import org.eclipse.core.databinding.property.ISimpleProperty; >+ >+/** >+ * @since 1.2 >+ * >+ */ >+public interface ISimpleListProperty extends ISimpleProperty, IListProperty { >+ /** >+ * Returns an unmodifiable List with the current contents of the source's >+ * list property >+ * >+ * @param source >+ * the property source >+ * @return an unmodifiable List with the current contents of the source's >+ * list property >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public List getList(Object source); >+ >+ /** >+ * Updates the property on the source with the specified change. >+ * >+ * @param source >+ * the property source >+ * @param list >+ * the new list >+ * @param diff >+ * a diff describing the change >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public void setList(Object source, List list, ListDiff diff); >+} >Index: src/org/eclipse/core/internal/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java >diff -N src/org/eclipse/core/internal/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,375 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.value; >+ >+import java.util.AbstractSet; >+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 org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.IStaleListener; >+import org.eclipse.core.databinding.observable.ObservableTracker; >+import org.eclipse.core.databinding.observable.StaleEvent; >+import org.eclipse.core.databinding.observable.map.AbstractObservableMap; >+import org.eclipse.core.databinding.observable.map.IMapChangeListener; >+import org.eclipse.core.databinding.observable.map.IObservableMap; >+import org.eclipse.core.databinding.observable.map.MapChangeEvent; >+import org.eclipse.core.databinding.observable.map.MapDiff; >+import org.eclipse.core.databinding.observable.set.IObservableSet; >+import org.eclipse.core.databinding.observable.set.ISetChangeListener; >+import org.eclipse.core.databinding.observable.set.SetChangeEvent; >+import org.eclipse.core.databinding.observable.set.WritableSet; >+import org.eclipse.core.databinding.property.INativePropertyListener; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; >+import org.eclipse.core.databinding.property.value.ISimpleValueProperty; >+import org.eclipse.core.internal.databinding.IdentityWrapper; >+import org.eclipse.core.internal.databinding.Util; >+ >+/** >+ * @since 1.2 >+ * >+ */ >+public class ObservableMapSimpleValuePropertyObservableMap extends >+ AbstractObservableMap implements IPropertyObservable { >+ private IObservableMap masterMap; >+ private ISimpleValueProperty detailProperty; >+ >+ private IObservableSet knownMasterValues; >+ private Map cachedValues; >+ >+ private boolean updating = false; >+ >+ private IMapChangeListener masterListener = new IMapChangeListener() { >+ public void handleMapChange(final MapChangeEvent event) { >+ if (!isDisposed()) { >+ updateKnownValues(); >+ if (!updating) >+ fireMapChange(convertDiff(event.diff)); >+ } >+ } >+ >+ private void updateKnownValues() { >+ Set identityKnownValues = new HashSet(); >+ for (Iterator it = masterMap.values().iterator(); it.hasNext();) { >+ identityKnownValues.add(new IdentityWrapper(it.next())); >+ } >+ >+ knownMasterValues.retainAll(identityKnownValues); >+ knownMasterValues.addAll(identityKnownValues); >+ } >+ >+ private MapDiff convertDiff(MapDiff diff) { >+ Map oldValues = new HashMap(); >+ Map newValues = new HashMap(); >+ >+ Set addedKeys = diff.getAddedKeys(); >+ for (Iterator it = addedKeys.iterator(); it.hasNext();) { >+ Object key = it.next(); >+ Object newSource = diff.getNewValue(key); >+ Object newValue = detailProperty.getValue(newSource); >+ newValues.put(key, newValue); >+ } >+ >+ Set removedKeys = diff.getRemovedKeys(); >+ for (Iterator it = removedKeys.iterator(); it.hasNext();) { >+ Object key = it.next(); >+ Object oldSource = diff.getOldValue(key); >+ Object oldValue = detailProperty.getValue(oldSource); >+ oldValues.put(key, oldValue); >+ } >+ >+ Set changedKeys = new HashSet(diff.getChangedKeys()); >+ for (Iterator it = changedKeys.iterator(); it.hasNext();) { >+ Object key = it.next(); >+ >+ Object oldSource = diff.getOldValue(key); >+ Object newSource = diff.getNewValue(key); >+ >+ Object oldValue = detailProperty.getValue(oldSource); >+ Object newValue = detailProperty.getValue(newSource); >+ >+ if (Util.equals(oldValue, newValue)) { >+ it.remove(); >+ } else { >+ oldValues.put(key, oldValue); >+ newValues.put(key, newValue); >+ } >+ } >+ >+ return Diffs.createMapDiff(addedKeys, removedKeys, changedKeys, >+ oldValues, newValues); >+ } >+ }; >+ >+ private IStaleListener staleListener = new IStaleListener() { >+ public void handleStale(StaleEvent staleEvent) { >+ fireStale(); >+ } >+ }; >+ >+ private INativePropertyListener detailListener; >+ >+ /** >+ * @param map >+ * @param valueProperty >+ */ >+ public ObservableMapSimpleValuePropertyObservableMap(IObservableMap map, >+ ISimpleValueProperty valueProperty) { >+ super(map.getRealm()); >+ this.masterMap = map; >+ this.detailProperty = valueProperty; >+ >+ ISimplePropertyListener listener = new ISimplePropertyListener() { >+ public void handlePropertyChange(SimplePropertyEvent event) { >+ notifyIfChanged(event.getSource()); >+ } >+ }; >+ this.detailListener = detailProperty.adaptListener(listener); >+ } >+ >+ protected void firstListenerAdded() { >+ knownMasterValues = new WritableSet(getRealm()); >+ cachedValues = new HashMap(); >+ knownMasterValues.addSetChangeListener(new ISetChangeListener() { >+ public void handleSetChange(SetChangeEvent event) { >+ for (Iterator it = event.diff.getRemovals().iterator(); it >+ .hasNext();) { >+ IdentityWrapper wrapper = (IdentityWrapper) it.next(); >+ Object key = wrapper.unwrap(); >+ detailProperty.removeListener(key, detailListener); >+ cachedValues.remove(wrapper); >+ } >+ for (Iterator it = event.diff.getAdditions().iterator(); it >+ .hasNext();) { >+ IdentityWrapper wrapper = (IdentityWrapper) it.next(); >+ Object key = wrapper.unwrap(); >+ cachedValues.put(wrapper, detailProperty.getValue(key)); >+ detailProperty.addListener(key, detailListener); >+ } >+ } >+ }); >+ for (Iterator it = masterMap.values().iterator(); it.hasNext();) { >+ knownMasterValues.add(new IdentityWrapper(it.next())); >+ } >+ >+ masterMap.addMapChangeListener(masterListener); >+ masterMap.addStaleListener(staleListener); >+ } >+ >+ protected void lastListenerRemoved() { >+ masterMap.removeMapChangeListener(masterListener); >+ masterMap.removeStaleListener(staleListener); >+ if (knownMasterValues != null) { >+ knownMasterValues.clear(); // removes attached listeners >+ knownMasterValues.dispose(); >+ knownMasterValues = null; >+ } >+ cachedValues.clear(); >+ cachedValues = null; >+ } >+ >+ private Set entrySet; >+ >+ public Set entrySet() { >+ getterCalled(); >+ if (entrySet == null) >+ entrySet = new EntrySet(); >+ return entrySet; >+ } >+ >+ class EntrySet extends AbstractSet { >+ public Iterator iterator() { >+ return new Iterator() { >+ Iterator it = masterMap.entrySet().iterator(); >+ >+ public boolean hasNext() { >+ getterCalled(); >+ return it.hasNext(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ Map.Entry next = (Map.Entry) it.next(); >+ return new MapEntry(next.getKey()); >+ } >+ >+ public void remove() { >+ it.remove(); >+ } >+ }; >+ } >+ >+ public int size() { >+ return masterMap.size(); >+ } >+ } >+ >+ class MapEntry implements Map.Entry { >+ private Object key; >+ >+ MapEntry(Object key) { >+ this.key = key; >+ } >+ >+ public Object getKey() { >+ getterCalled(); >+ return key; >+ } >+ >+ public Object getValue() { >+ getterCalled(); >+ if (!masterMap.containsKey(key)) >+ return null; >+ return detailProperty.getValue(masterMap.get(key)); >+ } >+ >+ public Object setValue(Object value) { >+ if (!masterMap.containsKey(key)) >+ return null; >+ Object source = masterMap.get(key); >+ >+ Object oldValue = detailProperty.getValue(source); >+ >+ updating = true; >+ try { >+ detailProperty.setValue(source, value); >+ } finally { >+ updating = false; >+ } >+ >+ notifyIfChanged(source); >+ >+ return oldValue; >+ } >+ >+ public boolean equals(Object o) { >+ getterCalled(); >+ if (o == this) >+ return true; >+ if (o == null) >+ return false; >+ if (!(o instanceof Map.Entry)) >+ return false; >+ Map.Entry that = (Map.Entry) o; >+ return Util.equals(this.getKey(), that.getKey()) >+ && Util.equals(this.getValue(), that.getValue()); >+ } >+ >+ public int hashCode() { >+ getterCalled(); >+ Object value = getValue(); >+ return (key == null ? 0 : key.hashCode()) >+ ^ (value == null ? 0 : value.hashCode()); >+ } >+ } >+ >+ public Object put(Object key, Object value) { >+ if (!masterMap.containsKey(key)) >+ return null; >+ Object masterValue = masterMap.get(key); >+ Object oldValue = detailProperty.getValue(key); >+ detailProperty.setValue(masterValue, value); >+ notifyIfChanged(masterValue); >+ return oldValue; >+ } >+ >+ private void notifyIfChanged(Object masterValue) { >+ if (cachedValues != null) { >+ final Set keys = keysFor(masterValue); >+ >+ final Object oldValue = cachedValues.get(new IdentityWrapper( >+ masterValue)); >+ final Object newValue = detailProperty.getValue(masterValue); >+ >+ if (!Util.equals(oldValue, newValue)) { >+ cachedValues.put(new IdentityWrapper(masterValue), newValue); >+ fireMapChange(new MapDiff() { >+ public Set getAddedKeys() { >+ return Collections.EMPTY_SET; >+ } >+ >+ public Set getChangedKeys() { >+ return keys; >+ } >+ >+ public Set getRemovedKeys() { >+ return Collections.EMPTY_SET; >+ } >+ >+ public Object getNewValue(Object key) { >+ return newValue; >+ } >+ >+ public Object getOldValue(Object key) { >+ return oldValue; >+ } >+ }); >+ } >+ } >+ } >+ >+ private Set keysFor(Object value) { >+ Set keys = new HashSet(); >+ >+ for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) { >+ Map.Entry entry = (Entry) it.next(); >+ if (entry.getValue() == value) { >+ keys.add(entry.getKey()); >+ } >+ } >+ >+ return keys; >+ } >+ >+ public boolean isStale() { >+ getterCalled(); >+ return masterMap.isStale(); >+ } >+ >+ private void getterCalled() { >+ ObservableTracker.getterCalled(this); >+ } >+ >+ public Object getObserved() { >+ return masterMap; >+ } >+ >+ public IProperty getProperty() { >+ return detailProperty; >+ } >+ >+ public synchronized void dispose() { >+ if (masterMap != null) { >+ masterMap.removeMapChangeListener(masterListener); >+ masterMap = null; >+ } >+ if (knownMasterValues != null) { >+ knownMasterValues.clear(); // detaches listeners >+ knownMasterValues.dispose(); >+ knownMasterValues = null; >+ } >+ >+ masterListener = null; >+ detailListener = null; >+ detailProperty = null; >+ cachedValues = null; >+ >+ super.dispose(); >+ } >+} >Index: src/org/eclipse/core/databinding/property/value/ISimpleValueProperty.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/value/ISimpleValueProperty.java >diff -N src/org/eclipse/core/databinding/property/value/ISimpleValueProperty.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/property/value/ISimpleValueProperty.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,40 @@ >+/******************************************************************************* >+ * Copyright (c) 2009 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation >+ ******************************************************************************/ >+ >+package org.eclipse.core.databinding.property.value; >+ >+import org.eclipse.core.databinding.property.ISimpleProperty; >+ >+/** >+ * @since 1.2 >+ */ >+public interface ISimpleValueProperty extends IValueProperty, ISimpleProperty { >+ /** >+ * Returns the value of the property on the specified source object >+ * >+ * @param source >+ * the property source (may be null) >+ * @return the current value of the source's value property >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public Object getValue(Object source); >+ >+ /** >+ * Sets the source's value property to the specified value >+ * >+ * @param source >+ * the property source >+ * @param value >+ * the new value >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public void setValue(Object source, Object value); >+} >Index: src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java >diff -N src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,210 @@ >+/******************************************************************************* >+ * Copyright (c) 2009 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.value; >+ >+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 org.eclipse.core.databinding.observable.Realm; >+import org.eclipse.core.databinding.observable.map.IMapChangeListener; >+import org.eclipse.core.databinding.observable.map.IObservableMap; >+import org.eclipse.core.databinding.observable.map.MapChangeEvent; >+import org.eclipse.core.databinding.observable.set.IObservableSet; >+import org.eclipse.core.databinding.observable.set.ISetChangeListener; >+import org.eclipse.core.databinding.observable.set.SetChangeEvent; >+import org.eclipse.core.databinding.observable.set.WritableSet; >+import org.eclipse.core.databinding.property.value.DelegatingValueProperty; >+import org.eclipse.core.databinding.property.value.IValueProperty; >+import org.eclipse.core.internal.databinding.IdentityWrapper; >+import org.eclipse.core.internal.databinding.Util; >+ >+/** >+ * @since 3.3 >+ * >+ */ >+abstract class DelegatingCache { >+ private Realm realm; >+ private DelegatingValueProperty detailProperty; >+ private IObservableSet elements; >+ private Map delegateCaches; >+ >+ private class DelegateCache implements IMapChangeListener { >+ private final IValueProperty delegate; >+ private final IObservableSet masterElements; >+ private final IObservableMap masterElementValues; >+ private final Map cachedValues; >+ >+ DelegateCache(IValueProperty delegate) { >+ this.delegate = delegate; >+ this.masterElements = new WritableSet(realm, Collections.EMPTY_SET, >+ elements.getElementType()); >+ this.masterElementValues = delegate.observeDetail(masterElements); >+ this.cachedValues = new HashMap(); >+ >+ masterElementValues.addMapChangeListener(this); >+ } >+ >+ void add(Object masterElement) { >+ boolean wasEmpty = masterElements.isEmpty(); >+ >+ masterElements.add(masterElement); >+ cachedValues.put(new IdentityWrapper(masterElement), >+ masterElementValues.get(masterElement)); >+ >+ if (wasEmpty) >+ delegateCaches.put(delegate, this); >+ } >+ >+ void remove(Object masterElement) { >+ cachedValues.remove(new IdentityWrapper(masterElement)); >+ masterElements.remove(masterElement); >+ if (cachedValues.isEmpty()) >+ dispose(); >+ } >+ >+ Object get(Object masterElement) { >+ return cachedValues.get(new IdentityWrapper(masterElement)); >+ } >+ >+ Object put(Object masterElement, Object detailValue) { >+ Object oldValue = masterElementValues.put(masterElement, >+ detailValue); >+ notifyIfChanged(masterElement); >+ return oldValue; >+ } >+ >+ boolean containsValue(Object detailValue) { >+ return cachedValues.containsValue(detailValue); >+ } >+ >+ public void handleMapChange(MapChangeEvent event) { >+ Set changedKeys = event.diff.getChangedKeys(); >+ for (Iterator it = changedKeys.iterator(); it.hasNext();) >+ notifyIfChanged(it.next()); >+ } >+ >+ private void notifyIfChanged(Object masterElement) { >+ Object oldValue = cachedValues.get(new IdentityWrapper( >+ masterElement)); >+ Object newValue = masterElementValues.get(masterElement); >+ if (!Util.equals(oldValue, newValue)) { >+ cachedValues.put(new IdentityWrapper(masterElement), newValue); >+ handleValueChange(masterElement, oldValue, newValue); >+ } >+ } >+ >+ void handleValueChange(Object masterElement, Object oldValue, >+ Object newValue) { >+ DelegatingCache.this.handleValueChange(masterElement, oldValue, >+ newValue); >+ } >+ >+ void dispose() { >+ delegateCaches.remove(delegate); >+ masterElementValues.dispose(); >+ masterElements.dispose(); >+ cachedValues.clear(); >+ } >+ } >+ >+ DelegatingCache(Realm realm, DelegatingValueProperty detailProperty) { >+ this.realm = realm; >+ this.detailProperty = detailProperty; >+ >+ this.elements = new WritableSet(realm); >+ this.delegateCaches = new HashMap(); >+ >+ elements.addSetChangeListener(new ISetChangeListener() { >+ public void handleSetChange(SetChangeEvent event) { >+ for (Iterator it = event.diff.getRemovals().iterator(); it >+ .hasNext();) { >+ IdentityWrapper wrapper = (IdentityWrapper) it.next(); >+ Object element = wrapper.unwrap(); >+ getCache(element).remove(element); >+ >+ } >+ for (Iterator it = event.diff.getAdditions().iterator(); it >+ .hasNext();) { >+ IdentityWrapper wrapper = (IdentityWrapper) it.next(); >+ Object element = wrapper.unwrap(); >+ getCache(element).add(element); >+ } >+ } >+ }); >+ } >+ >+ private DelegateCache getCache(Object masterElement) { >+ IValueProperty delegate = detailProperty.getDelegate(masterElement); >+ if (delegateCaches.containsKey(delegate)) { >+ return (DelegateCache) delegateCaches.get(delegate); >+ } >+ return new DelegateCache(delegate); >+ } >+ >+ Object get(Object element) { >+ return getCache(element).get(element); >+ } >+ >+ Object put(Object element, Object value) { >+ return getCache(element).put(element, value); >+ } >+ >+ boolean contains(Object value) { >+ for (Iterator it = delegateCaches.values().iterator(); it.hasNext();) { >+ DelegateCache cache = (DelegateCache) it.next(); >+ if (cache.containsValue(value)) >+ return true; >+ } >+ return false; >+ } >+ >+ private Set identitySet(Collection elements) { >+ Set result = new HashSet(); >+ for (Iterator it = elements.iterator(); it.hasNext();) { >+ result.add(new IdentityWrapper(it.next())); >+ } >+ return result; >+ } >+ >+ void addAll(Collection elements) { >+ this.elements.addAll(identitySet(elements)); >+ } >+ >+ void retainAll(Collection elements) { >+ this.elements.retainAll(identitySet(elements)); >+ } >+ >+ abstract void handleValueChange(Object masterElement, Object oldValue, >+ Object newValue); >+ >+ void dispose() { >+ if (elements != null) { >+ elements.clear(); // clears caches >+ elements.dispose(); >+ elements = null; >+ } >+ >+ if (delegateCaches != null) { >+ for (Iterator it = delegateCaches.values().iterator(); it.hasNext();) { >+ DelegateCache cache = (DelegateCache) it.next(); >+ cache.dispose(); >+ } >+ delegateCaches.clear(); >+ delegateCaches = null; >+ } >+ } >+} >Index: src/org/eclipse/core/internal/databinding/property/value/SimpleValuePropertyObservableValue.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/value/SimpleValuePropertyObservableValue.java >diff -N src/org/eclipse/core/internal/databinding/property/value/SimpleValuePropertyObservableValue.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/value/SimpleValuePropertyObservableValue.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,131 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.value; >+ >+import org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.Realm; >+import org.eclipse.core.databinding.observable.value.AbstractObservableValue; >+import org.eclipse.core.databinding.observable.value.ValueDiff; >+import org.eclipse.core.databinding.property.INativePropertyListener; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; >+import org.eclipse.core.databinding.property.value.ISimpleValueProperty; >+import org.eclipse.core.internal.databinding.Util; >+ >+/** >+ * @since 1.2 >+ * >+ */ >+public class SimpleValuePropertyObservableValue extends AbstractObservableValue >+ implements IPropertyObservable { >+ private Object source; >+ private ISimpleValueProperty property; >+ >+ private boolean updating = false; >+ private Object cachedValue; >+ >+ private INativePropertyListener listener; >+ >+ /** >+ * @param realm >+ * @param source >+ * @param property >+ */ >+ public SimpleValuePropertyObservableValue(Realm realm, Object source, >+ ISimpleValueProperty property) { >+ super(realm); >+ this.source = source; >+ this.property = property; >+ } >+ >+ protected void firstListenerAdded() { >+ if (!isDisposed()) { >+ cachedValue = property.getValue(source); >+ if (listener == null) { >+ listener = property >+ .adaptListener(new ISimplePropertyListener() { >+ public void handlePropertyChange( >+ final SimplePropertyEvent event) { >+ if (!isDisposed() && !updating) { >+ getRealm().exec(new Runnable() { >+ public void run() { >+ notifyIfChanged((ValueDiff) event.diff); >+ } >+ }); >+ } >+ } >+ }); >+ } >+ property.addListener(source, listener); >+ } >+ } >+ >+ protected void lastListenerRemoved() { >+ if (listener != null) { >+ property.removeListener(source, listener); >+ } >+ cachedValue = null; >+ } >+ >+ protected Object doGetValue() { >+ notifyIfChanged(null); >+ return property.getValue(source); >+ } >+ >+ protected void doSetValue(Object value) { >+ updating = true; >+ try { >+ property.setValue(source, value); >+ } finally { >+ updating = false; >+ } >+ >+ notifyIfChanged(null); >+ } >+ >+ private void notifyIfChanged(ValueDiff diff) { >+ if (hasListeners()) { >+ Object oldValue = cachedValue; >+ Object newValue = cachedValue = property.getValue(source); >+ if (diff == null) >+ diff = Diffs.createValueDiff(oldValue, newValue); >+ if (hasListeners() && !Util.equals(oldValue, newValue)) { >+ fireValueChange(diff); >+ } >+ } >+ } >+ >+ public Object getValueType() { >+ return property.getValueType(); >+ } >+ >+ public Object getObserved() { >+ return source; >+ } >+ >+ public IProperty getProperty() { >+ return property; >+ } >+ >+ public synchronized void dispose() { >+ if (!isDisposed()) { >+ if (listener != null) >+ property.removeListener(source, listener); >+ source = null; >+ property = null; >+ listener = null; >+ } >+ super.dispose(); >+ } >+} >Index: src/org/eclipse/core/databinding/property/set/ISimpleSetProperty.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/set/ISimpleSetProperty.java >diff -N src/org/eclipse/core/databinding/property/set/ISimpleSetProperty.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/property/set/ISimpleSetProperty.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,46 @@ >+/******************************************************************************* >+ * Copyright (c) 2009 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.databinding.property.set; >+ >+import java.util.Set; >+ >+import org.eclipse.core.databinding.observable.set.SetDiff; >+import org.eclipse.core.databinding.property.ISimpleProperty; >+ >+/** >+ * @since 1.2 >+ * >+ */ >+public interface ISimpleSetProperty extends ISimpleProperty, ISetProperty { >+ /** >+ * Returns a Set with the current contents of the source's set property >+ * >+ * @param source >+ * the property source >+ * @return a Set with the current contents of the source's set property >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public Set getSet(Object source); >+ >+ /** >+ * Updates the property on the source with the specified change. >+ * >+ * @param source >+ * the property source >+ * @param set >+ * the new set >+ * @param diff >+ * a diff describing the change >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public void setSet(Object source, Set set, SetDiff diff); >+} >Index: src/org/eclipse/core/internal/databinding/property/list/SimpleListPropertyObservableList.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/list/SimpleListPropertyObservableList.java >diff -N src/org/eclipse/core/internal/databinding/property/list/SimpleListPropertyObservableList.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/list/SimpleListPropertyObservableList.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,667 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.list; >+ >+import java.util.ArrayList; >+import java.util.Collection; >+import java.util.Collections; >+import java.util.ConcurrentModificationException; >+import java.util.Iterator; >+import java.util.List; >+import java.util.ListIterator; >+ >+import org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.ObservableTracker; >+import org.eclipse.core.databinding.observable.Realm; >+import org.eclipse.core.databinding.observable.list.AbstractObservableList; >+import org.eclipse.core.databinding.observable.list.ListDiff; >+import org.eclipse.core.databinding.observable.list.ListDiffEntry; >+import org.eclipse.core.databinding.property.INativePropertyListener; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; >+import org.eclipse.core.databinding.property.list.ISimpleListProperty; >+ >+/** >+ * @since 1.2 >+ * >+ */ >+public class SimpleListPropertyObservableList extends AbstractObservableList >+ implements IPropertyObservable { >+ private Object source; >+ private ISimpleListProperty property; >+ >+ private volatile boolean updating = false; >+ >+ private volatile int modCount = 0; >+ >+ private INativePropertyListener listener; >+ >+ private List cachedList; >+ >+ /** >+ * @param realm >+ * @param source >+ * @param property >+ */ >+ public SimpleListPropertyObservableList(Realm realm, Object source, >+ ISimpleListProperty property) { >+ super(realm); >+ this.source = source; >+ this.property = property; >+ } >+ >+ protected void firstListenerAdded() { >+ if (!isDisposed()) { >+ cachedList = getList(); >+ >+ if (listener == null) { >+ listener = property >+ .adaptListener(new ISimplePropertyListener() { >+ public void handlePropertyChange( >+ final SimplePropertyEvent event) { >+ modCount++; >+ if (!isDisposed() && !updating) { >+ getRealm().exec(new Runnable() { >+ public void run() { >+ notifyIfChanged((ListDiff) event.diff); >+ } >+ }); >+ } >+ } >+ }); >+ } >+ property.addListener(source, listener); >+ } >+ } >+ >+ protected void lastListenerRemoved() { >+ if (listener != null) { >+ property.removeListener(source, listener); >+ } >+ >+ cachedList = null; >+ } >+ >+ private void getterCalled() { >+ ObservableTracker.getterCalled(this); >+ } >+ >+ public Object getElementType() { >+ return property.getElementType(); >+ } >+ >+ // Queries >+ >+ private List getList() { >+ return property.getList(source); >+ } >+ >+ protected int doGetSize() { >+ return getList().size(); >+ } >+ >+ public boolean contains(Object o) { >+ getterCalled(); >+ return getList().contains(o); >+ } >+ >+ public boolean containsAll(Collection c) { >+ getterCalled(); >+ return getList().containsAll(c); >+ } >+ >+ public Object get(int index) { >+ getterCalled(); >+ return getList().get(index); >+ } >+ >+ public int indexOf(Object o) { >+ getterCalled(); >+ return getList().indexOf(o); >+ } >+ >+ public boolean isEmpty() { >+ getterCalled(); >+ return getList().isEmpty(); >+ } >+ >+ public int lastIndexOf(Object o) { >+ getterCalled(); >+ return getList().lastIndexOf(o); >+ } >+ >+ public Object[] toArray() { >+ getterCalled(); >+ return getList().toArray(); >+ } >+ >+ public Object[] toArray(Object[] a) { >+ getterCalled(); >+ return getList().toArray(a); >+ } >+ >+ // Single change operations >+ >+ public boolean add(Object o) { >+ checkRealm(); >+ add(getList().size(), o); >+ return true; >+ } >+ >+ public void add(int index, Object o) { >+ checkRealm(); >+ boolean wasUpdating = updating; >+ updating = true; >+ List list = new ArrayList(getList()); >+ list.add(index, o); >+ ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, >+ true, o)); >+ try { >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ } >+ >+ public Iterator iterator() { >+ getterCalled(); >+ return new Iterator() { >+ int expectedModCount = modCount; >+ List list = new ArrayList(getList()); >+ ListIterator iterator = list.listIterator(); >+ >+ Object lastElement = null; >+ int lastIndex = -1; >+ >+ public boolean hasNext() { >+ getterCalled(); >+ checkForComodification(); >+ return iterator.hasNext(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ checkForComodification(); >+ Object next = lastElement = iterator.next(); >+ lastIndex = iterator.previousIndex(); >+ return next; >+ } >+ >+ public void remove() { >+ checkRealm(); >+ checkForComodification(); >+ if (lastIndex == -1) >+ throw new IllegalStateException(); >+ >+ iterator.remove(); // stay in sync >+ ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >+ lastIndex, false, lastElement)); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ lastElement = null; >+ lastIndex = -1; >+ >+ expectedModCount = modCount; >+ } >+ >+ private void checkForComodification() { >+ if (expectedModCount != modCount) >+ throw new ConcurrentModificationException(); >+ } >+ }; >+ } >+ >+ public Object move(int oldIndex, int newIndex) { >+ checkRealm(); >+ >+ List list = getList(); >+ int size = list.size(); >+ if (oldIndex < 0 || oldIndex >= size || newIndex < 0 >+ || newIndex >= size) >+ throw new IndexOutOfBoundsException(); >+ >+ if (oldIndex == newIndex) >+ return list.get(oldIndex); >+ >+ list = new ArrayList(list); >+ Object element = list.remove(oldIndex); >+ list.add(newIndex, element); >+ >+ ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >+ oldIndex, false, element), Diffs.createListDiffEntry(newIndex, >+ true, element)); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return element; >+ } >+ >+ public boolean remove(Object o) { >+ checkRealm(); >+ >+ int index = getList().indexOf(o); >+ if (index == -1) >+ return false; >+ >+ remove(index); >+ >+ return true; >+ } >+ >+ public ListIterator listIterator() { >+ return listIterator(0); >+ } >+ >+ public ListIterator listIterator(final int index) { >+ getterCalled(); >+ return new ListIterator() { >+ int expectedModCount = modCount; >+ List list = new ArrayList(getList()); >+ ListIterator iterator = list.listIterator(index); >+ >+ Object lastElement = null; >+ int lastIndex = -1; >+ >+ public boolean hasNext() { >+ getterCalled(); >+ checkForComodification(); >+ return iterator.hasNext(); >+ } >+ >+ public int nextIndex() { >+ getterCalled(); >+ checkForComodification(); >+ return iterator.nextIndex(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ checkForComodification(); >+ lastElement = iterator.next(); >+ lastIndex = iterator.previousIndex(); >+ return lastElement; >+ } >+ >+ public boolean hasPrevious() { >+ getterCalled(); >+ checkForComodification(); >+ return iterator.hasPrevious(); >+ } >+ >+ public int previousIndex() { >+ getterCalled(); >+ checkForComodification(); >+ return iterator.previousIndex(); >+ } >+ >+ public Object previous() { >+ getterCalled(); >+ checkForComodification(); >+ lastElement = iterator.previous(); >+ lastIndex = iterator.nextIndex(); >+ return lastElement; >+ } >+ >+ public void add(Object o) { >+ checkRealm(); >+ checkForComodification(); >+ int index = iterator.nextIndex(); >+ >+ iterator.add(o); // keep in sync >+ >+ List list = getList(); >+ list.add(index, o); >+ ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >+ index, true, o)); >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ lastElement = null; >+ lastIndex = -1; >+ expectedModCount = modCount; >+ } >+ >+ public void set(Object o) { >+ checkRealm(); >+ checkForComodification(); >+ >+ iterator.set(o); >+ ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >+ lastIndex, false, lastElement), Diffs >+ .createListDiffEntry(lastIndex, true, o)); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ lastElement = o; >+ expectedModCount = modCount; >+ } >+ >+ public void remove() { >+ checkRealm(); >+ checkForComodification(); >+ if (lastIndex == -1) >+ throw new IllegalStateException(); >+ >+ iterator.remove(); // keep in sync >+ ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( >+ lastIndex, false, lastElement)); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ lastElement = null; >+ lastIndex = -1; >+ expectedModCount = modCount; >+ } >+ >+ private void checkForComodification() { >+ if (expectedModCount != modCount) >+ throw new ConcurrentModificationException(); >+ } >+ }; >+ } >+ >+ public Object remove(int index) { >+ checkRealm(); >+ >+ List list = new ArrayList(getList()); >+ Object element = list.remove(index); >+ ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, >+ false, element)); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return element; >+ } >+ >+ public Object set(int index, Object o) { >+ checkRealm(); >+ >+ List list = new ArrayList(getList()); >+ Object oldElement = list.set(index, o); >+ >+ ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, >+ false, oldElement), Diffs.createListDiffEntry(index, true, o)); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return oldElement; >+ } >+ >+ public List subList(int fromIndex, int toIndex) { >+ getterCalled(); >+ return Collections.unmodifiableList(getList().subList(fromIndex, >+ toIndex)); >+ } >+ >+ // Bulk change operations >+ >+ public boolean addAll(Collection c) { >+ checkRealm(); >+ >+ return addAll(getList().size(), c); >+ } >+ >+ public boolean addAll(int index, Collection c) { >+ checkRealm(); >+ >+ if (c.isEmpty()) >+ return false; >+ >+ List list = new ArrayList(getList()); >+ list.addAll(index, c); >+ >+ ListDiffEntry[] entries = new ListDiffEntry[c.size()]; >+ int offsetIndex = 0; >+ for (Iterator it = c.iterator(); it.hasNext();) { >+ Object element = it.next(); >+ entries[offsetIndex] = Diffs.createListDiffEntry(index >+ + offsetIndex, true, element); >+ offsetIndex++; >+ } >+ ListDiff diff = Diffs.createListDiff(entries); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return true; >+ } >+ >+ public boolean removeAll(Collection c) { >+ checkRealm(); >+ >+ if (c.isEmpty()) >+ return false; >+ >+ List list = getList(); >+ if (list.isEmpty()) >+ return false; >+ >+ list = new ArrayList(list); >+ List entries = new ArrayList(); >+ ListDiff diff; >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ for (ListIterator it = list.listIterator(); it.hasNext();) { >+ Object element = it.next(); >+ int index = it.previousIndex(); >+ if (c.contains(element)) { >+ it.remove(); >+ entries.add(Diffs >+ .createListDiffEntry(index, false, element)); >+ } >+ } >+ if (entries.isEmpty()) >+ return false; >+ >+ diff = Diffs.createListDiff((ListDiffEntry[]) entries >+ .toArray(new ListDiffEntry[entries.size()])); >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return !diff.isEmpty(); >+ } >+ >+ public boolean retainAll(Collection c) { >+ checkRealm(); >+ >+ List list = getList(); >+ if (list.isEmpty()) >+ return false; >+ >+ if (c.isEmpty()) { >+ clear(); >+ return true; >+ } >+ >+ list = new ArrayList(list); >+ List entries = new ArrayList(); >+ ListDiff diff; >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ for (ListIterator it = list.listIterator(); it.hasNext();) { >+ Object element = it.next(); >+ int index = it.previousIndex(); >+ if (!c.contains(element)) { >+ it.remove(); >+ entries.add(Diffs >+ .createListDiffEntry(index, false, element)); >+ } >+ } >+ if (entries.isEmpty()) >+ return false; >+ >+ diff = Diffs.createListDiff((ListDiffEntry[]) entries >+ .toArray(new ListDiffEntry[entries.size()])); >+ property.setList(source, list, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ >+ return !diff.isEmpty(); >+ } >+ >+ public void clear() { >+ checkRealm(); >+ >+ List list = getList(); >+ if (list.isEmpty()) >+ return; >+ >+ List entries = new ArrayList(); >+ for (Iterator it = list.iterator(); it.hasNext();) { >+ // always report 0 as the remove index >+ entries.add(Diffs.createListDiffEntry(0, false, it.next())); >+ } >+ >+ ListDiff diff = Diffs.createListDiff((ListDiffEntry[]) entries >+ .toArray(new ListDiffEntry[entries.size()])); >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ property.setList(source, Collections.EMPTY_LIST, diff); >+ modCount++; >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(null); >+ } >+ >+ private void notifyIfChanged(ListDiff diff) { >+ if (hasListeners()) { >+ List oldList = cachedList; >+ List newList = cachedList = property.getList(source); >+ if (diff == null) >+ diff = Diffs.computeListDiff(oldList, newList); >+ if (!diff.isEmpty()) { >+ fireListChange(diff); >+ } >+ } >+ } >+ >+ public boolean equals(Object o) { >+ getterCalled(); >+ return getList().equals(o); >+ } >+ >+ public int hashCode() { >+ getterCalled(); >+ return getList().hashCode(); >+ } >+ >+ public Object getObserved() { >+ return source; >+ } >+ >+ public IProperty getProperty() { >+ return property; >+ } >+ >+ public synchronized void dispose() { >+ if (!isDisposed()) { >+ if (listener != null) >+ property.removeListener(source, listener); >+ property = null; >+ source = null; >+ listener = null; >+ } >+ super.dispose(); >+ } >+} >Index: src/org/eclipse/core/internal/databinding/property/value/ObservableListDelegatingValuePropertyObservableList.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/value/ObservableListDelegatingValuePropertyObservableList.java >diff -N src/org/eclipse/core/internal/databinding/property/value/ObservableListDelegatingValuePropertyObservableList.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/value/ObservableListDelegatingValuePropertyObservableList.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,348 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.value; >+ >+import java.lang.reflect.Array; >+import java.util.ArrayList; >+import java.util.Collection; >+import java.util.Iterator; >+import java.util.List; >+import java.util.ListIterator; >+ >+import org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.IStaleListener; >+import org.eclipse.core.databinding.observable.ObservableTracker; >+import org.eclipse.core.databinding.observable.StaleEvent; >+import org.eclipse.core.databinding.observable.list.AbstractObservableList; >+import org.eclipse.core.databinding.observable.list.IListChangeListener; >+import org.eclipse.core.databinding.observable.list.IObservableList; >+import org.eclipse.core.databinding.observable.list.ListChangeEvent; >+import org.eclipse.core.databinding.observable.list.ListDiff; >+import org.eclipse.core.databinding.observable.list.ListDiffEntry; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.value.DelegatingValueProperty; >+ >+/** >+ * @since 1.2 >+ */ >+public class ObservableListDelegatingValuePropertyObservableList extends >+ AbstractObservableList implements IPropertyObservable { >+ private IObservableList masterList; >+ private DelegatingValueProperty detailProperty; >+ private DelegatingCache cache; >+ >+ private IListChangeListener masterListener = new IListChangeListener() { >+ public void handleListChange(ListChangeEvent event) { >+ if (isDisposed()) >+ return; >+ >+ cache.addAll(masterList); >+ >+ // Need both obsolete and new elements to convert diff >+ ListDiff diff = convertDiff(event.diff); >+ >+ cache.retainAll(masterList); >+ >+ fireListChange(diff); >+ } >+ >+ private ListDiff convertDiff(ListDiff diff) { >+ // Convert diff to detail value >+ ListDiffEntry[] masterEntries = diff.getDifferences(); >+ ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length]; >+ for (int i = 0; i < masterEntries.length; i++) { >+ ListDiffEntry masterDifference = masterEntries[i]; >+ int index = masterDifference.getPosition(); >+ boolean addition = masterDifference.isAddition(); >+ Object masterElement = masterDifference.getElement(); >+ Object detailValue = cache.get(masterElement); >+ >+ detailEntries[i] = Diffs.createListDiffEntry(index, addition, >+ detailValue); >+ } >+ return Diffs.createListDiff(detailEntries); >+ } >+ }; >+ >+ private IStaleListener staleListener = new IStaleListener() { >+ public void handleStale(StaleEvent staleEvent) { >+ fireStale(); >+ } >+ }; >+ >+ /** >+ * @param masterList >+ * @param valueProperty >+ */ >+ public ObservableListDelegatingValuePropertyObservableList( >+ IObservableList masterList, DelegatingValueProperty valueProperty) { >+ super(masterList.getRealm()); >+ this.masterList = masterList; >+ this.detailProperty = valueProperty; >+ this.cache = new DelegatingCache(getRealm(), valueProperty) { >+ void handleValueChange(Object masterElement, Object oldValue, >+ Object newValue) { >+ fireListChange(indicesOf(masterElement), oldValue, newValue); >+ } >+ }; >+ cache.addAll(masterList); >+ >+ masterList.addListChangeListener(masterListener); >+ masterList.addStaleListener(staleListener); >+ } >+ >+ protected int doGetSize() { >+ getterCalled(); >+ return masterList.size(); >+ } >+ >+ private void getterCalled() { >+ ObservableTracker.getterCalled(this); >+ } >+ >+ public Object get(int index) { >+ getterCalled(); >+ Object masterElement = masterList.get(index); >+ return cache.get(masterElement); >+ } >+ >+ public boolean add(Object o) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean addAll(Collection c) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean addAll(int index, Collection c) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean contains(Object o) { >+ getterCalled(); >+ return cache.contains(o); >+ } >+ >+ public boolean isEmpty() { >+ getterCalled(); >+ return masterList.isEmpty(); >+ } >+ >+ public boolean isStale() { >+ getterCalled(); >+ return masterList.isStale(); >+ } >+ >+ public Iterator iterator() { >+ getterCalled(); >+ return new Iterator() { >+ Iterator it = masterList.iterator(); >+ >+ public boolean hasNext() { >+ getterCalled(); >+ return it.hasNext(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ Object masterElement = it.next(); >+ return cache.get(masterElement); >+ } >+ >+ public void remove() { >+ throw new UnsupportedOperationException(); >+ } >+ }; >+ } >+ >+ public Object move(int oldIndex, int newIndex) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean remove(Object o) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean removeAll(Collection c) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean retainAll(Collection c) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public Object[] toArray() { >+ getterCalled(); >+ Object[] masterElements = masterList.toArray(); >+ Object[] result = new Object[masterElements.length]; >+ for (int i = 0; i < result.length; i++) { >+ result[i] = cache.get(masterElements[i]); >+ } >+ return result; >+ } >+ >+ public Object[] toArray(Object[] a) { >+ getterCalled(); >+ Object[] masterElements = masterList.toArray(); >+ if (a.length < masterElements.length) >+ a = (Object[]) Array.newInstance(a.getClass().getComponentType(), >+ masterElements.length); >+ for (int i = 0; i < masterElements.length; i++) { >+ a[i] = cache.get(masterElements[i]); >+ } >+ return a; >+ } >+ >+ public void add(int index, Object o) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public void clear() { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public ListIterator listIterator() { >+ return listIterator(0); >+ } >+ >+ public ListIterator listIterator(final int index) { >+ getterCalled(); >+ return new ListIterator() { >+ ListIterator it = masterList.listIterator(index); >+ Object lastMasterElement; >+ Object lastElement; >+ boolean haveIterated = false; >+ >+ public void add(Object arg0) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean hasNext() { >+ getterCalled(); >+ return it.hasNext(); >+ } >+ >+ public boolean hasPrevious() { >+ getterCalled(); >+ return it.hasPrevious(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ lastMasterElement = it.next(); >+ lastElement = cache.get(lastMasterElement); >+ haveIterated = true; >+ return lastElement; >+ } >+ >+ public int nextIndex() { >+ getterCalled(); >+ return it.nextIndex(); >+ } >+ >+ public Object previous() { >+ getterCalled(); >+ lastMasterElement = it.previous(); >+ lastElement = cache.get(lastMasterElement); >+ haveIterated = true; >+ return lastElement; >+ } >+ >+ public int previousIndex() { >+ getterCalled(); >+ return it.previousIndex(); >+ } >+ >+ public void remove() { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public void set(Object o) { >+ checkRealm(); >+ if (!haveIterated) >+ throw new IllegalStateException(); >+ >+ cache.put(lastMasterElement, o); >+ >+ lastElement = o; >+ } >+ }; >+ } >+ >+ private int[] indicesOf(Object masterElement) { >+ List indices = new ArrayList(); >+ >+ for (ListIterator it = masterList.listIterator(); it.hasNext();) { >+ if (masterElement == it.next()) >+ indices.add(new Integer(it.previousIndex())); >+ } >+ >+ int[] result = new int[indices.size()]; >+ for (int i = 0; i < result.length; i++) { >+ result[i] = ((Integer) indices.get(i)).intValue(); >+ } >+ return result; >+ } >+ >+ private void fireListChange(int[] indices, Object oldValue, Object newValue) { >+ ListDiffEntry[] differences = new ListDiffEntry[indices.length * 2]; >+ for (int i = 0; i < indices.length; i++) { >+ int index = indices[i]; >+ differences[i * 2] = Diffs.createListDiffEntry(index, false, >+ oldValue); >+ differences[i * 2 + 1] = Diffs.createListDiffEntry(index, true, >+ newValue); >+ } >+ fireListChange(Diffs.createListDiff(differences)); >+ } >+ >+ public Object remove(int index) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public Object set(int index, Object o) { >+ checkRealm(); >+ Object masterElement = masterList.get(index); >+ return cache.put(masterElement, o); >+ } >+ >+ public Object getObserved() { >+ return masterList; >+ } >+ >+ public IProperty getProperty() { >+ return detailProperty; >+ } >+ >+ public Object getElementType() { >+ return detailProperty.getValueType(); >+ } >+ >+ public synchronized void dispose() { >+ if (masterList != null) { >+ masterList.removeListChangeListener(masterListener); >+ masterList.removeStaleListener(staleListener); >+ masterList = null; >+ } >+ >+ if (cache != null) { >+ cache.dispose(); >+ cache = null; >+ } >+ >+ masterListener = null; >+ detailProperty = null; >+ >+ super.dispose(); >+ } >+} >Index: src/org/eclipse/core/databinding/property/ISimpleProperty.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/ISimpleProperty.java >diff -N src/org/eclipse/core/databinding/property/ISimpleProperty.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/property/ISimpleProperty.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,79 @@ >+/******************************************************************************* >+ * Copyright (c) 2009 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ ******************************************************************************/ >+ >+package org.eclipse.core.databinding.property; >+ >+import org.eclipse.core.databinding.property.list.SimpleListProperty; >+import org.eclipse.core.databinding.property.map.SimpleMapProperty; >+import org.eclipse.core.databinding.property.set.SimpleSetProperty; >+import org.eclipse.core.databinding.property.value.SimpleValueProperty; >+ >+/** >+ * Interface for immediate (as opposed to nested) properties of a particular >+ * source object. >+ * >+ * @since 1.2 >+ * @noimplement This interface is not intended to be implemented by clients. >+ * Clients should instead subclass one of the classes that >+ * implement this interface. Note that direct implementers of this >+ * interface outside of the framework will be broken in future >+ * releases when methods are added to this interface. >+ * @see SimpleValueProperty >+ * @see SimpleListProperty >+ * @see SimpleSetProperty >+ * @see SimpleMapProperty >+ */ >+public interface ISimpleProperty extends IProperty { >+ /** >+ * Returns a listener which implements the correct listener interface for >+ * the expected source object, and which parlays property change events from >+ * the source object to the given listener. If there is no listener API for >+ * this property, this method returns null. >+ * >+ * @param listener >+ * the property listener to receive events >+ * @return a native listener which parlays property change events to the >+ * specified listener. >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public INativePropertyListener adaptListener( >+ ISimplePropertyListener listener); >+ >+ /** >+ * Adds the specified listener as a listener for this property on the >+ * specified property source. If the source object has no listener API for >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} >+ * returns null), this method does nothing. >+ * >+ * @param source >+ * the property source >+ * @param listener >+ * a listener obtained from calling >+ * {@link #adaptListener(ISimplePropertyListener)}. >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public void addListener(Object source, INativePropertyListener listener); >+ >+ /** >+ * Removes the specified listener as a listener for this property on the >+ * specified property source. If the source object has no listener API for >+ * this property (i.e. {@link #adaptListener(ISimplePropertyListener)} >+ * returns null), this method does nothing. >+ * >+ * @param source >+ * the property source >+ * @param listener >+ * a listener obtained from calling >+ * {@link #adaptListener(ISimplePropertyListener)}. >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public void removeListener(Object source, INativePropertyListener listener); >+} >Index: src/org/eclipse/core/databinding/property/map/ISimpleMapProperty.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/map/ISimpleMapProperty.java >diff -N src/org/eclipse/core/databinding/property/map/ISimpleMapProperty.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/property/map/ISimpleMapProperty.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,46 @@ >+/******************************************************************************* >+ * Copyright (c) 2009 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.databinding.property.map; >+ >+import java.util.Map; >+ >+import org.eclipse.core.databinding.observable.map.MapDiff; >+import org.eclipse.core.databinding.property.ISimpleProperty; >+ >+/** >+ * @since 1.2 >+ */ >+public interface ISimpleMapProperty extends ISimpleProperty, IMapProperty { >+ /** >+ * Returns an unmodifiable Map with the current contents of the source's map >+ * property. >+ * >+ * @param source >+ * the property source >+ * @return a Map with the current contents of the source's map property >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public Map getMap(Object source); >+ >+ /** >+ * Updates the property on the source with the specified change. >+ * >+ * @param source >+ * the property source >+ * @param map >+ * the new map >+ * @param diff >+ * a diff describing the change >+ * @noreference This method is not intended to be referenced by clients. >+ */ >+ public void setMap(Object source, Map map, MapDiff diff); >+} >Index: src/org/eclipse/core/internal/databinding/property/value/ObservableMapDelegatingValuePropertyObservableMap.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/value/ObservableMapDelegatingValuePropertyObservableMap.java >diff -N src/org/eclipse/core/internal/databinding/property/value/ObservableMapDelegatingValuePropertyObservableMap.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/value/ObservableMapDelegatingValuePropertyObservableMap.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,316 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.value; >+ >+import java.util.AbstractSet; >+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 org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.IStaleListener; >+import org.eclipse.core.databinding.observable.ObservableTracker; >+import org.eclipse.core.databinding.observable.StaleEvent; >+import org.eclipse.core.databinding.observable.map.AbstractObservableMap; >+import org.eclipse.core.databinding.observable.map.IMapChangeListener; >+import org.eclipse.core.databinding.observable.map.IObservableMap; >+import org.eclipse.core.databinding.observable.map.MapChangeEvent; >+import org.eclipse.core.databinding.observable.map.MapDiff; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.value.DelegatingValueProperty; >+import org.eclipse.core.internal.databinding.Util; >+ >+/** >+ * @since 1.2 >+ */ >+public class ObservableMapDelegatingValuePropertyObservableMap extends >+ AbstractObservableMap implements IPropertyObservable { >+ private IObservableMap masterMap; >+ private DelegatingValueProperty detailProperty; >+ private DelegatingCache cache; >+ >+ private Set entrySet; >+ >+ class EntrySet extends AbstractSet { >+ public Iterator iterator() { >+ return new Iterator() { >+ Iterator it = masterMap.entrySet().iterator(); >+ >+ public boolean hasNext() { >+ getterCalled(); >+ return it.hasNext(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ Map.Entry next = (Map.Entry) it.next(); >+ return new MapEntry(next.getKey()); >+ } >+ >+ public void remove() { >+ it.remove(); >+ } >+ }; >+ } >+ >+ public int size() { >+ return masterMap.size(); >+ } >+ } >+ >+ class MapEntry implements Map.Entry { >+ private Object key; >+ >+ MapEntry(Object key) { >+ this.key = key; >+ } >+ >+ public Object getKey() { >+ getterCalled(); >+ return key; >+ } >+ >+ public Object getValue() { >+ getterCalled(); >+ >+ if (!masterMap.containsKey(key)) >+ return null; >+ >+ Object masterValue = masterMap.get(key); >+ return cache.get(masterValue); >+ } >+ >+ public Object setValue(Object value) { >+ checkRealm(); >+ >+ if (!masterMap.containsKey(key)) >+ return null; >+ >+ Object masterValue = masterMap.get(key); >+ return cache.put(masterValue, value); >+ } >+ >+ public boolean equals(Object o) { >+ getterCalled(); >+ if (o == this) >+ return true; >+ if (o == null) >+ return false; >+ if (!(o instanceof Map.Entry)) >+ return false; >+ Map.Entry that = (Map.Entry) o; >+ return Util.equals(this.getKey(), that.getKey()) >+ && Util.equals(this.getValue(), that.getValue()); >+ } >+ >+ public int hashCode() { >+ getterCalled(); >+ Object value = getValue(); >+ return (key == null ? 0 : key.hashCode()) >+ ^ (value == null ? 0 : value.hashCode()); >+ } >+ } >+ >+ private IMapChangeListener masterListener = new IMapChangeListener() { >+ public void handleMapChange(final MapChangeEvent event) { >+ if (isDisposed()) >+ return; >+ >+ cache.addAll(masterMap.values()); >+ >+ // Need both obsolete and new master values to convert diff >+ MapDiff diff = convertDiff(event.diff); >+ >+ cache.retainAll(masterMap.values()); >+ >+ fireMapChange(diff); >+ } >+ >+ private MapDiff convertDiff(MapDiff diff) { >+ Map oldValues = new HashMap(); >+ Map newValues = new HashMap(); >+ >+ Set addedKeys = diff.getAddedKeys(); >+ for (Iterator it = addedKeys.iterator(); it.hasNext();) { >+ Object key = it.next(); >+ Object masterValue = diff.getNewValue(key); >+ Object newValue = cache.get(masterValue); >+ newValues.put(key, newValue); >+ } >+ >+ Set removedKeys = diff.getRemovedKeys(); >+ for (Iterator it = removedKeys.iterator(); it.hasNext();) { >+ Object key = it.next(); >+ Object masterValue = diff.getOldValue(key); >+ Object oldValue = cache.get(masterValue); >+ oldValues.put(key, oldValue); >+ } >+ >+ Set changedKeys = new HashSet(diff.getChangedKeys()); >+ for (Iterator it = changedKeys.iterator(); it.hasNext();) { >+ Object key = it.next(); >+ >+ Object oldMasterValue = diff.getOldValue(key); >+ Object newMasterValue = diff.getNewValue(key); >+ >+ Object oldValue = cache.get(oldMasterValue); >+ Object newValue = cache.get(newMasterValue); >+ >+ if (Util.equals(oldValue, newValue)) { >+ it.remove(); >+ } else { >+ oldValues.put(key, oldValue); >+ newValues.put(key, newValue); >+ } >+ } >+ >+ return Diffs.createMapDiff(addedKeys, removedKeys, changedKeys, >+ oldValues, newValues); >+ } >+ }; >+ >+ private IStaleListener staleListener = new IStaleListener() { >+ public void handleStale(StaleEvent staleEvent) { >+ fireStale(); >+ } >+ }; >+ >+ /** >+ * @param map >+ * @param valueProperty >+ */ >+ public ObservableMapDelegatingValuePropertyObservableMap( >+ IObservableMap map, DelegatingValueProperty valueProperty) { >+ super(map.getRealm()); >+ this.masterMap = map; >+ this.detailProperty = valueProperty; >+ this.cache = new DelegatingCache(getRealm(), valueProperty) { >+ void handleValueChange(Object masterElement, Object oldValue, >+ Object newValue) { >+ fireMapChange(keysFor(masterElement), oldValue, newValue); >+ } >+ }; >+ cache.addAll(masterMap.values()); >+ >+ masterMap.addMapChangeListener(masterListener); >+ masterMap.addStaleListener(staleListener); >+ } >+ >+ public Set entrySet() { >+ getterCalled(); >+ if (entrySet == null) >+ entrySet = new EntrySet(); >+ return entrySet; >+ } >+ >+ private void getterCalled() { >+ ObservableTracker.getterCalled(this); >+ } >+ >+ public Object get(Object key) { >+ getterCalled(); >+ Object masterValue = masterMap.get(key); >+ return cache.get(masterValue); >+ } >+ >+ public Object put(Object key, Object value) { >+ if (!masterMap.containsKey(key)) >+ return null; >+ Object masterValue = masterMap.get(key); >+ return cache.put(masterValue, value); >+ } >+ >+ public boolean isStale() { >+ getterCalled(); >+ return masterMap.isStale(); >+ } >+ >+ public Object getObserved() { >+ return masterMap; >+ } >+ >+ public IProperty getProperty() { >+ return detailProperty; >+ } >+ >+ public Object getKeyType() { >+ return masterMap.getKeyType(); >+ } >+ >+ public Object getValueType() { >+ return detailProperty.getValueType(); >+ } >+ >+ private Set keysFor(Object masterValue) { >+ Set keys = new HashSet(); >+ >+ for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) { >+ Map.Entry entry = (Entry) it.next(); >+ if (entry.getValue() == masterValue) { >+ keys.add(entry.getKey()); >+ } >+ } >+ >+ return keys; >+ } >+ >+ private void fireMapChange(final Set changedKeys, final Object oldValue, >+ final Object newValue) { >+ fireMapChange(new MapDiff() { >+ public Set getAddedKeys() { >+ return Collections.EMPTY_SET; >+ } >+ >+ public Set getRemovedKeys() { >+ return Collections.EMPTY_SET; >+ } >+ >+ public Set getChangedKeys() { >+ return Collections.unmodifiableSet(changedKeys); >+ } >+ >+ public Object getOldValue(Object key) { >+ if (changedKeys.contains(key)) >+ return oldValue; >+ return null; >+ } >+ >+ public Object getNewValue(Object key) { >+ if (changedKeys.contains(key)) >+ return newValue; >+ return null; >+ } >+ }); >+ } >+ >+ public synchronized void dispose() { >+ if (masterMap != null) { >+ masterMap.removeMapChangeListener(masterListener); >+ masterMap.removeStaleListener(staleListener); >+ masterMap = null; >+ } >+ >+ if (cache != null) { >+ cache.dispose(); >+ cache = null; >+ } >+ >+ masterListener = null; >+ detailProperty = null; >+ >+ super.dispose(); >+ } >+} >Index: src/org/eclipse/core/internal/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java >=================================================================== >RCS file: src/org/eclipse/core/internal/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java >diff -N src/org/eclipse/core/internal/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/internal/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,449 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.internal.databinding.property.value; >+ >+import java.lang.reflect.Array; >+import java.util.ArrayList; >+import java.util.Collection; >+import java.util.HashMap; >+import java.util.HashSet; >+import java.util.Iterator; >+import java.util.List; >+import java.util.ListIterator; >+import java.util.Map; >+import java.util.Set; >+ >+import org.eclipse.core.databinding.observable.Diffs; >+import org.eclipse.core.databinding.observable.IStaleListener; >+import org.eclipse.core.databinding.observable.ObservableTracker; >+import org.eclipse.core.databinding.observable.StaleEvent; >+import org.eclipse.core.databinding.observable.list.AbstractObservableList; >+import org.eclipse.core.databinding.observable.list.IListChangeListener; >+import org.eclipse.core.databinding.observable.list.IObservableList; >+import org.eclipse.core.databinding.observable.list.ListChangeEvent; >+import org.eclipse.core.databinding.observable.list.ListDiff; >+import org.eclipse.core.databinding.observable.list.ListDiffEntry; >+import org.eclipse.core.databinding.observable.set.IObservableSet; >+import org.eclipse.core.databinding.observable.set.ISetChangeListener; >+import org.eclipse.core.databinding.observable.set.SetChangeEvent; >+import org.eclipse.core.databinding.observable.set.WritableSet; >+import org.eclipse.core.databinding.property.INativePropertyListener; >+import org.eclipse.core.databinding.property.IProperty; >+import org.eclipse.core.databinding.property.IPropertyObservable; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; >+import org.eclipse.core.databinding.property.value.ISimpleValueProperty; >+import org.eclipse.core.internal.databinding.IdentityWrapper; >+import org.eclipse.core.internal.databinding.Util; >+ >+/** >+ * @since 1.2 >+ */ >+public class ObservableListSimpleValuePropertyObservableList extends >+ AbstractObservableList implements IPropertyObservable { >+ private IObservableList masterList; >+ private ISimpleValueProperty detailProperty; >+ >+ private IObservableSet knownMasterElements; >+ private Map cachedValues; >+ >+ private boolean updating; >+ >+ private IListChangeListener masterListener = new IListChangeListener() { >+ public void handleListChange(ListChangeEvent event) { >+ if (!isDisposed()) { >+ updateKnownElements(); >+ fireListChange(convertDiff(event.diff)); >+ } >+ } >+ >+ private void updateKnownElements() { >+ Set identityKnownElements = new HashSet(); >+ for (Iterator it = masterList.iterator(); it.hasNext();) { >+ identityKnownElements.add(new IdentityWrapper(it.next())); >+ } >+ >+ knownMasterElements.retainAll(identityKnownElements); >+ knownMasterElements.addAll(identityKnownElements); >+ } >+ >+ private ListDiff convertDiff(ListDiff diff) { >+ // Convert diff to detail value >+ ListDiffEntry[] masterEntries = diff.getDifferences(); >+ ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length]; >+ for (int i = 0; i < masterEntries.length; i++) { >+ ListDiffEntry masterDifference = masterEntries[i]; >+ int index = masterDifference.getPosition(); >+ boolean addition = masterDifference.isAddition(); >+ Object masterElement = masterDifference.getElement(); >+ Object elementDetailValue = detailProperty >+ .getValue(masterElement); >+ detailEntries[i] = Diffs.createListDiffEntry(index, addition, >+ elementDetailValue); >+ } >+ return Diffs.createListDiff(detailEntries); >+ } >+ }; >+ >+ private IStaleListener staleListener = new IStaleListener() { >+ public void handleStale(StaleEvent staleEvent) { >+ fireStale(); >+ } >+ }; >+ >+ private INativePropertyListener detailListener; >+ >+ /** >+ * @param masterList >+ * @param valueProperty >+ */ >+ public ObservableListSimpleValuePropertyObservableList( >+ IObservableList masterList, ISimpleValueProperty valueProperty) { >+ super(masterList.getRealm()); >+ this.masterList = masterList; >+ this.detailProperty = valueProperty; >+ >+ ISimplePropertyListener listener = new ISimplePropertyListener() { >+ public void handlePropertyChange(SimplePropertyEvent event) { >+ if (!isDisposed() && !updating) { >+ notifyIfChanged(event.getSource()); >+ } >+ } >+ }; >+ this.detailListener = detailProperty.adaptListener(listener); >+ } >+ >+ protected void firstListenerAdded() { >+ knownMasterElements = new WritableSet(getRealm()); >+ cachedValues = new HashMap(); >+ knownMasterElements.addSetChangeListener(new ISetChangeListener() { >+ public void handleSetChange(SetChangeEvent event) { >+ for (Iterator it = event.diff.getRemovals().iterator(); it >+ .hasNext();) { >+ IdentityWrapper wrapper = (IdentityWrapper) it.next(); >+ Object key = wrapper.unwrap(); >+ detailProperty.removeListener(key, detailListener); >+ cachedValues.remove(wrapper); >+ } >+ for (Iterator it = event.diff.getAdditions().iterator(); it >+ .hasNext();) { >+ IdentityWrapper wrapper = (IdentityWrapper) it.next(); >+ Object key = wrapper.unwrap(); >+ cachedValues.put(wrapper, detailProperty.getValue(key)); >+ detailProperty.addListener(key, detailListener); >+ } >+ } >+ }); >+ for (Iterator it = masterList.iterator(); it.hasNext();) { >+ knownMasterElements.add(new IdentityWrapper(it.next())); >+ } >+ >+ masterList.addListChangeListener(masterListener); >+ masterList.addStaleListener(staleListener); >+ } >+ >+ protected void lastListenerRemoved() { >+ masterList.removeListChangeListener(masterListener); >+ masterList.removeStaleListener(staleListener); >+ if (knownMasterElements != null) { >+ knownMasterElements.clear(); // clears cachedValues >+ knownMasterElements.dispose(); >+ knownMasterElements = null; >+ } >+ cachedValues.clear(); >+ cachedValues = null; >+ } >+ >+ protected int doGetSize() { >+ getterCalled(); >+ return masterList.size(); >+ } >+ >+ private void getterCalled() { >+ ObservableTracker.getterCalled(this); >+ } >+ >+ public Object getElementType() { >+ return detailProperty.getValueType(); >+ } >+ >+ public Object get(int index) { >+ getterCalled(); >+ Object masterElement = masterList.get(index); >+ return detailProperty.getValue(masterElement); >+ } >+ >+ public boolean add(Object o) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean addAll(Collection c) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean addAll(int index, Collection c) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean contains(Object o) { >+ getterCalled(); >+ >+ for (Iterator it = masterList.iterator(); it.hasNext();) { >+ if (Util.equals(detailProperty.getValue(it.next()), o)) >+ return true; >+ } >+ return false; >+ } >+ >+ public boolean isEmpty() { >+ getterCalled(); >+ return masterList.isEmpty(); >+ } >+ >+ public boolean isStale() { >+ getterCalled(); >+ return masterList.isStale(); >+ } >+ >+ public Iterator iterator() { >+ getterCalled(); >+ return new Iterator() { >+ Iterator it = masterList.iterator(); >+ >+ public boolean hasNext() { >+ getterCalled(); >+ return it.hasNext(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ Object masterElement = it.next(); >+ return detailProperty.getValue(masterElement); >+ } >+ >+ public void remove() { >+ throw new UnsupportedOperationException(); >+ } >+ }; >+ } >+ >+ public Object move(int oldIndex, int newIndex) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean remove(Object o) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean removeAll(Collection c) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean retainAll(Collection c) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public Object[] toArray() { >+ getterCalled(); >+ Object[] masterElements = masterList.toArray(); >+ Object[] result = new Object[masterElements.length]; >+ for (int i = 0; i < result.length; i++) { >+ result[i] = detailProperty.getValue(masterElements[i]); >+ } >+ return result; >+ } >+ >+ public Object[] toArray(Object[] a) { >+ getterCalled(); >+ Object[] masterElements = masterList.toArray(); >+ if (a.length < masterElements.length) >+ a = (Object[]) Array.newInstance(a.getClass().getComponentType(), >+ masterElements.length); >+ for (int i = 0; i < masterElements.length; i++) { >+ a[i] = detailProperty.getValue(masterElements[i]); >+ } >+ return a; >+ } >+ >+ public void add(int index, Object o) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public void clear() { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public ListIterator listIterator() { >+ return listIterator(0); >+ } >+ >+ public ListIterator listIterator(final int index) { >+ getterCalled(); >+ return new ListIterator() { >+ ListIterator it = masterList.listIterator(index); >+ Object lastMasterElement; >+ Object lastElement; >+ boolean haveIterated = false; >+ >+ public void add(Object arg0) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public boolean hasNext() { >+ getterCalled(); >+ return it.hasNext(); >+ } >+ >+ public boolean hasPrevious() { >+ getterCalled(); >+ return it.hasPrevious(); >+ } >+ >+ public Object next() { >+ getterCalled(); >+ lastMasterElement = it.next(); >+ lastElement = detailProperty.getValue(lastMasterElement); >+ haveIterated = true; >+ return lastElement; >+ } >+ >+ public int nextIndex() { >+ getterCalled(); >+ return it.nextIndex(); >+ } >+ >+ public Object previous() { >+ getterCalled(); >+ lastMasterElement = it.previous(); >+ lastElement = detailProperty.getValue(lastMasterElement); >+ haveIterated = true; >+ return lastElement; >+ } >+ >+ public int previousIndex() { >+ getterCalled(); >+ return it.previousIndex(); >+ } >+ >+ public void remove() { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public void set(Object o) { >+ checkRealm(); >+ if (!haveIterated) >+ throw new IllegalStateException(); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ detailProperty.setValue(lastElement, o); >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(lastMasterElement); >+ >+ lastElement = o; >+ } >+ }; >+ } >+ >+ private void notifyIfChanged(Object masterElement) { >+ if (cachedValues != null) { >+ Object oldValue = cachedValues.get(new IdentityWrapper( >+ masterElement)); >+ Object newValue = detailProperty.getValue(masterElement); >+ if (!Util.equals(oldValue, newValue)) { >+ cachedValues.put(new IdentityWrapper(masterElement), newValue); >+ fireListChange(indicesOf(masterElement), oldValue, newValue); >+ } >+ } >+ } >+ >+ private int[] indicesOf(Object masterElement) { >+ List indices = new ArrayList(); >+ >+ for (ListIterator it = ObservableListSimpleValuePropertyObservableList.this.masterList >+ .listIterator(); it.hasNext();) { >+ if (masterElement == it.next()) >+ indices.add(new Integer(it.previousIndex())); >+ } >+ >+ int[] result = new int[indices.size()]; >+ for (int i = 0; i < result.length; i++) { >+ result[i] = ((Integer) indices.get(i)).intValue(); >+ } >+ return result; >+ } >+ >+ private void fireListChange(int[] indices, Object oldValue, Object newValue) { >+ ListDiffEntry[] differences = new ListDiffEntry[indices.length * 2]; >+ for (int i = 0; i < indices.length; i++) { >+ int index = indices[i]; >+ differences[i * 2] = Diffs.createListDiffEntry(index, false, >+ oldValue); >+ differences[i * 2 + 1] = Diffs.createListDiffEntry(index, true, >+ newValue); >+ } >+ fireListChange(Diffs.createListDiff(differences)); >+ } >+ >+ public Object remove(int index) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public Object set(int index, Object o) { >+ checkRealm(); >+ Object masterElement = masterList.get(index); >+ Object oldValue = detailProperty.getValue(masterElement); >+ >+ boolean wasUpdating = updating; >+ updating = true; >+ try { >+ detailProperty.setValue(masterElement, o); >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ notifyIfChanged(masterElement); >+ >+ return oldValue; >+ } >+ >+ public Object getObserved() { >+ return masterList; >+ } >+ >+ public IProperty getProperty() { >+ return detailProperty; >+ } >+ >+ public synchronized void dispose() { >+ if (masterList != null) { >+ masterList.removeListChangeListener(masterListener); >+ masterList = null; >+ } >+ if (knownMasterElements != null) { >+ knownMasterElements.clear(); // detaches listeners >+ knownMasterElements.dispose(); >+ knownMasterElements = null; >+ } >+ >+ masterListener = null; >+ detailListener = null; >+ detailProperty = null; >+ cachedValues = null; >+ >+ super.dispose(); >+ } >+} >\ No newline at end of file >Index: src/org/eclipse/core/databinding/property/SimplePropertyEvent.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/property/SimplePropertyEvent.java >diff -N src/org/eclipse/core/databinding/property/SimplePropertyEvent.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/property/SimplePropertyEvent.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,76 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 194734) >+ ******************************************************************************/ >+ >+package org.eclipse.core.databinding.property; >+ >+import java.util.EventObject; >+ >+import org.eclipse.core.databinding.observable.IDiff; >+import org.eclipse.core.internal.databinding.Util; >+ >+/** >+ * Base class for change events in the properties API >+ * >+ * @since 1.2 >+ */ >+public final class SimplePropertyEvent extends EventObject { >+ private static final long serialVersionUID = 1L; >+ >+ /** >+ * The property that changed >+ */ >+ public final IProperty property; >+ >+ /** >+ * A diff object describing the change in state, or null for an unknown >+ * change. >+ */ >+ public final IDiff diff; >+ >+ /** >+ * Constructs a PropertyChangeEvent with the given attributes >+ * >+ * @param source >+ * the property source >+ * @param property >+ * the property that changed on the source >+ * @param diff >+ * a diff describing the change in state, or null if the change >+ * is unknown. >+ */ >+ public SimplePropertyEvent(Object source, IProperty property, IDiff diff) { >+ super(source); >+ this.property = property; >+ this.diff = diff; >+ } >+ >+ public boolean equals(Object obj) { >+ if (obj == this) >+ return true; >+ if (obj == null) >+ return false; >+ if (getClass() != obj.getClass()) >+ return false; >+ >+ SimplePropertyEvent that = (SimplePropertyEvent) obj; >+ return Util.equals(getSource(), that.getSource()) >+ && Util.equals(this.property, that.property) >+ && Util.equals(this.diff, that.diff); >+ } >+ >+ public int hashCode() { >+ int hash = 17; >+ hash = hash * 37 + getSource().hashCode(); >+ hash = hash * 37 + property.hashCode(); >+ hash = hash * 37 + (diff == null ? 0 : diff.hashCode()); >+ return hash; >+ } >+} >#P org.eclipse.core.databinding.beans >Index: src/org/eclipse/core/internal/databinding/beans/BeanSetProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/Attic/BeanSetProperty.java,v >retrieving revision 1.1.2.7 >diff -u -r1.1.2.7 BeanSetProperty.java >--- src/org/eclipse/core/internal/databinding/beans/BeanSetProperty.java 14 Jan 2009 23:51:09 -0000 1.1.2.7 >+++ src/org/eclipse/core/internal/databinding/beans/BeanSetProperty.java 17 Jan 2009 00:49:40 -0000 >@@ -23,8 +23,8 @@ > import org.eclipse.core.databinding.observable.Diffs; > import org.eclipse.core.databinding.observable.set.SetDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; > import org.eclipse.core.databinding.property.set.SimpleSetProperty; > > /** >@@ -82,15 +82,15 @@ > } > > public INativePropertyListener adaptListener( >- final IPropertyChangeListener listener) { >+ final ISimplePropertyListener listener) { > return new Listener(listener); > } > > private class Listener implements INativePropertyListener, > PropertyChangeListener { >- private final IPropertyChangeListener listener; >+ private final ISimplePropertyListener listener; > >- private Listener(IPropertyChangeListener listener) { >+ private Listener(ISimplePropertyListener listener) { > this.listener = listener; > } > >@@ -104,7 +104,7 @@ > diff = null; > } > if (propertyDescriptor.getName().equals(evt.getPropertyName())) { >- listener.handlePropertyChange(new PropertyChangeEvent(evt >+ listener.handlePropertyChange(new SimplePropertyEvent(evt > .getSource(), BeanSetProperty.this, diff)); > } > } >Index: src/org/eclipse/core/internal/databinding/beans/PojoValueProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/Attic/PojoValueProperty.java,v >retrieving revision 1.1.2.5 >diff -u -r1.1.2.5 PojoValueProperty.java >--- src/org/eclipse/core/internal/databinding/beans/PojoValueProperty.java 6 Jan 2009 06:21:00 -0000 1.1.2.5 >+++ src/org/eclipse/core/internal/databinding/beans/PojoValueProperty.java 17 Jan 2009 00:49:40 -0000 >@@ -15,7 +15,7 @@ > import java.beans.PropertyDescriptor; > > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > import org.eclipse.core.databinding.property.value.SimpleValueProperty; > > /** >@@ -52,7 +52,7 @@ > } > > public INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/core/internal/databinding/beans/PojoSetProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/Attic/PojoSetProperty.java,v >retrieving revision 1.1.2.5 >diff -u -r1.1.2.5 PojoSetProperty.java >--- src/org/eclipse/core/internal/databinding/beans/PojoSetProperty.java 6 Jan 2009 06:21:00 -0000 1.1.2.5 >+++ src/org/eclipse/core/internal/databinding/beans/PojoSetProperty.java 17 Jan 2009 00:49:40 -0000 >@@ -21,7 +21,7 @@ > > import org.eclipse.core.databinding.observable.set.SetDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > import org.eclipse.core.databinding.property.set.SimpleSetProperty; > > /** >@@ -79,7 +79,7 @@ > } > > public INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/core/internal/databinding/beans/BeanListProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/Attic/BeanListProperty.java,v >retrieving revision 1.1.2.6 >diff -u -r1.1.2.6 BeanListProperty.java >--- src/org/eclipse/core/internal/databinding/beans/BeanListProperty.java 14 Jan 2009 23:51:09 -0000 1.1.2.6 >+++ src/org/eclipse/core/internal/databinding/beans/BeanListProperty.java 17 Jan 2009 00:49:40 -0000 >@@ -22,8 +22,8 @@ > import org.eclipse.core.databinding.observable.Diffs; > import org.eclipse.core.databinding.observable.list.ListDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; > import org.eclipse.core.databinding.property.list.SimpleListProperty; > > /** >@@ -81,16 +81,16 @@ > return propertyValue; > } > >- protected INativePropertyListener adaptListener( >- final IPropertyChangeListener listener) { >+ public INativePropertyListener adaptListener( >+ final ISimplePropertyListener listener) { > return new Listener(listener); > } > > private class Listener implements INativePropertyListener, > PropertyChangeListener { >- private final IPropertyChangeListener listener; >+ private final ISimplePropertyListener listener; > >- private Listener(IPropertyChangeListener listener) { >+ private Listener(ISimplePropertyListener listener) { > this.listener = listener; > } > >@@ -105,7 +105,7 @@ > } else { > diff = null; > } >- listener.handlePropertyChange(new PropertyChangeEvent(evt >+ listener.handlePropertyChange(new SimplePropertyEvent(evt > .getSource(), BeanListProperty.this, diff)); > } > } >Index: src/org/eclipse/core/internal/databinding/beans/PojoMapProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/Attic/PojoMapProperty.java,v >retrieving revision 1.1.2.5 >diff -u -r1.1.2.5 PojoMapProperty.java >--- src/org/eclipse/core/internal/databinding/beans/PojoMapProperty.java 6 Jan 2009 06:21:00 -0000 1.1.2.5 >+++ src/org/eclipse/core/internal/databinding/beans/PojoMapProperty.java 17 Jan 2009 00:49:40 -0000 >@@ -18,7 +18,7 @@ > > import org.eclipse.core.databinding.observable.map.MapDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > import org.eclipse.core.databinding.property.map.SimpleMapProperty; > > /** >@@ -66,7 +66,7 @@ > } > > public INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/core/internal/databinding/beans/BeanMapProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/Attic/BeanMapProperty.java,v >retrieving revision 1.1.2.6 >diff -u -r1.1.2.6 BeanMapProperty.java >--- src/org/eclipse/core/internal/databinding/beans/BeanMapProperty.java 14 Jan 2009 23:51:08 -0000 1.1.2.6 >+++ src/org/eclipse/core/internal/databinding/beans/BeanMapProperty.java 17 Jan 2009 00:49:40 -0000 >@@ -20,8 +20,8 @@ > import org.eclipse.core.databinding.observable.Diffs; > import org.eclipse.core.databinding.observable.map.MapDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; > import org.eclipse.core.databinding.property.map.SimpleMapProperty; > > /** >@@ -69,15 +69,15 @@ > } > > public INativePropertyListener adaptListener( >- final IPropertyChangeListener listener) { >+ final ISimplePropertyListener listener) { > return new Listener(listener); > } > > private class Listener implements INativePropertyListener, > PropertyChangeListener { >- private final IPropertyChangeListener listener; >+ private final ISimplePropertyListener listener; > >- private Listener(IPropertyChangeListener listener) { >+ private Listener(ISimplePropertyListener listener) { > this.listener = listener; > } > >@@ -92,7 +92,7 @@ > } else { > diff = null; > } >- listener.handlePropertyChange(new PropertyChangeEvent(evt >+ listener.handlePropertyChange(new SimplePropertyEvent(evt > .getSource(), BeanMapProperty.this, diff)); > } > } >Index: src/org/eclipse/core/internal/databinding/beans/PojoListProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/Attic/PojoListProperty.java,v >retrieving revision 1.1.2.5 >diff -u -r1.1.2.5 PojoListProperty.java >--- src/org/eclipse/core/internal/databinding/beans/PojoListProperty.java 6 Jan 2009 06:21:00 -0000 1.1.2.5 >+++ src/org/eclipse/core/internal/databinding/beans/PojoListProperty.java 17 Jan 2009 00:49:40 -0000 >@@ -20,7 +20,7 @@ > > import org.eclipse.core.databinding.observable.list.ListDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; > import org.eclipse.core.databinding.property.list.SimpleListProperty; > > /** >@@ -79,7 +79,7 @@ > } > > public INativePropertyListener adaptListener( >- IPropertyChangeListener listener) { >+ ISimplePropertyListener listener) { > return null; > } > >Index: src/org/eclipse/core/internal/databinding/beans/BeanValueProperty.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/Attic/BeanValueProperty.java,v >retrieving revision 1.1.2.6 >diff -u -r1.1.2.6 BeanValueProperty.java >--- src/org/eclipse/core/internal/databinding/beans/BeanValueProperty.java 14 Jan 2009 23:51:09 -0000 1.1.2.6 >+++ src/org/eclipse/core/internal/databinding/beans/BeanValueProperty.java 17 Jan 2009 00:49:40 -0000 >@@ -18,8 +18,8 @@ > import org.eclipse.core.databinding.observable.Diffs; > import org.eclipse.core.databinding.observable.value.ValueDiff; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; > import org.eclipse.core.databinding.property.value.SimpleValueProperty; > > /** >@@ -54,15 +54,15 @@ > } > > public INativePropertyListener adaptListener( >- final IPropertyChangeListener listener) { >+ final ISimplePropertyListener listener) { > return new Listener(listener); > } > > private class Listener implements INativePropertyListener, > PropertyChangeListener { >- private final IPropertyChangeListener listener; >+ private final ISimplePropertyListener listener; > >- private Listener(IPropertyChangeListener listener) { >+ private Listener(ISimplePropertyListener listener) { > this.listener = listener; > } > >@@ -76,7 +76,7 @@ > } else { > diff = null; > } >- listener.handlePropertyChange(new PropertyChangeEvent(evt >+ listener.handlePropertyChange(new SimplePropertyEvent(evt > .getSource(), BeanValueProperty.this, diff)); > } > } >#P org.eclipse.jface.examples.databinding >Index: src/org/eclipse/jface/examples/databinding/snippets/Snippet026AnonymousBeanProperties.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Attic/Snippet026AnonymousBeanProperties.java,v >retrieving revision 1.1.2.2 >diff -u -r1.1.2.2 Snippet026AnonymousBeanProperties.java >--- src/org/eclipse/jface/examples/databinding/snippets/Snippet026AnonymousBeanProperties.java 14 Jan 2009 23:51:07 -0000 1.1.2.2 >+++ src/org/eclipse/jface/examples/databinding/snippets/Snippet026AnonymousBeanProperties.java 17 Jan 2009 00:49:41 -0000 >@@ -26,8 +26,8 @@ > import org.eclipse.core.databinding.observable.set.SetDiff; > import org.eclipse.core.databinding.observable.value.IObservableValue; > import org.eclipse.core.databinding.property.INativePropertyListener; >-import org.eclipse.core.databinding.property.IPropertyChangeListener; >-import org.eclipse.core.databinding.property.PropertyChangeEvent; >+import org.eclipse.core.databinding.property.ISimplePropertyListener; >+import org.eclipse.core.databinding.property.SimplePropertyEvent; > import org.eclipse.core.databinding.property.set.DelegatingSetProperty; > import org.eclipse.core.databinding.property.set.ISetProperty; > import org.eclipse.core.databinding.property.set.SimpleSetProperty; >@@ -242,21 +242,21 @@ > } > } > >- protected INativePropertyListener adaptListener( >- final IPropertyChangeListener listener) { >+ public INativePropertyListener adaptListener( >+ final ISimplePropertyListener listener) { > return new Listener(listener); > } > > private class Listener implements INativePropertyListener, > PropertyChangeListener { >- private final IPropertyChangeListener listener; >+ private final ISimplePropertyListener listener; > >- Listener(IPropertyChangeListener listener) { >+ Listener(ISimplePropertyListener listener) { > this.listener = listener; > } > > public void propertyChange(java.beans.PropertyChangeEvent evt) { >- listener.handlePropertyChange(new PropertyChangeEvent(evt >+ listener.handlePropertyChange(new SimplePropertyEvent(evt > .getSource(), ContactGroupContactsProperty.this, null)); > } > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 194734
:
106529
|
107000
|
107001
|
107041
|
107042
|
111164
|
111165
|
111335
|
111336
|
111448
|
111449
|
111640
|
111641
|
111717
|
111719
|
111845
|
111846
|
111897
|
111898
|
111993
|
111994
|
112161
|
112162
|
112268
|
112269
|
112360
|
112361
|
112370
|
112371
|
112471
|
112472
|
112606
|
112607
|
112629
|
112630
|
113149
|
113150
|
113165
|
113166
|
114858
|
114859
|
115196
|
115197
|
115284
|
115458
|
115459
|
117500
|
117501
|
117990
|
117991
|
119231
|
119232
|
119274
|
120541
|
120542
|
120651
|
120652
|
120653
|
120654
|
120914
|
120915
|
120989
|
120990
|
121020
|
121021
|
121141
|
121142
|
122228
|
122229
|
122234
|
122235
|
122288
|
122289
|
122609
|
122610
|
122613
|
122614
|
122775
|
122776
|
122813
|
122814
| 122852 |
122853
|
122864
|
122865
|
123137
|
123138