How to trigger EditingSupport on TableViewer - java

I'm currently writing an application where I use a JFace TableViewer. There's a Button next to the table that adds a new item to it. The TableViewer has only one column in this example, but this column has an EditingSupport assigned to it.
That all works as expected. A new item is added to the table when I click the button and it's also selected automatically.
However, what I want to achieve is that the EditingSupport of this column is triggered for the new item, i.e. when a new item is added, the cell within the new row should automatically show the text input that shows up when you use the editing support.
How would I achieve that? Do I need to fake up a mouse event or is there something in the API that I'm missing?
Here's some example code that roughly shows the current state of the table
public static void main(String[] args)
{
final Display d = new Display();
Shell s = new Shell(d);
s.setLayout(new FillLayout());
List<Project> projects = new ArrayList<>();
Table table = new Table(s, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
table.setHeaderVisible(true);
TableViewer viewer = new TableViewer(table);
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.setInput(projects);
TableViewerColumn nameColumn = new TableViewerColumn(viewer, SWT.NONE);
nameColumn.getColumn().setText("Project name");
nameColumn.setLabelProvider(new ColumnLabelProvider()
{
#Override
public String getText(Object element)
{
Project p = (Project) element;
return p.name;
}
});
// Add the editing support
nameColumn.setEditingSupport(new ProjectNameEditingSupport(viewer));
// Button to add new item
Button add = new Button(s, SWT.PUSH);
add.setText("Add");
add.addListener(SWT.Selection, e -> {
// Create the new item
Project project = new Project("Project");
projects.add(project);
// Refresh the table
viewer.refresh();
// Select the item
viewer.setSelection(new StructuredSelection(project), true);
// TODO: Trigger editing support
});
for (TableColumn c : viewer.getTable().getColumns())
c.pack();
s.pack();
s.open();
s.setSize(300, 400);
while (!s.isDisposed())
{
if (!d.readAndDispatch())
d.sleep();
}
d.dispose();
}
private static class Project
{
private String name;
public Project(String name)
{
this.name = name;
}
}
public static class ProjectNameEditingSupport extends EditingSupport
{
private final TableViewer viewer;
private final CellEditor editor;
public ProjectNameEditingSupport(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 ((Project) element).name;
}
#Override
protected void setValue(Object element, Object userInputValue)
{
((Project) element).name = String.valueOf(userInputValue);
viewer.update(element, null);
}
}

IIRC you can use ColumnViewer::editElement in order to activate the editing control. The first method argument is the element that should be edited, the second argument is the index of the column on which the editor should be opened.
For example:
viewer.editElement( project, 0 );

Related

get apply button in preference page + swt eclipse

I have MyPreferencePage which extends PreferencePage. Inside the PreferencePage there is a method getApplyButton() I am overriding that method to get the apply button.
I need the apply button because there are some validators that I put on the data in the preference dialog and till the all the data is not correct I dont want the apply button to be enabled.
My code
public class DefaultColorsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
#Override
protected Control createContents(Composite parent) {
this.container = new Composite(parent, SWT.NONE);
this.container.setLayout(new GridLayout(1, false));
GridData gd_area = new GridData(SWT.FILL, SWT.FILL, true, true);
this.container.setLayoutData(gd_area);
this.defalutColoringGroup = new Group(container, SWT.NONE);
this.defalutColoringGroup.setLayout(new GridLayout(1, false));
this.defalutColoringGroup.setLayoutData(gd_area);
this.defalutColoringGroup.setText(Constants.DESCRIPTION_TEXT);
this.defaultColoringCheckBox = new Button(defalutColoringGroup, SWT.CHECK);
this.defaultColoringCheckBox.setText(Constants.DEFAULT_COLORING_BUTTON_TEXT);
errorLabel = new Label(defalutColoringGroup, SWT.NONE);
errorLabel.setText("Expression is not valid, enter a valid expression and try again!");
errorLabel.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
errorLabel.setVisible(false);
this.viewer = tableviewerComposite.createTableViewer(defalutColoringGroup);
this.viewer.setContentProvider(new ArrayContentProvider());
try {
contentProvider = new ContentProvider();
this.viewer.setInput(contentProvider.getScenarios());
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
return container;
}
#Override
protected Button getApplyButton() {
super.getApplyButton();
}
}
//Method to create columns of the table
private void createTableColumns(final TableViewer viewer,final Composite defalutColoringGroup) {
TableViewerColumn scenariosColumn = createTableViewerColumn(viewer,Constants.SCENARIOS_COLUMN_NAME,Constants.SCENARIOS_COLUMN_NUMBER);
ScenariosLabelProvider scenariosLabelProvider = new ScenariosLabelProvider();
scenariosColumn.setLabelProvider(scenariosLabelProvider);
scenariosColumn.setEditingSupport(new ScenariosEditingSupport(viewer));
//more columns
}
//Editing Support for column
public class ScenariosEditingSupport extends EditingSupport {
private final TableViewer viewer;
private final CellEditor editor;
private final DefaultColorsPreferencePage preferencePage;
public ScenariosEditingSupport(TableViewer viewer) {
super(viewer);
this.viewer = viewer;
this.editor = new TextCellEditor(viewer.getTable());
this.preferencePage = new DefaultColorsPreferencePage();
}
#Override
protected CellEditor getCellEditor(Object element) {
return editor;
}
#Override
protected boolean canEdit(Object element) {
return true;
}
#Override
protected Object getValue(Object element) {
return ((Content) element).getExpression();
}
#Override
protected void setValue(Object element, Object changedExpression) {
String expression = String.valueOf(changedExpression);
if(Repository.isExpressionValid(expression)){
((Content) element).setExpression(expression);
viewer.update(element, null);
}
else{
preferencePage.setValid(false);
preferencePage.setErrorMessage("Expression is not valid, enter a valid expression and try again!");
((Content) element).setExpression(expression);
viewer.update(element, null);
}
}
}
You don't access the Apply button to enable / disable the preference page. Instead call the
setValid(false);
method of PreferencePage to disable Apply and OK.
Call setValid(true) when the page is OK.
You might also want to call the setErrorMessage or setMessage methods to set a message while the page is invalid.

how to select entire tableviewer row when checkbox clicked (first column of the table has checkboxes in each row)

am beginner to SWT, anyone please help,
my problem is:
i have a table, which has 10 Columns,
the first column has Check box and the rest of the column are filled from Database,
when i check the checkbox i want that perticular row to be selected,
i am pasting my table code below,
public static void main(String arg[])
{
// shell and display declared here
mainTable = new TableViewer(content, SWT.H_SCROLL| SWT.V_SCROLL | SWT.BORDER |SWT.DM_FILL_BACKGROUND|SWT.FULL_SELECTION);
mainTable .getTable().setHeaderVisible(true);
mainTable .getTable().setLinesVisible(true);
mainTable .setContentProvider(new ArrayContentProvider());
// COLUM FOR PLACING THE CHECK BOXES
TableColumn columncOL=new TableColumn(mainTable .getTable(),SWT.NONE);
columncOL.setText("");
columncOL.setWidth(40);
TableViewerColumn columnaC=new TableViewerColumn(mainTable ,columncOL);
columnaC.setLabelProvider(new ColumnLabelProvider(){
Map<Object, Button> buttons = new HashMap<Object, Button>();
#Override
public void update(ViewerCell cell) {
TableItem item = (TableItem) cell.getItem();
Button button;
if(buttons.containsKey(cell.getElement()))
{
button = buttons.get(cell.getElement());
}
else
{
button = new Button((Composite) cell.getViewerRow().getControl(),SWT.CHECK);
String s = "Item 1";
button.setData(s, "Some other info or object here");
s = "Item 2";
button.setData(s, "This is item two");
//buttons.put(cell.getElement(), button);
}
TableEditor editor = new TableEditor(item.getParent());
editor.grabHorizontal = true;
editor.grabVertical = true;
editor.setEditor(button , item, cell.getColumnIndex());
editor.layout();
}
});
// CREATING 1st COLUMNS
TableColumn column1Head=new TableColumn(mainTable.getTable(),SWT.NONE);
column1Head.setText("col1");
column1Head.setWidth(200);
// setting column input
TableViewerColumn column1=new TableViewerColumn(mainTable,column1Head);
column1.setLabelProvider(new ColumnLabelProvider()
{
public String getText(Object Element)
{
Student ap=(Student )Element;
return ap.col1();
}
});
}
like this am creating remaing 8 columns
i want to select the entire row when a perticluar check box checked .
any one pleeeease help me As early as possible....
Use CheckboxTableViewer to show a table with check boxes:
mainTable = CheckboxTableViewer.newCheckList(content, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION);
To select the line when a check box is ticked you will need to use addCheckStateListener to select the checked row, something like:
mainTable.addCheckStateListener(new ICheckStateListener()
{
#Override
public void checkStateChanged(CheckStateChangedEvent event)
{
if (event.getChecked())
mainTable.setSelection(new StructuredSelection(event.getObject()));
}
});
Easy way :first column of the table has checkboxes in each row can
selected or not
CheckboxTableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER | SWT.FULL_SELECTION);
Table table = tableViewer.getTable();
table.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event e) {
Table table = (Table) e.widget;
TableItem item = table.getItem(table.getSelectionIndex());
for (int col = 0; col < table.getColumnCount(); col++)
{
//Table_Column Checked or Not
if(item.getChecked())
//return true
//all ready checked(true) to change unchecked(false)
item.setChecked(false);
else
//unchecked(false) to checked(true) each row
item.setChecked(true);
}
}
}
this is useful for you....thanks

