Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Rich Client Platform (RCP) » Single Model, TreeViewer, Databinding POJO, automatic update
Single Model, TreeViewer, Databinding POJO, automatic update [message #494843] Mon, 02 November 2009 21:51 Go to next message
epoch  is currently offline epoch Friend
Messages: 12
Registered: September 2009
Junior Member
This is following up on a previous post but is distinct enough to be in a separate thread.

My problem is that I want to use a single model (say, via a singleton) and a treeviewer.

This model has a list of domain objects (which are POJOs because they originate from a domain library).

I can bind the model to the treeviewer easily but I cannot work out how I could get the treeviewer to refresh when an object in the model changes. Obviously, because the model has POJO's, they do not have PropertyChangeSupport.

As an example, consider the following snippet (which compiles are demonstrates what I want to achieve). When an item in the treeview is selected, the name of that object is updated.

However, in this example, the domain object, Something does contain PropertyChangeSuport and thus works.

What do I do in order to keep the example working but remove the PropertyChangeSupport from the domain object? (which I can't really do in my application)

Cheers

/*******************************************************************************
 * Copyright (c) 2009 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.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.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ViewerSupport;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
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.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

class Something {
	PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.removePropertyChangeListener(listener);
	}

	public void addPropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.addPropertyChangeListener(listener);
	}

	public boolean hasListeners(String propertyName) {
		return changeSupport.hasListeners(propertyName);
	}

	public Something(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		changeSupport.firePropertyChange("name", this.name, this.name = name);
	}

	private String name;
}

class Model {
	PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.removePropertyChangeListener(listener);
	}

	public void addPropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.addPropertyChangeListener(listener);
	}

	public boolean hasListeners(String propertyName) {
		return changeSupport.hasListeners(propertyName);
	}

	private static Model singleton = new Model();

	public static Model getInstance() {
		return singleton;
	}

	public Model() {
		createList();
	}

	public void setList(List<Something> list) {
		changeSupport.firePropertyChange("list", this.list, this.list = list);
	}

	public List<Something> getList() {
		return list;
	}

	private void createList() {
		list = new ArrayList<Something>();
		for (int x = 0; x < 10; x++)
			list.add(new Something(String.format("Something %d", x)));
	}

	private List<Something> list;
}

public class SingleModelTest {

	public static void main(String[] args) {
		Display display = Display.getDefault();
		Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
			public void run() {
				try {
					SingleModelTest window = new SingleModelTest();
					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();
		final GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 1;
		shell.setLayout(gridLayout);

		Composite container = new Composite(shell, SWT.NONE);
		container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2,
				1));
		treeViewer = createTreeViewer(container);
		container.setLayout(new GridLayout());
		treeViewer.getTree().setLayoutData(
				new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));

		treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				if (event.getSelection() instanceof IStructuredSelection) {
					IStructuredSelection s = (IStructuredSelection) event
							.getSelection();
					if (s.getFirstElement() instanceof Something) {
						Something selection = (Something) s.getFirstElement();

						selection.setName("Something New");
					}
				}
			}
		});

		initExtraBindings(treeViewer);
	}

	private TreeViewer createTreeViewer(Composite parent) {
		TreeViewer viewer = new TreeViewer(parent, SWT.FULL_SELECTION
				| SWT.BORDER);
		viewer.setUseHashlookup(true);

		return viewer;
	}

	private void initExtraBindings(TreeViewer viewer) {
		ViewerSupport.bind(viewer, Model.getInstance(), BeanProperties.list(
				"list", Model.class), BeanProperties.value(Something.class,
				"name"));
	}

	private TreeViewer treeViewer;
	private Shell shell;
}


Re: Single Model, TreeViewer, Databinding POJO, automatic update [message #494846 is a reply to message #494843] Mon, 02 November 2009 22:13 Go to previous messageGo to next message
Wim Jongman is currently offline Wim JongmanFriend
Messages: 423
Registered: July 2009
Senior Member
Hi,

Who changes the model?

Regards,

Wim


> This is following up on a previous post but is distinct enough to be in a
separate thread.
>
> My problem is that I want to use a single model (say, via a singleton) and
a treeviewer.
>
> This model has a list of domain objects (which are POJOs because they
originate from a domain library).
>
> I can bind the model to the treeviewer easily but I cannot work out how I
could get the treeviewer to refresh when an object in the model changes.
Obviously, because the model has POJO's, they do not have
PropertyChangeSupport.
>
> As an example, consider the following snippet (which compiles are
demonstrates what I want to achieve). When an item in the treeview is
selected, the name of that object is updated.
>
> However, in this example, the domain object, Something does contain
PropertyChangeSuport and thus works.
>
> What do I do in order to keep the example working but remove the
PropertyChangeSupport from the domain object? (which I can't really do in my
application)
>
> Cheers
>
>
>
/*********************************************************** ********************
> * Copyright (c) 2009 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.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.jface.databinding.swt.SWTObservables;
> import org.eclipse.jface.databinding.viewers.ViewerSupport;
> import org.eclipse.jface.viewers.ISelectionChangedListener;
> import org.eclipse.jface.viewers.IStructuredSelection;
> import org.eclipse.jface.viewers.SelectionChangedEvent;
> 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.Composite;
> import org.eclipse.swt.widgets.Display;
> import org.eclipse.swt.widgets.Shell;
>
> class Something {
> PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
>
> public void removePropertyChangeListener(PropertyChangeListener listener) {
> changeSupport.removePropertyChangeListener(listener);
> }
>
> public void addPropertyChangeListener(PropertyChangeListener listener) {
> changeSupport.addPropertyChangeListener(listener);
> }
>
> public boolean hasListeners(String propertyName) {
> return changeSupport.hasListeners(propertyName);
> }
>
> public Something(String name) {
> super();
> this.name = name;
> }
>
> public String getName() {
> return name;
> }
>
> public void setName(String name) {
> changeSupport.firePropertyChange("name", this.name, this.name = name);
> }
>
> private String name;
> }
>
> class Model {
> PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
>
> public void removePropertyChangeListener(PropertyChangeListener listener) {
> changeSupport.removePropertyChangeListener(listener);
> }
>
> public void addPropertyChangeListener(PropertyChangeListener listener) {
> changeSupport.addPropertyChangeListener(listener);
> }
>
> public boolean hasListeners(String propertyName) {
> return changeSupport.hasListeners(propertyName);
> }
>
> private static Model singleton = new Model();
>
> public static Model getInstance() {
> return singleton;
> }
>
> public Model() {
> createList();
> }
>
> public void setList(List<Something> list) {
> changeSupport.firePropertyChange("list", this.list, this.list = list);
> }
>
> public List<Something> getList() {
> return list;
> }
>
> private void createList() {
> list = new ArrayList<Something>();
> for (int x = 0; x < 10; x++)
> list.add(new Something(String.format("Something %d", x)));
> }
>
> private List<Something> list;
> }
>
> public class SingleModelTest {
>
> public static void main(String[] args) {
> Display display = Display.getDefault();
> Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
> public void run() {
> try {
> SingleModelTest window = new SingleModelTest();
> 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();
> final GridLayout gridLayout = new GridLayout();
> gridLayout.numColumns = 1;
> shell.setLayout(gridLayout);
>
> Composite container = new Composite(shell, SWT.NONE);
> container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2,
> 1));
> treeViewer = createTreeViewer(container);
> container.setLayout(new GridLayout());
> treeViewer.getTree().setLayoutData(
> new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
>
> treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
> public void selectionChanged(SelectionChangedEvent event) {
> if (event.getSelection() instanceof IStructuredSelection) {
> IStructuredSelection s = (IStructuredSelection) event
> .getSelection();
> if (s.getFirstElement() instanceof Something) {
> Something selection = (Something) s.getFirstElement();
>
> selection.setName("Something New");
> }
> }
> }
> });
>
> initExtraBindings(treeViewer);
> }
>
> private TreeViewer createTreeViewer(Composite parent) {
> TreeViewer viewer = new TreeViewer(parent, SWT.FULL_SELECTION
> | SWT.BORDER);
> viewer.setUseHashlookup(true);
>
> return viewer;
> }
>
> private void initExtraBindings(TreeViewer viewer) {
> ViewerSupport.bind(viewer, Model.getInstance(), BeanProperties.list(
> "list", Model.class), BeanProperties.value(Something.class,
> "name"));
> }
>
> private TreeViewer treeViewer;
> private Shell shell;
> }
Re: Single Model, TreeViewer, Databinding POJO, automatic update [message #494850 is a reply to message #494843] Mon, 02 November 2009 22:25 Go to previous messageGo to next message
epoch  is currently offline epoch Friend
Messages: 12
Registered: September 2009
Junior Member
There are few use cases (but they might be fuelled by a misunderstanding).

In a perspective a Properties View and a Properties Dialog (the properties dialog might have a page which allows a name to be changed).

Does this help?

Cheers
Re: Single Model, TreeViewer, Databinding POJO, automatic update [message #494858 is a reply to message #494843] Mon, 02 November 2009 22:43 Go to previous messageGo to next message
Wim Jongman is currently offline Wim JongmanFriend
Messages: 423
Registered: July 2009
Senior Member
Hi,

Yes, because since you have a POJO with no warning mechanism you have to rely
on the updater of the model to wave the flag (name it the controller). When
the view comes op, it registers itself with the controller, which could be a
static class, for starters.

Controller() {

static List listners = new ArrayList();

static addListener(Listener listener){
listeners.add(listener);
}

changed(Object myPojo){
for(Listener listener:listeners)
listener.fire(myPojo);
}
}

then if the propertiesview or whatever updates your model

myPojo.setSomething(foo);
Controller.changed(myPojo);

and the view does

fire(Object pojo){
viewer.refresh(pojo, true); // or whatever you must do to refresh
}


Hope this helps,

Wim
Re: Single Model, TreeViewer, Databinding POJO, automatic update [message #494891 is a reply to message #494858] Tue, 03 November 2009 06:44 Go to previous messageGo to next message
T. Wilhelm is currently offline T. WilhelmFriend
Messages: 129
Registered: July 2009
Senior Member
Hey,

so i think there are some more ways. One is the way Wim already mentioned. In addition to that you could use the Decorater Pattern, or you simply subclass your Pojos and overwrite the set() methods.

Greetz
Thomas
Re: Single Model, TreeViewer, Databinding POJO, automatic update [message #496082 is a reply to message #494843] Sun, 08 November 2009 09:34 Go to previous message
epoch  is currently offline epoch Friend
Messages: 12
Registered: September 2009
Junior Member
I thought I'd share how I approached this problem is in the end and if there are any shortcomings, please let me know.

I have shared controller instance (a singleton) which is used through a perspective. The controller provides listeners for changes to the model, through IModelChangeEvent and IModelChangeListener. It is provides access to a shared model.


public interface IModelChangeEvent {
   enum Type { Add, Remove, Delete };
   void getObject();
   void getType();
}

// implementation (ModelChangeEvent) ommitted

public interface IModelChangeListener {
   void modelChanged(IModelChangeEvent event);
}

public class PerspectiveController {
   void addModelChangedListener(IModelChangeListener listener) {
      modelChangedListeners.add(listener);
   }

   void removeModelChangedListener(IModelChangedListener listener) {
      modelChangedListeners.remove(listener);
    }

   void fireModelChanged(IModelChangedEvent event) {
      for(IModelChangeListener listener : modelChangeListeners) {
          listener.modelChanged(event);
       }
    }



   private List<IModelChangeListener> modelChangeListeners = new LinkedList<IModelChangeListener>();
   private ScriptModel model = new ScriptModel();
}

public class ScriptModel {
   public List<DomainObject> getObjects() {
       // get domain objects from somewhere
   }
}


When a domain object is changed, say by the PropertiesView, the view calls the ScriptingPerspective.fireModelChanged(object, type); method to reflect changes throughout the perspective. For example:

domainObject.setName("A new name");
ScriptingPerspective.INSTANCE.fireModelChanged(new ModelChangedEvent(domainObject, Type.Update));


Views (such as a treeviewer) and also Editor parts listen for changes to the model and can now update accordingly.

I hope this helps and if anyone has any suggestions, please say.

Thanks everyone.
Previous Topic:Upgrading product fails?
Next Topic:work with read only data location
Goto Forum:
  


Current Time: Tue Apr 16 07:00:53 GMT 2024

Powered by FUDForum. Page generated in 0.21746 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top