/******************************************************************************* | |
* Copyright (c) 2008, 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 247997) | |
* Matthew Hall - bugs 261843, 260337, 265561 | |
******************************************************************************/ | |
package org.eclipse.xwt.tests.snipppets; | |
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 nameMap 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); | |
} | |
}); | |
} | |
} |