How to remove redundant column in tableviewer?

I created tableviewer .
The columns are created dynamically.
The problem that I always have another column in the table.
I checked the names of the columns and I didn't get any empty column.
Maybe it could be a configuration of the tableviewer .
Do you have any idea why I always have another column ?
//The gridViewer Class
public class MyGridViewer extends TableViewer {
public MyGridViewer (Composite parent) {
super(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
final Table table = this.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
this.setContentProvider(new MyModelProvider());
}
}
#Override
protected void inputChanged(Object input, Object oldInput) {
removeColumn();
tableCol = new TableViewerColumn(this, SWT.NONE);
column = tableCol.getColumn();
column.setText(dataColumnHeader.getName());
column.setWidth(100);
column.setResizable(true);
column.setMoveable(true);
tableCol.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
DataRow r = (DataRow) element;
DataCell c = r.getDataCellByName(dataColumnHeader.getName());
if (c != null && c.getValue() != null) {
return c.getValue().toString();
}
return null;
}
#Override
public Image getImage(Object element) {
//Add my imgae
}
});
editingSupport = new StringCellEditingSupport(this, dataColumnHeader);
tableCol.setEditingSupport(editingSupport);
super.inputChanged(input, oldInput);
}
I don't know exactly what "redundant" column you're reffering to, but maybe you haven't disposed it properly (if you're saying they are created dynamically).
If I were you, I would add them differently.
private void createColumns()
{
// First, dipose any previously created columns
for (TableColumn column : table.getColumns())
column.dispose();
// Then recreate them
for (MyColumnPO col : getColumns())
{
TableColumn newCol = new TableColumn(table, SWT.NONE);
newCol.setText( col.text );
newCol.setWidth( col.width );
}
}
MyColumnPO would be a POJO which stands for "My Column Presentation Object". This contains info about your columns (text, width, tooltip).
Now, in the getColumns() method, you add/create/delete/update desired columns, instantiating MyColumnPO objects, and adding them to a List which you will return.
Each time you need to re-create the columns dynamically, you call createColumns().

