Skip to main content



      Home
Home » Eclipse Projects » Eclipse Platform » [DataBinding] Example of multi-cell editable table
[DataBinding] Example of multi-cell editable table [message #319791] Fri, 31 August 2007 12:05 Go to next message
Eclipse UserFriend
Originally posted by: eclipse5.rizzoweb.com

I've been examining Snippet 013 which exhibits setting up a table cell
editor (TextCellEditor) using Data Binding. However, when I tried to
modify it to use a ComboBoxCellEditor instead, I am getting strange
problems.
Can anyone amend Snippet 013 to include another column that uses a Combo
to edit, or provide another Snippet? Are there any other examples of
Data Binding that I could look to?

TIA,
Eric
Re: [DataBinding] Example of multi-cell editable table [message #319829 is a reply to message #319791] Mon, 03 September 2007 12:07 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: eclipse5.rizzoweb.com

This is a multi-part message in MIME format.
--------------040901040608070509050202
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Eric Rizzo wrote:
> I've been examining Snippet 013 which exhibits setting up a table cell
> editor (TextCellEditor) using Data Binding. However, when I tried to
> modify it to use a ComboBoxCellEditor instead, I am getting strange
> problems.
> Can anyone amend Snippet 013 to include another column that uses a Combo
> to edit, or provide another Snippet? Are there any other examples of
> Data Binding that I could look to?

I've attached a modified Snippet 013 that attempts to set up a second
column cell editor using ComboBoxCellEditor. Basically, it is not
behaving at all correctly when it comes to rendering the selected row's
"month" value in the combo box. It seems to be somehow "remembering" the
last selected index, regardless of what the currently selected row's
value should be.

I've wrestled with this for several hours, trying different tings
including ExtendedComboBoxCellEditor with object values instead of
Strings. But I am obviously missing something. What am I doing wrong?

Thanks in advance,
Eric

--------------040901040608070509050202
Content-Type: text/plain;
name="Snippet013TableViewerEditing.java"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="Snippet013TableViewerEditing.java"

/*********************************************************** ********************
* Copyright (c) 2006 The Pampered Chef, Inc. 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:
* The Pampered Chef, Inc. - initial API and implementation
* Tom Schindl - cell editing
************************************************************ ******************/

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

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

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.value.IObservableVal ue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ObservableListContentP rovider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProv ider;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.viewers.*;
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 Snippet013TableViewerEditing {

private static class Month {
private String name;
public Month(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String toString() {
return name;
}
}

private static final String[] MonthNames = {"January", "February", "March", "April"};
private static final Month[] Months =
{
new Month(MonthNames[0]),new Month(MonthNames[1]),
new Month(MonthNames[2]),new Month(MonthNames[3])
};

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(propertyN ame,
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";
Month month;

public Person(String name, Month month) {
this.name = name;
this.month = month;
}

public String getName() {
return name;
}

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

public Month getMonth() {
return month;
}

public void setMonth(Month month) {
Month oldValue = this.month;
this.month = month;
firePropertyChange("month", oldValue, month);
}

}

// 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();
{
people.add(new Person("Steve Northover", Months[0]));
people.add(new Person("Grant Gayed", Months[1]));
people.add(new Person("Veronika Irvine", Months[2]));
people.add(new Person("Mike Wilson", Months[3]));
people.add(new Person("Christophe Cornu", Months[0]));
people.add(new Person("Lynne Kues", Months[1]));
}

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
*/
static class InlineTextEditingSupport extends EditingSupport {
private TextCellEditor editor;

private DataBindingContext bindingContext;
/**
* The current binding.
*/
private Binding binding;

private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper();

/**
* @param viewer
*/
public InlineTextEditingSupport(ColumnViewer viewer,
DataBindingContext bindingContext) {
super(viewer);
this.editor = new TextCellEditor((Composite) viewer.getControl());
this.bindingContext = bindingContext;
}

protected boolean canEdit(Object element) {
return true;
}

protected CellEditor getCellEditor(Object element) {
return editor;
}

protected Object getValue(Object element) {
// Not needed
return null;
}

protected void setValue(Object element, Object value) {
// Not Needed
}

protected void initializeCellEditorValue(CellEditor cellEditor,
ViewerCell cell) {
Object modelElement = cell.getElement();
IObservableValue observableValue = BeansObservables.observeValue(
modelElement, "name");

/*
* Creates a binding between the cell editor and the model that only
* updates the model when the current edit is saved.
*/
binding = bindingContext
.bindValue(SWTObservables.observeText(cellEditor
.getControl(), SWT.Modify), observableValue,
new UpdateValueStrategy(
UpdateValueStrategy.POLICY_CONVERT), null);

getViewer().getColumnViewerEditor().addEditorActivationListe ner(
activationListener);
}

protected void saveCellEditorValue(CellEditor cellEditor,
ViewerCell cell) {
binding.updateTargetToModel();
}

private class ColumnViewerEditorActivationListenerHelper extends
ColumnViewerEditorActivationListener {

public void afterEditorActivated(
ColumnViewerEditorActivationEvent event) {
// do nothing
}

public void afterEditorDeactivated(
ColumnViewerEditorDeactivationEvent event) {
if (binding != null) {
binding.dispose();
binding = null;
}
}

public void beforeEditorActivated(
ColumnViewerEditorActivationEvent event) {
// do nothing
}

public void beforeEditorDeactivated(
ColumnViewerEditorDeactivationEvent event) {
// do nothing
}
}
}

static class InlineComboEditingSupport extends EditingSupport {
private ComboBoxCellEditor editor;

private DataBindingContext bindingContext;
private Binding binding;

private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper();

public InlineComboEditingSupport(ColumnViewer viewer,
DataBindingContext bindingContext) {
super(viewer);
this.editor = new ComboBoxCellEditor(
(Composite) viewer.getControl(),
MonthNames,
SWT.READ_ONLY);
this.bindingContext = bindingContext;
}

protected boolean canEdit(Object element) {
return true;
}

protected CellEditor getCellEditor(Object element) {
return editor;
}

protected Object getValue(Object element) {
// Not needed
return null;
}

protected void setValue(Object element, Object value) {
// Not Needed
}

protected void initializeCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
Object modelElement = cell.getElement();
IObservableValue observableValue =
BeansObservables.observeValue(modelElement, "month");
IConverter intToMonthConverter = new Converter(Integer.TYPE, Month.class) {
public Object convert(Object fromObject) {
int selectedIndex = ((Integer)fromObject).intValue();
Object month = Months[selectedIndex];
System.out.println("Converted int " + fromObject + " to Month: " + month);
return month;
}
};

binding = bindingContext.bindValue(
SWTObservables.observeSingleSelectionIndex(cellEditor.getCon trol()),
observableValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_CONVERT).setC onverter(intToMonthConverter),
null);

getViewer().getColumnViewerEditor().addEditorActivationListe ner(activationListener);
}

protected void saveCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
binding.updateTargetToModel();
}

private class ColumnViewerEditorActivationListenerHelper extends
ColumnViewerEditorActivationListener {

public void afterEditorActivated(
ColumnViewerEditorActivationEvent event) {
// do nothing
}

public void afterEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {
if (binding != null) {
binding.dispose();
binding = null;
}
}

public void beforeEditorActivated(ColumnViewerEditorActivationEvent event) {
// do nothing
}

public void beforeEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {
// do nothing
}
}
}


// The GUI view
static class View {
private ViewModel viewModel;
private Table committers;
private Label selectedCommitter;
private Label monthLabel;

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);
monthLabel = 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.
DataBindingContext bindingContext = new DataBindingContext();
bindGUI(bindingContext);

// Open and return the Shell
shell.setSize(250, 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);
TableViewerColumn nameColumn = new TableViewerColumn(peopleViewer,
SWT.NONE);
nameColumn.setEditingSupport(new InlineTextEditingSupport(peopleViewer,
bindingContext));
nameColumn.getColumn().setWidth(100);

TableViewerColumn monthColumn = new TableViewerColumn(peopleViewer, SWT.NONE);
monthColumn.setEditingSupport(new InlineComboEditingSupport(peopleViewer, bindingContext));
monthColumn.getColumn().setWidth(100);

// Create a standard content provider
ObservableListContentProvider peopleViewerContentProvider = new ObservableListContentProvider();
peopleViewer.setContentProvider(peopleViewerContentProvider) ;

// And a standard label provider that maps columns
IObservableMap[] attributeMaps = BeansObservables.observeMaps(
peopleViewerContentProvider.getKnownElements(),
Person.class, new String[] {"name", "month" });
peopleViewer.setLabelProvider(new ObservableMapLabelProvider(attributeMaps));

// Now set the Viewer's input
peopleViewer.setInput(new WritableList(viewModel.getPeople(),
Person.class));

// bind selectedCommitter label to the name of the current selection
IObservableValue selection = ViewersObservables
.observeSingleSelection(peopleViewer);
bindingContext.bindValue(SWTObservables
.observeText(selectedCommitter), BeansObservables
.observeDetailValue(Realm.getDefault(), selection, "name",
String.class), null, null);

bindingContext.bindValue(
SWTObservables.observeText(monthLabel),
BeansObservables.observeDetailValue(Realm.getDefault(), selection, "month", Month.class),
null,
null);
}
}

}

