Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » JFace » [Databinding] between TreeViewer.selection and Button.enabled
[Databinding] between TreeViewer.selection and Button.enabled [message #484508] Mon, 07 September 2009 16:25 Go to next message
Heiko Ahlig is currently offline Heiko Ahlig
Messages: 62
Registered: July 2009
Member
This is a multi-part message in MIME format.
--------------060406060502010500020402
Content-Type: text/plain; charset=ISO-8859-15; format=flowed
Content-Transfer-Encoding: 7bit

Hi,
I tried to build a dialog, with an TreeViewer.
If there is no "connection" seleted, the Dialog Ok-Button should be
disabled.

As attachment is a sample, but there it dosent work.

Can somebody tell me whats wrong?

In addition, i find my solution for the ColumnLabelProvider not realy good.
Exists an solution to show diffrent LabelProperties for diffrent classes
in one column?


Greetings and thx for help

Heiko



--------------060406060502010500020402
Content-Type: text/plain;
name="SnippetDatabindingProblem.java"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="SnippetDatabindingProblem.java"

package org.eclipse.jface.examples.databinding.snippets;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.PojoProperties;
import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.property.list.IListProperty;
import org.eclipse.core.databinding.property.list.MultiListProperty ;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.IViewerObservableValue ;
import org.eclipse.jface.databinding.viewers.ObservableListTreeCont entProvider;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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;

public class SnippetDatabindingProblem {
public static void main(String[] args) {
final Display display = new Display();
Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
public void run() {
Shell shell = new Shell(display);
shell.setText("Data Binding Snippet 004");
shell.setLayout(new GridLayout());
shell.setLayoutData(new GridData());
Button button = new Button(shell, SWT.PUSH);
button.setText("Press to open dialog");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Shell eventShell = e.display.getActiveShell();
eventShell.setText("test");
LoginDialog dialog = new LoginDialog(eventShell);
dialog.open();
}

});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}
});
display.dispose();
}

static class LoginDialog extends TitleAreaDialog {
private DataBindingContext dbc;
private IViewerObservableValue selObs;

public LoginDialog(Shell parentShell) {
super(parentShell);

}

@Override
protected Control createDialogArea(Composite parent) {
this.setTitle("Login Dialog");
setMessage("Select Connection");
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, true);
layout.marginHeight = 5;
layout.marginWidth = 5;
layout.verticalSpacing = 5;
layout.horizontalSpacing = 5;
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
composite.setFont(parent.getFont());
// Build the separator line
Label titleBarSeparator = new Label(composite, SWT.HORIZONTAL
| SWT.SEPARATOR);
GridData sepLayoutData = new GridData(GridData.FILL_HORIZONTAL);
sepLayoutData.horizontalSpan = 2;
titleBarSeparator.setLayoutData(sepLayoutData);
Composite viewerComposite = new Composite(composite, SWT.NONE);
TreeViewer viewer = new TreeViewer(viewerComposite);
TreeViewerColumn column = new TreeViewerColumn(viewer, SWT.LEFT);
column.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
if (element instanceof ConnectorFactory) {
return ((ConnectorFactory) element).getConnectorType();
} else if (element instanceof Connection) {
return ((Connection) element).getName();
}
return super.getText(element);
}

});
TreeColumnLayout viewerLayout = new TreeColumnLayout();
viewerLayout.setColumnData(column.getColumn(),
new ColumnWeightData(100));
viewerComposite.setLayout(viewerLayout);
viewerComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
Group loginGroup = new Group(composite, SWT.NONE);
loginGroup.setText("Login data");
GridLayout groupLayout = new GridLayout(2, true);
groupLayout.marginWidth = 10;
groupLayout.marginHeight = 10;
loginGroup.setLayout(groupLayout);
loginGroup.setLayoutData(new GridData(GridData.FILL_BOTH));

dbc = new DataBindingContext();
IListProperty childrenProperty = new MultiListProperty(
new IListProperty[] {
PojoProperties.list("connectorFactories"),
PojoProperties.list("connections") });
ObservableListTreeContentProvider contentProvider = new ObservableListTreeContentProvider(
childrenProperty.listFactory(), null);
viewer.setContentProvider(contentProvider);
viewer.setInput(GlobalConfig.getInstance());
selObs = ViewersObservables.observeSingleSelection(viewer);

return composite;
}

@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
Button okButton = getButton(IDialogConstants.OK_ID);
ISWTObservableValue okBtnObs = SWTObservables
.observeEnabled(okButton);
UpdateValueStrategy strategy = new UpdateValueStrategy()
.setConverter(new MyConveter()).setAfterConvertValidator(
new MyValidator());
dbc.bindValue(okBtnObs, selObs, new UpdateValueStrategy(
UpdateValueStrategy.POLICY_NEVER), strategy);
}
}

static class GlobalConfig {

private static GlobalConfig instance;

public static GlobalConfig getInstance() {
if (instance == null) {
instance = new GlobalConfig();
}
return instance;
}

private List<ConnectorFactory> connectorFactories;

private GlobalConfig() {
this.connectorFactories = new ArrayList<ConnectorFactory>();
ConnectorFactory factoryA = new ConnectorFactory("Type A");
ArrayList<Connection> typeAList = new ArrayList<Connection>();
typeAList.add(new Connection("my first connection"));
typeAList.add(new Connection("an other connection"));
factoryA.setConnections(typeAList);
this.connectorFactories.add(factoryA);

ConnectorFactory factoryB = new ConnectorFactory("Type B");
ArrayList<Connection> typeBList = new ArrayList<Connection>();
typeBList.add(new Connection("connection to a server"));
typeBList.add(new Connection("connection to an other server"));
factoryB.setConnections(typeBList);
this.connectorFactories.add(factoryB);
}

public void setConnectorFactories(
List<ConnectorFactory> connectorFactories) {
this.connectorFactories = connectorFactories;
}

public List<ConnectorFactory> getConnectorFactories() {
return connectorFactories;
}

}

