JFace databinding BeansObservables observeDetailList

thomasmalcom

Grünschnabel
Hallo zusammen,

Ich versuche das Databinding zwischen einer Personentabelle(Tableviewer) und einer Detailansicht zu implementieren.
Die Personenklasse enthält eine String-Liste von emailadressen, die in der Detailansicht ebenfalls in einem Tableviewer dargestellt werden sollen, sobald in der Personentabelle ein Eintrag ausgewhlt wurde.
Bei einzelwerten funktioniert das Databinding tadellos, aber ich versuch verzweifelt das auch mit der Emailadressliste in der Detailansicht zu schaffen.

Eventuell wäre die Verwendung von BeansObservables.observeDetailList nötig, aber ich weiss nicht wie. Ich hab schon seit tagen nach Lösungen gesucht und gegoogelt.

Kann mir da bitte jemand dabei helfen?

Vielen lieben Dank im Voraus für eure Unterstützung

Lg Thomas


Anbei mein Code. Es gibt in Zeile:
Code:
ViewerSupport.bind(peoplesAddressViewer, new WritableList(((Person)selection.getValue()).getEmailadresses(), String.class), BeanProperties.value(
					List.class, "emailadresses"));

eine NullPointerException da zu dem zeitpunkt ein "selection.getValue()" null zurück liefert.
Code:
package demos.databinding;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.criteria.Selection;

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.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 DatabindingTableViewerTest {
	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";
		List<String> emailadresses = new ArrayList<String>();

		public List<String> getEmailadresses() {
			return emailadresses;
		}

		public void setEmailadresses(List<String> emailadresses) {
			this.emailadresses = emailadresses;
		}
		
		public void addEmailadress(String emailadress) {
			this.emailadresses.add(emailadress);
		}

		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();
		{
			Person p1 = new Person("Steve Northover");
			Person p2 = new Person("Grant Gayed");
			people.add(p1);
			people.add(p2);
		}

		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 Table comaddresses;
		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.
			comaddresses = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
			comaddresses.setLinesVisible(true);
			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);
			TableViewer peoplesAddressViewer = new TableViewer(comaddresses);
			
			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);
			
			ViewerSupport.bind(peoplesAddressViewer, new WritableList(((Person)selection.getValue()).getEmailadresses(), String.class), BeanProperties.value(
					List.class, "emailadresses"));

			bindingContext.bindValue(SWTObservables
					.observeText(selectedCommitter), BeansObservables
					.observeDetailValue(selection, "name", String.class));
		}
	}

}
 
Zurück