### Eclipse Workspace Patch 1.0 #P org.eclipse.core.databinding.property Index: src/org/eclipse/core/databinding/property/list/IListProperty.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/IListProperty.java,v retrieving revision 1.5 diff -u -r1.5 IListProperty.java --- src/org/eclipse/core/databinding/property/list/IListProperty.java 1 Jun 2010 19:22:39 -0000 1.5 +++ src/org/eclipse/core/databinding/property/list/IListProperty.java 20 Feb 2011 12:33:37 -0000 @@ -7,7 +7,7 @@ * * Contributors: * Matthew Hall - initial API and implementation (bug 194734) - * Matthew Hall - bug 195222 + * Matthew Hall - bug 195222, 300043 ******************************************************************************/ package org.eclipse.core.databinding.property.list; @@ -161,4 +161,12 @@ * properties */ public IListProperty values(IValueProperty detailValue); + + /** + * @param reducer + * the strategy that reduces the list down to a value. + * @return a read-only reduced value from this list property + * @since 1.4 + */ + public IValueProperty reduce(IListReducer reducer); } Index: src/org/eclipse/core/databinding/property/list/IListReducer.java =================================================================== RCS file: src/org/eclipse/core/databinding/property/list/IListReducer.java diff -N src/org/eclipse/core/databinding/property/list/IListReducer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/databinding/property/list/IListReducer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2010 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 300043) + ******************************************************************************/ + +package org.eclipse.core.databinding.property.list; + +import java.util.List; + +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.value.IObservableValue; + +/** + * A list-to-value reducer. List reducers may be used to condense a list + * property down to a value property. + * + * @since 1.4 + * @noimplement This interface is not intended to be implemented by clients. + * @see ListReducer + */ +public interface IListReducer { + + /** + * @param list + * the list to reduce + * @return the list reduction + */ + public Object reduce(List list); + + /** + * @return the value type of the reduction + */ + public Object getValueType(); + + /** + * @param master + * the master list to reduce + * @return an IObservableValue observing the reduction of the specified + * IObservableList + */ + public IObservableValue observeDetail(IObservableList master); + +} Index: src/org/eclipse/core/databinding/property/list/ListProperty.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/ListProperty.java,v retrieving revision 1.8 diff -u -r1.8 ListProperty.java --- src/org/eclipse/core/databinding/property/list/ListProperty.java 23 Dec 2010 21:43:31 -0000 1.8 +++ src/org/eclipse/core/databinding/property/list/ListProperty.java 20 Feb 2011 12:33:37 -0000 @@ -7,7 +7,7 @@ * * Contributors: * Matthew Hall - initial API and implementation (bug 194734) - * Matthew Hall - bug 195222 + * Matthew Hall - bug 195222, 300043 * Ovidio Mallo - bug 331348 ******************************************************************************/ @@ -27,6 +27,7 @@ import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.property.value.IValueProperty; import org.eclipse.core.internal.databinding.property.ListPropertyDetailValuesList; +import org.eclipse.core.internal.databinding.property.list.ReducedListValueProperty; /** * Abstract implementation of IListProperty. @@ -152,4 +153,11 @@ public final IListProperty values(IValueProperty detailValue) { return new ListPropertyDetailValuesList(this, detailValue); } + + /** + * @since 1.4 + */ + public final IValueProperty reduce(IListReducer reducer) { + return new ReducedListValueProperty(this, reducer); + } } Index: src/org/eclipse/core/databinding/property/list/ListReducer.java =================================================================== RCS file: src/org/eclipse/core/databinding/property/list/ListReducer.java diff -N src/org/eclipse/core/databinding/property/list/ListReducer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/databinding/property/list/ListReducer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2010 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 300043) + ******************************************************************************/ + +package org.eclipse.core.databinding.property.list; + +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.internal.databinding.property.value.ReducedListObservableValue; + +/** + * Abstract base implementation if {@link IListReducer}. + * + * @since 1.4 + */ +public abstract class ListReducer implements IListReducer { + + private final Object valueType; + + /** + * Constructs a list reducer with the given value type + * + * @param valueType + * the reduction value type + */ + protected ListReducer(Object valueType) { + this.valueType = valueType; + } + + public Object getValueType() { + return valueType; + } + + public IObservableValue observeDetail(IObservableList master) { + return new ReducedListObservableValue(master, this); + } + +} Index: src/org/eclipse/core/databinding/property/list/ListReducers.java =================================================================== RCS file: src/org/eclipse/core/databinding/property/list/ListReducers.java diff -N src/org/eclipse/core/databinding/property/list/ListReducers.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/databinding/property/list/ListReducers.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2010 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 300043) + ******************************************************************************/ + +package org.eclipse.core.databinding.property.list; + +import java.util.Iterator; +import java.util.List; + +/** + * Factory class for common list reducers + * + * @since 1.4 + */ +public class ListReducers { + /** + * @param delimiter + * the delimiter between each list element + * @return a String-valued list reducer which concatenates all elements in + * the list, with the specified delimiter between each element. + */ + public static IListReducer join(final String delimiter) { + return new ListReducer(String.class) { + public Object reduce(List list) { + StringBuffer buf = new StringBuffer(); + + for (Iterator it = list.iterator(); it.hasNext();) { + buf.append(it.next()); + if (it.hasNext()) + buf.append(delimiter); + } + + return buf.toString(); + } + }; + } +} Index: src/org/eclipse/core/internal/databinding/property/list/ReducedListValueProperty.java =================================================================== RCS file: src/org/eclipse/core/internal/databinding/property/list/ReducedListValueProperty.java diff -N src/org/eclipse/core/internal/databinding/property/list/ReducedListValueProperty.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/databinding/property/list/ReducedListValueProperty.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2010 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 300043) + ******************************************************************************/ + +package org.eclipse.core.internal.databinding.property.list; + +import org.eclipse.core.databinding.observable.ObservableTracker; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.property.list.IListReducer; +import org.eclipse.core.databinding.property.list.ListProperty; +import org.eclipse.core.databinding.property.value.ValueProperty; +import org.eclipse.core.internal.databinding.property.PropertyObservableUtil; + +/** + * + */ +public class ReducedListValueProperty extends ValueProperty { + + private final ListProperty masterProperty; + private final IListReducer reducer; + + /** + * @param masterProperty + * @param reducer + */ + public ReducedListValueProperty(ListProperty masterProperty, + IListReducer reducer) { + this.masterProperty = masterProperty; + this.reducer = reducer; + } + + public Object getValueType() { + return reducer.getValueType(); + } + + public IObservableValue observe(Realm realm, Object source) { + IObservableList masterList; + + ObservableTracker.setIgnore(true); + try { + masterList = masterProperty.observe(realm, source); + } finally { + ObservableTracker.setIgnore(false); + } + + IObservableValue detailValue = reducer.observeDetail(masterList); + PropertyObservableUtil.cascadeDispose(detailValue, masterList); + return detailValue; + } +} Index: src/org/eclipse/core/internal/databinding/property/value/ReducedListObservableValue.java =================================================================== RCS file: src/org/eclipse/core/internal/databinding/property/value/ReducedListObservableValue.java diff -N src/org/eclipse/core/internal/databinding/property/value/ReducedListObservableValue.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/databinding/property/value/ReducedListObservableValue.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2010 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 300043) + ******************************************************************************/ + +package org.eclipse.core.internal.databinding.property.value; + +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.value.ComputedValue; +import org.eclipse.core.databinding.property.list.IListReducer; + +/** + * + */ +public class ReducedListObservableValue extends ComputedValue { + + private IObservableList masterList; + private IListReducer reducer; + + /** + * @param masterList + * @param reducer + */ + public ReducedListObservableValue(IObservableList masterList, + IListReducer reducer) { + super(masterList.getRealm(), reducer.getValueType()); + this.masterList = masterList; + this.reducer = reducer; + } + + protected Object calculate() { + return reducer.reduce(masterList); + } + +} #P org.eclipse.jface.examples.databinding Index: src/org/eclipse/jface/examples/databinding/snippets/Snippet025TableViewerWithPropertyDerivedColumns.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet025TableViewerWithPropertyDerivedColumns.java,v retrieving revision 1.5 diff -u -r1.5 Snippet025TableViewerWithPropertyDerivedColumns.java --- src/org/eclipse/jface/examples/databinding/snippets/Snippet025TableViewerWithPropertyDerivedColumns.java 25 May 2009 20:52:49 -0000 1.5 +++ src/org/eclipse/jface/examples/databinding/snippets/Snippet025TableViewerWithPropertyDerivedColumns.java 20 Feb 2011 12:33:38 -0000 @@ -14,6 +14,9 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.beans.BeanProperties; @@ -21,10 +24,12 @@ import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.list.WritableList; import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.property.list.ListReducers; +import org.eclipse.core.databinding.property.value.IValueProperty; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.jface.databinding.swt.WidgetProperties; -import org.eclipse.jface.databinding.viewers.ViewerSupport; import org.eclipse.jface.databinding.viewers.ViewerProperties; +import org.eclipse.jface.databinding.viewers.ViewerSupport; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ComboViewer; @@ -106,11 +111,28 @@ String name = "Donald Duck"; Person mother; Person father; + List children = new ArrayList(); public Person(String name, Person mother, Person father) { this.name = name; this.mother = mother; this.father = father; + if (mother != null) { + mother.addChild(this); + } + if (father != null) { + father.addChild(this); + } + } + + private void addChild(Person person) { + children.add(person); + firePropertyChange("children", null, children); + } + + private void removeChild(Person person) { + children.remove(person); + firePropertyChange("children", null, children); } public String getName() { @@ -125,8 +147,18 @@ return mother; } + public Person[] getChildren() { + return (Person[]) children.toArray(new Person[children.size()]); + } + public void setMother(Person mother) { + if (this.mother != null) { + this.mother.removeChild(this); + } firePropertyChange("mother", this.mother, this.mother = mother); + if (this.mother != null) { + this.mother.addChild(this); + } } public Person getFather() { @@ -134,7 +166,13 @@ } public void setFather(Person father) { + if (this.father != null) { + this.father.removeChild(this); + } firePropertyChange("father", this.father, this.father = father); + if (this.father != null) { + this.father.addChild(this); + } } } @@ -145,6 +183,7 @@ // data access tier. Since this snippet doesn't have any persistent objects // ro retrieve, this ViewModel just instantiates a model object to edit. static class ViewModel { + // The model to bind private IObservableList people = new WritableList(); { @@ -197,6 +236,7 @@ createColumn("Maternal Grandfather"); createColumn("Paternal Grandmother"); createColumn("Paternal Grandfather"); + createColumn("Children").setWidth(200); duckFamily.setLinesVisible(true); @@ -216,17 +256,18 @@ GridLayoutFactory.swtDefaults().numColumns(2).applyTo(shell); // Open and return the Shell - shell.setSize(800, 300); + shell.setSize(1000, 300); shell.open(); return shell; } - private void createColumn(String string) { + private TableColumn createColumn(String string) { final TableColumn column = new TableColumn(duckFamily, SWT.NONE); column.setText(string); column.pack(); if (column.getWidth() < 100) column.setWidth(100); + return column; } protected void bindGUI(DataBindingContext dbc) { @@ -240,10 +281,7 @@ }); ViewerSupport.bind(peopleViewer, viewModel.getPeople(), - BeanProperties.values(Person.class, new String[] { "name", - "mother.name", "father.name", "mother.mother.name", - "mother.father.name", "father.mother.name", - "father.father.name" })); + getProperties()); IObservableValue masterSelection = ViewerProperties .singleSelection().observe(peopleViewer); @@ -269,4 +307,20 @@ "father").observeDetail(masterSelection)); } } + + private static IValueProperty[] getProperties() { + List properties = new ArrayList(); + + // Add the "simple" properties. + properties.addAll(Arrays.asList(BeanProperties.values(Person.class, + new String[] { "name", "mother.name", "father.name", + "mother.mother.name", "mother.father.name", + "father.mother.name", "father.father.name" }))); + + // Add the "complex" property. + properties.add(BeanProperties.list("children").values("name").reduce( + ListReducers.join(", "))); + + return properties.toArray(new IValueProperty[properties.size()]); + } }