Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » JFace » TreeViewer and DataBinding(Bidirectional DataBinding in treeviewer)
TreeViewer and DataBinding [message #556296] Tue, 31 August 2010 15:59 Go to next message
budili Missing name is currently offline budili Missing nameFriend
Messages: 64
Registered: May 2010
Member
Hello,

i want to build an treeviewer with bidirectional databinding.
At the moment i have a treeviewer with unidirectional databinding (ui to model), but i want the binding model -> ui, too.
How i can realize this?

I have a complex model, and dont know how i should the to build it.
I have read a litte bit of CNF and LunaRCP, but dont know if this could help me.



Re: TreeViewer and DataBinding [message #556401 is a reply to message #556296] Wed, 01 September 2010 07:43 Go to previous messageGo to next message
budili Missing name is currently offline budili Missing nameFriend
Messages: 64
Registered: May 2010
Member
I have seen the snippet 29 from the databinding examples, and that looks very nice. I want use the ObservableListTreeContentProvider, but i dont know how i can paste my model to this Provider. The constructor needs an obsverable factory. How i can build this factory ?

My model looks like this (without getter and setter):
public class MainModelClass
{
    private SystemConfig; 
    private List<ShelfConfig> shelfConfig;
}

public class SystemConfig 
{
    private GlobalTimer globalTimer;
    private NumberTable numberTable;
    private GroupTable groupTable;
}

public class ShelfConfig
{
    private SlotTable slotTable;
    private DxiTable dxiTable;
    private DapTable dapTable;
}

Thats my original model, generated from JAXB. The root of the model is the "MainModelClass". Now i want the following structure in my treeviewer:

+ Main
   - GlobalTime
   - NumberTable
   - GroupTable
   + Shelf 1
         - SlotTable
         - DxiTable
         - DapTable
   + Shelf 2
         - SlotTable
         - DxiTable
         - DapTable
   + Shelf 3 
         - SlotTable
         - DxiTable
         - DapTable
   + Shelf N

[Updated on: Wed, 01 September 2010 07:44]

Report message to a moderator

Re: TreeViewer and DataBinding [message #556603 is a reply to message #556401] Thu, 02 September 2010 04:55 Go to previous messageGo to next message
Matthew Hall is currently offline Matthew HallFriend
Messages: 368
Registered: July 2009
Senior Member
You have to have some kind of object to contain the root nodes in the
tree, and set that as your input.

Typically what you do is extend DelegatingListProperty, and in your
doGetDelegate method return the appropriate list property depending on
the type of the object passed in. e.g. if the object is Main, you would
return BeanProperties.list(Main.class, "shelves").

However in your case, you're showing value properties alongside the
usual "children" list properties, so you have to roll your own
observable factory. Something like this:

final Object input = new Object[] { main };
IObservableFactory childrenFactory = new IObservableFactory() {
public IObservable createObservable(Object target) {
if (target == input) {
return Properties.selfList(Main.class)
.observe(Collections.singletonList(target));
}
if (target instanceof Main) {
return observeMainChildren((Main) target);
}
if (target instanceof Shelf) {
return observeShelfChildren((Shelf) target);
}
}

private IObservable observeMainChildren(Main target) {
final IObservableValue globalTimer =
BeanProperties.value("globalTimer").observe(target);
final IObservableValue numberTable =
BeanProperties.value("numberTable").observe(target);
final IObservableValue groupTable =
BeanProperties.value("groupTable").observe(target);

IObservableList valueChildren = new ComputedList() {
protected List calculate() {
return Arrays.asList(globalTimer.getValue(),
numberTable.getValue(),
groupTable.getValue());
}
});

return new MultiList(new IObservableList[] {
valueChildren,
BeanProperties.list("shelves").observe(target);
});
}

private IObservable observeShelfChildren(Shelf target) {
... etc
}
};

viewer.setInput(input);

There might be a possibility of a memory leak the way I've written this,
so you might want to attach a dispose listener to the valueChildren
observable to make sure that the globalTimer, numberTable and groupTable
observables get disposed along with the computed list.

Hope this helps,

Matthew

On 09/01/2010 01:43 AM, budili wrote:
> I have seen the snippet 29 from the databinding examples, and that looks
> very nice. I want use the ObservableListTreeContentProvider, but i dont
> want how i can paste my model to this Provider. The constructor needs an
> obsverable factory.
> My model looks like this (without getter and setter):
>
> public class MainModelClass
> {
> private SystemConfig; private List<ShelfConfig> shelfConfig;
> }
>
> public class SystemConfig {
> private GlobalTimer globalTimer;
> private NumberTable numberTable;
> private GroupTable groupTable;
> }
>
> public class ShelfConfig
> {
> private SlotTable slotTable;
> private DxiTable dxiTable;
> private DapTable dapTable;
> }
>
> Thats my original model, generated from JAXB. The root of the model is
> the "MainModelClass". Now i want the following structure in my treeviewer:
>
>
> + Main
> - GlobalTime
> - NumberTable
> - GroupTable
> + Shelf 1
> - SlotTable
> - DxiTable
> - DapTable
> + Shelf 2
> - SlotTable
> - DxiTable
> - DapTable
> + Shelf 3 - SlotTable
> - DxiTable
> - DapTable
> + Shelf N
>
Re: TreeViewer and DataBinding [message #556806 is a reply to message #556603] Thu, 02 September 2010 16:32 Go to previous messageGo to next message
budili Missing name is currently offline budili Missing nameFriend
Messages: 64
Registered: May 2010
Member
Hallo Matthew,

that's very nice and works well, but i have one problem with your solution. I have now the whole model in my treeviewer, but it dont update the treeviewer if i add "ShelfConfig's" in my model list. The viewer dont refreshed. Heres my code:

final Object[] input = new Object[] { new MainModelClass() };
        final IObservableFactory childrenFactory = new NaviObservableFactory(input, viewer);
        final ObservableListTreeContentProvider contentProvider = new ObservableListTreeContentProvider(childrenFactory, null);
        viewer.setContentProvider(contentProvider);
        final IObservableSet knownElements = contentProvider.getKnownElements();
        viewer.setLabelProvider(new NavigationLabelProvider(BeanProperties.value("logKey").observeDetail(knownElements)));
        viewer.setInput(input[0]);


And here is my factory class:
public class NaviObservableFactory implements IObservableFactory
{
    private final transient Object input;


    public NaviObservableFactory(final Object input)
    {
        this.input = input;
    }

    @Override
    public final IObservable createObservable(final Object target)
    {
        if (target == input)
        {
            return Properties.selfList(MainModelClass.class).observe(Collections.singletonList(target));
        }
        if (target instanceof MainModelClass)
        {
            return observeMainChildren((MainModelClass) target);
        }
        if (target instanceof ShelfConfig)
        {
            return observeShelfChildren((ShelfConfig) target);
        }

        return null;
    }

    private IObservable observeMainChildren(final MainModelClass target)
    {
        final IObservableValue numberTable= BeanProperties.value("systemConfig.numberTable").observe(target);
        final IObservableValue groupTable = BeanProperties.value("systemConfig.groupTable").observe(target);

        final IObservableList valueChildren = new ComputedList()
        {
            @Override
            protected List calculate()
            {
                return Arrays.asList(numberTable.getValue(), groupTable.getValue());
            }
        };
        return new MultiList(new IObservableList[] { valueChildren, BeanProperties.list("shelfConfig").observe(target) });
    }

    private IObservable observeShelfChildren(final ShelfConfig target)
    {
        final IObservableValue slotTable= BeanProperties.value("slotTable").observe(target);
        final IObservableList valueChildren = new ComputedList()
        {
            @Override
            protected List calculate()
            {
                return Arrays.asList(slotTable.getValue());
            }
        };

        return new MultiList(new IObservableList[] { valueChildren });
    }
}


All works with this method very well, only the update dont work.
What could be the problem?

If i add a new ShelfConfig, for example so:
new ShelfConfig shelf = new ShelfConfig();
MainModelClass.getShelfConfigs.add(shelf);


than the viewer dont updates. Only if i doing an manual refresh,
than its updates. Have anyone an solution?
Re: TreeViewer and DataBinding [message #557186 is a reply to message #556806] Sun, 05 September 2010 20:44 Go to previous messageGo to next message
Matthew Hall is currently offline Matthew HallFriend
Messages: 368
Registered: July 2009
Senior Member
Based on your example it looks like you are modifying the
MainModel.shelfConfigs internal state directly. In order for
BeanProperties to catch on to the change, you should make your
getShelfConfigs() return a Collections.unmodifiableList view of your
internal state. Then add methods new to add and remove shelves, and
which fire the appropriate PropertyChangeEvent :

public class MainModel {

private PropertyChangeSupport changeSupport =
new PropertyChangeSupport(this);

private List<ShelfConfig> shelfConfigs;

public List<ShelfConfig> getShelfConfigs() {
return Collections.unmodifiableList(shelfConfigs);
}

public void setShelfConfigs(List<ShelfConfigs> shelfConfigs) {
List<ShelfConfig> oldState = getShelfConfigs();
this.shelfConfigs = shelfConfigs;
List<ShelfConfig> newState = getShelfConfigs();
changeSupport.firePropertyChange("shelfConfigs", oldState,
newState);
}

public void addShelfConfig(ShelfConfig config) {
List<ShelfConfig> oldState = getShelfConfigs();
if (shelfConfigs.add(config)) {
List<ShelfConfig> newState = getShelfConfigs();
changeSupport.firePropertyChange("shelfConfigs", oldState,
newState);
}
}

public void addShelfConfig(ShelfConfig config) {
List<ShelfConfig> oldState = getShelfConfigs();
if (shelfconfigs.remove(config)) {
List<ShelfConfig> newState = getShelfConfigs();
changeSupport.firePropertyChange("shelfConfigs", oldState,
newState);
}
}

// traditional add/remove property change listener methods

}

Hope this helps,

Matthew

On 09/02/2010 10:32 AM, budili wrote:
> All works with this method very well, only the update dont work.
> What could be the problem?
> If i add a new ShelfConfig, for example so:
>
> new ShelfConfig shelf = new ShelfConfig();
> MainModelClass.getShelfConfigs.add(shelf);
>
>
> than the viewer dont updates. Only if i doing an manual refresh, than
> its updates. Have anyone an solution?
Re: TreeViewer and DataBinding [message #557187 is a reply to message #556806] Sun, 05 September 2010 20:49 Go to previous messageGo to next message
Matthew Hall is currently offline Matthew HallFriend
Messages: 368
Registered: July 2009
Senior Member
Also don't forget to add dispose listeners to the computed list so that
the IObservableValues above get disposed, otherwise you will get a
memory leak. Additional code inline:

On 09/02/2010 10:32 AM, budili wrote:
> private IObservable observeMainChildren(final MainModelClass target)
> {
> final IObservableValue numberTable=
> BeanProperties.value("systemConfig.numberTable").observe(target);
> final IObservableValue groupTable =
> BeanProperties.value("systemConfig.groupTable").observe(target);
>
> final IObservableList valueChildren = new ComputedList()
> {
> @Override
> protected List calculate()
> {
> return Arrays.asList(numberTable.getValue(), groupTable.getValue());
> }
> };

valueChildren.addDisposeListener(new IDisposeListener() {
public void handleDispose(DisposeEvent event) {
numberTable.dispose();
groupTable.dispose();
}
} );

> return new MultiList(new IObservableList[] { valueChildren,
> BeanProperties.list("shelfConfig").observe(target) });
> }

Matthew
Re: TreeViewer and DataBinding [message #557233 is a reply to message #557187] Mon, 06 September 2010 08:30 Go to previous message
budili Missing name is currently offline budili Missing nameFriend
Messages: 64
Registered: May 2010
Member
Hello Matthew,

that's very nice, thx for your answers.

I have three another questions:

1.
You have said i have to dispose the IObservableValues.
Whats about the BeanProperties.list("shelves") ?
I Should dispose this list too?

2.
What kind of observables i should to dispose in general ?

3.
I dont understand the scenario with the Collections.unmodifiableList:
public List<ShelfConfig> getShelfConfigs() {
return Collections.unmodifiableList(shelfConfigs);
}

I have try it, but it dont work. At the moment i add the shelfConfig direct in my model and refreh after the viewer.
Previous Topic:How to avoid scaling of column images in jface TableViewer
Next Topic:TreeViewer with checkboxes
Goto Forum:
  


Current Time: Fri Apr 26 06:01:56 GMT 2024

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

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

Back to the top