# HG changeset patch # User Frank Benoit # Date 1240133635 -7200 # Node ID 6086085e153dd1b533df5046a5d63716aeac8f3d # Parent 0ca1aee7decfcccd5952784d9f08c3136453b4ea Added databinding snippets. unmodified java sources. diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet001NestedSelectionWithCombo.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet001NestedSelectionWithCombo.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,216 @@ +/******************************************************************************* + * Copyright (c) 2006 The Pampered Chef, Inc. 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: + * The Pampered Chef, Inc. - initial API and implementation + * Brad Reynolds - bug 116920 + * Matthew Hall - bug 260329 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.HashSet; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.Observables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.map.IObservableMap; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.ListViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * Demonstrates nested selection.
+ * At the first level, user may select a person.
+ * At the second level, user may select a city to associate with the selected
+ * person or edit the person's name. + */ +public class Snippet001NestedSelectionWithCombo { + public static void main(String[] args) { + ViewModel viewModel = new ViewModel(); + Shell shell = new View(viewModel).createShell(); + + // The SWT event loop + Display display = Display.getCurrent(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + + // 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); + } + } + + // The data model class. This is normally a persistent class of some sort. + // + // This example implements full JavaBeans bound properties so that changes + // to instances of this class will automatically be propogated to the UI. + public static class Person extends AbstractModelObject { + // Constructor + public Person(String name, String city) { + this.name = name; + this.city = city; + } + + // Some JavaBean bound properties... + String name; + + String city; + + public String getName() { + return name; + } + + public void setName(String name) { + String oldValue = this.name; + this.name = name; + firePropertyChange("name", oldValue, name); + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + String oldValue = this.city; + this.city = city; + firePropertyChange("city", oldValue, city); + } + } + + // The View's model--the root of our GUI's Model graph + // + // Typically each View class has a corresponding ViewModel class. + // The ViewModel is responsible for getting the objects to edit from the + // DAO. Since this snippet doesn't have any persistent objects to + // retrieve, this ViewModel just instantiates some objects to edit. + // + // This ViewModel also implements JavaBean bound properties. + static class ViewModel extends AbstractModelObject { + // The model to bind + private ArrayList people = new ArrayList(); + { + people.add(new Person("Wile E. Coyote", "Tucson")); + people.add(new Person("Road Runner", "Lost Horse")); + people.add(new Person("Bugs Bunny", "Forrest")); + } + + // Choice of cities for the Combo + private ArrayList cities = new ArrayList(); + { + cities.add("Tucson"); + cities.add("AcmeTown"); + cities.add("Lost Horse"); + cities.add("Forrest"); + cities.add("Lost Mine"); + } + + public ArrayList getPeople() { + return people; + } + + public ArrayList getCities() { + return cities; + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + Shell shell = new Shell(Display.getCurrent()); + Realm realm = SWTObservables.getRealm(shell.getDisplay()); + + List peopleList = new List(shell, SWT.BORDER); + Text name = new Text(shell, SWT.BORDER); + Combo city = new Combo(shell, SWT.BORDER | SWT.READ_ONLY); + + ListViewer peopleListViewer = new ListViewer(peopleList); + IObservableMap attributeMap = BeansObservables.observeMap( + Observables.staticObservableSet(realm, new HashSet( + viewModel.getPeople())), Person.class, "name"); + peopleListViewer.setLabelProvider(new ObservableMapLabelProvider( + attributeMap)); + peopleListViewer.setContentProvider(new ArrayContentProvider()); + peopleListViewer.setInput(viewModel.getPeople()); + + DataBindingContext dbc = new DataBindingContext(realm); + IObservableValue selectedPerson = ViewersObservables + .observeSingleSelection(peopleListViewer); + dbc.bindValue(SWTObservables.observeText(name, SWT.Modify), + BeansObservables.observeDetailValue(selectedPerson, + "name", String.class)); + + ComboViewer cityViewer = new ComboViewer(city); + cityViewer.setContentProvider(new ArrayContentProvider()); + cityViewer.setInput(viewModel.getCities()); + + IObservableValue citySelection = ViewersObservables + .observeSingleSelection(cityViewer); + dbc.bindValue(citySelection, BeansObservables.observeDetailValue( + selectedPerson, "city", String.class)); + + GridLayoutFactory.swtDefaults().applyTo(shell); + // Open and return the Shell + shell.pack(); + shell.open(); + return shell; + } + } + +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet002UpdateComboRetainSelection.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet002UpdateComboRetainSelection.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2006 The Pampered Chef, Inc. 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: + * The Pampered Chef, Inc. - initial API and implementation + * Brad Reynolds - bug 116920 + * Matthew Hall - bug 260329 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.IObservable; +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.masterdetail.IObservableFactory; +import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * Shows how to bind a Combo so that when update its items, the selection is + * retained if at all possible. + * + * @since 3.2 + */ +public class Snippet002UpdateComboRetainSelection { + public static void main(String[] args) { + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + ViewModel viewModel = new ViewModel(); + Shell shell = new View(viewModel).createShell(); + + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + + // Print the results + System.out.println(viewModel.getText()); + } + }); + display.dispose(); + } + + // 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); + } + } + + // The View's model--the root of our Model graph for this particular GUI. + public static class ViewModel extends AbstractModelObject { + private String text = "beef"; + + private List choices = new ArrayList(); + { + choices.add("pork"); + choices.add("beef"); + choices.add("poultry"); + choices.add("vegatables"); + } + + public List getChoices() { + return choices; + } + + public void setChoices(List choices) { + List old = this.choices; + this.choices = choices; + firePropertyChange("choices", old, choices); + } + + public String getText() { + return text; + } + + public void setText(String text) { + String oldValue = this.text; + this.text = text; + firePropertyChange("text", oldValue, text); + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + /** + * used to make a new choices array unique + */ + static int count; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + Shell shell = new Shell(Display.getCurrent()); + shell.setLayout(new RowLayout(SWT.VERTICAL)); + + Combo combo = new Combo(shell, SWT.BORDER | SWT.READ_ONLY); + Button reset = new Button(shell, SWT.NULL); + reset.setText("reset collection"); + reset.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + List newList = new ArrayList(); + newList.add("Chocolate"); + newList.add("Vanilla"); + newList.add("Mango Parfait"); + newList.add("beef"); + newList.add("Cheesecake"); + newList.add(Integer.toString(++count)); + viewModel.setChoices(newList); + } + }); + + // Print value out first + System.out.println(viewModel.getText()); + + DataBindingContext dbc = new DataBindingContext(); + + IObservableList list = MasterDetailObservables.detailList(BeansObservables.observeValue(viewModel, "choices"), + getListDetailFactory(), + String.class); + dbc.bindList(SWTObservables.observeItems(combo), list); + dbc.bindValue(SWTObservables.observeText(combo), BeansObservables.observeValue(viewModel, "text")); + + // Open and return the Shell + shell.pack(); + shell.open(); + return shell; + } + } + + private static IObservableFactory getListDetailFactory() { + return new IObservableFactory() { + public IObservable createObservable(Object target) { + WritableList list = WritableList.withElementType(String.class); + list.addAll((Collection) target); + return list; + } + }; + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet003UpdateComboBindUsingViewer.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet003UpdateComboBindUsingViewer.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,175 @@ +/******************************************************************************* + * Copyright (c) 2006 The Pampered Chef, Inc. 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: + * The Pampered Chef, Inc. - initial API and implementation + * Brad Reynolds - bug 116920 + * Matthew Hall - bugs 260329, 260337 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.property.Properties; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ViewerSupport; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * Shows how to bind a Combo so that when update its items, the selection is + * retained if at all possible. + * + * @since 3.2 + */ +public class Snippet003UpdateComboBindUsingViewer { + public static void main(String[] args) { + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + ViewModel viewModel = new ViewModel(); + Shell shell = new View(viewModel).createShell(); + + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + // Print the results + System.out.println(viewModel.getText()); + } + }); + display.dispose(); + } + + // 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); + } + } + + // The View's model--the root of our Model graph for this particular GUI. + public static class ViewModel extends AbstractModelObject { + private String text = "beef"; + + private List choices = new ArrayList(); + { + choices.add("pork"); + choices.add("beef"); + choices.add("poultry"); + choices.add("vegatables"); + } + + public List getChoices() { + return choices; + } + + public void setChoices(List choices) { + this.choices = choices; + firePropertyChange("choices", null, null); + } + + public String getText() { + return text; + } + + public void setText(String text) { + String oldValue = this.text; + this.text = text; + firePropertyChange("text", oldValue, text); + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + Shell shell = new Shell(Display.getCurrent()); + shell.setLayout(new RowLayout(SWT.VERTICAL)); + + Combo combo = new Combo(shell, SWT.BORDER | SWT.READ_ONLY); + ComboViewer viewer = new ComboViewer(combo); + Button reset = new Button(shell, SWT.NULL); + reset.setText("reset collection"); + reset.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + List newList = new ArrayList(); + newList.add("Chocolate"); + newList.add("Vanilla"); + newList.add("Mango Parfait"); + newList.add("beef"); + newList.add("Cheesecake"); + viewModel.setChoices(newList); + } + }); + + // Print value out first + System.out.println(viewModel.getText()); + + DataBindingContext dbc = new DataBindingContext(); + ViewerSupport.bind(viewer, BeansObservables.observeList(viewModel, + "choices", String.class), Properties + .selfValue(String.class)); + + dbc.bindValue(ViewersObservables.observeSingleSelection(viewer), + BeansObservables.observeValue(viewModel, "text")); + + // Open and return the Shell + shell.pack(); + shell.open(); + return shell; + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet004DataBindingContextErrorLabel.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet004DataBindingContextErrorLabel.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2006 Brad Reynolds 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: + * Brad Reynolds - initial API and implementation + * Brad Reynolds - bug 116920, 159768 + * Matthew Hall - bug 260329 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import org.eclipse.core.databinding.AggregateValidationStatus; +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.swt.SWT; +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.Text; + +/** + * Snippet that displays how to bind the validation error of the + * {@link DataBindingContext} to a label. http://www.eclipse.org + * + * @since 3.2 + */ +public class Snippet004DataBindingContextErrorLabel { + public static void main(String[] args) { + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + Shell shell = new Shell(display); + shell.setText("Data Binding Snippet 004"); + shell.setLayout(new GridLayout(2, false)); + + new Label(shell, SWT.NONE).setText("Enter '5' to be valid:"); + + Text text = new Text(shell, SWT.BORDER); + WritableValue value = WritableValue.withValueType(String.class); + new Label(shell, SWT.NONE).setText("Error:"); + + Label errorLabel = new Label(shell, SWT.BORDER); + errorLabel.setForeground(display.getSystemColor(SWT.COLOR_RED)); + GridDataFactory.swtDefaults().hint(200, SWT.DEFAULT).applyTo( + errorLabel); + + DataBindingContext dbc = new DataBindingContext(); + + // Bind the text to the value. + dbc.bindValue( + SWTObservables.observeText(text, SWT.Modify), + value, + new UpdateValueStrategy().setAfterConvertValidator(new FiveValidator()), + null); + + // Bind the error label to the validation error on the dbc. + dbc.bindValue(SWTObservables.observeText(errorLabel), + new AggregateValidationStatus(dbc.getBindings(), + AggregateValidationStatus.MAX_SEVERITY)); + + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + }); + display.dispose(); + } + + /** + * Validator that returns validation errors for any value other than 5. + * + * @since 3.2 + */ + private static class FiveValidator implements IValidator { + public IStatus validate(Object value) { + return ("5".equals(value)) ? Status.OK_STATUS : ValidationStatus + .error("the value was '" + value + "', not '5'"); + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet005MenuUpdater.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet005MenuUpdater.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 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 + * Brad Reynolds - bug 116920 + *******************************************************************************/ +package org.eclipse.jface.examples.databinding.snippets; + +import java.util.Date; +import java.util.Iterator; + +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.WritableList; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.internal.databinding.provisional.swt.MenuUpdater; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.Shell; + +/** + */ +public class Snippet005MenuUpdater { + public static void main(String[] args) { + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + Shell shell = new Shell(display); + + final WritableList menuItemStrings = new WritableList(); + display.asyncExec(new Runnable() { + public void run() { + System.out.println("adding item"); + menuItemStrings.add(new Date().toString()); + display.timerExec(5000, this); + } + }); + + Menu bar = new Menu(shell, SWT.BAR); + shell.setMenuBar(bar); + MenuItem fileItem = new MenuItem(bar, SWT.CASCADE); + fileItem.setText("&Test Menu"); + final Menu submenu = new Menu(shell, SWT.DROP_DOWN); + fileItem.setMenu(submenu); + new MenuUpdater(submenu) { + protected void updateMenu() { + System.out.println("updating menu"); + MenuItem[] items = submenu.getItems(); + int itemIndex = 0; + for (Iterator it = menuItemStrings.iterator(); it + .hasNext();) { + MenuItem item; + if (itemIndex < items.length) { + item = items[itemIndex++]; + } else { + item = new MenuItem(submenu, SWT.NONE); + } + String string = (String) it.next(); + item.setText(string); + } + while (itemIndex < items.length) { + items[itemIndex++].dispose(); + } + } + }; + + shell.open(); + + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + display.dispose(); + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet006Spreadsheet.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet006Spreadsheet.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,315 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 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 + * Brad Reynolds - bug 116920 + *******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.text.NumberFormat; +import java.text.ParseException; + +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.WritableList; +import org.eclipse.core.databinding.observable.value.ComputedValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.internal.databinding.provisional.swt.TableUpdater; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ControlEditor; +import org.eclipse.swt.custom.TableCursor; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; + +/** + * @since 1.1 + * + */ +public class Snippet006Spreadsheet { + + private static final int COUNTER_UPDATE_DELAY = 1000; + + private static final int NUM_COLUMNS = 6; + + private static final int NUM_ROWS = 16; + + /** + * 0 for no output, 1 for some, 2 for more + */ + private static int DEBUG_LEVEL = 0; + + /** + * If true, there will be a automatic counter at B1. + */ + private static boolean FUNKY_COUNTER = false; + + /** + * // * If true, all formulas (except for row 1 and column A) will be the + * sum of the values of their left and top neighbouring cells. + */ + private static boolean FUNKY_FORMULAS = true; + + static WritableValue[][] cellFormulas = new WritableValue[NUM_ROWS][NUM_COLUMNS]; + + static ComputedValue[][] cellValues = new ComputedValue[NUM_ROWS][NUM_COLUMNS]; + + static class ComputedCellValue extends ComputedValue { + private final IObservableValue cellFormula; + + private boolean calculating; + + ComputedCellValue(IObservableValue cellFormula) { + this.cellFormula = cellFormula; + } + + protected Object calculate() { + if (calculating) { + return "#cycle"; + } + try { + calculating = true; + return evaluate(cellFormula.getValue()); + } finally { + calculating = false; + } + } + + private Object evaluate(Object value) { + if (DEBUG_LEVEL >= 2) { + System.out.println("evaluating " + this + " ..."); + } + if (value == null) { + return ""; + } + try { + String s = (String) value; + if (!s.startsWith("=")) { + return s; + } + String addition = s.substring(1); + int indexOfPlus = addition.indexOf('+'); + String operand1 = addition.substring(0, indexOfPlus); + double value1 = eval(operand1); + String operand2 = addition.substring(indexOfPlus + 1); + double value2 = eval(operand2); + return NumberFormat.getNumberInstance().format(value1 + value2); + } catch (Exception ex) { + return ex.getMessage(); + } + } + + /** + * @param s + * @return + * @throws ParseException + */ + private double eval(String s) throws ParseException { + if (s.length() == 0) { + return 0; + } + char character = s.charAt(0); + if (Character.isLetter(character)) { + character = Character.toLowerCase(character); + // reference to other cell + int columnIndex = character - 'a'; + int rowIndex = 0; + rowIndex = NumberFormat.getNumberInstance().parse( + s.substring(1)).intValue() - 1; + String value = (String) cellValues[rowIndex][columnIndex] + .getValue(); + return value.length() == 0 ? 0 : NumberFormat + .getNumberInstance().parse(value).doubleValue(); + } + return NumberFormat.getNumberInstance().parse(s).doubleValue(); + } + } + + protected static int counter; + + public static void main(String[] args) { + + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + Shell shell = new Shell(display); + shell.setText("Data Binding Snippet 006"); + + final Table table = new Table(shell, SWT.BORDER | SWT.MULTI + | SWT.FULL_SELECTION | SWT.VIRTUAL); + table.setLinesVisible(true); + table.setHeaderVisible(true); + + for (int i = 0; i < NUM_COLUMNS; i++) { + TableColumn tableColumn = new TableColumn(table, SWT.NONE); + tableColumn.setText(Character.toString((char) ('A' + i))); + tableColumn.setWidth(60); + } + WritableList list = new WritableList(); + for (int i = 0; i < NUM_ROWS; i++) { + list.add(new Object()); + for (int j = 0; j < NUM_COLUMNS; j++) { + cellFormulas[i][j] = new WritableValue(); + cellValues[i][j] = new ComputedCellValue( + cellFormulas[i][j]); + if (!FUNKY_FORMULAS || i == 0 || j == 0) { + cellFormulas[i][j].setValue(""); + } else { + cellFormulas[i][j].setValue("=" + + cellReference(i - 1, j) + "+" + + cellReference(i, j - 1)); + } + } + } + + new TableUpdater(table, list) { + protected void updateItem(int rowIndex, TableItem item, Object element) { + if (DEBUG_LEVEL >= 1) { + System.out.println("updating row " + rowIndex); + } + for (int j = 0; j < NUM_COLUMNS; j++) { + item.setText(j, (String) cellValues[rowIndex][j] + .getValue()); + } + } + }; + + if (FUNKY_COUNTER) { + // counter in A1 + display.asyncExec(new Runnable() { + public void run() { + cellFormulas[0][1].setValue("" + counter++); + display.timerExec(COUNTER_UPDATE_DELAY, this); + } + }); + } + + // create a TableCursor to navigate around the table + final TableCursor cursor = new TableCursor(table, SWT.NONE); + // create an editor to edit the cell when the user hits "ENTER" + // while over a cell in the table + final ControlEditor editor = new ControlEditor(cursor); + editor.grabHorizontal = true; + editor.grabVertical = true; + + cursor.addSelectionListener(new SelectionAdapter() { + // when the TableEditor is over a cell, select the + // corresponding row + // in + // the table + public void widgetSelected(SelectionEvent e) { + table.setSelection(new TableItem[] { cursor.getRow() }); + } + + // when the user hits "ENTER" in the TableCursor, pop up a + // text + // editor so that + // they can change the text of the cell + public void widgetDefaultSelected(SelectionEvent e) { + final Text text = new Text(cursor, SWT.NONE); + TableItem row = cursor.getRow(); + int rowIndex = table.indexOf(row); + int columnIndex = cursor.getColumn(); + text + .setText((String) cellFormulas[rowIndex][columnIndex] + .getValue()); + text.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + // close the text editor and copy the data over + // when the user hits "ENTER" + if (e.character == SWT.CR) { + TableItem row = cursor.getRow(); + int rowIndex = table.indexOf(row); + int columnIndex = cursor.getColumn(); + cellFormulas[rowIndex][columnIndex] + .setValue(text.getText()); + text.dispose(); + } + // close the text editor when the user hits + // "ESC" + if (e.character == SWT.ESC) { + text.dispose(); + } + } + }); + editor.setEditor(text); + text.setFocus(); + } + }); + // Hide the TableCursor when the user hits the "MOD1" or "MOD2" + // key. + // This alows the user to select multiple items in the table. + cursor.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.MOD1 || e.keyCode == SWT.MOD2 + || (e.stateMask & SWT.MOD1) != 0 + || (e.stateMask & SWT.MOD2) != 0) { + cursor.setVisible(false); + } + } + }); + // Show the TableCursor when the user releases the "MOD2" or + // "MOD1" key. + // This signals the end of the multiple selection task. + table.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + if (e.keyCode == SWT.MOD1 + && (e.stateMask & SWT.MOD2) != 0) + return; + if (e.keyCode == SWT.MOD2 + && (e.stateMask & SWT.MOD1) != 0) + return; + if (e.keyCode != SWT.MOD1 + && (e.stateMask & SWT.MOD1) != 0) + return; + if (e.keyCode != SWT.MOD2 + && (e.stateMask & SWT.MOD2) != 0) + return; + + TableItem[] selection = table.getSelection(); + TableItem row = (selection.length == 0) ? table + .getItem(table.getTopIndex()) : selection[0]; + table.showItem(row); + cursor.setSelection(row, 0); + cursor.setVisible(true); + cursor.setFocus(); + } + }); + + GridLayoutFactory.fillDefaults().generateLayout(shell); + shell.setSize(400, 300); + shell.open(); + + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + display.dispose(); + } + + private static String cellReference(int rowIndex, int columnIndex) { + String cellReference = "" + ((char) ('A' + columnIndex)) + + (rowIndex + 1); + return cellReference; + } + +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet007ColorLabelProvider.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet007ColorLabelProvider.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2006 Brad Reynolds 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: + * Brad Reynolds - initial API and implementation + * IBM Corporation - see bug 137934 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.Observables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.map.IObservableMap; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; +import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITableColorProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +/** + * An example showing how to create a {@link ILabelProvider label provider} that + * to provide colors. + * + * @since 3.2 + */ +public class Snippet007ColorLabelProvider { + /** + * @param args + */ + public static void main(String[] args) { + final List persons = new ArrayList(); + persons.add(new Person("Fiona Apple", Person.FEMALE)); + persons.add(new Person("Elliot Smith", Person.MALE)); + persons.add(new Person("Diana Krall", Person.FEMALE)); + persons.add(new Person("David Gilmour", Person.MALE)); + + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + Shell shell = new Shell(display); + shell.setText("Gender Bender"); + shell.setLayout(new GridLayout()); + + Table table = new Table(shell, SWT.SINGLE | SWT.H_SCROLL + | SWT.V_SCROLL | SWT.BORDER); + GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); + table.setLayoutData(gridData); + table.setHeaderVisible(true); + table.setLinesVisible(true); + TableColumn column = new TableColumn(table, SWT.NONE); + column.setText("No"); + column.setWidth(20); + column = new TableColumn(table, SWT.NONE); + column.setText("Name"); + column.setWidth(100); + final TableViewer viewer = new TableViewer(table); + + IObservableList observableList = Observables + .staticObservableList(persons); + ObservableListContentProvider contentProvider = new ObservableListContentProvider(); + + viewer.setContentProvider(contentProvider); + + // this does not have to correspond to the columns in the table, + // we just list all attributes that affect the table content. + IObservableMap[] attributes = BeansObservables.observeMaps( + contentProvider.getKnownElements(), Person.class, + new String[] { "name", "gender" }); + + class ColorLabelProvider extends ObservableMapLabelProvider + implements ITableColorProvider { + Color male = display.getSystemColor(SWT.COLOR_BLUE); + + Color female = new Color(display, 255, 192, 203); + + ColorLabelProvider(IObservableMap[] attributes) { + super(attributes); + } + + // to drive home the point that attributes does not have to + // match + // the columns + // in the table, we change the column text as follows: + public String getColumnText(Object element, int index) { + if (index == 0) { + return Integer + .toString(persons.indexOf(element) + 1); + } + return ((Person) element).getName(); + } + + public Color getBackground(Object element, int index) { + return null; + } + + public Color getForeground(Object element, int index) { + if (index == 0) + return null; + Person person = (Person) element; + return (person.getGender() == Person.MALE) ? male + : female; + } + + public void dispose() { + super.dispose(); + female.dispose(); + } + } + viewer.setLabelProvider(new ColorLabelProvider(attributes)); + + viewer.setInput(observableList); + + table.getColumn(0).pack(); + + Button button = new Button(shell, SWT.PUSH); + button.setText("Toggle Gender"); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent arg0) { + StructuredSelection selection = (StructuredSelection) viewer + .getSelection(); + if (selection != null && !selection.isEmpty()) { + Person person = (Person) selection + .getFirstElement(); + person + .setGender((person.getGender() == Person.MALE) ? Person.FEMALE + : Person.MALE); + } + } + }); + + shell.setSize(300, 400); + shell.open(); + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + }); + display.dispose(); + } + + static class Person { + static final int MALE = 0; + + static final int FEMALE = 1; + + private String name; + + private int gender; + + private PropertyChangeSupport changeSupport = new PropertyChangeSupport( + this); + + Person(String name, int gender) { + this.name = name; + this.gender = gender; + } + + /** + * Returns the name. Method declared public to satisfy Java bean + * conventions + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param listener + */ + public void addPropertyChangeListener(PropertyChangeListener listener) { + changeSupport.addPropertyChangeListener(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + changeSupport.removePropertyChangeListener(listener); + } + + /** + * Returns the gender. Method declared public to satisfy Java bean + * conventions + * + * @return the gender + */ + public int getGender() { + return gender; + } + + void setGender(int gender) { + changeSupport.firePropertyChange("gender", this.gender, + this.gender = gender); + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet008ComputedValue.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet008ComputedValue.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2006 Brad Reynolds 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: + * Brad Reynolds - initial API and implementation + * Matthew Hall - bug 260329 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.observable.ObservableTracker; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.ComputedValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * Snippet that demostrates a simple use case using ComputedValue to format a + * name as the user enters first and last name. + * + * @since 3.2 + */ +public class Snippet008ComputedValue { + /** + * @param args + */ + public static void main(String[] args) { + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + Shell shell = new Shell(display); + shell.setLayout(new FillLayout()); + + final UI ui = new UI(shell); + final Data data = new Data(); + + // Bind the UI to the Data. + DataBindingContext dbc = new DataBindingContext(); + dbc.bindValue(SWTObservables.observeText(ui.firstName, + SWT.Modify), data.firstName); + dbc.bindValue(SWTObservables.observeText(ui.lastName, + SWT.Modify), data.lastName); + + // Construct the formatted name observable. + FormattedName formattedName = new FormattedName(data.firstName, + data.lastName); + + // Bind the formatted name Text to the formatted name + // observable. + dbc.bindValue(SWTObservables.observeText(ui.formattedName, + SWT.None), formattedName, new UpdateValueStrategy(false, UpdateValueStrategy.POLICY_NEVER), null); + + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + }); + display.dispose(); + } + + /** + * Creates the formatted name on change of the first or last name + * observables. + *

