Data binding master-detail (how?)

SWT Designer allows you to create the views, editors, perspectives, pref pages, composites, etc. that comprise Eclipse SWT & RCP applications and plug-ins.

Moderators: Konstantin.Scheglov, gnebling, Alexander.Mitin, jwren, Eric Clayberg

Data binding master-detail (how?)

Postby byronpdx » Mon Aug 18, 2008 2:31 pm

I am having difficulty figuring out if your databinding wizard does master detail data binding. In particular I have a gui composite that displays MyObject. I want to be able to set MyObject to any MyObject and have the display update. I don't want to have to recreate the gui each time and redoing data binding does not work (has some interesting side effects). So I found that using WritableValue (wv below) and the following

Code: Select all
      IObservableValue personObsNameObserveValue = BeansObservables
              .observeDetailValue(Realm.getDefault(), wv, "name",
                      String.class);
      IObservableValue addressTextTextObserveWidget = SWTObservables
              .observeText(addressText, SWT.Modify);
      IObservableValue nameTextTextObserveWidget = SWTObservables
              .observeText(nameText, SWT.Modify);
      IObservableValue addressNameObserveValue = BeansObservables
              .observeDetailValue(Realm.getDefault(), wv, "address",
                      String.class);
      //
      //
      DataBindingContext bindingContext = new DataBindingContext();
      //
      bindingContext.bindValue(nameTextTextObserveWidget,
              personObsNameObserveValue, null, null);
      bindingContext.bindValue(addressTextTextObserveWidget,
              addressNameObserveValue, null, null);

allows everything to work. But I can't seem to create this using the wizard. Am I stuck doing this by hand? Or is there something I am missing with the wizard. Now that I have figured it out I can do it quickly, as long as I don't try and use the wizard. It doesn't even parse this, leaves it blank.

Thanks
Byron Palmer
TriMet MTP Programmer/Analyst
byronpdx
 
Posts: 3
Joined: Mon Aug 18, 2008 1:55 pm

Re: Data binding master-detail (how?)

Postby Eric Clayberg » Tue Aug 19, 2008 5:49 am

It would be helpful to see a complete example of what you are trying to do. I can't do much with a code fragment.

Also, have you looked at the PhoneBookUsingDetailComposite and PhoneBookDetailComposite classes supplied with our DataBindingTest project?

That illustrates one way to do master detail data binding.
Eric Clayberg
Software Engineering Manager
Google
http://code.google.com/webtoolkit/download.html

Author: "Eclipse Plug-ins"
http://www.qualityeclipse.com
Eric Clayberg
Moderator
 
Posts: 4503
Joined: Tue Sep 30, 2003 6:39 am
Location: Boston, MA USA

Re: Data binding master-detail (how?)

Postby byronpdx » Tue Aug 19, 2008 8:05 am

I have looked at the master-detail example. This has some value for me but does not solve my problem. I need to be able to have a gui composite that displays an object. I need to be able to change to different objects and have the gui work properly. Using the default binding from the wizard binds this to a fixed object. There does not seem to be a method that will flush out all the old bindings and allow new ones to be created for a different instance of the object. Keeping all those bindings going is not a good idea. I looked and found the class org.eclipse.core.databinding.observable.value.WritableValue which encapsulates the object so that binding can be done to an object that changes. In particular, the WritableValue object is updated with a new instance of the bound object using the setValue(Object) method. But this means that the binding is different.

Instead of having a standard binding given by the wizard, the following is needed to create the binding to the object encapsulated by WritableValue.
Code: Select all
IObservableValue personObsNameObserveValue = BeansObservables.observeDetailValue(Realm.getDefault(), wv, "name",
                      String.class);

This binds the value of the object set in the WritableValue instance wv with the "name" property of that object.

The binding to the text element is the same, and the connection of these two is the same. So the change is in the creation of the IObservableValue. This is different from your example because yours uses ViewersObservables to allow multiple selections to be made.

The full code to duplicate this is shown below. My question is whether the designer will be improved to allow the creation and handling of the WritableValue or will that have to be done by hand? It isn't difficult except that it takes more time to do by hand than through the wizard.

Thanks
----
Visual class
Code: Select all
package com.palmer;

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.observable.value.WritableValue;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.StatusLineManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
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.Control;
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;

public class TestBind extends ApplicationWindow {
   
   private Text addressText;
   private Text nameText;
   private Person[] persons = { new Person("Bill Diddly", "123 SW 18th"),
           new Person("Helen Proof", "723 SE Clinton"),
           new Person("Sammy Hanker", "4363 NE 33rd") };
   private WritableValue wv = new WritableValue();

   /**
    * Create the application window
    */
   public TestBind() {
      super(null);
      createActions();
      addToolBar(SWT.FLAT | SWT.WRAP);
      addMenuBar();
      addStatusLine();
      setPerson(new Person());
   }