static class ConnectorFactory {

private String connectorType;
private List<Connection> connections;

public ConnectorFactory(String type) {
this.connectorType = type;
}

public String getConnectorType() {
return this.connectorType;
}

public void setConnections(List<Connection> connections) {
this.connections = connections;
}

public List<Connection> getConnections() {
return connections;
}
}

static class Connection {

private String name;

public Connection(String name) {
this.name = name;
}

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

public String getName() {
return name;
}
}

static class MyConveter implements IConverter {

public Object convert(Object fromObject) {
Boolean result = Boolean.FALSE;
if (fromObject != null && fromObject instanceof Connection) {
result = Boolean.TRUE;
}
return result;
}

public Object getFromType() {
return Connection.class;
}

public Object getToType() {
return Boolean.class;
}

}

static class MyValidator implements IValidator {

public IStatus validate(Object value) {
Boolean input = (Boolean) value;
if (input) {
return Status.OK_STATUS;
}
return new Status(IStatus.ERROR, "id", "No connection selected");
}

}
}

--------------060406060502010500020402--
Re: [Databinding] between TreeViewer.selection and Button.enabled [message #484620 is a reply to message #484508] Tue, 08 September 2009 09:56 Go to previous messageGo to next message
Matthew Hall is currently offline Matthew Hall
Messages: 368
Registered: July 2009
Senior Member
Heiko Ahlig wrote:
> Hi,
> I tried to build a dialog, with an TreeViewer.
> If there is no "connection" seleted, the Dialog Ok-Button should be
> disabled.

TitleAreaDialogSupport does enable/disable the button yet, since there
are no methods in TitleAreaDialog corresponding to
WizardPage.setPageComplete. However we could add a method:

TitleAreaDialog.create(
TitleAreaDialog, DataBindingContext, int buttonId)

This way whenever the validation status changed we would call:

TitleAreaDialog.getButton(buttonId).setEnabled(statusIsValid );

If this would help you, then please file a bug for this in Bugzilla and
I will add it to my to-do list.

> In addition, i find my solution for the ColumnLabelProvider not realy good.
> Exists an solution to show diffrent LabelProperties for diffrent classes
> in one column?

Yes:
* If you are using ViewerColumns then you can use
ObservableMapCellLabelProvider.
* With multiple element types, you can extend DelegatingValueProperty
and delegate to the appropriate property depending on the runtime type.
In practice this is about as much code as what you are doing now, but
with the added benefit of getting automatic updates in the viewer
whenever the model changes value:

TreeViewer viewer = ...
TreeViewerColumn viewCol = ...
ObservableListTreeContentProvider contentProvider = ...

IValueProperty viewProp = new DelegatingValueProperty() {
IValueProperty connectorFactoryType =
BeanProperties.value( ConnectorFactory.class, "connectorType");
IValueProperty connectorName =
BeanProperties.value( Connector.class, "name");

protected IValueProperty doGetDelegate(Object source) {
if (source instanceof ConnectorFactory.class)
return connectorFactoryType;
if (sourc einstanceof Connector)
return connectorName;
}
}

viewCol.setLabelProvider(new ObservableMapCellLabelProvider(
viewProp.observeDetail(contentProvider.getKnownElement())));

One more thing: you are using PojoProperties which does not fire
property change events when the model objects change. In most cases it
is preferable to use BeanProperties so that you can update the model
from anywhere and have your viewers and other bound controls updated for
you. In practice this is usually as simple as declaring a ModelObject
(or whatever you want to call it) class, extending your model classes
from that, and making some simple tweaks to the model classes:

public class ModelObject {
private PropertyChangeSupport changeSupport =
new PropertyChangeSupport( this );

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

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

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

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

protected void firePropertyChange(
String propertyName, Object oldValue, Object newValue ) {
if ( changeSupport.hasListeners( propertyName ) ) {
if ( oldValue == null || newValue == null ||
!oldValue.equals( newValue ) ) {
changeSupport.firePropertyChange(
propertyName, oldValue, newValue );
}
}
}
}

public class Connection extends ModelObject {
private String name;

public Connection(String name) {
this.name = name;
}

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

public String getName() {
return name;
}
}

Hope this helps,

Matthew
Re: [Databinding] between TreeViewer.selection and Button.enabled [message #484643 is a reply to message #484620] Tue, 08 September 2009 11:06 Go to previous message
Matthew Hall is currently offline Matthew Hall
Messages: 368
Registered: July 2009
Senior Member
Matthew Hall wrote:
> TitleAreaDialogSupport does enable/disable the button yet, since there
> are no methods in TitleAreaDialog corresponding to
> WizardPage.setPageComplete. However we could add a method:

I meant to say, TitleAreaDialogSupport does *not* enable/disable the
button. Sorry if my answer was confusing.

Matthew
Previous Topic:ContentProposalAdapter
Next Topic:TableViewer, CellEditors and contextual menu
Goto Forum:
  


Current Time: Tue Jul 29 23:07:12 EDT 2014

Powered by FUDForum. Page generated in 0.01997 seconds