+ * The key to understanding ComputedValue is understanding that it knows of + * the observables that are queried without being told. This is done with + * {@link ObservableTracker} voodoo. When calculate() is invoked + * ObservableTracker records the observables that are + * queried. It then exposes those observables and ComputedValue + * can listen to changes in those objects and react accordingly. + *

+ * + * @since 3.2 + */ + static class FormattedName extends ComputedValue { + private IObservableValue firstName; + + private IObservableValue lastName; + + FormattedName(IObservableValue firstName, IObservableValue lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + protected Object calculate() { + String lastName = (String) this.lastName.getValue(); + String firstName = (String) this.firstName.getValue(); + lastName = (lastName != null && lastName.length() > 0) ? lastName + : "[Last Name]"; + firstName = (firstName != null && firstName.length() > 0) ? firstName + : "[First Name]"; + + StringBuffer buffer = new StringBuffer(); + buffer.append(lastName).append(", ").append(firstName); + + return buffer.toString(); + } + } + + static class Data { + final WritableValue firstName; + + final WritableValue lastName; + + Data() { + firstName = new WritableValue("", String.class); + lastName = new WritableValue("", String.class); + } + } + + /** + * Composite that creates the UI. + * + * @since 3.2 + */ + static class UI extends Composite { + final Text firstName; + + final Text lastName; + + final Text formattedName; + + UI(Composite parent) { + super(parent, SWT.NONE); + + GridLayoutFactory.swtDefaults().numColumns(2).applyTo(this); + + new Label(this, SWT.NONE).setText("First Name:"); + new Label(this, SWT.NONE).setText("Last Name"); + + GridDataFactory gdf = GridDataFactory.swtDefaults().align(SWT.FILL, + SWT.FILL).grab(true, false); + firstName = new Text(this, SWT.BORDER); + gdf.applyTo(firstName); + + lastName = new Text(this, SWT.BORDER); + gdf.applyTo(lastName); + + gdf = GridDataFactory.swtDefaults().span(2, 1).grab(true, false) + .align(SWT.FILL, SWT.BEGINNING); + Label label = new Label(this, SWT.NONE); + label.setText("Formatted Name:"); + gdf.applyTo(label); + + formattedName = new Text(this, SWT.BORDER); + formattedName.setEditable(false); + gdf.applyTo(formattedName); + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet009TableViewer.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet009TableViewer.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2006 The Pampered Chef, Inc. 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: + * Coconut Palm Software, Inc. - Initial API and implementation + * Matthew Hall - bug 260337 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.WritableList; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ViewerSupport; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +/** + * Demonstrates binding a TableViewer to a collection. + */ +public class Snippet009TableViewer { + public static void main(String[] args) { + final Display display = Display.getDefault(); + + // In an RCP application, the threading Realm will be set for you + // automatically by the Workbench. In an SWT application, you can do + // this once, wrpping your binding method call. + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + + ViewModel viewModel = new ViewModel(); + Shell shell = new View(viewModel).createShell(); + + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + } + + // 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); + } + } + + // The data model class. This is normally a persistent class of some sort. + static class Person extends AbstractModelObject { + // A property... + String name = "John Smith"; + + public Person(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + String oldValue = this.name; + this.name = name; + firePropertyChange("name", oldValue, name); + } + } + + // The View's model--the root of our Model graph for this particular GUI. + // + // Typically each View class has a corresponding ViewModel class. + // The ViewModel is responsible for getting the objects to edit from the + // 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 List people = new LinkedList(); + { + people.add(new Person("Steve Northover")); + people.add(new Person("Grant Gayed")); + people.add(new Person("Veronika Irvine")); + people.add(new Person("Mike Wilson")); + people.add(new Person("Christophe Cornu")); + people.add(new Person("Lynne Kues")); + people.add(new Person("Silenio Quarti")); + } + + public List getPeople() { + return people; + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + private Table committers; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + Display display = Display.getDefault(); + Shell shell = new Shell(display); + shell.setLayout(new FillLayout()); + committers = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION); + committers.setLinesVisible(true); + TableColumn column = new TableColumn(committers, SWT.NONE); + + // Set up data binding. + TableViewer peopleViewer = new TableViewer(committers); + ViewerSupport.bind(peopleViewer, new WritableList(viewModel + .getPeople(), Person.class), BeanProperties.value( + Person.class, "name")); + + column.pack(); + + // Open and return the Shell + shell.setSize(100, 300); + shell.open(); + return shell; + } + } + +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet010MasterDetail.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet010MasterDetail.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2007 Brad Reynolds 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: + * Brad Reynolds - initial API and implementation + * Matthew Hall - bug 260329 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ListViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * Snippet that displays a simple master detail use case. A list of persons is + * displayed in a list and upon selection the name of the selected person will + * be displayed in a Text widget. + */ +public class Snippet010MasterDetail { + public static void main(String[] args) { + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + Shell shell = new Shell(display); + shell.setLayout(new GridLayout()); + + Person[] persons = new Person[] { new Person("Me"), + new Person("Myself"), new Person("I") }; + + ListViewer viewer = new ListViewer(shell); + viewer.setContentProvider(new ArrayContentProvider()); + viewer.setInput(persons); + + Text name = new Text(shell, SWT.BORDER | SWT.READ_ONLY); + + // 1. Observe changes in selection. + IObservableValue selection = ViewersObservables + .observeSingleSelection(viewer); + + // 2. Observe the name property of the current selection. + IObservableValue detailObservable = BeansObservables + .observeDetailValue(selection, "name", String.class); + + // 3. Bind the Text widget to the name detail (selection's + // name). + new DataBindingContext().bindValue(SWTObservables.observeText( + name, SWT.None), detailObservable, + new UpdateValueStrategy(false, + UpdateValueStrategy.POLICY_NEVER), null); + + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + }); + display.dispose(); + } + + public static class Person { + private String name; + private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this); + + Person(String name) { + this.name = name; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + changeSupport.addPropertyChangeListener(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + changeSupport.removePropertyChangeListener(listener); + } + + /** + * @return Returns the name. + */ + public String getName() { + return name; + } + + public String toString() { + return name; + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet011ValidateMultipleBindingsSnippet.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet011ValidateMultipleBindingsSnippet.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,129 @@ + /******************************************************************************* + * Copyright (c) 2007 Brad Reynolds 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: + * Brad Reynolds - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.IValueChangeListener; +import org.eclipse.core.databinding.observable.value.ValueChangeEvent; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * Snippet that validates values across multiple bindings on change of each + * observable. If the values of the target observables are not equal the model + * is not updated. When the values are equal they will be written to sysout. + * + * @author Brad Reynolds + */ +public class Snippet011ValidateMultipleBindingsSnippet { + public static void main(String[] args) { + Realm.runWithDefault(SWTObservables.getRealm(Display.getDefault()), + new Runnable() { + public void run() { + Snippet011ValidateMultipleBindingsSnippet.run(); + } + }); + } + + private static void run() { + Shell shell = new Shell(); + + View view = new View(shell); + final Model model = new Model(); + + DataBindingContext dbc = new DataBindingContext(); + dbc.bindValue(SWTObservables.observeText(view.text1, SWT.Modify), + model.value1, new UpdateValueStrategy() + .setAfterConvertValidator(new CrossFieldValidator( + model.value2)), null); + dbc.bindValue(SWTObservables.observeText(view.text2, SWT.Modify), + model.value2, new UpdateValueStrategy() + .setAfterConvertValidator(new CrossFieldValidator( + model.value1)), null); + + // DEBUG - print to show value change + model.value1.addValueChangeListener(new IValueChangeListener() { + public void handleValueChange(ValueChangeEvent event) { + System.out.println("Value 1: " + model.value1.getValue()); + } + }); + + // DEBUG - print to show value change + model.value2.addValueChangeListener(new IValueChangeListener() { + public void handleValueChange(ValueChangeEvent event) { + System.out.println("Value 2: " + model.value2.getValue()); + } + }); + + shell.pack(); + shell.open(); + Display display = shell.getDisplay(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + } + + /** + * @since 3.2 + * + */ + private static final class CrossFieldValidator implements IValidator { + /** + * + */ + private final IObservableValue other; + + /** + * @param model + */ + private CrossFieldValidator(IObservableValue other) { + this.other = other; + } + + public IStatus validate(Object value) { + if (!value.equals(other.getValue())) { + return ValidationStatus.ok(); + } + return ValidationStatus.error("values cannot be the same"); + } + } + + static class Model { + WritableValue value1 = new WritableValue(); + WritableValue value2 = new WritableValue(); + } + + static class View { + Text text1; + Text text2; + + View(Composite composite) { + composite.setLayout(new GridLayout(2, true)); + text1 = new Text(composite, SWT.BORDER); + text2 = new Text(composite, SWT.BORDER); + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet012CompositeUpdater.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet012CompositeUpdater.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2007 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.jface.examples.databinding.snippets; + +import java.util.Timer; +import java.util.TimerTask; + +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.WritableList; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.internal.databinding.provisional.swt.CompositeUpdater; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Widget; + +/** + * @since 3.2 + * + */ +public class Snippet012CompositeUpdater { + + public static void main(String[] args) { + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + Shell shell = new Shell(display); + + final WritableList list = new WritableList(); + + Button button = new Button(shell, SWT.PUSH); + button.setText("add"); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected( + org.eclipse.swt.events.SelectionEvent e) { + list.add(0, new Counter()); + } + }); + + final Composite composite = new Composite(shell, SWT.None); + + new CompositeUpdater(composite, list) { + protected Widget createWidget(int index) { + Label label = new Label(composite, SWT.BORDER); + //requestLayout(label); + return label; + } + + protected void updateWidget(Widget widget, Object element) { + ((Label) widget).setText(((Counter) element).getValue() + + ""); + requestLayout((Label)widget); + } + }; + GridLayoutFactory.fillDefaults().numColumns(10).generateLayout(composite); + + GridDataFactory.fillDefaults().grab(true, true).applyTo( + composite); + + GridLayoutFactory.fillDefaults().generateLayout(shell); + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + }); + display.dispose(); + } + + static Timer timer = new Timer(true); + + static class Counter extends WritableValue { + Counter() { + super(new Integer(0), Integer.class); + scheduleIncrementTask(); + } + + private void scheduleIncrementTask() { + timer.schedule(new TimerTask() { + public void run() { + // we have to get onto the realm (UI thread) to perform the + // increment + getRealm().asyncExec(new Runnable() { + public void run() { + Integer currentVal = (Integer) getValue(); + setValue(new Integer(currentVal.intValue() + 1)); + } + }); + scheduleIncrementTask(); + } + }, 1000); + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet013TableViewerEditing.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet013TableViewerEditing.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,236 @@ +/******************************************************************************* + * Copyright (c) 2006 The Pampered Chef, Inc. 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: + * The Pampered Chef, Inc. - initial API and implementation + * Tom Schindl - cell editing + * Matthew Hall - bugs 260329, 260337 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.WritableList; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ObservableValueEditingSupport; +import org.eclipse.jface.databinding.viewers.ViewerSupport; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.ViewerCell; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; + +/** + * Demonstrates binding a TableViewer to a collection using the 3.3 Viewer APIs. + */ +public class Snippet013TableViewerEditing { + public static void main(String[] args) { + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + ViewModel viewModel = new ViewModel(); + Shell shell = new View(viewModel).createShell(); + + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + } + + // 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); + } + } + + // The data model class. This is normally a persistent class of some sort. + static class Person extends AbstractModelObject { + // A property... + String name = "John Smith"; + + public Person(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + String oldValue = this.name; + this.name = name; + firePropertyChange("name", oldValue, name); + } + } + + // The View's model--the root of our Model graph for this particular GUI. + // + // Typically each View class has a corresponding ViewModel class. + // The ViewModel is responsible for getting the objects to edit from the + // 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 List people = new LinkedList(); + { + people.add(new Person("Steve Northover")); + people.add(new Person("Grant Gayed")); + people.add(new Person("Veronika Irvine")); + people.add(new Person("Mike Wilson")); + people.add(new Person("Christophe Cornu")); + people.add(new Person("Lynne Kues")); + people.add(new Person("Silenio Quarti")); + } + + public List getPeople() { + return people; + } + } + + /** + * Editing support that uses JFace Data Binding to control the editing + * lifecycle. The standard EditingSupport get/setValue(...) lifecycle is not + * used. + * + * @since 3.3 + */ + private static class InlineEditingSupport extends + ObservableValueEditingSupport { + private CellEditor cellEditor; + + /** + * @param viewer + * @param dbc + */ + public InlineEditingSupport(ColumnViewer viewer, DataBindingContext dbc) { + + super(viewer, dbc); + cellEditor = new TextCellEditor((Composite) viewer.getControl()); + } + + protected CellEditor getCellEditor(Object element) { + return cellEditor; + } + + protected IObservableValue doCreateCellEditorObservable( + CellEditor cellEditor) { + + return SWTObservables.observeText(cellEditor.getControl(), + SWT.Modify); + } + + protected IObservableValue doCreateElementObservable(Object element, + ViewerCell cell) { + return BeansObservables.observeValue(element, "name"); + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + private Table committers; + private Label selectedCommitter; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + Display display = Display.getDefault(); + Shell shell = new Shell(display); + shell.setLayout(new FillLayout(SWT.VERTICAL)); + committers = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION); + committers.setLinesVisible(true); + + selectedCommitter = new Label(shell, SWT.NONE); + // Set up data binding. In an RCP application, the threading + // Realm + // will be set for you automatically by the Workbench. In an SWT + // application, you can do this once, wrpping your binding + // method call. + DataBindingContext bindingContext = new DataBindingContext(); + bindGUI(bindingContext); + + // Open and return the Shell + shell.setSize(100, 300); + shell.open(); + return shell; + } + + protected void bindGUI(DataBindingContext bindingContext) { + // Since we're using a JFace Viewer, we do first wrap our Table... + TableViewer peopleViewer = new TableViewer(committers); + TableViewerColumn column = new TableViewerColumn(peopleViewer, + SWT.NONE); + column.setEditingSupport(new InlineEditingSupport(peopleViewer, + bindingContext)); + column.getColumn().setWidth(100); + + // Bind viewer to model + ViewerSupport.bind(peopleViewer, new WritableList(viewModel + .getPeople(), Person.class), BeanProperties.value( + Person.class, "name")); + + // bind selectedCommitter label to the name of the current selection + IObservableValue selection = ViewersObservables + .observeSingleSelection(peopleViewer); + bindingContext.bindValue(SWTObservables + .observeText(selectedCommitter), BeansObservables + .observeDetailValue(selection, "name", String.class)); + } + } + +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet014WizardDialog.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet014WizardDialog.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2007 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: + * Boris Bokowski, IBM Corporation - initial API and implementation + * Matthew Hall - bug 260329 + *******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.util.Date; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.wizard.WizardPageSupport; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.wizard.IWizard; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * Creates and opens a wizard dialog with two simple wizard pages. + */ +public class Snippet014WizardDialog { + + static class FirstWizardPage extends WizardPage { + private final class SingleDigitValidator implements IValidator { + public IStatus validate(Object value) { + Integer i = (Integer) value; + if (i == null) { + return ValidationStatus + .info("Please enter a value."); + } + if (i.intValue() < 0 || i.intValue() > 9) { + return ValidationStatus + .error("Value must be between 0 and 9."); + } + return ValidationStatus.ok(); + } + } + + protected FirstWizardPage() { + super("First", "First Page", ImageDescriptor + .createFromImage(new Image(Display.getDefault(), 16, 16))); + } + + public void createControl(Composite parent) { + DataBindingContext dbc = new DataBindingContext(); + WizardPageSupport.create(this, dbc); + Composite composite = new Composite(parent, SWT.NONE); + Label label = new Label(composite, SWT.NONE); + label.setText("Enter a number between 0 and 9:"); + Text text = new Text(composite, SWT.BORDER); + + dbc.bindValue( + SWTObservables.observeText(text, SWT.Modify), + ((SampleWizard) getWizard()).getModel().intValue, + new UpdateValueStrategy().setAfterConvertValidator(new SingleDigitValidator()), + null); + + GridLayoutFactory.swtDefaults().numColumns(2).generateLayout( + composite); + setControl(composite); + } + } + + static class SecondWizardPage extends WizardPage { + protected SecondWizardPage() { + super("Second", "Second Page", ImageDescriptor + .createFromImage(new Image(Display.getDefault(), 16, 16))); + } + + public void createControl(Composite parent) { + DataBindingContext dbc = new DataBindingContext(); + WizardPageSupport.create(this, dbc); + Composite composite = new Composite(parent, SWT.NONE); + Label label = new Label(composite, SWT.NONE); + label.setText("Enter a date:"); + Text text = new Text(composite, SWT.BORDER); + + dbc.bindValue( + SWTObservables.observeText(text, SWT.Modify), + ((SampleWizard) getWizard()).getModel().dateValue); + + GridLayoutFactory.swtDefaults().numColumns(2).generateLayout( + composite); + setControl(composite); + } + } + + static class SampleWizardModel { + IObservableValue intValue = new WritableValue(null, Integer.class); + IObservableValue dateValue = new WritableValue(null, Date.class); + } + + static class SampleWizard extends Wizard { + + private SampleWizardModel model = new SampleWizardModel(); + + public void addPages() { + addPage(new FirstWizardPage()); + addPage(new SecondWizardPage()); + } + + public SampleWizardModel getModel() { + return model; + } + + public String getWindowTitle() { + return "Data Binding Snippet014"; + } + + public boolean performFinish() { + return true; + } + + } + + public static void main(String[] args) { + Display display = new Display(); + + // note that the "runWithDefault" will be done for you if you are using + // the + // Workbench as opposed to just JFace/SWT. + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + IWizard wizard = new SampleWizard(); + WizardDialog dialog = new WizardDialog(null, wizard); + dialog.open(); + // The SWT event loop + Display display = Display.getCurrent(); + while (dialog.getShell() != null + && !dialog.getShell().isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + } + +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet015DelayTextModifyEvents.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet015DelayTextModifyEvents.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,119 @@ +/************************************************************************************************************ + * Copyright (c) 2007 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 180746) + * Boris Bokowski, IBM - initial API and implementation + * Matthew Hall - bugs 260329, 264286 + ***********************************************************************************************************/ +package org.eclipse.jface.examples.databinding.snippets; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.observable.Observables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.databinding.swt.ISWTObservableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.internal.databinding.provisional.swt.ControlUpdater; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.resource.FontDescriptor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.resource.ResourceManager; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +public class Snippet015DelayTextModifyEvents { + + private static void createControls(Shell shell) { + final Label field1 = createLabel(shell, SWT.NONE, "Field 1 "); + + Text text1 = new Text(shell, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, false).hint(200, SWT.DEFAULT) + .applyTo(text1); + createLabel(shell, SWT.NONE, "200ms delay"); + + final Label field2 = createLabel(shell, SWT.NONE, "Field 2 "); + + Text text2 = new Text(shell, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, false).hint(200, SWT.DEFAULT) + .applyTo(text2); + + createLabel(shell, SWT.NONE, "1000ms delay"); + + final ISWTObservableValue delayed1 = WidgetProperties.text(SWT.Modify) + .observeDelayed(200, text1); + final ISWTObservableValue delayed2 = WidgetProperties.text(SWT.Modify) + .observeDelayed(1000, text2); + + // (In a real application,you would want to dispose the resource manager + // when you are done with it) + ResourceManager resourceManager = new LocalResourceManager( + JFaceResources.getResources()); + final Font shellFont = shell.getFont(); + final Font italicFont = resourceManager.createFont(FontDescriptor + .createFrom(shellFont).setStyle(SWT.ITALIC)); + + final IObservableValue stale1 = Observables.observeStale(delayed1); + new ControlUpdater(field2) { + protected void updateControl() { + boolean stale = ((Boolean) stale1.getValue()).booleanValue(); + field2.setFont(stale ? italicFont : shellFont); + } + }; + + final IObservableValue stale2 = Observables.observeStale(delayed2); + new ControlUpdater(field1) { + protected void updateControl() { + boolean stale = ((Boolean) stale2.getValue()).booleanValue(); + field1.setFont(stale ? italicFont : shellFont); + } + }; + + String info = "Pending changes are applied immediately if the observed control loses focus"; + GridDataFactory.fillDefaults().span(3, 1).applyTo( + createLabel(shell, SWT.WRAP, info)); + + DataBindingContext dbc = new DataBindingContext(); + + dbc.bindValue(delayed1, delayed2); + } + + private static Label createLabel(Composite parent, int style, String text) { + Label label = new Label(parent, style); + label.setText(text); + return label; + } + + public static void main(String[] args) { + final Display display = new Display(); + + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + Shell shell = new Shell(); + shell.setLayout(new GridLayout(3, false)); + + createControls(shell); + + shell.pack(); + shell.open(); + while (!shell.isDisposed()) + if (!display.readAndDispatch()) + display.sleep(); + } + + }); + + display.dispose(); + } + +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet016TableUpdater.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet016TableUpdater.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2007 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.jface.examples.databinding.snippets; + +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.WritableList; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.internal.databinding.provisional.swt.TableUpdater; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; + +/** + * @since 3.2 + * + */ +public class Snippet016TableUpdater { + public static void main(String[] args) { + final Display display = new Display(); + + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + final Shell shell = createShell(display); + GridLayoutFactory.fillDefaults().generateLayout(shell); + shell.open(); + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + } + + static class Stuff { + private WritableValue counter = new WritableValue(new Integer(1), Integer.class); + + public Stuff(final Display display) { + display.timerExec(1000, new Runnable() { + public void run() { + counter.setValue(new Integer(1 + ((Integer) counter + .getValue()).intValue())); + display.timerExec(1000, this); + } + }); + } + + public String toString() { + return counter.getValue().toString(); + } + } + + protected static Shell createShell(final Display display) { + Shell shell = new Shell(); + Table t = new Table(shell, SWT.VIRTUAL); + final WritableList list = new WritableList(); + new TableUpdater(t, list) { + + protected void updateItem(int index, TableItem item, Object element) { + item.setText(element.toString()); + } + }; + display.timerExec(2000, new Runnable() { + public void run() { + list.add(new Stuff(display)); + display.timerExec(2000, this); + } + }); + return shell; + } + +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet017TableViewerWithDerivedColumns.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet017TableViewerWithDerivedColumns.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (c) 2006 The Pampered Chef, Inc. 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: + * Coconut Palm Software, Inc. - Initial API and implementation + * Matthew Hall - bugs 260329, 260337 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.beans.BeansObservables; +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.IObservableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ViewerSupport; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Combo; +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; + +/** + * Demonstrates binding a TableViewer to a collection. + */ +public class Snippet017TableViewerWithDerivedColumns { + public static void main(String[] args) { + final Display display = new Display(); + + // Set up data binding. In an RCP application, the threading Realm + // will be set for you automatically by the Workbench. In an SWT + // application, you can do this once, wrapping your binding + // method call. + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + ViewModel viewModel = new ViewModel(); + Shell shell = new View(viewModel).createShell(); + + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + } + + // 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); + } + } + + private static Person UNKNOWN = new Person("unknown", null, null); + + // The data model class. This is normally a persistent class of some sort. + static class Person extends AbstractModelObject { + // A property... + String name = "Donald Duck"; + Person mother; + Person father; + + public Person(String name, Person mother, Person father) { + this.name = name; + this.mother = mother; + this.father = father; + } + + public String getName() { + return name; + } + + public void setName(String name) { + String oldValue = this.name; + this.name = name; + firePropertyChange("name", oldValue, name); + } + + public Person getMother() { + return mother; + } + + public void setMother(Person mother) { + firePropertyChange("mother", this.mother, this.mother = mother); + } + + public Person getFather() { + return father; + } + + public void setFather(Person father) { + firePropertyChange("father", this.father, this.father = father); + } + + public String toString() { + return name; + } + } + + // The View's model--the root of our Model graph for this particular GUI. + // + // Typically each View class has a corresponding ViewModel class. + // The ViewModel is responsible for getting the objects to edit from the + // 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(); + { + Person fergus = new Person("Fergus McDuck", UNKNOWN, UNKNOWN); + Person downy = new Person("Downy O'Drake", UNKNOWN, UNKNOWN); + Person scrooge = new Person("Scrooge McDuck", downy, fergus); + Person hortense = new Person("Hortense McDuck", downy, fergus); + Person quackmore = new Person("Quackmore Duck", UNKNOWN, UNKNOWN); + Person della = new Person("Della Duck", hortense, quackmore); + Person donald = new Person("Donald Duck", hortense, quackmore); + donald.setFather(quackmore); + donald.setMother(hortense); + della.setFather(quackmore); + della.setMother(hortense); + hortense.setMother(downy); + hortense.setFather(fergus); + scrooge.setMother(downy); + scrooge.setFather(fergus); + people.add(UNKNOWN); + people.add(downy); + people.add(fergus); + people.add(scrooge); + people.add(quackmore); + people.add(hortense); + people.add(della); + people.add(donald); + } + + public IObservableList getPeople() { + return people; + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + private Table duckFamily; + private Text nameText; + private Combo motherCombo; + private Combo fatherCombo; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + Display display = Display.getDefault(); + Shell shell = new Shell(display); + duckFamily = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION); + duckFamily.setHeaderVisible(true); + GridDataFactory.defaultsFor(duckFamily).span(2, 1).applyTo( + duckFamily); + createColumn("Name"); + createColumn("Mother"); + createColumn("Father"); + createColumn("Grandmother"); + duckFamily.setLinesVisible(true); + + new Label(shell, SWT.NONE).setText("Name:"); + nameText = new Text(shell, SWT.BORDER); + GridDataFactory.defaultsFor(nameText).grab(true, false).applyTo( + nameText); + + new Label(shell, SWT.NONE).setText("Mother:"); + motherCombo = new Combo(shell, SWT.READ_ONLY); + + new Label(shell, SWT.NONE).setText("Father:"); + fatherCombo = new Combo(shell, SWT.READ_ONLY); + + DataBindingContext bindingContext = new DataBindingContext(); + bindGUI(bindingContext); + + GridLayoutFactory.swtDefaults().numColumns(2).applyTo(shell); + // Open and return the Shell + shell.setSize(500, 300); + shell.open(); + return shell; + } + + private void createColumn(String string) { + final TableColumn column = new TableColumn(duckFamily, SWT.NONE); + column.setWidth(100); + column.setText(string); + } + + protected void bindGUI(DataBindingContext bindingContext) { + // Since we're using a JFace Viewer, we do first wrap our Table... + TableViewer peopleViewer = new TableViewer(duckFamily); + peopleViewer.addFilter(new ViewerFilter() { + public boolean select(Viewer viewer, Object parentElement, + Object element) { + return element != UNKNOWN; + } + }); + + // Bind viewers to model + ViewerSupport.bind(peopleViewer, viewModel.getPeople(), + BeanProperties.values(new String[] { "name", "mother.name", + "father.name", "mother.mother.name" })); + + // Bind viewer selection to detail fields + IObservableValue selection = ViewersObservables + .observeSingleSelection(peopleViewer); + bindingContext.bindValue(SWTObservables.observeText(nameText, + SWT.Modify), BeansObservables.observeDetailValue(selection, + "name", String.class)); + + ComboViewer mothercomboViewer = new ComboViewer(motherCombo); + ViewerSupport.bind(mothercomboViewer, viewModel.getPeople(), + BeanProperties.value("name")); + bindingContext.bindValue(ViewersObservables + .observeSingleSelection(mothercomboViewer), + BeansObservables.observeDetailValue(selection, "mother", + Person.class)); + + ComboViewer fatherComboViewer = new ComboViewer(fatherCombo); + ViewerSupport.bind(fatherComboViewer, viewModel.getPeople(), + BeanProperties.value("name")); + bindingContext.bindValue(ViewersObservables + .observeSingleSelection(fatherComboViewer), + BeansObservables.observeDetailValue(selection, "father", + Person.class)); + } + } + +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet018CheckboxTableViewerCheckedSelection.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet018CheckboxTableViewerCheckedSelection.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,362 @@ +/******************************************************************************* + * 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 124684) + * Matthew Hall - bugs 260329, 260337 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.value.ComputedValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ViewerSupport; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; + +/** + * Snippet 018: Binding to the checked elements in a CheckboxTableViewer. + */ +public class Snippet018CheckboxTableViewerCheckedSelection { + public static void main(String[] args) { + // The SWT event loop + final Display display = Display.getDefault(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + ViewModel viewModel = createSampleModel(); + + Shell shell = new View(viewModel).createShell(); + shell.open(); + while (!shell.isDisposed()) + if (!display.readAndDispatch()) + display.sleep(); + } + }); + display.dispose(); + } + + private static ViewModel createSampleModel() { + ViewModel viewModel = new ViewModel(); + + Person stan = createPerson("Stan"); + Person kyle = createPerson("Kyle"); + Person eric = createPerson("Eric"); + Person kenny = createPerson("Kenny"); + Person wendy = createPerson("Wendy"); + Person butters = createPerson("Butters"); + + setFriends(stan, new Person[] { kyle, eric, kenny, wendy }); + setFriends(kyle, new Person[] { stan, eric, kenny }); + setFriends(eric, new Person[] { eric }); + setFriends(kenny, new Person[] { stan, kyle, eric }); + setFriends(wendy, new Person[] { stan }); + setFriends(butters, new Person[0]); + + Person[] people = new Person[] { stan, kyle, eric, kenny, wendy, + butters }; + viewModel.setPeople(Arrays.asList(people)); + return viewModel; + } + + private static Person createPerson(String name) { + Person person = new Person(); + person.setName(name); + return person; + } + + private static void setFriends(Person person, Person[] friends) { + person.setFriends(new HashSet(Arrays.asList(friends))); + } + + // 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); + } + } + + // The data model class. + static class Person extends AbstractModelObject { + private String name; + private Set friends = new HashSet(); + + public String getName() { + return name; + } + + public void setName(String name) { + firePropertyChange("name", this.name, this.name = name); + } + + public Set getFriends() { + return new HashSet(friends); + } + + public void setFriends(Set friends) { + firePropertyChange("friends", this.friends, + this.friends = new HashSet(friends)); + } + + public String toString() { + return name; + } + } + + // The View's model--the root of our Model graph for this particular GUI. + // + // Typically each View class has a corresponding ViewModel class. + // + // The ViewModel is responsible for getting the objects to edit from the + // data access tier. Since this snippet doesn't have any persistent objects + // to retrieve, this ViewModel just instantiates a model object to edit. + static class ViewModel extends AbstractModelObject { + private List people = new ArrayList(); + + public List getPeople() { + return new ArrayList(people); + } + + public void setPeople(List people) { + firePropertyChange("people", this.people, + this.people = new ArrayList(people)); + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + + private Shell shell; + + private Button addPersonButton; + private Button removePersonButton; + private TableViewer peopleViewer; + private Text personName; + private CheckboxTableViewer friendsViewer; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + final Display display = Display.getCurrent(); + shell = new Shell(display); + + createUI(shell); + + // Bind UI + bindUI(); + + // Open and return the Shell + shell.setSize(shell.computeSize(400, SWT.DEFAULT)); + shell.open(); + return shell; + } + + private void createUI(Shell shell) { + shell.setText("Binding checked elements in CheckboxTableViewer"); + shell.setLayout(new GridLayout(2, false)); + + new Label(shell, SWT.NONE).setText("People"); + + Composite buttons = new Composite(shell, SWT.NONE); + GridDataFactory.swtDefaults().align(SWT.RIGHT, SWT.CENTER).applyTo( + buttons); + GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(true) + .applyTo(buttons); + addPersonButton = new Button(buttons, SWT.PUSH); + addPersonButton.setText("Add"); + GridDataFactory.fillDefaults().applyTo(addPersonButton); + removePersonButton = new Button(buttons, SWT.PUSH); + removePersonButton.setText("Remove"); + GridDataFactory.fillDefaults().applyTo(removePersonButton); + + Composite peopleComposite = new Composite(shell, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).span(2, 1).applyTo( + peopleComposite); + TableColumnLayout peopleColumnLayout = new TableColumnLayout(); + peopleComposite.setLayout(peopleColumnLayout); + + peopleViewer = new TableViewer(peopleComposite, SWT.SINGLE + | SWT.BORDER | SWT.FULL_SELECTION); + + Table peopleTable = peopleViewer.getTable(); + peopleTable.setHeaderVisible(true); + peopleTable.setLinesVisible(true); + + TableColumn nameColumn = new TableColumn(peopleTable, SWT.NONE); + nameColumn.setText("Name"); + peopleColumnLayout.setColumnData(nameColumn, + new ColumnWeightData(1)); + + TableColumn friendsColumn = new TableColumn(peopleTable, SWT.NONE); + friendsColumn.setText("Friends"); + peopleColumnLayout.setColumnData(friendsColumn, + new ColumnWeightData(3)); + + new Label(shell, SWT.NONE).setText("Name"); + + personName = new Text(shell, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, false) + .applyTo(personName); + + new Label(shell, SWT.NONE).setText("Friends"); + + Composite friendsComposite = new Composite(shell, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo( + friendsComposite); + TableColumnLayout friendsColumnLayout = new TableColumnLayout(); + friendsComposite.setLayout(friendsColumnLayout); + + friendsViewer = CheckboxTableViewer.newCheckList(friendsComposite, + SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION); + + Table friendsTable = friendsViewer.getTable(); + friendsTable.setHeaderVisible(true); + friendsTable.setLinesVisible(true); + TableColumn friendNameColumn = new TableColumn(friendsTable, + SWT.NONE); + friendNameColumn.setText("Name"); + friendsColumnLayout.setColumnData(friendNameColumn, + new ColumnWeightData(1)); + + GridDataFactory.fillDefaults().grab(true, true).applyTo( + friendsViewer.getTable()); + } + + private void bindUI() { + DataBindingContext dbc = new DataBindingContext(); + + final IObservableList people = BeansObservables.observeList(Realm + .getDefault(), viewModel, "people"); + + addPersonButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + InputDialog dlg = new InputDialog(shell, "Add Person", + "Enter name:", "", new IInputValidator() { + public String isValid(String newText) { + if (newText == null + || newText.length() == 0) + return "Name cannot be empty"; + return null; + } + }); + if (dlg.open() == Window.OK) { + Person person = new Person(); + person.setName(dlg.getValue()); + people.add(person); + peopleViewer.setSelection(new StructuredSelection( + person)); + } + } + }); + + removePersonButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + IStructuredSelection selected = (IStructuredSelection) peopleViewer + .getSelection(); + if (selected.isEmpty()) + return; + Person person = (Person) selected.getFirstElement(); + if (MessageDialog.openConfirm(shell, "Remove person", + "Remove " + person.getName() + "?")) + people.remove(person); + } + }); + + ViewerSupport.bind(peopleViewer, people, BeanProperties.values( + Person.class, new String[] { "name", "friends" })); + + final IObservableValue selectedPerson = ViewersObservables + .observeSingleSelection(peopleViewer); + + IObservableValue personSelected = new ComputedValue(Boolean.TYPE) { + protected Object calculate() { + return Boolean.valueOf(selectedPerson.getValue() != null); + } + }; + dbc.bindValue(SWTObservables.observeEnabled(removePersonButton), + personSelected); + dbc.bindValue(SWTObservables.observeEnabled(friendsViewer + .getTable()), personSelected); + + dbc.bindValue(SWTObservables.observeText(personName, SWT.Modify), + BeansObservables.observeDetailValue(selectedPerson, "name", + String.class)); + + ViewerSupport.bind(friendsViewer, people, BeanProperties.value( + Person.class, "name")); + + dbc.bindSet(ViewersObservables.observeCheckedElements( + friendsViewer, Person.class), BeansObservables + .observeDetailSet(selectedPerson, "friends", Person.class)); + } + } +} \ No newline at end of file diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet019TreeViewerWithListFactory.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet019TreeViewerWithListFactory.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,326 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 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 + * Matthew Hall - bugs 260329, 260337 + *******************************************************************************/ +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.ComputedValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ViewerSupport; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; + +public class Snippet019TreeViewerWithListFactory { + + private Button pasteButton; + private Button copyButton; + private Shell shell; + private Button addChildBeanButton; + private Button removeBeanButton; + private TreeViewer beanViewer; + private Tree tree; + private Text beanText; + private DataBindingContext m_bindingContext; + + private Bean input = createBean("input"); + private IObservableValue clipboard; + + /** + * Launch the application + * + * @param args + */ + public static void main(String[] args) { + Display display = Display.getDefault(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + try { + Snippet019TreeViewerWithListFactory window = new Snippet019TreeViewerWithListFactory(); + window.open(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + /** + * Open the window + */ + public void open() { + final Display display = Display.getDefault(); + createContents(); + shell.open(); + shell.layout(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + + /** + * Create contents of the window + */ + protected void createContents() { + shell = new Shell(); + final GridLayout gridLayout_1 = new GridLayout(); + gridLayout_1.numColumns = 2; + shell.setLayout(gridLayout_1); + shell.setSize(535, 397); + shell.setText("SWT Application"); + + final Composite group = new Composite(shell, SWT.NONE); + final RowLayout rowLayout = new RowLayout(); + rowLayout.marginTop = 0; + rowLayout.marginRight = 0; + rowLayout.marginLeft = 0; + rowLayout.marginBottom = 0; + rowLayout.pack = false; + group.setLayout(rowLayout); + group + .setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, + 2, 1)); + + final Button addRootButton = new Button(group, SWT.NONE); + addRootButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + List list = input.getList(); + Bean root = createBean("root"); + list.add(root); + input.setList(list); + + beanViewer.setSelection(new StructuredSelection(root)); + beanText.selectAll(); + beanText.setFocus(); + } + }); + addRootButton.setText("Add Root"); + + addChildBeanButton = new Button(group, SWT.NONE); + addChildBeanButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + Bean parent = getSelectedBean(); + List list = new ArrayList(parent.getList()); + Bean child = createBean("child"); + list.add(child); + parent.setList(list); + + beanViewer.setSelection(new StructuredSelection(child)); + beanText.selectAll(); + beanText.setFocus(); + } + }); + addChildBeanButton.setText("Add Child"); + + removeBeanButton = new Button(group, SWT.NONE); + removeBeanButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + TreeItem selectedItem = beanViewer.getTree().getSelection()[0]; + TreeItem parentItem = selectedItem.getParentItem(); + Bean parent; + int index; + if (parentItem == null) { + parent = input; + index = beanViewer.getTree().indexOf(selectedItem); + } else { + parent = (Bean) parentItem.getData(); + index = parentItem.indexOf(selectedItem); + } + + List list = new ArrayList(parent.getList()); + list.remove(index); + parent.setList(list); + } + }); + removeBeanButton.setText("Remove"); + + copyButton = new Button(group, SWT.NONE); + copyButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + clipboard.setValue(getSelectedBean()); + } + }); + copyButton.setText("Copy"); + + pasteButton = new Button(group, SWT.NONE); + pasteButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + Bean copy = (Bean) clipboard.getValue(); + if (copy == null) + return; + Bean parent = getSelectedBean(); + if (parent == null) + parent = input; + + List list = new ArrayList(parent.getList()); + list.add(copy); + parent.setList(list); + + beanViewer.setSelection(new StructuredSelection(copy)); + beanText.selectAll(); + beanText.setFocus(); + } + }); + pasteButton.setText("Paste"); + + final Button refreshButton = new Button(group, SWT.NONE); + refreshButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + beanViewer.refresh(); + } + }); + refreshButton.setText("Refresh"); + + beanViewer = new TreeViewer(shell, SWT.FULL_SELECTION | SWT.BORDER); + beanViewer.setUseHashlookup(true); + tree = beanViewer.getTree(); + tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); + + final Label itemNameLabel = new Label(shell, SWT.NONE); + itemNameLabel.setText("Item Name"); + + beanText = new Text(shell, SWT.BORDER); + final GridData gd_beanValue = new GridData(SWT.FILL, SWT.CENTER, true, + false); + beanText.setLayoutData(gd_beanValue); + m_bindingContext = initDataBindings(); + // + initExtraBindings(m_bindingContext); + } + + private static Bean createBean(String name) { + return new Bean(name); + } + + protected DataBindingContext initDataBindings() { + IObservableValue treeViewerSelectionObserveSelection = ViewersObservables + .observeSingleSelection(beanViewer); + IObservableValue textTextObserveWidget = SWTObservables.observeText( + beanText, SWT.Modify); + IObservableValue treeViewerValueObserveDetailValue = BeansObservables + .observeDetailValue(treeViewerSelectionObserveSelection, + "text", String.class); + // + // + DataBindingContext bindingContext = new DataBindingContext(); + // + bindingContext.bindValue(textTextObserveWidget, + treeViewerValueObserveDetailValue); + // + return bindingContext; + } + + private Bean getSelectedBean() { + IStructuredSelection selection = (IStructuredSelection) beanViewer + .getSelection(); + if (selection.isEmpty()) + return null; + return (Bean) selection.getFirstElement(); + } + + private void initExtraBindings(DataBindingContext dbc) { + final IObservableValue beanViewerSelection = ViewersObservables + .observeSingleSelection(beanViewer); + IObservableValue beanSelected = new ComputedValue(Boolean.TYPE) { + protected Object calculate() { + return Boolean.valueOf(beanViewerSelection.getValue() != null); + } + }; + dbc.bindValue(SWTObservables.observeEnabled(addChildBeanButton), + beanSelected); + dbc.bindValue(SWTObservables.observeEnabled(removeBeanButton), + beanSelected); + + clipboard = new WritableValue(); + dbc.bindValue(SWTObservables.observeEnabled(copyButton), beanSelected); + dbc.bindValue(SWTObservables.observeEnabled(pasteButton), + new ComputedValue(Boolean.TYPE) { + protected Object calculate() { + return Boolean.valueOf(clipboard.getValue() != null); + } + }); + + ViewerSupport.bind(beanViewer, input, BeanProperties.list("list", + Bean.class), BeanProperties.value(Bean.class, "text")); + } + + static class Bean { + /* package */PropertyChangeSupport changeSupport = new PropertyChangeSupport( + this); + private String text; + private List list; + + public Bean(String text) { + this.text = text; + list = new ArrayList(); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + changeSupport.addPropertyChangeListener(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + changeSupport.removePropertyChangeListener(listener); + } + + public String getText() { + return text; + } + + public void setText(String value) { + changeSupport.firePropertyChange("text", this.text, + this.text = value); + } + + public List getList() { + if (list == null) + return null; + return new ArrayList(list); + } + + public void setList(List list) { + if (list != null) + list = new ArrayList(list); + changeSupport.firePropertyChange("list", this.list, + this.list = list); + } + + public boolean hasListeners(String propertyName) { + return changeSupport.hasListeners(propertyName); + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet020TreeViewerWithSetFactory.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet020TreeViewerWithSetFactory.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,325 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 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 + * Matthew Hall - bugs 260329, 260337 + *******************************************************************************/ +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.ComputedValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ViewerSupport; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; + +public class Snippet020TreeViewerWithSetFactory { + + private Button pasteButton; + private Button copyButton; + private Shell shell; + private Button addChildBeanButton; + private Button removeBeanButton; + private TreeViewer beanViewer; + private Tree tree; + private Text beanText; + private DataBindingContext m_bindingContext; + + private Bean input = createBean("input"); + private IObservableValue clipboard; + static int counter = 0; + + /** + * Launch the application + * + * @param args + */ + public static void main(String[] args) { + Display display = Display.getDefault(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + try { + Snippet020TreeViewerWithSetFactory window = new Snippet020TreeViewerWithSetFactory(); + window.open(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + /** + * Open the window + */ + public void open() { + final Display display = Display.getDefault(); + createContents(); + shell.open(); + shell.layout(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + + /** + * Create contents of the window + */ + protected void createContents() { + shell = new Shell(); + final GridLayout gridLayout_1 = new GridLayout(); + gridLayout_1.numColumns = 2; + shell.setLayout(gridLayout_1); + shell.setSize(535, 397); + shell.setText("SWT Application"); + + final Composite group = new Composite(shell, SWT.NONE); + final RowLayout rowLayout = new RowLayout(); + rowLayout.marginTop = 0; + rowLayout.marginRight = 0; + rowLayout.marginLeft = 0; + rowLayout.marginBottom = 0; + rowLayout.pack = false; + group.setLayout(rowLayout); + group + .setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, + 2, 1)); + + final Button addRootButton = new Button(group, SWT.NONE); + addRootButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + Set set = input.getSet(); + Bean root = createBean("root"); + set.add(root); + input.setSet(set); + + beanViewer.setSelection(new StructuredSelection(root)); + beanText.selectAll(); + beanText.setFocus(); + } + }); + addRootButton.setText("Add Root"); + + addChildBeanButton = new Button(group, SWT.NONE); + addChildBeanButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + Bean parent = getSelectedBean(); + Set set = new HashSet(parent.getSet()); + Bean child = createBean("child" + (counter++)); + set.add(child); + parent.setSet(set); + + // beanViewer.setSelection(new StructuredSelection(parent)); + // beanText.selectAll(); + // beanText.setFocus(); + } + }); + addChildBeanButton.setText("Add Child"); + + removeBeanButton = new Button(group, SWT.NONE); + removeBeanButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + TreeItem selectedItem = beanViewer.getTree().getSelection()[0]; + Bean bean = (Bean) selectedItem.getData(); + TreeItem parentItem = selectedItem.getParentItem(); + Bean parent; + if (parentItem == null) + parent = input; + else + parent = (Bean) parentItem.getData(); + + Set set = new HashSet(parent.getSet()); + set.remove(bean); + parent.setSet(set); + } + }); + removeBeanButton.setText("Remove"); + + copyButton = new Button(group, SWT.NONE); + copyButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + clipboard.setValue(getSelectedBean()); + } + }); + copyButton.setText("Copy"); + + pasteButton = new Button(group, SWT.NONE); + pasteButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + Bean copy = (Bean) clipboard.getValue(); + if (copy == null) + return; + Bean parent = getSelectedBean(); + if (parent == null) + parent = input; + + Set set = new HashSet(parent.getSet()); + set.add(copy); + parent.setSet(set); + + beanViewer.setSelection(new StructuredSelection(copy)); + beanText.selectAll(); + beanText.setFocus(); + } + }); + pasteButton.setText("Paste"); + + final Button refreshButton = new Button(group, SWT.NONE); + refreshButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + beanViewer.refresh(); + } + }); + refreshButton.setText("Refresh"); + + beanViewer = new TreeViewer(shell, SWT.FULL_SELECTION | SWT.BORDER); + beanViewer.setUseHashlookup(true); + beanViewer.setComparator(new ViewerComparator()); + tree = beanViewer.getTree(); + tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); + + final Label itemNameLabel = new Label(shell, SWT.NONE); + itemNameLabel.setText("Item Name"); + + beanText = new Text(shell, SWT.BORDER); + final GridData gd_beanValue = new GridData(SWT.FILL, SWT.CENTER, true, + false); + beanText.setLayoutData(gd_beanValue); + m_bindingContext = initDataBindings(); + // + initExtraBindings(m_bindingContext); + } + + private static Bean createBean(String name) { + return new Bean(name); + } + + protected DataBindingContext initDataBindings() { + IObservableValue treeViewerSelectionObserveSelection = ViewersObservables + .observeSingleSelection(beanViewer); + IObservableValue textTextObserveWidget = SWTObservables.observeText( + beanText, SWT.Modify); + IObservableValue treeViewerValueObserveDetailValue = BeansObservables + .observeDetailValue(treeViewerSelectionObserveSelection, + "text", String.class); + // + // + DataBindingContext bindingContext = new DataBindingContext(); + // + bindingContext.bindValue(textTextObserveWidget, + treeViewerValueObserveDetailValue); + // + return bindingContext; + } + + private Bean getSelectedBean() { + IStructuredSelection selection = (IStructuredSelection) beanViewer + .getSelection(); + if (selection.isEmpty()) + return null; + return (Bean) selection.getFirstElement(); + } + + private void initExtraBindings(DataBindingContext dbc) { + final IObservableValue beanViewerSelection = ViewersObservables + .observeSingleSelection(beanViewer); + IObservableValue beanSelected = new ComputedValue(Boolean.TYPE) { + protected Object calculate() { + return Boolean.valueOf(beanViewerSelection.getValue() != null); + } + }; + dbc.bindValue(SWTObservables.observeEnabled(addChildBeanButton), + beanSelected); + dbc.bindValue(SWTObservables.observeEnabled(removeBeanButton), + beanSelected); + + clipboard = new WritableValue(); + dbc.bindValue(SWTObservables.observeEnabled(copyButton), beanSelected); + dbc.bindValue(SWTObservables.observeEnabled(pasteButton), + new ComputedValue(Boolean.TYPE) { + protected Object calculate() { + return Boolean.valueOf(clipboard.getValue() != null); + } + }); + + ViewerSupport.bind(beanViewer, input, BeanProperties.set("set", + Bean.class), BeanProperties.value(Bean.class, "text")); + } + + static class Bean { + /* package */PropertyChangeSupport changeSupport = new PropertyChangeSupport( + this); + private String text; + private Set set; + + public Bean(String text) { + this.text = text; + set = new HashSet(); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + changeSupport.addPropertyChangeListener(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + changeSupport.removePropertyChangeListener(listener); + } + + public String getText() { + return text; + } + + public void setText(String value) { + changeSupport.firePropertyChange("text", this.text, + this.text = value); + } + + public Set getSet() { + if (set == null) + return null; + return new HashSet(set); + } + + public void setSet(Set set) { + if (set != null) + set = new HashSet(set); + changeSupport.firePropertyChange("set", this.set, this.set = set); + } + + public boolean hasListeners(String propertyName) { + return changeSupport.hasListeners(propertyName); + } + } +} \ No newline at end of file diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet021MultiFieldValidation.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet021MultiFieldValidation.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,357 @@ +/******************************************************************************* + * 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 218269) + * Matthew Hall - bug 260329 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.core.databinding.DataBindingContext; +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.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.core.databinding.validation.MultiValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; +import org.eclipse.jface.databinding.wizard.WizardPageSupport; +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ListViewer; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.IWizard; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Text; + +/** + * @since 3.2 + * + */ +public class Snippet021MultiFieldValidation extends WizardPage { + + private List list_1; + private List list; + private Button addAddendButton; + private Button removeAddendButton; + private Text sumModelValue; + private Text field2ModelValue; + private Text field1ModelValue; + private Text sumTarget; + private Text field2Target; + private Text field1Target; + private ListViewer addendsTarget; + private ListViewer addendsModelValue; + + /** + * Create the wizard + */ + public Snippet021MultiFieldValidation() { + super("snippet021"); + setTitle("Snippet 021 - Multi-field Validators"); + setDescription("Enter values which satisfy the cross-field constraints"); + } + + /** + * Create contents of the wizard + * + * @param parent + */ + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + final GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 2; + container.setLayout(gridLayout); + // + setControl(container); + + final Group bothEvenOrGroup = new Group(container, SWT.NONE); + bothEvenOrGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, + false)); + bothEvenOrGroup.setText("Numbers must be both even or both odd"); + final GridLayout gridLayout_1 = new GridLayout(); + gridLayout_1.numColumns = 3; + bothEvenOrGroup.setLayout(gridLayout_1); + new Label(bothEvenOrGroup, SWT.NONE); + + final Label targetLabel = new Label(bothEvenOrGroup, SWT.NONE); + targetLabel.setText("Target"); + + final Label modelLabel = new Label(bothEvenOrGroup, SWT.NONE); + modelLabel.setText("Model"); + + final Label field1Label = new Label(bothEvenOrGroup, SWT.NONE); + field1Label.setText("Field 1"); + + field1Target = new Text(bothEvenOrGroup, SWT.BORDER); + final GridData gd_field1Target = new GridData(SWT.FILL, SWT.CENTER, + true, false); + field1Target.setLayoutData(gd_field1Target); + + field1ModelValue = new Text(bothEvenOrGroup, SWT.READ_ONLY | SWT.BORDER); + final GridData gd_field1ModelValue = new GridData(SWT.FILL, SWT.CENTER, + true, false); + field1ModelValue.setLayoutData(gd_field1ModelValue); + + final Label field2Label = new Label(bothEvenOrGroup, SWT.NONE); + field2Label.setText("Field 2"); + + field2Target = new Text(bothEvenOrGroup, SWT.BORDER); + final GridData gd_field2Target = new GridData(SWT.FILL, SWT.CENTER, + true, false); + field2Target.setLayoutData(gd_field2Target); + + field2ModelValue = new Text(bothEvenOrGroup, SWT.READ_ONLY | SWT.BORDER); + final GridData gd_field2ModelValue = new GridData(SWT.FILL, SWT.CENTER, + true, false); + field2ModelValue.setLayoutData(gd_field2ModelValue); + + final Group sumOfAllGroup = new Group(container, SWT.NONE); + sumOfAllGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, + true)); + sumOfAllGroup.setText("Addends must add up to sum"); + final GridLayout gridLayout_2 = new GridLayout(); + gridLayout_2.numColumns = 3; + sumOfAllGroup.setLayout(gridLayout_2); + new Label(sumOfAllGroup, SWT.NONE); + + final Label targetLabel_1 = new Label(sumOfAllGroup, SWT.NONE); + targetLabel_1.setText("Target"); + + final Label modelLabel_1 = new Label(sumOfAllGroup, SWT.NONE); + modelLabel_1.setText("Model"); + + final Label expectedSumLabel = new Label(sumOfAllGroup, SWT.NONE); + expectedSumLabel.setText("Sum"); + + sumTarget = new Text(sumOfAllGroup, SWT.BORDER); + final GridData gd_sumTarget = new GridData(SWT.FILL, SWT.CENTER, true, + false); + sumTarget.setLayoutData(gd_sumTarget); + + sumModelValue = new Text(sumOfAllGroup, SWT.READ_ONLY | SWT.BORDER); + final GridData gd_sumModelValue = new GridData(SWT.FILL, SWT.CENTER, + true, false); + sumModelValue.setLayoutData(gd_sumModelValue); + + final Label addendsLabel = new Label(sumOfAllGroup, SWT.NONE); + addendsLabel.setText("Addends"); + + addendsTarget = new ListViewer(sumOfAllGroup, SWT.V_SCROLL | SWT.BORDER); + list_1 = addendsTarget.getList(); + list_1 + .setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true, 1, + 2)); + + addendsModelValue = new ListViewer(sumOfAllGroup, SWT.V_SCROLL + | SWT.BORDER); + list = addendsModelValue.getList(); + list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true, 1, 2)); + + final Composite composite = new Composite(sumOfAllGroup, SWT.NONE); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + final GridLayout gridLayout_3 = new GridLayout(); + gridLayout_3.marginWidth = 0; + gridLayout_3.marginHeight = 0; + composite.setLayout(gridLayout_3); + + addAddendButton = new Button(composite, SWT.NONE); + addAddendButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, + false)); + addAddendButton.setText("Add"); + + removeAddendButton = new Button(composite, SWT.NONE); + removeAddendButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, + false, false)); + removeAddendButton.setText("Remove"); + + bindUI(); + } + + private void bindUI() { + DataBindingContext dbc = new DataBindingContext(); + + bindEvensAndOddsGroup(dbc); + bindSumAndAddendsGroup(dbc); + + WizardPageSupport.create(this, dbc); + } + + private void bindEvensAndOddsGroup(DataBindingContext dbc) { + IObservableValue targetField1 = SWTObservables.observeText( + field1Target, SWT.Modify); + final IObservableValue middleField1 = new WritableValue(null, + Integer.TYPE); + dbc.bindValue(targetField1, middleField1); + + IObservableValue targetField2 = SWTObservables.observeText( + field2Target, SWT.Modify); + final IObservableValue middleField2 = new WritableValue(null, + Integer.TYPE); + dbc.bindValue(targetField2, middleField2); + + MultiValidator validator = new MultiValidator() { + protected IStatus validate() { + Integer field1 = (Integer) middleField1.getValue(); + Integer field2 = (Integer) middleField2.getValue(); + if (Math.abs(field1.intValue()) % 2 != Math.abs(field2 + .intValue()) % 2) + return ValidationStatus + .error("Fields 1 and 2 must be both even or both odd"); + return null; + } + }; + dbc.addValidationStatusProvider(validator); + + IObservableValue modelField1 = new WritableValue(new Integer(1), + Integer.TYPE); + IObservableValue modelField2 = new WritableValue(new Integer(4), + Integer.TYPE); + dbc.bindValue(validator.observeValidatedValue(middleField1), + modelField1); + dbc.bindValue(validator.observeValidatedValue(middleField2), + modelField2); + + dbc.bindValue(SWTObservables.observeText(field1ModelValue, SWT.Modify), + modelField1); + dbc.bindValue(SWTObservables.observeText(field2ModelValue, SWT.Modify), + modelField2); + } + + private void bindSumAndAddendsGroup(DataBindingContext dbc) { + IObservableValue targetSum = SWTObservables.observeText(sumTarget, + SWT.Modify); + final IObservableValue middleSum = new WritableValue(null, Integer.TYPE); + dbc.bindValue(targetSum, middleSum); + + final IObservableList targetAddends = new WritableList(new ArrayList(), + Integer.TYPE); + addendsTarget.setContentProvider(new ObservableListContentProvider()); + addendsTarget.setInput(targetAddends); + + addAddendButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(final SelectionEvent e) { + InputDialog dialog = new InputDialog(getShell(), + "Input addend", "Enter an integer addend", "0", + new IInputValidator() { + public String isValid(String newText) { + try { + Integer.valueOf(newText); + return null; + } catch (NumberFormatException e) { + return "Enter a number between " + + Integer.MIN_VALUE + " and " + + Integer.MAX_VALUE; + } + } + }); + if (dialog.open() == Window.OK) { + targetAddends.add(Integer.valueOf(dialog.getValue())); + } + } + }); + + removeAddendButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + IStructuredSelection selection = (IStructuredSelection) addendsTarget + .getSelection(); + if (!selection.isEmpty()) + targetAddends.remove(selection.getFirstElement()); + } + }); + + IObservableValue modelSum = new WritableValue(new Integer(5), + Integer.TYPE); + dbc.bindValue(SWTObservables.observeText(sumModelValue, SWT.Modify), + modelSum); + + IObservableList modelAddends = new WritableList(new ArrayList(), + Integer.TYPE); + + MultiValidator validator = new MultiValidator() { + protected IStatus validate() { + Integer sum = (Integer) middleSum.getValue(); + int actualSum = 0; + for (Iterator iterator = targetAddends.iterator(); iterator + .hasNext();) { + actualSum += ((Integer) iterator.next()).intValue(); + } + if (sum.intValue() != actualSum) + return ValidationStatus.error("Sum of addends is " + + actualSum + ", expecting " + sum); + return ValidationStatus.ok(); + } + }; + dbc.addValidationStatusProvider(validator); + + addendsModelValue + .setContentProvider(new ObservableListContentProvider()); + addendsModelValue.setInput(modelAddends); + + dbc.bindValue(validator.observeValidatedValue(middleSum), modelSum); + dbc.bindList(validator.observeValidatedList(targetAddends), + modelAddends); + } + + static class MultiFieldValidationWizard extends Wizard { + public void addPages() { + addPage(new Snippet021MultiFieldValidation()); + } + + public String getWindowTitle() { + return "Snippet 021 - Multi-field Validation"; + } + + public boolean performFinish() { + return true; + } + } + + public static void main(String[] args) { + Display display = new Display(); + + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + IWizard wizard = new MultiFieldValidationWizard(); + WizardDialog dialog = new WizardDialog(null, wizard); + dialog.open(); + + // The SWT event loop + Display display = Display.getCurrent(); + while (dialog.getShell() != null + && !dialog.getShell().isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + + display.dispose(); + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet022ComputedListCombo.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet022ComputedListCombo.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2008 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.jface.examples.databinding.snippets; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.ComputedList; +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.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.2 + * + */ +public class Snippet022ComputedListCombo { + private static WritableList model; + + public static void main(String[] args) { + Display display = new Display(); + final Shell shell = new Shell(display); + shell.setLayout(new GridLayout(1, false)); + + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + Snippet022ComputedListCombo snippet = new Snippet022ComputedListCombo(); + snippet.createModel(); + snippet.createControls(shell); + } + }); + + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + } + + /** + * + */ + protected void createModel() { + model = new WritableList(); + model.add(new Thing("Alice", true, false)); + model.add(new Thing("Beth", true, false)); + model.add(new Thing("Cathy", true, false)); + model.add(new Thing("Arthur", false, true)); + model.add(new Thing("Bob", false, true)); + model.add(new Thing("Curtis", false, true)); + model.add(new Thing("Snail", true, true)); + model.add(new Thing("Nail", false, false)); + } + + /** + * @param shell + */ + protected void createControls(Shell shell) { + Composite composite = new Composite(shell, SWT.NONE); + Group group = new Group(composite, SWT.NONE); + group.setText("Filter"); + Button male = new Button(group, SWT.CHECK); + male.setText("Male"); + Button female = new Button(group, SWT.CHECK); + female.setText("Female"); + final IObservableValue femaleObservable = SWTObservables + .observeSelection(female); + final IObservableValue maleObservable = SWTObservables + .observeSelection(male); + Combo combo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY); + GridDataFactory.defaultsFor(combo).align(SWT.BEGINNING, SWT.BEGINNING) + .applyTo(combo); + ComboViewer viewer = new ComboViewer(combo); + viewer.setContentProvider(new ObservableListContentProvider()); + // We should really have an out-of-the box filtered list... + IObservableList filteredList = new ComputedList() { + protected List calculate() { + ArrayList result = new ArrayList(); + for (Iterator it = model.iterator(); it.hasNext();) { + Thing thing = (Thing) it.next(); + if (((Boolean) femaleObservable.getValue()).booleanValue() + && !thing.female) + continue; + if (((Boolean) maleObservable.getValue()).booleanValue() + && !thing.male) + continue; + result.add(thing); + } + return result; + } + }; + viewer.setInput(filteredList); + GridLayoutFactory.swtDefaults().applyTo(group); + GridLayoutFactory.swtDefaults().applyTo(composite); + } + + static class Thing { + String name; + boolean male; + boolean female; + + public Thing(String name, boolean female, boolean male) { + this.name = name; + this.female = female; + this.male = male; + } + + public String toString() { + return name; + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet023ConditionalVisibility.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet023ConditionalVisibility.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2008 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.jface.examples.databinding.snippets; + +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.jface.databinding.swt.ISWTObservableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.internal.databinding.provisional.swt.ControlUpdater; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * @since 3.2 + * + */ +public class Snippet023ConditionalVisibility { + public static void main(String[] args) { + Display display = new Display(); + final Shell shell = new Shell(display); + shell.setLayout(new GridLayout(1, false)); + + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + new Snippet023ConditionalVisibility().createControls(shell); + } + }); + + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + } + + Text text; + Text toText; + Text fromText; + + /** + * @param shell + */ + private void createControls(Shell shell) { + Composite composite = new Composite(shell, SWT.NONE); + Group radioGroup = new Group(composite, SWT.NONE); + radioGroup.setText("Type"); + Button textButton = new Button(radioGroup, SWT.RADIO); + textButton.setText("Text"); + Button rangeButton = new Button(radioGroup, SWT.RADIO); + rangeButton.setText("Range"); + GridLayoutFactory.swtDefaults().generateLayout(radioGroup); + + final Composite oneOfTwo = new Composite(composite, SWT.NONE); + final StackLayout stackLayout = new StackLayout(); + oneOfTwo.setLayout(stackLayout); + + final Group rangeGroup = new Group(oneOfTwo, SWT.NONE); + rangeGroup.setText("Range"); + Label fromLabel = new Label(rangeGroup, SWT.NONE); + fromLabel.setText("From:"); + fromText = new Text(rangeGroup, SWT.SINGLE | SWT.LEAD | SWT.BORDER); + + Label toLabel = new Label(rangeGroup, SWT.NONE); + toLabel.setText("To:"); + toText = new Text(rangeGroup, SWT.SINGLE | SWT.LEAD | SWT.BORDER); + GridLayoutFactory.swtDefaults().numColumns(2) + .generateLayout(rangeGroup); + + final Group textGroup = new Group(oneOfTwo, SWT.NONE); + textGroup.setText("Text"); + Label label = new Label(textGroup, SWT.NONE); + label.setText("Text:"); + text = new Text(textGroup, SWT.SINGLE | SWT.LEAD | SWT.BORDER); + GridLayoutFactory.swtDefaults().numColumns(2).generateLayout(textGroup); + + GridLayoutFactory.swtDefaults().numColumns(2).generateLayout(composite); + + final ISWTObservableValue rangeSelected = SWTObservables + .observeSelection(rangeButton); + final ISWTObservableValue textSelected = SWTObservables + .observeSelection(textButton); + + // Note that ControlUpdater is not API. + new ControlUpdater(oneOfTwo) { + protected void updateControl() { + if (((Boolean) rangeSelected.getValue()).booleanValue()) { + stackLayout.topControl = rangeGroup; + oneOfTwo.layout(); + } else if (((Boolean) textSelected.getValue()).booleanValue()) { + stackLayout.topControl = textGroup; + oneOfTwo.layout(); + } + } + }; + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet024SelectObservableValue.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet024SelectObservableValue.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,123 @@ +/******************************************************************************* + * 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 249992) + * Matthew Hall - bug 260329 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.SelectObservableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.IViewerObservableValue; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ListViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Shell; + +/** + * Demonstrate usage of SelectObservableValue + * + * @since 3.2 + */ +public class Snippet024SelectObservableValue { + protected Shell shell; + + public static void main(String[] args) { + final Display display = Display.getDefault(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + try { + Snippet024SelectObservableValue window = new Snippet024SelectObservableValue(); + window.open(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + public void open() { + final Display display = Display.getDefault(); + createContents(); + shell.open(); + shell.layout(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + + protected void createContents() { + shell = new Shell(); + shell.setSize(400, 300); + shell.setLayout(new GridLayout(2, true)); + shell.setText("Snippet024SelectObservableValue"); + + final ListViewer listViewer = new ListViewer(shell, SWT.BORDER); + listViewer.setContentProvider(new ArrayContentProvider()); + listViewer.getList().setLayoutData( + new GridData(SWT.FILL, SWT.FILL, true, true)); + + final Group group = new Group(shell, SWT.NONE); + group.setText("Radio Group"); + group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + group.setLayout(new GridLayout()); + + // Data Binding + Color[] colors = Color.values(); + + listViewer.setInput(colors); + IViewerObservableValue listViewerSelection = ViewersObservables + .observeSingleSelection(listViewer); + + SelectObservableValue radioGroup = new SelectObservableValue(); + for (int i = 0; i < colors.length; i++) { + Button button = new Button(group, SWT.RADIO); + button.setText(colors[i].toString()); + radioGroup.addOption(colors[i], SWTObservables + .observeSelection(button)); + } + + DataBindingContext dbc = new DataBindingContext(); + dbc.bindValue(radioGroup, listViewerSelection); + } + + public static class Color { + public static final Color RED = new Color("Red"); + public static final Color ORANGE = new Color("Orange"); + public static final Color YELLOW = new Color("Yellow"); + public static final Color GREEN = new Color("Green"); + public static final Color BLUE = new Color("Blue"); + public static final Color INDIGO = new Color("Indigo"); + public static final Color VIOLET = new Color("Violet"); + + private final String name; + + private Color(String name) { + this.name = name; + } + + public String toString() { + return name; + } + + public static Color[] values() { + return new Color[] { RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, + VIOLET }; + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet025TableViewerWithPropertyDerivedColumns.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet025TableViewerWithPropertyDerivedColumns.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,272 @@ +/******************************************************************************* + * Copyright (c) 2006 The Pampered Chef, Inc. 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: + * Coconut Palm Software, Inc. - Initial API and implementation + * Matthew Hall - bug 195222, 261843, 260337 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +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.IObservableValue; +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.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Combo; +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; + +/** + * Demonstrates binding a TableViewer to a collection. + */ +public class Snippet025TableViewerWithPropertyDerivedColumns { + public static void main(String[] args) { + final Display display = new Display(); + + // Set up data binding. In an RCP application, the threading Realm + // will be set for you automatically by the Workbench. In an SWT + // application, you can do this once, wrapping your binding + // method call. + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + ViewModel viewModel = new ViewModel(); + Shell shell = new View(viewModel).createShell(); + + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + } + + // 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); + } + } + + private static Person UNKNOWN = new Person("unknown", null, null); + + // The data model class. This is normally a persistent class of some sort. + static class Person extends AbstractModelObject { + // A property... + String name = "Donald Duck"; + Person mother; + Person father; + + public Person(String name, Person mother, Person father) { + this.name = name; + this.mother = mother; + this.father = father; + } + + public String getName() { + return name; + } + + public void setName(String name) { + firePropertyChange("name", this.name, this.name = name); + } + + public Person getMother() { + return mother; + } + + public void setMother(Person mother) { + firePropertyChange("mother", this.mother, this.mother = mother); + } + + public Person getFather() { + return father; + } + + public void setFather(Person father) { + firePropertyChange("father", this.father, this.father = father); + } + } + + // The View's model--the root of our Model graph for this particular GUI. + // + // Typically each View class has a corresponding ViewModel class. + // The ViewModel is responsible for getting the objects to edit from the + // 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(); + { + Person fergus = new Person("Fergus McDuck", UNKNOWN, UNKNOWN); + Person downy = new Person("Downy O'Drake", UNKNOWN, UNKNOWN); + Person scrooge = new Person("Scrooge McDuck", downy, fergus); + Person hortense = new Person("Hortense McDuck", downy, fergus); + Person quackmore = new Person("Quackmore Duck", UNKNOWN, UNKNOWN); + Person della = new Person("Della Duck", hortense, quackmore); + Person donald = new Person("Donald Duck", hortense, quackmore); + people.add(UNKNOWN); + people.add(downy); + people.add(fergus); + people.add(scrooge); + people.add(quackmore); + people.add(hortense); + people.add(della); + people.add(donald); + } + + public IObservableList getPeople() { + return people; + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + private Table duckFamily; + private Text nameText; + private Combo motherCombo; + private Combo fatherCombo; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + Display display = Display.getDefault(); + Shell shell = new Shell(display); + duckFamily = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION); + duckFamily.setHeaderVisible(true); + GridDataFactory.defaultsFor(duckFamily).span(2, 1).applyTo( + duckFamily); + createColumn("Name"); + createColumn("Mother"); + createColumn("Father"); + createColumn("Maternal Grandmother"); + createColumn("Maternal Grandfather"); + createColumn("Paternal Grandmother"); + createColumn("Paternal Grandfather"); + + duckFamily.setLinesVisible(true); + + new Label(shell, SWT.NONE).setText("Name:"); + nameText = new Text(shell, SWT.BORDER); + GridDataFactory.defaultsFor(nameText).grab(true, false).applyTo( + nameText); + + new Label(shell, SWT.NONE).setText("Mother:"); + motherCombo = new Combo(shell, SWT.READ_ONLY); + + new Label(shell, SWT.NONE).setText("Father:"); + fatherCombo = new Combo(shell, SWT.READ_ONLY); + + DataBindingContext bindingContext = new DataBindingContext(); + bindGUI(bindingContext); + + GridLayoutFactory.swtDefaults().numColumns(2).applyTo(shell); + // Open and return the Shell + shell.setSize(800, 300); + shell.open(); + return shell; + } + + private void createColumn(String string) { + final TableColumn column = new TableColumn(duckFamily, SWT.NONE); + column.setText(string); + column.pack(); + if (column.getWidth() < 100) + column.setWidth(100); + } + + protected void bindGUI(DataBindingContext dbc) { + // Since we're using a JFace Viewer, we do first wrap our Table... + TableViewer peopleViewer = new TableViewer(duckFamily); + peopleViewer.addFilter(new ViewerFilter() { + public boolean select(Viewer viewer, Object parentElement, + Object element) { + return element != UNKNOWN; + } + }); + + 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" })); + + IObservableValue masterSelection = ViewerProperties + .singleSelection().observe(peopleViewer); + + dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(nameText), + BeanProperties.value(Person.class, "name").observeDetail( + masterSelection)); + + ComboViewer mothercomboViewer = new ComboViewer(motherCombo); + ViewerSupport.bind(mothercomboViewer, viewModel.getPeople(), + BeanProperties.value(Person.class, "name")); + + dbc.bindValue(ViewerProperties.singleSelection().observe( + mothercomboViewer), BeanProperties.value(Person.class, + "mother").observeDetail(masterSelection)); + + ComboViewer fatherComboViewer = new ComboViewer(fatherCombo); + ViewerSupport.bind(fatherComboViewer, viewModel.getPeople(), + BeanProperties.value(Person.class, "name")); + + dbc.bindValue(ViewerProperties.singleSelection().observe( + fatherComboViewer), BeanProperties.value(Person.class, + "father").observeDetail(masterSelection)); + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet026AnonymousBeanProperties.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet026AnonymousBeanProperties.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,400 @@ +/******************************************************************************* + * 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 247997) + * Matthew Hall - bugs 261843, 260337, 265561 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Collections; +import java.util.Iterator; +import java.util.Set; +import java.util.TreeSet; + +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.set.SetDiff; +import org.eclipse.core.databinding.observable.value.ComputedValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.property.INativePropertyListener; +import org.eclipse.core.databinding.property.IProperty; +import org.eclipse.core.databinding.property.ISimplePropertyListener; +import org.eclipse.core.databinding.property.NativePropertyListener; +import org.eclipse.core.databinding.property.set.DelegatingSetProperty; +import org.eclipse.core.databinding.property.set.ISetProperty; +import org.eclipse.core.databinding.property.set.SimpleSetProperty; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.databinding.viewers.ViewerProperties; +import org.eclipse.jface.databinding.viewers.ViewerSupport; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; + +/** + * @since 3.2 + * + */ +public class Snippet026AnonymousBeanProperties { + private ComboViewer statusViewer; + private Combo combo; + private Text nameText; + private TreeViewer contactViewer; + + public static void main(String[] args) { + Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + try { + Snippet026AnonymousBeanProperties window = new Snippet026AnonymousBeanProperties(); + window.open(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + private ApplicationModel model; + private Shell shell; + private Tree tree; + + // 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 ContactGroup extends AbstractModelObject implements + Comparable { + private String name; + private Set contacts = new TreeSet(); + + ContactGroup(String name) { + this.name = checkNull(name); + } + + private String checkNull(String string) { + if (string == null) + throw new NullPointerException(); + return string; + } + + public String getName() { + return name; + } + + public void setName(String name) { + firePropertyChange("name", this.name, this.name = checkNull(name)); + } + + public Set getContacts() { + return new TreeSet(contacts); + } + + public void addContact(Contact contact) { + Set oldValue = getContacts(); + contacts.add(contact); + Set newValue = getContacts(); + firePropertyChange("contacts", oldValue, newValue); + } + + public void removeContact(Contact contact) { + Set oldValue = getContacts(); + contacts.remove(contact); + Set newValue = getContacts(); + firePropertyChange("contacts", oldValue, newValue); + } + + public int compareTo(Object o) { + ContactGroup that = (ContactGroup) o; + return this.name.compareTo(that.name); + } + } + + public static class Contact extends AbstractModelObject implements + Comparable { + private String name; + private String status; + + private String checkNull(String string) { + if (string == null) + throw new NullPointerException(); + return string; + } + + public Contact(String name, String status) { + this.name = checkNull(name); + this.status = checkNull(status); + } + + public String getName() { + return name; + } + + public void setName(String name) { + firePropertyChange("name", this.name, this.name = checkNull(name)); + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + firePropertyChange("status", this.status, + this.status = checkNull(status)); + } + + public int compareTo(Object o) { + Contact that = (Contact) o; + int result = this.name.compareTo(that.name); + if (result == 0) + result = this.status.compareTo(that.status); + return result; + } + } + + public static class ApplicationModel extends AbstractModelObject { + private Set groups = new TreeSet(); + + public Set getGroups() { + return new TreeSet(groups); + } + + public void setGroups(Set groups) { + Set oldValue = getGroups(); + this.groups = new TreeSet(groups); + Set newValue = getGroups(); + firePropertyChange("groups", oldValue, newValue); + } + } + + /** + * Set property for the "contacts" property of a ContactGroup. Since + * ContactGroup does not have a setContacts() method we have to write our + * own property to apply set changes incrementally through the addContact + * and removeContact methods. + */ + public static class ContactGroupContactsProperty extends SimpleSetProperty { + public Object getElementType() { + return Contact.class; + } + + protected Set doGetSet(Object source) { + if (source == null) + return Collections.EMPTY_SET; + return ((ContactGroup) source).getContacts(); + } + + protected void doSetSet(Object source, Set set, SetDiff diff) { + ContactGroup group = (ContactGroup) source; + for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) { + Contact contact = (Contact) it.next(); + group.removeContact(contact); + } + for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) { + Contact contact = (Contact) it.next(); + group.addContact(contact); + } + } + + public INativePropertyListener adaptListener( + final ISimplePropertyListener listener) { + return new Listener(this, listener); + } + + private class Listener extends NativePropertyListener implements + PropertyChangeListener { + Listener(IProperty property, ISimplePropertyListener listener) { + super(property, listener); + } + + public void propertyChange(PropertyChangeEvent evt) { + fireChange(evt.getSource(), null); + } + + protected void doAddTo(Object source) { + ((ContactGroup) source).addPropertyChangeListener("contacts", + this); + } + + protected void doRemoveFrom(Object source) { + ((ContactGroup) source).removePropertyChangeListener( + "contacts", this); + } + } + } + + public void open() { + model = createDefaultModel(); + + final Display display = Display.getDefault(); + createContents(); + bindUI(); + shell.open(); + shell.layout(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + + private static final String[] statuses = new String[] { "Online", "Idle", + "Busy", "Offline" }; + + /** + * @return + */ + private ApplicationModel createDefaultModel() { + ContactGroup swtGroup = new ContactGroup("SWT"); + swtGroup.addContact(new Contact("Steve Northover", "Busy")); + swtGroup.addContact(new Contact("Grant Gayed", "Online")); + swtGroup.addContact(new Contact("Veronika Irvine", "Offline")); + swtGroup.addContact(new Contact("Mike Wilson", "Online")); + swtGroup.addContact(new Contact("Christophe Cornu", "Idle")); + swtGroup.addContact(new Contact("Lynne Kues", "Online")); + swtGroup.addContact(new Contact("Silenio Quarti", "Idle")); + + ContactGroup jdbGroup = new ContactGroup("JFace Data Binding"); + jdbGroup.addContact(new Contact("Boris Bokowski", "Online")); + jdbGroup.addContact(new Contact("Matthew Hall", "Idle")); + + Set groups = new TreeSet(); + groups.add(swtGroup); + groups.add(jdbGroup); + ApplicationModel model = new ApplicationModel(); + model.setGroups(groups); + + return model; + } + + /** + * Create contents of the window + */ + protected void createContents() { + shell = new Shell(); + shell.setSize(379, 393); + shell.setText("Snippet026AnonymousBeanProperties"); + final GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 4; + shell.setLayout(gridLayout); + + contactViewer = new TreeViewer(shell, SWT.BORDER); + tree = contactViewer.getTree(); + tree.setHeaderVisible(true); + tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1)); + + final TreeColumn nameColumn = new TreeColumn(tree, SWT.NONE); + nameColumn.setWidth(163); + nameColumn.setText("Name"); + + final TreeColumn newColumnTreeColumn = new TreeColumn(tree, SWT.NONE); + newColumnTreeColumn.setWidth(100); + newColumnTreeColumn.setText("Status"); + + final Label nameLabel = new Label(shell, SWT.NONE); + nameLabel.setText("Name"); + + nameText = new Text(shell, SWT.BORDER); + final GridData gd_nameText = new GridData(SWT.FILL, SWT.CENTER, true, + false); + nameText.setLayoutData(gd_nameText); + + final Label statusLabel = new Label(shell, SWT.NONE); + statusLabel.setLayoutData(new GridData()); + statusLabel.setText("Status"); + + statusViewer = new ComboViewer(shell, SWT.READ_ONLY); + combo = statusViewer.getCombo(); + combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + } + + private void bindUI() { + ISetProperty treeChildrenProperty = new DelegatingSetProperty() { + ISetProperty modelGroups = BeanProperties.set( + ApplicationModel.class, "groups"); + ISetProperty groupContacts = BeanProperties.set(ContactGroup.class, + "contacts"); + + protected ISetProperty doGetDelegate(Object source) { + if (source instanceof ApplicationModel) + return modelGroups; + if (source instanceof ContactGroup) + return groupContacts; + return null; + } + }; + + ViewerSupport.bind(contactViewer, model, treeChildrenProperty, + BeanProperties.values(new String[] { "name", "status" })); + + contactViewer.expandAll(); + + final IObservableValue selection = ViewerProperties.singleSelection() + .observe(contactViewer); + + DataBindingContext dbc = new DataBindingContext(); + + dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(nameText), + BeanProperties.value("name").observeDetail(selection)); + + statusViewer.setContentProvider(new ArrayContentProvider()); + statusViewer.setInput(statuses); + + dbc.bindValue(ViewerProperties.singleSelection().observe(statusViewer), + BeanProperties.value("status").observeDetail(selection)); + + dbc.bindValue(WidgetProperties.enabled().observe( + statusViewer.getControl()), new ComputedValue() { + protected Object calculate() { + return Boolean.valueOf(selection.getValue() instanceof Contact); + } + }); + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet027ExternalValidator.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet027ExternalValidator.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,262 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Code 9 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: + * Chris Aniszczyk - initial API and implementation + * Boris Bokowski, IBM - minor changes + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.validation.MultiValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.wizard.WizardPageSupport; +import org.eclipse.jface.wizard.IWizard; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * This snippet demonstrates how to integrate an external validator + * + * @since 3.5 + */ +public class Snippet027ExternalValidator extends WizardPage { + + private Text nameValue; + private Text emailValue; + private Text phoneNumberValue; + + private Contact contact; + + // 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); + } + } + + static class Contact extends AbstractModelObject { + String name; + String email; + String phoneNumber; + + public Contact(String name, String email, String number) { + this.name = name; + this.email = email; + this.phoneNumber = number; + } + + public String getName() { + return name; + } + + public void setName(String name) { + String oldValue = this.name; + this.name = name; + firePropertyChange("name", oldValue, name); + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + String oldValue = this.email; + this.email = email; + firePropertyChange("email", oldValue, email); + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String number) { + String oldValue = this.phoneNumber; + this.phoneNumber = number; + firePropertyChange("phoneNumber", oldValue, number); + } + + public IStatus validate() { + if (name.indexOf(' ') == -1) { + return ValidationStatus + .error("Please enter both first and last name separated by a space."); + } + if (email.indexOf('@') == -1) { + return ValidationStatus + .error("Please enter a valid email address containing '@'."); + } + if (!phoneNumber.startsWith("+")) { + return ValidationStatus + .error("Please enter the phone number in international format starting with '+'."); + } + return Status.OK_STATUS; + } + + } + + /** + * Create the wizard + */ + public Snippet027ExternalValidator() { + super("snippet024"); + setTitle("Snippet 024 - External Validation"); + setDescription("Please enter contact details."); + } + + /** + * Create contents of the wizard + * + * @param parent + */ + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + final GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 2; + container.setLayout(gridLayout); + setControl(container); + + final Label nameLabel = new Label(container, SWT.NONE); + nameLabel.setText("Name"); + + nameValue = new Text(container, SWT.BORDER); + final GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false); + nameValue.setLayoutData(gd); + + final Label emailLabel = new Label(container, SWT.NONE); + emailLabel.setText("Email"); + + emailValue = new Text(container, SWT.BORDER); + emailValue.setLayoutData(gd); + + final Label phoneLabel = new Label(container, SWT.NONE); + phoneLabel.setText("Phone"); + + phoneNumberValue = new Text(container, SWT.BORDER); + phoneNumberValue.setLayoutData(gd); + + contact = new Contact("BorisBokowski", "boris.at.somecompany.com", + "1-123-456-7890"); + + bindUI(); + } + + private void bindUI() { + DataBindingContext dbc = new DataBindingContext(); + + final IObservableValue name = BeansObservables.observeValue(contact, + "name"); + dbc.bindValue(SWTObservables.observeText(nameValue, SWT.Modify), name, + null, null); + + final IObservableValue email = BeansObservables.observeValue(contact, + "email"); + dbc.bindValue(SWTObservables.observeText(emailValue, SWT.Modify), + email, null, null); + + final IObservableValue phone = BeansObservables.observeValue(contact, + "phoneNumber"); + dbc.bindValue(SWTObservables.observeText(phoneNumberValue, SWT.Modify), + phone, null, null); + + MultiValidator validator = new MultiValidator() { + protected IStatus validate() { + + // Everything accessed here will trigger re-validation. + name.getValue(); + email.getValue(); + phone.getValue(); + + System.out.println("Validating..."); + + return contact.validate(); + } + }; + dbc.addValidationStatusProvider(validator); + + WizardPageSupport.create(this, dbc); + } + + static class ExternalValidationWizard extends Wizard { + public void addPages() { + addPage(new Snippet027ExternalValidator()); + } + + public String getWindowTitle() { + return "Snippet 024 - External Validation"; + } + + public boolean performFinish() { + return true; + } + } + + public static void main(String[] args) { + Display display = new Display(); + + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + IWizard wizard = new ExternalValidationWizard(); + WizardDialog dialog = new WizardDialog(null, wizard); + dialog.open(); + + // The SWT event loop + Display display = Display.getCurrent(); + while (dialog.getShell() != null + && !dialog.getShell().isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + + display.dispose(); + } +} \ No newline at end of file diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet028DuplexingObservableValue.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet028DuplexingObservableValue.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,297 @@ +/******************************************************************************* + * 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) + * Matthew Hall - bugs 262407, 260337 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +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.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.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")); + + ViewerSupport.bind(viewer, movies, BeanProperties.values( + MovieInfo.class, new String[] { "title", "releaseDate", + "director", "writer" })); + + // 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), + DuplexingObservableValue.withDefaults(BeanProperties.value( + "title").observeDetail(selections), "", + "")); + dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(releaseDate), + DuplexingObservableValue.withDefaults(BeanProperties.value( + "releaseDate").observeDetail(selections), "", + "")); + dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(director), + DuplexingObservableValue.withDefaults(BeanProperties.value( + "director").observeDetail(selections), "", + "")); + dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(writer), + DuplexingObservableValue.withDefaults(BeanProperties.value( + "writer").observeDetail(selections), "", + "")); + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet029TreeViewerMultiListProperty.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet029TreeViewerMultiListProperty.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,257 @@ +/******************************************************************************* + * 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) + * Matthew Hall - bugs 262407, 260337 + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.property.list.IListProperty; +import org.eclipse.core.databinding.property.list.MultiListProperty; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ObservableListTreeContentProvider; +import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.2 + * + */ +public class Snippet029TreeViewerMultiListProperty { + protected Shell shell; + private TreeViewer viewer; + + /** + * Launch the application + * + * @param args + */ + public static void main(String[] args) { + try { + Snippet029TreeViewerMultiListProperty window = new Snippet029TreeViewerMultiListProperty(); + 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(new FillLayout()); + + viewer = new TreeViewer(shell, SWT.FULL_SELECTION | SWT.MULTI + | SWT.BORDER); + + 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 Catalog extends AbstractModelObject { + private String name; + private List catalogs = new ArrayList(); + private List items = new ArrayList(); + + public Catalog(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + firePropertyChange("name", this.name, this.name = name); + } + + public List getCatalogs() { + return catalogs; + } + + public void setCatalogs(List catalogs) { + firePropertyChange("catalogs", this.catalogs, + this.catalogs = catalogs); + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + firePropertyChange("items", this.items, this.items = items); + } + } + + public static class CatalogItem extends AbstractModelObject { + private String name; + + public CatalogItem(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + firePropertyChange("name", this.name, this.name = name); + } + } + + private void bindUI() { + List items; + + Catalog fruits = new Catalog("Fruits"); + items = new ArrayList(); + items.add(new CatalogItem("Apple")); + items.add(new CatalogItem("Orange")); + fruits.setCatalogs(items); + + Catalog vegetables = new Catalog("Vegetables"); + items = new ArrayList(); + items.add(new CatalogItem("Peas")); + items.add(new CatalogItem("Carrots")); + items.add(new CatalogItem("Potatoes")); + vegetables.setItems(items); + + Catalog foods = new Catalog("Foods"); + items = new ArrayList(); + items.add(fruits); + items.add(vegetables); + foods.setCatalogs(items); + + items = new ArrayList(); + items.add(new CatalogItem("Own Hand")); + foods.setItems(items); + + Catalog catalog = new Catalog("Main Catalog"); + items = new ArrayList(); + items.add(foods); + catalog.setCatalogs(items); + + IListProperty childrenProperty = new MultiListProperty( + new IListProperty[] { BeanProperties.list("catalogs"), + BeanProperties.list("items") }); + + ObservableListTreeContentProvider contentProvider = new ObservableListTreeContentProvider( + childrenProperty.listFactory(), null); + viewer.setContentProvider(contentProvider); + + ObservableMapLabelProvider labelProvider = new ObservableMapLabelProvider( + BeanProperties.value("name").observeDetail( + contentProvider.getKnownElements())) { + Image catalogImage = createCatalogImage(); + Image catalogItemImage = createCatalogItemImage(); + + public Image getImage(Object element) { + if (element instanceof Catalog) + return catalogImage; + if (element instanceof CatalogItem) + return catalogItemImage; + return super.getImage(element); + } + + public void dispose() { + catalogImage.dispose(); + catalogItemImage.dispose(); + super.dispose(); + } + + private Image createCatalogImage() { + Display display = Display.getCurrent(); + Image catalogImage = new Image(display, 12, 12); + GC gc = new GC(catalogImage); + gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN)); + gc.fillArc(1, 1, 10, 10, 0, 360); + gc.dispose(); + return catalogImage; + } + + private Image createCatalogItemImage() { + Display display = Display.getCurrent(); + Image catalogImage = new Image(display, 12, 12); + GC gc = new GC(catalogImage); + gc.setBackground(display.getSystemColor(SWT.COLOR_CYAN)); + gc.fillPolygon(new int[] { 1, 10, 5, 1, 6, 1, 10, 10, 1, 10 }); + gc.dispose(); + return catalogImage; + } + }; + viewer.setLabelProvider(labelProvider); + + viewer.setInput(catalog); + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet030DateAndTimeObservableValue.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet030DateAndTimeObservableValue.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,146 @@ +/******************************************************************************* + * 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 169876) + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.util.Date; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.DateAndTimeObservableValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.DateTime; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * @since 3.2 + * + */ +public class Snippet030DateAndTimeObservableValue { + protected Shell shell; + private Text modelText; + private DateTime date; + private DateTime calendar; + private DateTime time; + private Button syncTime; + + /** + * Launch the application + * + * @param args + */ + public static void main(String[] args) { + try { + Snippet030DateAndTimeObservableValue window = new Snippet030DateAndTimeObservableValue(); + 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.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + }); + } + + protected void createContents() { + shell = new Shell(); + GridLayout layout = new GridLayout(); + layout.numColumns = 3; + shell.setLayout(layout); + shell.setText("Snippet030DateAndTimeObservableValue.java"); + + new Label(shell, SWT.NONE).setText("Model date + time"); + modelText = new Text(shell, SWT.BORDER); + modelText.setEditable(false); + modelText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, + 2, 1)); + + new Label(shell, SWT.NONE).setText("Target date (SWT.DATE)"); + date = new DateTime(shell, SWT.DATE | SWT.BORDER); + date.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, + 1)); + + new Label(shell, SWT.NONE).setText("Target date (SWT.CALENDAR)"); + calendar = new DateTime(shell, SWT.CALENDAR); + calendar.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, + 2, 1)); + + new Label(shell, SWT.NONE).setText("Target time"); + time = new DateTime(shell, SWT.TIME | SWT.BORDER); + + syncTime = new Button(shell, SWT.CHECK); + syncTime.setLayoutData(new GridData()); + syncTime.setText("Sync with system time"); + + bindUI(); + } + + private void bindUI() { + DataBindingContext dbc = new DataBindingContext(); + + IObservableValue model = WritableValue.withValueType(Date.class); + model.setValue(new Date()); + + dbc.bindValue(WidgetProperties.text().observe(modelText), model); + + final IObservableValue timeSelection = WidgetProperties.selection() + .observe(time); + + dbc.bindValue(new DateAndTimeObservableValue(WidgetProperties + .selection().observe(date), timeSelection), model); + dbc.bindValue(new DateAndTimeObservableValue(WidgetProperties + .selection().observe(calendar), timeSelection), model); + + syncTime.addListener(SWT.Selection, new Listener() { + Runnable runnable = new Runnable() { + public void run() { + if (syncTime.getSelection()) { + timeSelection.setValue(new Date()); + Display.getCurrent().timerExec(100, this); + } + } + }; + + public void handleEvent(Event event) { + time.setEnabled(!syncTime.getSelection()); + if (syncTime.getSelection()) { + runnable.run(); + } + } + }); + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet031JFaceObservable.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet031JFaceObservable.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (c) 2008 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.jface.examples.databinding.snippets; + +import org.eclipse.core.commands.common.EventManager; +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.property.value.IValueProperty; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.util.JFaceProperties; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +public class Snippet031JFaceObservable { + + public static final String NAME_PROPERTY = "name_property"; + + public static void main(String[] args) { + Display display = new Display(); + final ViewModel viewModel = new ViewModel(); + + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + final Shell shell = new View(viewModel).createShell(); + // The SWT event loop + Display display = Display.getCurrent(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + // Print the results + System.out.println("person.getName() = " + + viewModel.getPerson().getName()); + } + + // The data model class. This is normally a persistent class of some sort. + // + // In this example, we extend the EventManager class + // to manage our listeners and we fire a property change + // event when the object state changes. + public static class Person extends EventManager { + // A property... + String name = "HelloWorld"; + + public String getName() { + return name; + } + + public void setName(String name) { + fireChange(new PropertyChangeEvent(this, NAME_PROPERTY, this.name, + this.name = name)); + } + + public void addPropertyChangeListener(IPropertyChangeListener listener) { + addListenerObject(listener); + } + + public void removePropertyChangeListener( + IPropertyChangeListener listener) { + removeListenerObject(listener); + } + + private void fireChange(PropertyChangeEvent event) { + final Object[] list = getListeners(); + for (int i = 0; i < list.length; ++i) { + ((IPropertyChangeListener) list[i]).propertyChange(event); + } + } + + } + + // The View's model--the root of our Model graph for this particular GUI. + // + // Typically each View class has a corresponding ViewModel class. + // The ViewModel is responsible for getting the objects to edit from the + // DAO. Since this snippet doesn't have any persistent objects to + // retrieve, this ViewModel just instantiates a model object to edit. + static class ViewModel { + // The model to bind + private Person person = new Person(); + + public Person getPerson() { + return person; + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + private Text name; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + Display display = Display.getDefault(); + Shell shell = new Shell(display); + shell.setLayout(new RowLayout(SWT.VERTICAL)); + name = new Text(shell, SWT.BORDER); + + // Bind it + DataBindingContext bindingContext = new DataBindingContext(); + Person person = viewModel.getPerson(); + + IValueProperty nameProperty = JFaceProperties.value(Person.class, + "name", NAME_PROPERTY); + + bindingContext.bindValue(SWTObservables.observeText(name, + SWT.Modify), nameProperty.observe(person), null, null); + + Label label = new Label(shell, SWT.NONE); + bindingContext.bindValue(SWTObservables.observeText(label), + nameProperty.observe(person), null, null); + + // Open and return the Shell + shell.pack(); + shell.open(); + return shell; + } + } + +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet032TableViewerColumnEditing.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet032TableViewerColumnEditing.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,255 @@ +/******************************************************************************* + * Copyright (c) 2006 The Pampered Chef, Inc. 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: + * The Pampered Chef, Inc. - initial API and implementation + * Tom Schindl - cell editing + * Matthew Hall - bugs 260329, 260337 + * Heiko Ahlig - bug 267712 + *******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.beans.IBeanValueProperty; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.list.WritableList; +import org.eclipse.core.databinding.observable.map.IObservableMap; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.property.Properties; +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.CellEditorProperties; +import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; +import org.eclipse.jface.databinding.viewers.ObservableMapCellLabelProvider; +import org.eclipse.jface.databinding.viewers.ObservableValueEditingSupport; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TextCellEditor; +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; + +/** + * Demonstrates binding a TableViewer with multiple columns to a collection. + */ +public class Snippet032TableViewerColumnEditing { + public static void main(String[] args) { + final Display display = new Display(); + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + ViewModel viewModel = new ViewModel(); + Shell shell = new View(viewModel).createShell(); + + // The SWT event loop + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + }); + } + + // 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); + } + } + + // The data model class. This is normally a persistent class of some sort. + static class Person extends AbstractModelObject { + // A property... + String name; + String firstName; + + public Person(String firstName, String name) { + this.name = name; + this.firstName = firstName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + firePropertyChange("name", this.name, this.name = name); + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + firePropertyChange("firstName", this.firstName, + this.firstName = firstName); + } + } + + // The View's model--the root of our Model graph for this particular GUI. + // + // Typically each View class has a corresponding ViewModel class. + // The ViewModel is responsible for getting the objects to edit from the + // 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 List people = new LinkedList(); + { + people.add(new Person("Dave", "Orme")); + people.add(new Person("Gili", "Mendel")); + people.add(new Person("Joe", "Winchester")); + people.add(new Person("Boris", "Bokowski")); + people.add(new Person("Brad", "Reynolds")); + people.add(new Person("Matthew", "Hall")); + } + + public List getPeople() { + return people; + } + } + + // The GUI view + static class View { + private ViewModel viewModel; + private Table committers; + private Label selectedCommitterName; + private Label selectedCommitterFirstName; + + public View(ViewModel viewModel) { + this.viewModel = viewModel; + } + + public Shell createShell() { + // Build a UI + Display display = Display.getDefault(); + Shell shell = new Shell(display); + shell.setLayout(new GridLayout(2, true)); + committers = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION); + committers.setLinesVisible(true); + committers.setHeaderVisible(true); + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + layoutData.horizontalSpan = 2; + committers.setLayoutData(layoutData); + + GridData fieldLayoutData = new GridData(SWT.FILL, SWT.BEGINNING, + true, false); + selectedCommitterName = new Label(shell, SWT.NONE); + selectedCommitterName.setLayoutData(fieldLayoutData); + + selectedCommitterFirstName = new Label(shell, SWT.NONE); + selectedCommitterFirstName.setLayoutData(fieldLayoutData); + + DataBindingContext bindingContext = new DataBindingContext(); + bindGUI(bindingContext); + + // Open and return the Shell + shell.setSize(250, 300); + shell.open(); + return shell; + } + + protected void bindGUI(DataBindingContext bindingContext) { + // Since we're using a JFace Viewer, we do first wrap our Table... + TableViewer peopleViewer = new TableViewer(committers); + + TableViewerColumn columnName = new TableViewerColumn(peopleViewer, + SWT.NONE); + columnName.getColumn().setText("Name"); + columnName.getColumn().setWidth(100); + + TableViewerColumn columnFirstName = new TableViewerColumn( + peopleViewer, SWT.NONE); + columnFirstName.getColumn().setText("FirstName"); + columnFirstName.getColumn().setWidth(100); + + // Bind viewer to model + IBeanValueProperty propName = BeanProperties.value(Person.class, + "name"); + IBeanValueProperty propFirstname = BeanProperties.value( + Person.class, "firstName"); + + IValueProperty cellEditorControlText = CellEditorProperties + .control().value(WidgetProperties.text()); + + columnName.setEditingSupport(ObservableValueEditingSupport.create( + peopleViewer, bindingContext, + new TextCellEditor(committers), cellEditorControlText, + propName)); + columnFirstName.setEditingSupport(ObservableValueEditingSupport + .create(peopleViewer, bindingContext, new TextCellEditor( + committers), cellEditorControlText, propFirstname)); + + ObservableListContentProvider contentProvider = new ObservableListContentProvider(); + peopleViewer.setContentProvider(contentProvider); + + // Bind the LabelProviders to the model and columns + IObservableMap[] result = Properties.observeEach(contentProvider + .getKnownElements(), new IBeanValueProperty[] { propName, + propFirstname }); + + columnName.setLabelProvider(new ObservableMapCellLabelProvider( + result[0])); + columnFirstName + .setLabelProvider(new ObservableMapCellLabelProvider( + result[1])); + + peopleViewer.setInput(new WritableList(viewModel.getPeople(), + Person.class)); + + // bind selectedCommitter labels to the name and forname of the + // current selection + IObservableValue selection = ViewersObservables + .observeSingleSelection(peopleViewer); + bindingContext.bindValue(SWTObservables + .observeText(selectedCommitterName), BeansObservables + .observeDetailValue(selection, "name", String.class)); + bindingContext.bindValue(SWTObservables + .observeText(selectedCommitterFirstName), BeansObservables + .observeDetailValue(selection, "firstName", String.class)); + } + } +} diff -r 0ca1aee7decf -r 6086085e153d org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet033CrossValidationControlDecoration.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet033CrossValidationControlDecoration.d Sun Apr 19 11:33:55 2009 +0200 @@ -0,0 +1,151 @@ +/******************************************************************************* + * 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 268472) + ******************************************************************************/ + +package org.eclipse.jface.examples.databinding.snippets; + +import java.util.Date; + +import org.eclipse.core.databinding.observable.Observables; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.validation.MultiValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.internal.databinding.provisional.fieldassist.ControlDecorationSupport; +import org.eclipse.jface.internal.databinding.provisional.fieldassist.ControlDecorationUpdater; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.DateTime; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.2 + * + */ +public class Snippet033CrossValidationControlDecoration { + protected Shell shell; + private DateTime startDate; + private DateTime endDate; + + /** + * Launch the application + * + * @param args + */ + public static void main(String[] args) { + try { + Snippet033CrossValidationControlDecoration window = new Snippet033CrossValidationControlDecoration(); + 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.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + } + }); + } + + protected void createContents() { + shell = new Shell(); + GridLayout layout = new GridLayout(); + layout.numColumns = 4; + shell.setLayout(layout); + shell.setText("Snippet033CrossValidationControlDecoration.java"); + + final Label label = new Label(shell, SWT.NONE); + label.setLayoutData(new GridData()); + label.setText("Start date"); + startDate = new DateTime(shell, SWT.CALENDAR); + final GridData gd_startDate = new GridData(); + gd_startDate.horizontalIndent = 10; + startDate.setLayoutData(gd_startDate); + + final Label startDateLabel = new Label(shell, SWT.NONE); + startDateLabel.setLayoutData(new GridData()); + startDateLabel.setText("End date"); + endDate = new DateTime(shell, SWT.CALENDAR); + final GridData gd_endDate = new GridData(); + gd_endDate.horizontalIndent = 10; + endDate.setLayoutData(gd_endDate); + + bindUI(); + } + + private void bindUI() { + IObservableValue startDateObservable = WidgetProperties.selection() + .observe(startDate); + IObservableValue endDateObservable = WidgetProperties.selection() + .observe(endDate); + + ControlDecorationSupport.create(new DateRangeValidator( + startDateObservable, endDateObservable, + "Start date must be on or before end date"), SWT.LEFT + | SWT.CENTER); + + // Customize the decoration's description text and image + ControlDecorationUpdater decorationUpdater = new ControlDecorationUpdater() { + protected String getDescriptionText(IStatus status) { + return "ERROR: " + super.getDescriptionText(status); + } + + protected Image getImage(IStatus status) { + return status.isOK() ? null : Display.getCurrent() + .getSystemImage(SWT.ICON_ERROR); + } + }; + ControlDecorationSupport.create(new DateRangeValidator(Observables + .constantObservableValue(new Date()), startDateObservable, + "Choose a starting date later than today"), SWT.LEFT | SWT.TOP, + (Composite) null, decorationUpdater); + } + + private static class DateRangeValidator extends MultiValidator { + private final IObservableValue start; + private final IObservableValue end; + private final String errorMessage; + + public DateRangeValidator(IObservableValue start, IObservableValue end, + String errorMessage) { + this.start = start; + this.end = end; + this.errorMessage = errorMessage; + } + + protected IStatus validate() { + Date startDate = (Date) start.getValue(); + Date endDate = (Date) end.getValue(); + if (startDate.compareTo(endDate) > 0) + return ValidationStatus.error(errorMessage); + return ValidationStatus.ok(); + } + } +}