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 123767 Details for
Bug 175735
[DataBinding] DuplexingObservableValue
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Updated snippet to include more movies, to demonstrate duplexing of multiple selection
clipboard.txt (text/plain), 23.09 KB, created by
Matthew Hall
on 2009-01-26 12:04:01 EST
(
hide
)
Description:
Updated snippet to include more movies, to demonstrate duplexing of multiple selection
Filename:
MIME Type:
Creator:
Matthew Hall
Created:
2009-01-26 12:04:01 EST
Size:
23.09 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.jface.examples.databinding >Index: src/org/eclipse/jface/examples/databinding/snippets/Snippet028DuplexingObservableValue.java >=================================================================== >RCS file: src/org/eclipse/jface/examples/databinding/snippets/Snippet028DuplexingObservableValue.java >diff -N src/org/eclipse/jface/examples/databinding/snippets/Snippet028DuplexingObservableValue.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/jface/examples/databinding/snippets/Snippet028DuplexingObservableValue.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,321 @@ >+/******************************************************************************* >+ * 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 175735) >+ ******************************************************************************/ >+ >+package org.eclipse.jface.examples.databinding.snippets; >+ >+import java.beans.PropertyChangeListener; >+import java.beans.PropertyChangeSupport; >+import java.util.Collection; >+import java.util.Iterator; >+ >+import org.eclipse.core.databinding.DataBindingContext; >+import org.eclipse.core.databinding.beans.BeanProperties; >+import org.eclipse.core.databinding.observable.Realm; >+import org.eclipse.core.databinding.observable.list.IObservableList; >+import org.eclipse.core.databinding.observable.list.WritableList; >+import org.eclipse.core.databinding.observable.value.DuplexingObservableValue; >+import org.eclipse.core.databinding.property.Properties; >+import org.eclipse.jface.databinding.swt.SWTObservables; >+import org.eclipse.jface.databinding.swt.WidgetProperties; >+import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; >+import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider; >+import org.eclipse.jface.databinding.viewers.ViewerProperties; >+import org.eclipse.jface.util.Util; >+import org.eclipse.jface.viewers.StructuredSelection; >+import org.eclipse.jface.viewers.TableViewer; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.layout.GridData; >+import org.eclipse.swt.layout.GridLayout; >+import org.eclipse.swt.widgets.Display; >+import org.eclipse.swt.widgets.Label; >+import org.eclipse.swt.widgets.Shell; >+import org.eclipse.swt.widgets.Table; >+import org.eclipse.swt.widgets.TableColumn; >+import org.eclipse.swt.widgets.Text; >+ >+/** >+ * @since 3.2 >+ * >+ */ >+public class Snippet028DuplexingObservableValue { >+ protected Shell shell; >+ private TableViewer viewer; >+ private Table table; >+ private Text releaseDate; >+ private Text title; >+ private Text director; >+ private Text writer; >+ >+ /** >+ * Launch the application >+ * >+ * @param args >+ */ >+ public static void main(String[] args) { >+ try { >+ Snippet028DuplexingObservableValue window = new Snippet028DuplexingObservableValue(); >+ window.open(); >+ } catch (Exception e) { >+ e.printStackTrace(); >+ } >+ } >+ >+ /** >+ * Open the window >+ */ >+ public void open() { >+ final Display display = Display.getDefault(); >+ Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { >+ public void run() { >+ createContents(); >+ shell.open(); >+ shell.layout(); >+ while (!shell.isDisposed()) { >+ if (!display.readAndDispatch()) >+ display.sleep(); >+ } >+ } >+ }); >+ } >+ >+ protected void createContents() { >+ shell = new Shell(); >+ shell.setSize(509, 375); >+ shell.setText("Snippet028DuplexingObservableValue.java"); >+ final GridLayout gridLayout = new GridLayout(); >+ gridLayout.makeColumnsEqualWidth = true; >+ gridLayout.numColumns = 4; >+ shell.setLayout(gridLayout); >+ >+ viewer = new TableViewer(shell, SWT.FULL_SELECTION | SWT.MULTI >+ | SWT.BORDER); >+ table = viewer.getTable(); >+ table.setLinesVisible(true); >+ table.setHeaderVisible(true); >+ table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1)); >+ >+ final TableColumn newColumnTableColumn_1 = new TableColumn(table, >+ SWT.NONE); >+ newColumnTableColumn_1.setWidth(120); >+ newColumnTableColumn_1.setText("Movie"); >+ >+ final TableColumn newColumnTableColumn = new TableColumn(table, >+ SWT.NONE); >+ >+ newColumnTableColumn.setWidth(120); >+ newColumnTableColumn.setText("Release Date"); >+ >+ final TableColumn newColumnTableColumn_2 = new TableColumn(table, >+ SWT.NONE); >+ newColumnTableColumn_2.setWidth(120); >+ newColumnTableColumn_2.setText("Director"); >+ >+ final TableColumn newColumnTableColumn_3 = new TableColumn(table, >+ SWT.NONE); >+ newColumnTableColumn_3.setWidth(120); >+ newColumnTableColumn_3.setText("Writer"); >+ >+ final Label movieLabel = new Label(shell, SWT.NONE); >+ movieLabel.setText("Movie"); >+ >+ final Label directorLabel = new Label(shell, SWT.NONE); >+ directorLabel.setLayoutData(new GridData()); >+ directorLabel.setText("Release Date"); >+ >+ final Label producerLabel = new Label(shell, SWT.NONE); >+ producerLabel.setText("Director"); >+ >+ final Label scoreLabel = new Label(shell, SWT.NONE); >+ scoreLabel.setText("Writer"); >+ >+ title = new Text(shell, SWT.BORDER); >+ final GridData gd_title = new GridData(SWT.FILL, SWT.CENTER, true, >+ false); >+ title.setLayoutData(gd_title); >+ >+ releaseDate = new Text(shell, SWT.BORDER); >+ final GridData gd_releaseDate = new GridData(SWT.FILL, SWT.CENTER, >+ true, false); >+ releaseDate.setLayoutData(gd_releaseDate); >+ >+ director = new Text(shell, SWT.BORDER); >+ final GridData gd_director = new GridData(SWT.FILL, SWT.CENTER, true, >+ false); >+ director.setLayoutData(gd_director); >+ >+ writer = new Text(shell, SWT.BORDER); >+ final GridData gd_writer = new GridData(SWT.FILL, SWT.CENTER, true, >+ false); >+ writer.setLayoutData(gd_writer); >+ >+ bindUI(); >+ } >+ >+ // Minimal JavaBeans support >+ public static abstract class AbstractModelObject { >+ private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport( >+ this); >+ >+ public void addPropertyChangeListener(PropertyChangeListener listener) { >+ propertyChangeSupport.addPropertyChangeListener(listener); >+ } >+ >+ public void addPropertyChangeListener(String propertyName, >+ PropertyChangeListener listener) { >+ propertyChangeSupport.addPropertyChangeListener(propertyName, >+ listener); >+ } >+ >+ public void removePropertyChangeListener(PropertyChangeListener listener) { >+ propertyChangeSupport.removePropertyChangeListener(listener); >+ } >+ >+ public void removePropertyChangeListener(String propertyName, >+ PropertyChangeListener listener) { >+ propertyChangeSupport.removePropertyChangeListener(propertyName, >+ listener); >+ } >+ >+ protected void firePropertyChange(String propertyName, Object oldValue, >+ Object newValue) { >+ propertyChangeSupport.firePropertyChange(propertyName, oldValue, >+ newValue); >+ } >+ } >+ >+ public static class MovieInfo extends AbstractModelObject { >+ private String title; >+ private String releaseDate; >+ private String director; >+ private String writer; >+ >+ public MovieInfo(String title, String releaseDate, String director, >+ String writer) { >+ this.title = title; >+ this.releaseDate = releaseDate; >+ this.director = director; >+ this.writer = writer; >+ } >+ >+ public String getTitle() { >+ return title; >+ } >+ >+ public void setTitle(String title) { >+ firePropertyChange("title", this.title, this.title = title); >+ } >+ >+ public String getReleaseDate() { >+ return releaseDate; >+ } >+ >+ public void setReleaseDate(String releaseDate) { >+ firePropertyChange("releaseDate", this.releaseDate, >+ this.releaseDate = releaseDate); >+ } >+ >+ public String getDirector() { >+ return director; >+ } >+ >+ public void setDirector(String director) { >+ firePropertyChange("director", this.director, >+ this.director = director); >+ } >+ >+ public String getWriter() { >+ return writer; >+ } >+ >+ public void setWriter(String writer) { >+ firePropertyChange("writer", this.writer, this.writer = writer); >+ } >+ } >+ >+ private void bindUI() { >+ IObservableList movies = new WritableList(); >+ movies.add(new MovieInfo("007: Quantum of Solace", "October 31, 2008", >+ "Marc Forster", "Robert Wade")); >+ movies.add(new MovieInfo("Batman Begins", "June 15, 2005", >+ "Christopher Nolan", "David S. Goyer")); >+ movies.add(new MovieInfo("Cloverfield", "January 18, 2008", >+ "Matt Reeves", "Drew Goddard")); >+ movies.add(new MovieInfo("The Dark Knight", "July 18, 2008", >+ "Christopher Nolan", "David S. Goyer")); >+ movies.add(new MovieInfo("Finding Nemo", "May 30, 2003", >+ "Andrew Stanton", "Andrew Stanton")); >+ movies.add(new MovieInfo("Get Smart", "June 20, 2008", "Peter Segal", >+ "Tom J. Astle")); >+ movies.add(new MovieInfo( >+ "Indiana Jones and the Kingdom of the Crystal Skull", >+ "May 22, 2008", "Steven Spielberg", "Drunken Lemurs")); >+ movies.add(new MovieInfo("Iron Man", "May 2, 2008", "Jon Favreau", >+ "Mark Fergus")); >+ movies.add(new MovieInfo("Raiders of the Lost Ark", "June 12, 1981", >+ "Steven Spielberg", "George Lucas")); >+ movies.add(new MovieInfo("Valkyrie", "December 25, 2008", >+ "Bryan Singer", "Christopher McQuarrie")); >+ movies.add(new MovieInfo("Wall-E", "June 27, 2008", "Andrew Stanton", >+ "Andrew Stanton")); >+ movies.add(new MovieInfo("Wanted", "June 27, 2008", >+ "Timur Bekmambetov", "Michael Brandt")); >+ >+ ObservableListContentProvider cp = new ObservableListContentProvider(); >+ viewer.setContentProvider(cp); >+ viewer.setLabelProvider(new ObservableMapLabelProvider(Properties >+ .observeEach(cp.getKnownElements(), BeanProperties >+ .values(new String[] { "title", "releaseDate", >+ "director", "writer" })))); >+ viewer.setInput(movies); >+ >+ // Select Batman Begins and The Dark Knight, which have the same >+ // director and writer >+ viewer.setSelection(new StructuredSelection(new Object[] { >+ movies.get(1), movies.get(3) })); >+ >+ DataBindingContext dbc = new DataBindingContext(); >+ >+ IObservableList selections = ViewerProperties.multipleSelection() >+ .observe(viewer); >+ dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(title), >+ new StringDuplexingObservableValue(BeanProperties >+ .value("title").observeDetail(selections))); >+ dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(releaseDate), >+ new StringDuplexingObservableValue(BeanProperties.value( >+ "releaseDate").observeDetail(selections))); >+ dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(director), >+ new StringDuplexingObservableValue(BeanProperties.value( >+ "director").observeDetail(selections))); >+ dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(writer), >+ new StringDuplexingObservableValue(BeanProperties.value( >+ "writer").observeDetail(selections))); >+ } >+ >+ private static class StringDuplexingObservableValue extends >+ DuplexingObservableValue { >+ >+ public StringDuplexingObservableValue(IObservableList target) { >+ super(target); >+ } >+ >+ protected Object coalesceElements(Collection elements) { >+ Iterator it = elements.iterator(); >+ if (!it.hasNext()) >+ return ""; >+ Object first = it.next(); >+ while (it.hasNext()) { >+ if (!Util.equals(first, it.next())) >+ return "<Multiple values>"; >+ } >+ return first; >+ } >+ } >+} >#P org.eclipse.core.databinding >Index: src/org/eclipse/core/databinding/observable/value/DuplexingObservableValue.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/observable/value/DuplexingObservableValue.java >diff -N src/org/eclipse/core/databinding/observable/value/DuplexingObservableValue.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/observable/value/DuplexingObservableValue.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,196 @@ >+/******************************************************************************* >+ * 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 175735) >+ ******************************************************************************/ >+ >+package org.eclipse.core.databinding.observable.value; >+ >+import java.util.Collection; >+ >+import org.eclipse.core.databinding.observable.ChangeEvent; >+import org.eclipse.core.databinding.observable.IChangeListener; >+import org.eclipse.core.databinding.observable.IStaleListener; >+import org.eclipse.core.databinding.observable.StaleEvent; >+import org.eclipse.core.databinding.observable.list.IObservableList; >+ >+/** >+ * @since 1.2 >+ */ >+public abstract class DuplexingObservableValue extends AbstractObservableValue { >+ private IObservableList target; >+ private final Object valueType; >+ >+ private boolean dirty = true; >+ private boolean updating = false; >+ private Object cachedValue = null; // applicable only while hasListener() >+ >+ private PrivateInterface privateInterface; >+ >+ /** >+ * @param target >+ */ >+ public DuplexingObservableValue(IObservableList target) { >+ this(target, target.getElementType()); >+ } >+ >+ /** >+ * @param target >+ * @param valueType >+ */ >+ public DuplexingObservableValue(IObservableList target, Object valueType) { >+ super(target.getRealm()); >+ this.target = target; >+ this.valueType = valueType; >+ } >+ >+ private class PrivateInterface implements IChangeListener, IStaleListener { >+ public void handleChange(ChangeEvent event) { >+ if (!updating) >+ makeDirty(); >+ } >+ >+ public void handleStale(StaleEvent staleEvent) { >+ if (!dirty) { >+ fireStale(); >+ } >+ } >+ } >+ >+ protected void firstListenerAdded() { >+ if (privateInterface == null) >+ privateInterface = new PrivateInterface(); >+ target.addChangeListener(privateInterface); >+ target.addStaleListener(privateInterface); >+ } >+ >+ protected void lastListenerRemoved() { >+ target.removeChangeListener(privateInterface); >+ target.removeStaleListener(privateInterface); >+ } >+ >+ protected final void makeDirty() { >+ if (hasListeners() && !dirty) { >+ dirty = true; >+ >+ // copy the old value >+ final Object oldValue = cachedValue; >+ // Fire the "dirty" event. This implementation recomputes the new >+ // value lazily. >+ fireValueChange(new ValueDiff() { >+ public Object getOldValue() { >+ return oldValue; >+ } >+ >+ public Object getNewValue() { >+ return getValue(); >+ } >+ }); >+ } >+ } >+ >+ public boolean isStale() { >+ getValue(); >+ return target.isStale(); >+ } >+ >+ protected Object doGetValue() { >+ if (!hasListeners()) >+ return coalesceElements(target); >+ >+ if (dirty) { >+ cachedValue = coalesceElements(target); >+ dirty = false; >+ if (target.isStale()) >+ fireStale(); >+ } >+ >+ return cachedValue; >+ } >+ >+ protected abstract Object coalesceElements(Collection elements); >+ >+ protected void doSetValue(Object value) { >+ final Object oldValue = cachedValue; >+ >+ boolean wasUpdating = updating; >+ try { >+ updating = true; >+ for (int i = 0; i < target.size(); i++) >+ target.set(i, value); >+ } finally { >+ updating = wasUpdating; >+ } >+ >+ // Fire the "dirty" event. This implementation recomputes the new >+ // value lazily. >+ if (hasListeners()) { >+ fireValueChange(new ValueDiff() { >+ public Object getOldValue() { >+ return oldValue; >+ } >+ >+ public Object getNewValue() { >+ return getValue(); >+ } >+ }); >+ } >+ } >+ >+ public Object getValueType() { >+ return valueType; >+ } >+ >+ public synchronized void addChangeListener(IChangeListener listener) { >+ super.addChangeListener(listener); >+ // If somebody is listening, we need to make sure we attach our own >+ // listeners >+ computeValueForListeners(); >+ } >+ >+ public synchronized void addValueChangeListener( >+ IValueChangeListener listener) { >+ super.addValueChangeListener(listener); >+ // If somebody is listening, we need to make sure we attach our own >+ // listeners >+ computeValueForListeners(); >+ } >+ >+ /** >+ * Some clients just add a listener and expect to get notified even if they >+ * never called getValue(), so we have to call getValue() ourselves here to >+ * be sure. Need to be careful about realms though, this method can be >+ * called outside of our realm. See also bug 198211. If a client calls this >+ * outside of our realm, they may receive change notifications before the >+ * runnable below has been executed. It is their job to figure out what to >+ * do with those notifications. >+ */ >+ private void computeValueForListeners() { >+ getRealm().exec(new Runnable() { >+ public void run() { >+ // We are not currently listening. >+ if (hasListeners()) { >+ // But someone is listening for changes. Call getValue() >+ // to make sure we start listening to the observables we >+ // depend on. >+ getValue(); >+ } >+ } >+ }); >+ } >+ >+ public synchronized void dispose() { >+ if (privateInterface != null && target != null) { >+ target.removeChangeListener(privateInterface); >+ target.removeStaleListener(privateInterface); >+ } >+ target = null; >+ privateInterface = null; >+ super.dispose(); >+ } >+} >#P org.eclipse.jface.tests.databinding >Index: src/org/eclipse/jface/tests/databinding/BindingTestSuite.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/BindingTestSuite.java,v >retrieving revision 1.101 >diff -u -r1.101 BindingTestSuite.java >--- src/org/eclipse/jface/tests/databinding/BindingTestSuite.java 24 Jan 2009 23:42:58 -0000 1.101 >+++ src/org/eclipse/jface/tests/databinding/BindingTestSuite.java 26 Jan 2009 17:02:39 -0000 >@@ -14,7 +14,7 @@ > * Matthew Hall - bugs 210115, 212468, 212223, 206839, 208858, 208322, > * 212518, 215531, 221351, 184830, 213145, 218269, 239015, > * 237703, 237718, 222289, 247394, 233306, 247647, 254524, >- * 246103, 249992, 256150, 256543, 262269 >+ * 246103, 249992, 256150, 256543, 262269, 175735 > * Ovidio Mallo - bug 237163, bug 235195 > *******************************************************************************/ > package org.eclipse.jface.tests.databinding; >@@ -65,6 +65,7 @@ > import org.eclipse.core.tests.databinding.observable.value.AbstractVetoableValueTest; > import org.eclipse.core.tests.databinding.observable.value.ComputedValueTest; > import org.eclipse.core.tests.databinding.observable.value.DecoratingObservableValueTest; >+import org.eclipse.core.tests.databinding.observable.value.DuplexingObservableValueTest; > import org.eclipse.core.tests.databinding.observable.value.SelectObservableValueTest; > import org.eclipse.core.tests.databinding.observable.value.WritableValueTest; > import org.eclipse.core.tests.databinding.util.PolicyTest; >@@ -268,6 +269,7 @@ > addTestSuite(AbstractVetoableValueTest.class); > addTestSuite(ComputedValueTest.class); > addTest(DecoratingObservableValueTest.suite()); >+ addTestSuite(DuplexingObservableValueTest.class); > addTest(SelectObservableValueTest.suite()); > addTest(WritableValueTest.suite()); > >Index: src/org/eclipse/core/tests/databinding/observable/value/DuplexingObservableValueTest.java >=================================================================== >RCS file: src/org/eclipse/core/tests/databinding/observable/value/DuplexingObservableValueTest.java >diff -N src/org/eclipse/core/tests/databinding/observable/value/DuplexingObservableValueTest.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/tests/databinding/observable/value/DuplexingObservableValueTest.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,85 @@ >+/******************************************************************************* >+ * 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 173735) >+ *******************************************************************************/ >+ >+package org.eclipse.core.tests.databinding.observable.value; >+ >+import java.util.ArrayList; >+import java.util.Collection; >+import java.util.Iterator; >+ >+import org.eclipse.core.databinding.observable.list.IObservableList; >+import org.eclipse.core.databinding.observable.list.WritableList; >+import org.eclipse.core.databinding.observable.value.DuplexingObservableValue; >+import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase; >+import org.eclipse.jface.util.Util; >+ >+/** >+ * @since 1.0 >+ * >+ */ >+public class DuplexingObservableValueTest extends AbstractDefaultRealmTestCase { >+ private IObservableList list; >+ private DuplexingObservableValue observable; >+ >+ protected void setUp() throws Exception { >+ super.setUp(); >+ list = new WritableList(new ArrayList(), String.class); >+ } >+ >+ public void testValueType_InheritFromTargetList() throws Exception { >+ observable = new DuplexingObservableValue(list) { >+ protected Object coalesceElements(Collection elements) { >+ return null; >+ } >+ }; >+ assertEquals( >+ "value type should be the element type of the target list", >+ String.class, observable.getValueType()); >+ } >+ >+ public void testValueType_ProvidedInConstructor() throws Exception { >+ observable = new DuplexingObservableValue(list, Object.class) { >+ protected Object coalesceElements(Collection elements) { >+ return null; >+ } >+ }; >+ assertEquals("value type should be the type passed to constructor", >+ Object.class, observable.getValueType()); >+ } >+ >+ public void test_getValue() throws Exception { >+ observable = new DuplexingObservableValue(list) { >+ protected Object coalesceElements(Collection elements) { >+ Iterator it = elements.iterator(); >+ if (!it.hasNext()) >+ return null; >+ Object first = it.next(); >+ while (it.hasNext()) { >+ Object next = it.next(); >+ if (!Util.equals(first, next)) >+ return "<Multiple Values>"; >+ } >+ return first; >+ } >+ }; >+ assertNull(observable.getValue()); >+ list.add("42"); >+ assertEquals("Value should be \"42\"", "42", observable.getValue()); >+ list.add("42"); >+ assertEquals("Value should be \"42\"", "42", observable.getValue()); >+ list.add("watermelon"); >+ assertEquals("<Multiple Values>", observable.getValue()); >+ list.remove(2); >+ assertEquals("Value should be \"42\"", "42", observable.getValue()); >+ list.clear(); >+ assertNull(observable.getValue()); >+ } >+}
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 175735
:
123708
|
123709
| 123767 |
123768