How to initial check elements in a CheckboxTreeviewer

I'm using a custom Dialog with a CheckboxTreeViewer inside my GMF Editor, which works fine so far, as you can see below:
After closing the Dialog, the selected element are saved so far. Now my Problem:
When I open the dialog again, all elements are unchecked. So I thought it would be easy to tell the treeViewer that specific elements should be initially checked.
But it turned out that it's not that easy, as the Tree initially consist of the root element. The other elements are not added until the tree expands. Elements are added by calling the getChildren(Object parentElement) of the ContentProvider.
So it seems that I can't check specific elements initially, but rather have to provide a dynamically approach. I'm looking for something like an element added listener, but there seems none to exist.
Here is the part, where I'm creating the CheckboxTreeViewer
Composite container = (Composite) super.createDialogArea(parent);
tv = new CheckboxTreeViewer(container, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
tv.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
tv.setAutoExpandLevel(2);
tv.setContentProvider(new FeaturePropertyDialogContentProvider(this));
tv.setLabelProvider(new FeaturePropertyDialogLabelProvider());
tv.setInput(productLine);
tv.setExpandPreCheckFilters(true);
return container;
And here is the getChildren method of my ContentProvider:
#Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof PL) {
PL p = (PL) parentElement;
return new Object[] { p.getPropertyList() };
}
else if (parentElement instanceof PropertyList) {
PropertyList propertyList = (PropertyList) parentElement;
return propertyList.getGeneralPlatforms().toArray();
} else if (parentElement instanceof GeneralPlatform) {
GeneralPlatform platform = (GeneralPlatform) parentElement;
return platform.getHardwareElements().toArray();
}
} else {
return null;
}
}
Any ideas on this?
--------------------Solution---------------------
Found the following solution by myself, which works fine for me so far:
tv.expandAll();
tv.setCheckedElements(preSelectedProperties.toArray());
tv.collapseAll();
tv.expandToLevel(2);
You should add a listener on the tree viewer to get a notification when a node gets expanded (method addTreeListener() on TreeViewer). At that time, the nodes are already in the tree, and you can check the check-box.
Here is a snippet of a tree that sets the check state when the tree is expanded:
public class Snippet {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final Map<String, Boolean> userChecks = new HashMap<>();
final CheckboxTreeViewer tv = new CheckboxTreeViewer(shell, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
GridData gridData = new GridData(GridData.FILL_BOTH);
tv.getTree().setLayoutData(gridData);
final FeaturePropertyDialogContentProvider provider = new FeaturePropertyDialogContentProvider(tv);
tv.setContentProvider(provider);
tv.setInput("root");
tv.addCheckStateListener(new ICheckStateListener() {
#Override
public void checkStateChanged(CheckStateChangedEvent event) {
userChecks.put((String) event.getElement(), event.getChecked());
}
});
tv.addTreeListener(new ITreeViewerListener() {
#Override
public void treeCollapsed(TreeExpansionEvent event) {
}
#Override
public void treeExpanded(TreeExpansionEvent event) {
final Object element = event.getElement();
final Object[] children = provider.getChildren(element);
for (Object child : children) {
if (userChecks.containsKey(child)) {
tv.setChecked(child, userChecks.get(child));
} else if (child.equals("b")) {
tv.setChecked(child, true);
}
}
}
});
shell.setSize(200, 200);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
private static class FeaturePropertyDialogContentProvider implements ITreeContentProvider {
final CheckboxTreeViewer tv;
private FeaturePropertyDialogContentProvider(CheckboxTreeViewer tv) {
this.tv = tv;
}
#Override
public Object[] getElements(Object inputElement) {
return this.getChildren(inputElement);
}
#Override
public Object[] getChildren(Object parentElement) {
switch ((String) parentElement) {
case "root":
return new String[]{"1"};
case "1":
return new String[]{"a", "b", "c"};
default:
return new String[0];
}
}
#Override
public Object getParent(Object element) {
return null;
}
#Override
public boolean hasChildren(Object element) {
return this.getChildren(element).length > 0;
}
#Override
public void dispose() {
}
#Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
}
In this example, I only compare the node value with the string "b".
Edit: in this context, elements are immutable (for some reason they cannot be changed), and the solution with wrapping objects in tree nodes is not accepted (see comments).
In that case, you can save user check actions in a map, and when setting checked/unchecked state, search for any previous user check actions. I think it is reasonable to assume the map is simple and will not grow too much. User has to check a lot of nodes to get it big :)
I updated the snippet to keep track of user checks.

Creating context menu only for a particular item selected in the Tree Viewer

I have a TreeViewer, and I created a context menu with some actions.
With this code snippet below, I get the context menu for all tree items.
protected void createMasterPart(final IManagedForm managedForm, final Composite parent)
{
Tree t = toolkit.createTree(client, SWT.NULL);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 20;
gd.widthHint = 100;
t.setLayoutData(gd);
toolkit.paintBordersFor(client);
section.setClient(client);
final SectionPart spart = new SectionPart(section);
managedForm.addPart(spart);
viewer = new TreeViewer(t);
viewer.addSelectionChangedListener(new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent event)
{
managedForm.fireSelectionChanged(spart, event.getSelection());
}
});
viewer.setContentProvider(new MasterTreeContentProvider());
viewer.setInput(page.getEditor().getEditorInput());
m_newKeyAction = new AddNewKeyAction(viewer, parent.getShell());
m_newValueAction = new AddNewValueAction(viewer, parent.getShell());
hookContextMenu();
}
private void hookContextMenu()
{
MenuManager menuMgr = new MenuManager();
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager)
{
fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
}
protected void fillContextMenu( IMenuManager manager )
{
manager.add( m_newKeyAction );
manager.add( m_newValueAction );
}
I want this context menu to be displayed only for tree items of particular type.
Please let me know how do I get this done.

Categories