   /**
    * Create contents of the application window
    *
    * @param parent
    */
   @Override
   protected Control createContents(Composite parent) {
      Composite container = new Composite(parent, SWT.NONE);
      final GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 2;
      container.setLayout(gridLayout);

      final Label nameLabel = new Label(container, SWT.NONE);
      nameLabel.setText("Name");

      this.nameText = new Text(container, SWT.BORDER);
      final GridData gd_nameText = new GridData(SWT.FILL, SWT.CENTER, true,
              false);
      this.nameText.setLayoutData(gd_nameText);

      final Label addressLabel = new Label(container, SWT.NONE);
      addressLabel.setText("Address");

      this.addressText = new Text(container, SWT.BORDER);
      final GridData gd_addressText = new GridData(SWT.FILL, SWT.CENTER,
              true, false);
      this.addressText.setLayoutData(gd_addressText);
      new Label(container, SWT.NONE);

      final Button printButton = new Button(container, SWT.NONE);
      printButton.addMouseListener(new MouseAdapter() {
         public void mouseUp(final MouseEvent e) {
            System.out.println(getPerson());
         }
      });
      printButton.setText("Print");
      new Label(container, SWT.NONE);

      final Button newButton = new Button(container, SWT.NONE);
      newButton.addMouseListener(new MouseAdapter() {
         public void mouseUp(final MouseEvent e) {
            setPerson(new Person());
            getPerson().setName("new");
            initDataBindings();
         }
      });
      newButton.setText("New");

      final Group group = new Group(container, SWT.NONE);
      group.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2,
              1));
      final GridLayout gridLayout_1 = new GridLayout();
      gridLayout_1.numColumns = 3;
      group.setLayout(gridLayout_1);

      final Button person1Button = new Button(group, SWT.NONE);
      person1Button.addSelectionListener(new SelectionAdapter() {
         public void widgetSelected(final SelectionEvent e) {
            do_person1Button_widgetSelected(e);
         }
      });
      person1Button.setText("Person 1");

      final Button person2Button = new Button(group, SWT.NONE);
      person2Button.addSelectionListener(new SelectionAdapter() {
         public void widgetSelected(final SelectionEvent e) {
            do_person2Button_widgetSelected(e);
         }
      });
      person2Button.setText("Person 2");

      final Button person3Button = new Button(group, SWT.NONE);
      person3Button.addSelectionListener(new SelectionAdapter() {
         public void widgetSelected(final SelectionEvent e) {
            do_person3Button_widgetSelected(e);
         }
      });
      person3Button.setText("Person 3");
      initDataBindings();
      return container;
   }

   /**
    * Create the actions
    */
   private void createActions() {
      // Create the actions
   }

   /**
    * Create the menu manager
    *
    * @return the menu manager
    */
   @Override
   protected MenuManager createMenuManager() {
      MenuManager menuManager = new MenuManager("menu");
      return menuManager;
   }

   /**
    * Create the toolbar manager
    *
    * @return the toolbar manager
    */
   @Override
   protected ToolBarManager createToolBarManager(int style) {
      ToolBarManager toolBarManager = new ToolBarManager(style);
      return toolBarManager;
   }

   /**
    * Create the status line manager
    *
    * @return the status line manager
    */
   @Override
   protected StatusLineManager createStatusLineManager() {
      StatusLineManager statusLineManager = new StatusLineManager();
      statusLineManager.setMessage(null, "");
      return statusLineManager;
   }

   /**
    * 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 {
               TestBind window = new TestBind();
               window.setBlockOnOpen(true);
               window.open();
               Display.getCurrent().dispose();
            } catch (Exception e) {
               e.printStackTrace();
            }
         }
      });
   }

   /**
    * Configure the shell
    *
    * @param newShell
    */
   @Override
   protected void configureShell(Shell newShell) {
      super.configureShell(newShell);
      newShell.setText("New Application");
   }

   /**
    * Return the initial size of the window
    */
   @Override
   protected Point getInitialSize() {
      return new Point(500, 375);
   }

   /**
    * @param person
    *            the person to set
    */
   public void setPerson(Person person) {
      wv.setValue(person);
   }

   /**
    * @return the person
    */
   public Person getPerson() {
      return (Person) wv.getValue();
   }

   protected void do_person1Button_widgetSelected(final SelectionEvent e) {
      System.out.println("set person 0");
      setPerson(persons[0]);
   }

   protected void do_person2Button_widgetSelected(final SelectionEvent e) {
      System.out.println("set person 1");
      setPerson(persons[1]);
   }

   protected void do_person3Button_widgetSelected(final SelectionEvent e) {
      System.out.println("set person 2");
      setPerson(persons[2]);
   }
   protected DataBindingContext initDataBindings() {
      IObservableValue personObsNameObserveValue = BeansObservables
              .observeDetailValue(Realm.getDefault(), wv, "name",
                      String.class);
      IObservableValue addressTextTextObserveWidget = SWTObservables
              .observeText(addressText, SWT.Modify);
      IObservableValue nameTextTextObserveWidget = SWTObservables
              .observeText(nameText, SWT.Modify);
      IObservableValue addressNameObserveValue = BeansObservables
              .observeDetailValue(Realm.getDefault(), wv, "address",
                      String.class);
      //
      //
      DataBindingContext bindingContext = new DataBindingContext();
      //
      bindingContext.bindValue(nameTextTextObserveWidget,
              personObsNameObserveValue, null, null);
      bindingContext.bindValue(addressTextTextObserveWidget,
              addressNameObserveValue, null, null);
      //
      return bindingContext;
   }

}

