Reputation: 27
I have a treeviewer with one column containing Strings. I made an "add button".
what I want is when the user add a row, I want to move the "edit cursor" to the new row.
I have 2 problems:
when I add new data with
tableViewer.add()
tableViewer.getTable().getItemCount()
is not updated ! So i can't select the last row...
Plus, when I set ColumnViewerEditorActivationStrategy
. I cannot select anymore with tableViewer.setSelection()
Here the detailled source code
public class CompositeTableViewer extends Composite {
private TableViewer tableViewer;
private List<String> columnNames;
int correctionSelection = 0;
public CompositeTableViewer(Composite parent, int style, List<String> columnNames, boolean rowAddable)
{
this(parent, style, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER, columnNames, rowAddable);
}
public CompositeTableViewer(Composite parent, int style, int tableViewerStyle, List<String> columnNames, boolean rowAddable)
{
super(parent, style);
GridLayout layout = new GridLayout(3, false);
layout.marginWidth = 4;
this.setLayout(layout);
this.setBackground(SWTResourceManager.getColor(SWT.COLOR_DARK_RED));
setTableViewer(new TableViewer(this, tableViewerStyle));
TextCellEditor columnEditor = new TextCellEditor(tableViewer.getTable());
CellEditor[] editors = { columnEditor };
this.columnNames = columnNames;
tableViewer.setColumnProperties(this.columnNames.toArray(new String[this.columnNames.size()]));
tableViewer.setContentProvider(new ArrayContentProvider());
tableViewer.setLabelProvider(new LabelProvider());
tableViewer.setCellEditors(editors);
tableViewer.setCellModifier(new StringListCellModifier(this));
//here I restricted the edit activation to double-click
changeColumnViewerEditorActivationStrategy();
final Table table = tableViewer.getTable();
table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
table.setLinesVisible(true);
createButtons(this, rowAddable);
}
public void setInput(List<Object> dataList)
{
this.tableViewer.setInput(dataList);
}
/**
* change the edition activation to double click
* otherwise that's block multi selection :/
*
*/
public TableViewerFocusCellManager changeColumnViewerEditorActivationStrategy()
{
TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(tableViewer, new FocusCellOwnerDrawHighlighter(tableViewer));
ColumnViewerEditorActivationStrategy activationSupport = new ColumnViewerEditorActivationStrategy(tableViewer)
{
protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event)
{
// Enable editor only with mouse double click
if (event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION)
{
EventObject source = event.sourceEvent;
if (source instanceof MouseEvent && ((MouseEvent) source).button == 3)
return false;
return true;
}
return false;
}
};
TableViewerEditor.create(tableViewer, focusCellManager, activationSupport, ColumnViewerEditor.TABBING_HORIZONTAL
| ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
return focusCellManager;
}
/**
* Add the "Add" and "Delete" buttons
*
* @param parent
* the parent composite
*/
private void createButtons(Composite parent, boolean rowAddable)
{
// Create and configure the "Add" button
Button add = new Button(parent, SWT.PUSH | SWT.CENTER);
add.setText("Add");
GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gridData.widthHint = 80;
add.setLayoutData(gridData);
add.setEnabled(rowAddable);
add.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent e)
{
tableViewer.add("-_-"); // suppose to be an empty string
int selection = CompositeTableViewer.this.tableViewer.getTable().getItemCount();
CompositeTableViewer.this.tableViewer.setSelection(
new StructuredSelection(tableViewer.getElementAt(selection - 1 + correctionSelection)), true);
tableViewer.setSelection(new StructuredSelection(CompositeTableViewer.this.tableViewer.getElementAt(selection - 1)), true);
}
});
// Create and configure the "Delete" button
Button delete = new Button(parent, SWT.PUSH | SWT.CENTER);
delete.setText("Delete");
gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gridData.widthHint = 80;
delete.setLayoutData(gridData);
delete.addSelectionListener(new SelectionAdapter()
{
// Remove the selection and refresh the view
public void widgetSelected(SelectionEvent e)
{
Object[] dataTable = (Object[]) ((IStructuredSelection) tableViewer.getSelection()).toArray();
if (dataTable != null)
{
tableViewer.remove(dataTable);
}
}
});
}
}
EDIT The problem was ArraycontentProvider can't be used for an editable table. and I should not use a list as a model. I change for a List. I put in comment my new source code
Upvotes: 1
Views: 1543
Reputation: 6456
I imported your code and modified it a little bit, and there's some things that seems to be wrong from what I can see.
First, ArraycontentProvider says this in the java doc:
this implementation of IStructuredContentProvider handles the case where the viewer input is an unchanging array or collection of elements
So your first task would be to write your own content provider. This is important because you will need to update the input you've set, and this content provider will likely not do that for you.
Second, you need to add columns to make them editable. For example:
TableViewerColumn c1 = new TableViewerColumn(tableViewer, tableViewerStyle);
c1.setLabelProvider(new CellLabelProvider() {
@Override
public void update(ViewerCell cell) {
}
});
c1.getColumn().setWidth(200);
c1.setEditingSupport(new FirstNameEditingSupport(tableViewer));
This will make your column editable with a dedicated editor. (Text in that case. I stole the editor from a nice tutorial that you can find here:
http://www.vogella.com/tutorials/EclipseJFaceTableAdvanced/article.html#jfaceeditor
Now with these changes, I managed to solve your problem of adding. You will need to have a model object that you can update. In my case, I created:
public static class TestObject {
private String text;
public TestObject(String text) {
this.text = text;
}
}
This is needed because in the editor, you will have to update the viewer's content with the edited content.
What I didn't do was to create a proper ContentProvider, so in my example I never persist my updates. However, the adding works, the double click works, and the editing works.
Now to your selection. The tableviewer add method says:
This method should be called (by the content provider) when a single element has been added to the model, in order to cause the viewer to accurately reflect the model. This method only affects the viewer, not the model. Note that there is another method for efficiently processing the simultaneous addition of multiple elements.
This comes back to your content provider. It needs to handle the fact that content has been added/edited/removed and update the model object accordingly.
This should get you started for now. Have a look at the tutorial by Lars vogel, it is very good and clear what to do. Let me know if there's more issues and i'll attempt to create a better example.
Artur
P.S.: Copy/pasting your code did not compile for me. Try providing a mini standalone example for your problem. That way it's easier to code against it and give you more detailed pointers.
Upvotes: 1
Reputation: 27
Here my new version
package features.dataManagement.entity.table.ui;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
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.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import features.dataManagement.entity.table.edit.StringEditingSupport;
import features.dataManagement.entity.table.model.RowStringContentProvider;
import features.dataManagement.entity.table.model.RowStringModel;
public class CompositeTableViewer extends Composite
{
private TableViewer tableViewer;
private List<String> columnNames;
private List<RowStringModel> modelList;
private Button addButton;
public CompositeTableViewer(Composite parent, int style, List<String> columnNames, boolean rowAddable)
{
this(parent, style, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER, columnNames, rowAddable);
}
public CompositeTableViewer(Composite parent, int style, int tableViewerStyle, List<String> columnNames, boolean rowAddable)
{
super(parent, style);
modelList = new ArrayList<RowStringModel>();
this.columnNames = columnNames;
GridLayout layout = new GridLayout(3, false);
layout.marginWidth = 4;
this.setLayout(layout);
Composite tableComposite = new Composite(this, SWT.NONE);
// set 3 columns for the buttons
tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
setTableViewer(new TableViewer(tableComposite, tableViewerStyle));
TableViewerColumn tableViewerColumn = createColumn(tableComposite, tableViewer, 0);
tableViewerColumn.setEditingSupport(new StringEditingSupport(tableViewer));
TableColumnLayout tableColumnLayout = new TableColumnLayout();
tableColumnLayout.setColumnData(tableViewerColumn.getColumn(), new ColumnWeightData(1, 100, true));
tableComposite.setLayout(tableColumnLayout);
tableViewer.setContentProvider(new RowStringContentProvider(tableViewer, modelList));
final Table table = tableViewer.getTable();
table.setLinesVisible(true);
createButtons(this, rowAddable);
}
/*
* this is specific to my project you can directly use a
* List<RowStringModel> modelList
*/
public void setInput(List<Object> dataList)
{
List<RowStringModel> dataStringList = new ArrayList<RowStringModel>();
for (Object str : dataList)
{
if (str instanceof String)
dataStringList.add(new RowStringModel((String) str));
}
modelList.addAll(dataStringList);
this.tableViewer.setInput(modelList);
}
/*
* this is specific to my project you can directly use a
* List<RowStringModel> modelList
*/
public List<Object> getInput()
{
List<Object> objectsInGui = new ArrayList<Object>();
for (RowStringModel rowStr : modelList)
{
objectsInGui.add(rowStr.getContent());
}
return objectsInGui;
}
public void addButtonEnable(boolean enabled)
{
this.addButton.setEnabled(enabled);
}
// create the columns for the table
private TableViewerColumn createColumn(final Composite parent, final TableViewer viewer, int colNumber)
{
TableViewerColumn col = createTableViewerColumn(this.columnNames.get(colNumber), colNumber);
col.setLabelProvider(new ColumnLabelProvider()
{
@Override
public String getText(Object element)
{
RowStringModel rsm = (RowStringModel) element;
return rsm.getContent();
}
/* slight difference for the actual lines */
@Override
public Color getBackground(final Object element)
{
if (element instanceof RowStringModel)
{
return new Color(Display.getDefault(), 245, 255, 250);
}
return super.getBackground(element);
}
});
return col;
}
private TableViewerColumn createTableViewerColumn(String title, final int colNumber)
{
final TableViewerColumn viewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
final TableColumn column = viewerColumn.getColumn();
column.setText(title);
column.setResizable(true);
column.setMoveable(true);
return viewerColumn;
}
/**
* Add the "Add" and "Delete" buttons
*
* @param parent
* the parent composite
*/
private void createButtons(Composite parent, boolean rowAddable)
{
// Create and configure the "Add" button
this.addButton = new Button(parent, SWT.PUSH | SWT.CENTER);
this.addButton.setText("Add");
GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gridData.widthHint = 80;
gridData.horizontalSpan = 1;
this.addButton.setLayoutData(gridData);
this.addButton.setEnabled(rowAddable);
this.addButton.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent e)
{
modelList.add(new RowStringModel(""));
tableViewer.refresh();
CompositeTableViewer.this.setFocus();
int selection = CompositeTableViewer.this.tableViewer.getTable().getItemCount();
CompositeTableViewer.this.tableViewer.setSelection(new StructuredSelection(tableViewer.getElementAt(selection - 1)), true);
}
});
// Create and configure the "Delete" button
Button delete = new Button(parent, SWT.PUSH | SWT.CENTER);
delete.setText("Delete");
gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gridData.widthHint = 80;
delete.setLayoutData(gridData);
delete.addSelectionListener(new SelectionAdapter()
{
// Remove the selection and refresh the view
public void widgetSelected(SelectionEvent e)
{
Object[] dataTable = (Object[]) ((IStructuredSelection) tableViewer.getSelection()).toArray();
if (dataTable != null)
{
for (Object data : dataTable)
{
modelList.remove(data);
}
tableViewer.refresh();
}
}
});
}
public TableViewer getTableViewer()
{
return tableViewer;
}
public void setTableViewer(TableViewer tableViewer)
{
this.tableViewer = tableViewer;
}
public List<String> getColumnNames()
{
return columnNames;
}
public void setColumnNames(List<String> columnNames)
{
this.columnNames = columnNames;
}
}
RowStringModel
package features.dataManagement.entity.table.model;
public class RowStringModel
{
private String content;
public RowStringModel(String content)
{
super();
this.content = content;
}
public String getContent()
{
return content;
}
public void setContent(String content)
{
this.content = content;
}
}
StringEditingSupport
package features.dataManagement.entity.table.edit;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import features.dataManagement.entity.table.model.RowStringModel;
public class StringEditingSupport extends EditingSupport
{
private final TableViewer viewer;
private final CellEditor editor;
public StringEditingSupport(TableViewer viewer)
{
super(viewer);
this.viewer = viewer;
this.editor = new TextCellEditor(viewer.getTable());
}
@Override
protected CellEditor getCellEditor(Object element) {
return editor;
}
@Override
protected boolean canEdit(Object element) {
return true;
}
@Override
protected Object getValue(Object element) {
return ((RowStringModel) element).getContent();
}
@Override
protected void setValue(Object element, Object userInputValue) {
((RowStringModel) element).setContent(String.valueOf(userInputValue));
viewer.update(element, null);
}
}
RowStringContentProvider
package features.dataManagement.entity.table.model;
import java.util.List;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
public class RowStringContentProvider implements IStructuredContentProvider, IItemModelListViewer<RowStringModel>
{
private TableViewer tableViewer;
private List<RowStringModel> modelList;
public RowStringContentProvider(TableViewer tableViewer, List<RowStringModel> modelList)
{
this.tableViewer = tableViewer;
this.modelList = modelList;
}
public void inputChanged(Viewer v, Object oldInput, Object newInput)
{
}
public void dispose()
{
}
// Return the tasks as an array of Objects
public Object[] getElements(Object parent)
{
return modelList.toArray();
}
public void addItemModel(RowStringModel itemModel)
{
tableViewer.add(itemModel);
}
@Override
public void removeItemModel(RowStringModel itemModel)
{
tableViewer.remove(itemModel);
}
@Override
public void updateItemModel(RowStringModel itemModel)
{
tableViewer.update(itemModel, null);
}
}
Upvotes: 0