--------------040901040608070509050202--
Re: [DataBinding] Example of multi-cell editable table [message #319835 is a reply to message #319829] Tue, 04 September 2007 00:45 Go to previous messageGo to next message
Eclipse UserFriend
This is a multi-part message in MIME format.
--------------000003090507020400080008
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Hi Eric. You need an IConverter to convert from a Month to the
selection index. Attached is an updated snippet.

The way I debugged this was I found the target observable,
CComboSingleSelectionObservableValue, and looked for the
doSetValue(Object) implementation. For this observable it was in
SingleSelectionObservableValue. Then I set a breakpoint in that method.
When the editor is bound it thru a ClassCastException because the
value being set was a Month and not an int. So from there I wrote a
converter and passed it to bindValue(...).

-brad

Eric Rizzo wrote:
> Eric Rizzo wrote:
>> I've been examining Snippet 013 which exhibits setting up a table cell
>> editor (TextCellEditor) using Data Binding. However, when I tried to
>> modify it to use a ComboBoxCellEditor instead, I am getting strange
>> problems.
>> Can anyone amend Snippet 013 to include another column that uses a
>> Combo to edit, or provide another Snippet? Are there any other
>> examples of Data Binding that I could look to?
>
> I've attached a modified Snippet 013 that attempts to set up a second
> column cell editor using ComboBoxCellEditor. Basically, it is not
> behaving at all correctly when it comes to rendering the selected row's
> "month" value in the combo box. It seems to be somehow "remembering" the
> last selected index, regardless of what the currently selected row's
> value should be.
>
> I've wrestled with this for several hours, trying different tings
> including ExtendedComboBoxCellEditor with object values instead of
> Strings. But I am obviously missing something. What am I doing wrong?
>
> Thanks in advance,
> Eric
>
>
> ------------------------------------------------------------ ------------
>
> /*********************************************************** ********************
> * Copyright (c) 2006 The Pampered Chef, Inc. 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:
> * The Pampered Chef, Inc. - initial API and implementation
> * Tom Schindl - cell editing
> ************************************************************ ******************/
>
> package org.eclipse.jface.examples.databinding.snippets;
>
> import java.beans.PropertyChangeListener;
> import java.beans.PropertyChangeSupport;
> import java.util.LinkedList;
> import java.util.List;
>
> import org.eclipse.core.databinding.Binding;
> import org.eclipse.core.databinding.DataBindingContext;
> import org.eclipse.core.databinding.UpdateValueStrategy;
> import org.eclipse.core.databinding.beans.BeansObservables;
> import org.eclipse.core.databinding.conversion.Converter;
> import org.eclipse.core.databinding.conversion.IConverter;
> import org.eclipse.core.databinding.observable.Realm;
> import org.eclipse.core.databinding.observable.list.WritableList;
> import org.eclipse.core.databinding.observable.map.IObservableMap;
> import org.eclipse.core.databinding.observable.value.IObservableVal ue;
> import org.eclipse.jface.databinding.swt.SWTObservables;
> import org.eclipse.jface.databinding.viewers.ObservableListContentP rovider;
> import org.eclipse.jface.databinding.viewers.ObservableMapLabelProv ider;
> import org.eclipse.jface.databinding.viewers.ViewersObservables;
> import org.eclipse.jface.viewers.*;
> 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 Snippet013TableViewerEditing {
>
> private static class Month {
> private String name;
> public Month(String name) {
> this.name = name;
> }
> public String getName() {
> return name;
> }
> public String toString() {
> return name;
> }
> }
>
> private static final String[] MonthNames = {"January", "February", "March", "April"};
> private static final Month[] Months =
> {
> new Month(MonthNames[0]),new Month(MonthNames[1]),
> new Month(MonthNames[2]),new Month(MonthNames[3])
> };
>
> 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(propertyN ame,
> 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";
> Month month;
>
> public Person(String name, Month month) {
> this.name = name;
> this.month = month;
> }
>
> public String getName() {
> return name;
> }
>
> public void setName(String name) {
> String oldValue = this.name;
> this.name = name;
> firePropertyChange("name", oldValue, name);
> }
>
> public Month getMonth() {
> return month;
> }
>
> public void setMonth(Month month) {
> Month oldValue = this.month;
> this.month = month;
> firePropertyChange("month", oldValue, month);
> }
>
> }
>
> // 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();
> {
> people.add(new Person("Steve Northover", Months[0]));
> people.add(new Person("Grant Gayed", Months[1]));
> people.add(new Person("Veronika Irvine", Months[2]));
> people.add(new Person("Mike Wilson", Months[3]));
> people.add(new Person("Christophe Cornu", Months[0]));
> people.add(new Person("Lynne Kues", Months[1]));
> }
>
> 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
> */
> static class InlineTextEditingSupport extends EditingSupport {
> private TextCellEditor editor;
>
> private DataBindingContext bindingContext;
> /**
> * The current binding.
> */
> private Binding binding;
>
> private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper();
>
> /**
> * @param viewer
> */
> public InlineTextEditingSupport(ColumnViewer viewer,
> DataBindingContext bindingContext) {
> super(viewer);
> this.editor = new TextCellEditor((Composite) viewer.getControl());
> this.bindingContext = bindingContext;
> }
>
> protected boolean canEdit(Object element) {
> return true;
> }
>
> protected CellEditor getCellEditor(Object element) {
> return editor;
> }
>
> protected Object getValue(Object element) {
> // Not needed
> return null;
> }
>
> protected void setValue(Object element, Object value) {
> // Not Needed
> }
>
> protected void initializeCellEditorValue(CellEditor cellEditor,
> ViewerCell cell) {
> Object modelElement = cell.getElement();
> IObservableValue observableValue = BeansObservables.observeValue(
> modelElement, "name");
>
> /*
> * Creates a binding between the cell editor and the model that only
> * updates the model when the current edit is saved.
> */
> binding = bindingContext
> .bindValue(SWTObservables.observeText(cellEditor
> .getControl(), SWT.Modify), observableValue,
> new UpdateValueStrategy(
> UpdateValueStrategy.POLICY_CONVERT), null);
>
> getViewer().getColumnViewerEditor().addEditorActivationListe ner(
> activationListener);
> }
>
> protected void saveCellEditorValue(CellEditor cellEditor,
> ViewerCell cell) {
> binding.updateTargetToModel();
> }
>
> private class ColumnViewerEditorActivationListenerHelper extends
> ColumnViewerEditorActivationListener {
>
> public void afterEditorActivated(
> ColumnViewerEditorActivationEvent event) {
> // do nothing
> }
>
> public void afterEditorDeactivated(
> ColumnViewerEditorDeactivationEvent event) {
> if (binding != null) {
> binding.dispose();
> binding = null;
> }
> }
>
> public void beforeEditorActivated(
> ColumnViewerEditorActivationEvent event) {
> // do nothing
> }
>
> public void beforeEditorDeactivated(
> ColumnViewerEditorDeactivationEvent event) {
> // do nothing
> }
> }
> }
>
> static class InlineComboEditingSupport extends EditingSupport {
> private ComboBoxCellEditor editor;
>
> private DataBindingContext bindingContext;
> private Binding binding;
>
> private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper();
>
> public InlineComboEditingSupport(ColumnViewer viewer,
> DataBindingContext bindingContext) {
> super(viewer);
> this.editor = new ComboBoxCellEditor(
> (Composite) viewer.getControl(),
> MonthNames,
> SWT.READ_ONLY);
> this.bindingContext = bindingContext;
> }
>
> protected boolean canEdit(Object element) {
> return true;
> }
>
> protected CellEditor getCellEditor(Object element) {
> return editor;
> }
>
> protected Object getValue(Object element) {
> // Not needed
> return null;
> }
>
> protected void setValue(Object element, Object value) {
> // Not Needed
> }
>
> protected void initializeCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
> Object modelElement = cell.getElement();
> IObservableValue observableValue =
> BeansObservables.observeValue(modelElement, "month");
> IConverter intToMonthConverter = new Converter(Integer.TYPE, Month.class) {
> public Object convert(Object fromObject) {
> int selectedIndex = ((Integer)fromObject).intValue();
> Object month = Months[selectedIndex];
> System.out.println("Converted int " + fromObject + " to Month: " + month);
> return month;
> }
> };
>
> binding = bindingContext.bindValue(
> SWTObservables.observeSingleSelectionIndex(cellEditor.getCon trol()),
> observableValue,
> new UpdateValueStrategy(UpdateValueStrategy.POLICY_CONVERT).setC onverter(intToMonthConverter),
> null);
>
> getViewer().getColumnViewerEditor().addEditorActivationListe ner(activationListener);
> }
>
> protected void saveCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
> binding.updateTargetToModel();
> }
>
> private class ColumnViewerEditorActivationListenerHelper extends
> ColumnViewerEditorActivationListener {
>
> public void afterEditorActivated(
> ColumnViewerEditorActivationEvent event) {
> // do nothing
> }
>
> public void afterEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {
> if (binding != null) {
> binding.dispose();
> binding = null;
> }
> }
>
> public void beforeEditorActivated(ColumnViewerEditorActivationEvent event) {
> // do nothing
> }
>
> public void beforeEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {
> // do nothing
> }
> }
> }
>
>
> // The GUI view
> static class View {
> private ViewModel viewModel;
> private Table committers;
> private Label selectedCommitter;
> private Label monthLabel;
>
> 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);
> monthLabel = 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.
> DataBindingContext bindingContext = new DataBindingContext();
> bindGUI(bindingContext);
>
> // Open and return the Shell
> shell.setSize(250, 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);
> TableViewerColumn nameColumn = new TableViewerColumn(peopleViewer,
> SWT.NONE);
> nameColumn.setEditingSupport(new InlineTextEditingSupport(peopleViewer,
> bindingContext));
> nameColumn.getColumn().setWidth(100);
>
> TableViewerColumn monthColumn = new TableViewerColumn(peopleViewer, SWT.NONE);
> monthColumn.setEditingSupport(new InlineComboEditingSupport(peopleViewer, bindingContext));
> monthColumn.getColumn().setWidth(100);
>
> // Create a standard content provider
> ObservableListContentProvider peopleViewerContentProvider = new ObservableListContentProvider();
> peopleViewer.setContentProvider(peopleViewerContentProvider) ;
>
> // And a standard label provider that maps columns
> IObservableMap[] attributeMaps = BeansObservables.observeMaps(
> peopleViewerContentProvider.getKnownElements(),
> Person.class, new String[] {"name", "month" });
> peopleViewer.setLabelProvider(new ObservableMapLabelProvider(attributeMaps));
>
> // Now set the Viewer's input
> peopleViewer.setInput(new WritableList(viewModel.getPeople(),
> Person.class));
>
> // bind selectedCommitter label to the name of the current selection
> IObservableValue selection = ViewersObservables
> .observeSingleSelection(peopleViewer);
> bindingContext.bindValue(SWTObservables
> .observeText(selectedCommitter), BeansObservables
> .observeDetailValue(Realm.getDefault(), selection, "name",
> String.class), null, null);
>
> bindingContext.bindValue(
> SWTObservables.observeText(monthLabel),
> BeansObservables.observeDetailValue(Realm.getDefault(), selection, "month", Month.class),
> null,
> null);
> }
> }
>
> }