Person class
Code: Select all
/**
*
*/
package com.palmer;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;


/**
* @author byron
*
*/
public class Person  {
   private String name;

   private String address;

   public Person() {
      super();
      setName("");
      setAddress("");
   }

   /**
    * @param name
    * @param address
    */
   public Person(String name, String address) {
      super();
      setName(name);
      setAddress(address);
   }

   public String getName() {
      return name;
   }

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

   public String getAddress() {
      return address;
   }

   public void setAddress(String address) {
      firePropertyChange("address", this.address, address);
      this.address = address;
   }

   @Override
   public String toString() {
      StringBuffer buf = new StringBuffer();
      buf.append("Person [ Name:").append(name);
      buf.append(" Address:").append(address).append(" ]");
      return buf.toString();
   }
   //-------------------------------------------------

   transient private PropertyChangeSupport propertyChangeSupport =
      new PropertyChangeSupport(this);


   public void addPropertyChangeListener(String propertyName,
         PropertyChangeListener listener) {
      System.out.println("addPropertyChangeListener" + propertyName);
      propertyChangeSupport.addPropertyChangeListener(propertyName,
            listener);
   }


   public void removePropertyChangeListener(String propertyName,
         PropertyChangeListener listener) {
      System.out.println("removePropertyChangeListener "+propertyName);
      propertyChangeSupport.removePropertyChangeListener(propertyName,
            listener);
   }


   protected void firePropertyChange(String propertyName, Object oldValue,
         Object newValue) {
      System.out.println("firePropertyChange " + propertyName + " "
              + oldValue + " -> " + newValue);
      propertyChangeSupport.firePropertyChange(propertyName, oldValue,
            newValue);
   }
}
Byron Palmer
TriMet MTP Programmer/Analyst
byronpdx
 
Posts: 3
Joined: Mon Aug 18, 2008 1:55 pm

Re: Data binding master-detail (how?)

Postby Eric Clayberg » Tue Aug 19, 2008 11:35 am

byronpdx wrote:I have looked at the master-detail example. This has some value for me but does not solve my problem. I need to be able to have a gui composite that displays an object. I need to be able to change to different objects and have the gui work properly.

That is what the example I pointed you to does. The PhoneBookDetailComposite has a setPerson() method that does exactly this.

byronpdx wrote:Using the default binding from the wizard binds this to a fixed object. There does not seem to be a method that will flush out all the old bindings and allow new ones to be created for a different instance of the object.

DataBindingContext.dispose()?

byronpdx wrote:My question is whether the designer will be improved to allow the creation and handling of the WritableValue

Designer v6.7.0 already has good support for WritableValues used as direct bound objects or as attributes of other objects.

Image

It does not yet have support for sub attributes of complex WritableValues which appears to be what you are looking for (you are the first to ever ask for that).

We have added that to our list of things to support in the future.
Eric Clayberg
Software Engineering Manager
Google
http://code.google.com/webtoolkit/download.html

Author: "Eclipse Plug-ins"
http://www.qualityeclipse.com
Eric Clayberg
Moderator
 
Posts: 4503
Joined: Tue Sep 30, 2003 6:39 am
Location: Boston, MA USA

Re: Data binding master-detail (how?)

Postby Eric Clayberg » Sat Aug 23, 2008 10:37 am

Eric Clayberg wrote:It does not yet have support for sub attributes of complex WritableValues which appears to be what you are looking for (you are the first to ever ask for that).
We have added that to our list of things to support in the future.

Give this a try in the very latest SWT Designer build.

master_detail1.gif
Select "Detail for IObservableValue"
master_detail1.gif (55.65 KiB) Viewed 1553 times

master_detail2.gif
Specifiy master bean class and select property
master_detail2.gif (23.42 KiB) Viewed 1551 times
Eric Clayberg
Software Engineering Manager
Google
http://code.google.com/webtoolkit/download.html

Author: "Eclipse Plug-ins"
http://www.qualityeclipse.com
Eric Clayberg
Moderator
 
Posts: 4503
Joined: Tue Sep 30, 2003 6:39 am
Location: Boston, MA USA


Return to SWT Designer

Who is online

Users browsing this forum: No registered users and 2 guests