--------------000003090507020400080008
Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0";
name="Snippet013TableViewerEditing.java"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="Snippet013TableViewerEditing.java"

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

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

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.value.IObservableVal ue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ObservableListContentP rovider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProv ider;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationListen er;
import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEven t;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.EditingSupport;
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;

public class Snippet013TableViewerEditing {

private static class Month {
private String name;

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

public String getName() {
return name;
}

public String toString() {
return name;
}
}

private static final String[] MonthNames = { "January", "February",
"March", "April" };

private static final Month[] Months = { new Month(MonthNames[0]),
new Month(MonthNames[1]), new Month(MonthNames[2]),
new Month(MonthNames[3]) };

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(propertyN ame,
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";

Month month;

public Person(String name, Month month) {
this.name = name;
this.month = month;
}

public String getName() {
return name;
}

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

public Month getMonth() {
return month;
}

public void setMonth(Month month) {
Month oldValue = this.month;
this.month = month;
firePropertyChange("month", oldValue, month);
}

}

// 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();
{
people.add(new Person("Steve Northover", Months[0]));
people.add(new Person("Grant Gayed", Months[1]));
people.add(new Person("Veronika Irvine", Months[2]));
people.add(new Person("Mike Wilson", Months[3]));
people.add(new Person("Christophe Cornu", Months[0]));
people.add(new Person("Lynne Kues", Months[1]));
}

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
*/
static class InlineTextEditingSupport extends EditingSupport {
private TextCellEditor editor;

private DataBindingContext bindingContext;

/**
* The current binding.
*/
private Binding binding;

private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper();

/**
* @param viewer
*/
public InlineTextEditingSupport(ColumnViewer viewer,
DataBindingContext bindingContext) {
super(viewer);
this.editor = new TextCellEditor((Composite) viewer.getControl());
this.bindingContext = bindingContext;
}

protected boolean canEdit(Object element) {
return true;
}

protected CellEditor getCellEditor(Object element) {
return editor;
}

protected Object getValue(Object element) {
// Not needed
return null;
}

protected void setValue(Object element, Object value) {
// Not Needed
}

protected void initializeCellEditorValue(CellEditor cellEditor,
ViewerCell cell) {
Object modelElement = cell.getElement();
IObservableValue observableValue = BeansObservables.observeValue(
modelElement, "name");

/*
* Creates a binding between the cell editor and the model that only
* updates the model when the current edit is saved.
*/
binding = bindingContext
.bindValue(SWTObservables.observeText(cellEditor
.getControl(), SWT.Modify), observableValue,
new UpdateValueStrategy(
UpdateValueStrategy.POLICY_CONVERT), null);

getViewer().getColumnViewerEditor().addEditorActivationListe ner(
activationListener);
}

protected void saveCellEditorValue(CellEditor cellEditor,
ViewerCell cell) {
binding.updateTargetToModel();
}

private class ColumnViewerEditorActivationListenerHelper extends
ColumnViewerEditorActivationListener {

public void afterEditorActivated(
ColumnViewerEditorActivationEvent event) {
// do nothing
}

public void afterEditorDeactivated(
ColumnViewerEditorDeactivationEvent event) {
if (binding != null) {
binding.dispose();
binding = null;
}
}

public void beforeEditorActivated(
ColumnViewerEditorActivationEvent event) {
// do nothing
}

public void beforeEditorDeactivated(
ColumnViewerEditorDeactivationEvent event) {
// do nothing
}
}
}

static class InlineComboEditingSupport extends EditingSupport {
private ComboBoxCellEditor editor;

private DataBindingContext bindingContext;

private Binding binding;

private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper();

public InlineComboEditingSupport(ColumnViewer viewer,
DataBindingContext bindingContext) {
super(viewer);
this.editor = new ComboBoxCellEditor((Composite) viewer
.getControl(), MonthNames, SWT.READ_ONLY);
this.bindingContext = bindingContext;
}

protected boolean canEdit(Object element) {
return true;
}

protected CellEditor getCellEditor(Object element) {
return editor;
}

protected Object getValue(Object element) {
// Not needed
return null;
}

protected void setValue(Object element, Object value) {
// Not Needed
}

protected void initializeCellEditorValue(CellEditor cellEditor,
ViewerCell cell) {
Object modelElement = cell.getElement();
IObservableValue observableValue = BeansObservables.observeValue(
modelElement, "month");
IConverter intToMonthConverter = new Converter(Integer.TYPE,
Month.class) {
public Object convert(Object fromObject) {
int selectedIndex = ((Integer) fromObject).intValue();
Object month = Months[selectedIndex];
System.out.println("Converted int " + fromObject
+ " to Month: " + month);
return month;
}
};

IConverter monthToIntConverter = new Converter(Month.class,
Integer.TYPE) {
public Object convert(Object fromObject) {
Month month = (Month) fromObject;
for (int i = 0; i < Months.length; i++) {
if (Months[i].equals(month)) {
return new Integer(i);
}
}

throw new RuntimeException("Invalid month.");
}
};

binding = bindingContext.bindValue(SWTObservables
.observeSingleSelectionIndex(cellEditor.getControl()),
observableValue, new UpdateValueStrategy(
UpdateValueStrategy.POLICY_CONVERT)
.setConverter(intToMonthConverter),
new UpdateValueStrategy()
.setConverter(monthToIntConverter));

getViewer().getColumnViewerEditor().addEditorActivationListe ner(
activationListener);
}

protected void saveCellEditorValue(CellEditor cellEditor,
ViewerCell cell) {
binding.updateTargetToModel();
}

private class ColumnViewerEditorActivationListenerHelper extends
ColumnViewerEditorActivationListener {

public void afterEditorActivated(
ColumnViewerEditorActivationEvent event) {
// do nothing
}

public void afterEditorDeactivated(
ColumnViewerEditorDeactivationEvent event) {
if (binding != null) {
binding.dispose();
binding = null;
}
}

public void beforeEditorActivated(
ColumnViewerEditorActivationEvent event) {
// do nothing
}

public void beforeEditorDeactivated(
ColumnViewerEditorDeactivationEvent event) {
// do nothing
}
}
}

// The GUI view
static class View {
private ViewModel viewModel;

private Table committers;

private Label selectedCommitter;

private Label monthLabel;

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);
monthLabel = 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.
DataBindingContext bindingContext = new DataBindingContext();
bindGUI(bindingContext);

// Open and return the Shell
shell.setSize(250, 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);
TableViewerColumn nameColumn = new TableViewerColumn(peopleViewer,
SWT.NONE);
nameColumn.setEditingSupport(new InlineTextEditingSupport(
peopleViewer, bindingContext));
nameColumn.getColumn().setWidth(100);

TableViewerColumn monthColumn = new TableViewerColumn(peopleViewer,
SWT.NONE);
monthColumn.setEditingSupport(new InlineComboEditingSupport(
peopleViewer, bindingContext));
monthColumn.getColumn().setWidth(100);

// Create a standard content provider
ObservableListContentProvider peopleViewerContentProvider = new ObservableListContentProvider();
peopleViewer.setContentProvider(peopleViewerContentProvider) ;

// And a standard label provider that maps columns
IObservableMap[] attributeMaps = BeansObservables.observeMaps(
peopleViewerContentProvider.getKnownElements(),
Person.class, new String[] { "name", "month" });
peopleViewer.setLabelProvider(new ObservableMapLabelProvider(
attributeMaps));

// Now set the Viewer's input
peopleViewer.setInput(new WritableList(viewModel.getPeople(),
Person.class));

// bind selectedCommitter label to the name of the current selection
IObservableValue selection = ViewersObservables
.observeSingleSelection(peopleViewer);
bindingContext.bindValue(SWTObservables
.observeText(selectedCommitter), BeansObservables
.observeDetailValue(Realm.getDefault(), selection, "name",
String.class), null, null);

bindingContext.bindValue(SWTObservables.observeText(monthLab el),
BeansObservables.observeDetailValue(Realm.getDefault(),
selection, "month", Month.class), null, null);
}
}

}

--------------000003090507020400080008--
Re: [DataBinding] Example of multi-cell editable table [message #319837 is a reply to message #319835] Tue, 04 September 2007 01:58 Go to previous message
Eclipse UserFriend
Brad Reynolds schrieb:
> Hi Eric. You need an IConverter to convert from a Month to the
> selection index. Attached is an updated snippet.
>
> The way I debugged this was I found the target observable,
> CComboSingleSelectionObservableValue, and looked for the
> doSetValue(Object) implementation. For this observable it was in
> SingleSelectionObservableValue. Then I set a breakpoint in that method.
> When the editor is bound it thru a ClassCastException because the value
> being set was a Month and not an int. So from there I wrote a converter
> and passed it to bindValue(...).
>
> -brad
>

Great. I hope we can eventually provide an Viewer ontop of
ComboBoxCellEditor in 3.4 then all this conversion stuff happening for
many many people is gone. If you'd like to see something like this then
vote for https://bugs.eclipse.org/bugs/show_bug.cgi?id=104225

Tom

--
B e s t S o l u t i o n . at
------------------------------------------------------------ --------
Tom Schindl JFace-Committer
------------------------------------------------------------ --------
Previous Topic:Activate CellEditor programmatically
Next Topic:How to know if top menu is still shown/hidden
Goto Forum:
  


Current Time: Fri Jul 25 06:04:13 EDT 2025

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

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

Back to the top