Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [platform-ui-dev] Proposing a change to how cell editors are used in TableViewer

Abeer,

The use case and your change look reasonable overall.  Ideally we'd do it 
by augmenting the existing viewers rather than defining new ones though.
The best approach would be for you to file this as an enhancement request 
in bugzilla, and we could then proceed from there.

Regards,
Nick




Abeer <abeer@xxxxxxxxxx> 
Sent by: platform-ui-dev-admin@xxxxxxxxxxx
07/23/2004 04:41 AM
Please respond to
platform-ui-dev


To
platform-ui-dev@xxxxxxxxxxx
cc

Subject
[platform-ui-dev] Proposing a change to how cell editors are used in 
TableViewer






Hi,
I am working a lot with Table and TableViewer classes, and have the
following requirements:

If the celleditor control is a combo box, the values list has to be
populated dynamically depending on the data in the selected row
(TableItem).
Also, sometimes, i have to dynamically change the control being offered
as a cell editor depending on the data in the selected TableItem. (eg:
many times i have to dynamically decide between a Text and a Combo
control for that column (both are valid in specific cicumstances).

There is no provision currently in the Eclipse source for doing this,
so i have created a subinterface of the ICellModifier interface, and
have added a hack to the TableViewerImpl class (in
activateCellEditor()). I also had to hack the TableViewer class to use
my class intead of TableViewerImpl. Actually, the change is just of one
line in TableViewerImpl. I am attaching the three source files. Please
tell me if this change is possible to the jface codebase, else i will
have to maintain my code in sync with the jface code.

Thanx in advance
Abeer

P.S.: I am also attaching an application specific implementation of the
INPCellModifier, to illustrate how i am using this interface.

package com.kenati.npeint.tools.cliide.ui.widgets;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellModifier;

/**
 * @author abeer
 */
public interface INPCellModifier extends ICellModifier
{
    public CellEditor getCellEditor(Object element, String property);
}

package com.kenati.npeint.tools.cliide.ui.widgets;

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

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;

import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.IViewerLabelProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerLabel;
import org.eclipse.jface.viewers.ViewerSorter;

/**
 * We are using all the code from the TableViewer class as is since the
 * TableViewer is not intended to be subclassed.
 * We have only two changes in this class
 * TableViewer uses the class TableViewerImpl and we want to use 
 * the class NPTableViewerImpl instead.
 * Also we are using the interface INPCellModifier instead of 
ICellModifier
 * We need maintain to this class in sync with future releases of Eclipse
 */
public class NPTableViewer extends StructuredViewer {

                 /**
                  * Internal table viewer implementation.
                  */
    /**
                  * ****************************
                  * Abeer :) - this is the only diff between TableViewer 
and NPTableViewer
                  * using NPTableViewerImpl instead of TableViewerImpl
                  * ****************************
     */
                 private NPTableViewerImpl tableViewerImpl;

                 /**
                  * This viewer's table control.
                  */
                 private Table table;

                 /**
                  * This viewer's table editor.
                  */
                 private TableEditor tableEditor;
/**
 * Creates a table viewer on a newly-created table control under the given 
parent.
 * The table control is created using the SWT style bits <code>MULTI, 
H_SCROLL, V_SCROLL,</code> and <code>BORDER</code>.
 * The viewer has no input, no content provider, a default label provider, 

 * no sorter, and no filters. The table has no columns.
 *
 * @param parent the parent control
 */
public NPTableViewer(Composite parent) {
                 this(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | 
SWT.BORDER);
}
/**
 * Creates a table viewer on a newly-created table control under the given 
parent.
 * The table control is created using the given style bits.
 * The viewer has no input, no content provider, a default label provider, 

 * no sorter, and no filters. The table has no columns.
 *
 * @param parent the parent control
 * @param style SWT style bits
 */
public NPTableViewer(Composite parent, int style) {
                 this(new Table(parent, style));
}
/**
 * Creates a table viewer on the given table control.
 * The viewer has no input, no content provider, a default label provider, 

 * no sorter, and no filters. 
 *
 * @param table the table control
 */
public NPTableViewer(Table table) {
                 this.table = table;
                 hookControl(table);
                 tableEditor = new TableEditor(table);
                 initTableViewerImpl();
}
/**
 * Adds the given elements to this table viewer.
 * If this viewer does not have a sorter, the elements are added at the 
end
 * in the order given; otherwise the elements are inserted at appropriate 
positions.
 * <p>
 * This method should be called (by the content provider) when elements 
 * have 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.
 * </p>
 *
 * @param elements the elements to add
 */
public void add(Object[] elements) {
                 assertElementsNotNull(elements); 
                 Object[] filtered = filter(elements);
                 for (int i = 0; i < filtered.length; i++){
                                 Object element = filtered[i];
                                 int index = indexForElement(element);
                                 updateItem(new TableItem(getTable(), 
SWT.NONE, index), element);
                 }
}
/**
 * Adds the given element to this table viewer.
 * If this viewer does not have a sorter, the element is added at the end;
 * otherwise the element is inserted at the appropriate position.
 * <p>
 * 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.
 * </p>
 *
 * @param element the element to add
 */
public void add(Object element) {
                 add(new Object[] { element });
}
/**
 * Cancels a currently active cell editor. All changes already done in the 
cell
 * editor are lost.
 */
public void cancelEditing() {
                 tableViewerImpl.cancelEditing();
}
/* (non-Javadoc)
 * Method declared on StructuredViewer.
 */
protected Widget doFindInputItem(Object element) {
                 if (equals(element, getRoot()))
                                 return getTable();
                 return null;
}
/* (non-Javadoc)
 * Method declared on StructuredViewer.
 */
protected Widget doFindItem(Object element) {
                 TableItem[] children = table.getItems();
                 for (int i = 0; i < children.length; i++) {
                                 TableItem item = children[i];
                                 Object data = item.getData();
                                 if (data != null && equals(data, 
element))
                                                 return item;
                 }

                 return null;
}
/* (non-Javadoc)
 * Method declared on StructuredViewer.
 */
protected void doUpdateItem(Widget widget, Object element, boolean 
fullMap) {
                 if (widget instanceof TableItem) {
                                 final TableItem item = (TableItem) 
widget;
 
                                 // remember element we are showing
                                 if (fullMap) {
                                                 associate(element, item);
                                 } else {
                                                 item.setData(element);
                                                 mapElement(element, 
item); 
                                 }
 
                                 IBaseLabelProvider prov = 
getLabelProvider();
                                 ITableLabelProvider tprov = null;
                                 ILabelProvider lprov = null;
 
 
                                 if (prov instanceof ITableLabelProvider) 
{
                                                 tprov = 
(ITableLabelProvider) prov;
                                 }
                                 else {
                                                 lprov = (ILabelProvider) 
prov;
                                 }
                                 int columnCount = table.getColumnCount();
                                 TableItem ti = item;
                                 // Also enter loop if no columns added. 
See 1G9WWGZ: JFUIF:WINNT - TableViewer with 0 columns does not work
                                 for (int column = 0; column < columnCount 
|| column == 0; column++) {
                                                 // Similar code in 
TableTreeViewer.doUpdateItem()
                                                 String text = 
"";//$NON-NLS-1$
                                                 Image image = null;
                                                 if (tprov != null) {
                                                                 text = 
tprov.getColumnText(element, column);
                                                                 image = 
tprov.getColumnImage(element, column);
                                                 }
                                                 else {
                                                                 if 
(column == 0) {
  if (lprov instanceof IViewerLabelProvider) {
                 IViewerLabelProvider itemProvider = 
(IViewerLabelProvider) lprov;
                 ViewerLabel updateLabel = new 
ViewerLabel(item.getText(),item.getImage());
  
                 itemProvider.updateLabel(updateLabel, element);
                 text = updateLabel.getText();
                 image = updateLabel.getImage();  
  
  }
  else{
                 text = lprov.getText(element);
                 image = lprov.getImage(element); 
  }
                                                 }
                                 }
                                                 ti.setText(column, text);
                                                 if (ti.getImage(column) 
!= image) {
 ti.setImage(column, image);
                                                 }
                                 }
                                 if (prov instanceof IColorProvider) {
                                                 IColorProvider cprov = 
(IColorProvider) prov;
 ti.setForeground(cprov.getForeground(element));
 ti.setBackground(cprov.getBackground(element));
                                 }
                                 if (prov instanceof IFontProvider) {
                                     IFontProvider fprov = (IFontProvider) 
prov;
                                     ti.setFont(fprov.getFont(element));
                                 } 
                 }
}
/**
 * Starts editing the given element.
 *
 * @param element the element
 * @param column the column number
 */
public void editElement(Object element, int column) {
                 tableViewerImpl.editElement(element,column);
}
/**
 * Returns the cell editors of this table viewer.
 *
 * @return the list of cell editors
 */
public CellEditor[] getCellEditors() {
                 return tableViewerImpl.getCellEditors();
}
/**
 * Returns the cell modifier of this table viewer.
 *
 * @return the cell modifier
 */
public ICellModifier getCellModifier() {
                 return tableViewerImpl.getCellModifier();
}
/**
 * Returns the column properties of this table viewer.
 * The properties must correspond with the columns of the table control.
 * They are used to identify the column in a cell modifier.
 *
 * @return the list of column properties
 */
public Object[] getColumnProperties() {
                 return tableViewerImpl.getColumnProperties();
}
/* (non-Javadoc)
 * Method declared on Viewer.
 */
public Control getControl() {
                 return table;
}
/**
 * Returns the element with the given index from this table viewer.
 * Returns <code>null</code> if the index is out of range.
 * <p>
 * This method is internal to the framework.
 * </p>
 *
 * @param index the zero-based index
 * @return the element at the given index, or <code>null</code> if the
 *   index is out of range
 */
public Object getElementAt(int index) {
                 if (index >= 0 && index < table.getItemCount()) {
                                 TableItem i = table.getItem(index);
                                 if(i != null)
                                     return i.getData();
                 }
                 return null;
}
/**
 * The table viewer implementation of this <code>Viewer</code> framework
 * method returns the label provider, which in the case of table 
 * viewers will be an instance of either <code>ITableLabelProvider</code>
 * or <code>ILabelProvider</code>.
 * If it is an <code>ITableLabelProvider</code>, then it provides a
 * separate label text and image for each column. If it is an 
 * <code>ILabelProvider</code>, then it provides only the label text 
 * and image for the first column, and any remaining columns are blank.
 */
public IBaseLabelProvider getLabelProvider() {
                 return super.getLabelProvider();
}
/* (non-Javadoc)
 * Method declared on StructuredViewer.
 */
protected List getSelectionFromWidget() {
                 Widget[] items = table.getSelection();
                 ArrayList list = new ArrayList(items.length);
                 for (int i = 0; i < items.length; i++) {
                                 Widget item = items[i];
                                 Object e = item.getData();
                                 if (e != null)
                                                 list.add(e);
                 }
                 return list;
}
/**
 * Returns this table viewer's table control.
 *
 * @return the table control
 */
public Table getTable() {
                 return table;
}
/* (non-Javadoc)
 * Method declared on StructuredViewer.
 */
protected void hookControl(Control control) {
                 super.hookControl(control);
                 Table tableControl = (Table)control;
                 tableControl.addMouseListener(new MouseAdapter() {
                                 public void mouseDown(MouseEvent e) {
 tableViewerImpl.handleMouseDown(e);
                                 }
                 });
}
/*
 * Returns the index where the item should be inserted.
*/
protected int indexForElement(Object element) {
                 ViewerSorter sorter = getSorter();
                 if(sorter == null)
                                 return table.getItemCount();
                 int count = table.getItemCount();
                 int min = 0, max = count - 1;
                 while (min <= max) {
                                 int mid = (min + max) / 2;
                                 Object data = 
table.getItem(mid).getData();
                                 int compare = sorter.compare(this, data, 
element);
                                 if (compare == 0) {
                                                 // find first item > 
element
                                                 while (compare == 0) {
                                                                 ++mid;
                                                                 if (mid 
>= count) {
  break;
                                                                 }
                                                                 data = 
table.getItem(mid).getData();
                                                                 compare = 
sorter.compare(this, data, element);
                                                 }
                                                 return mid;
                                 }
                                 if (compare < 0)
                                                 min = mid + 1;
                                 else
                                                 max = mid - 1;
                 }
                 return min;
}
/**
 * Initializes the table viewer implementation.
 */
/**
 * ****************************
 * Abeer :) - this is the only diff between TableViewer and NPTableViewer
 * using NPTableViewerImpl instead of TableViewerImpl
 * ****************************
 */
private void initTableViewerImpl() {
                 tableViewerImpl = new NPTableViewerImpl(this) {
                                 Rectangle getBounds(Item item, int 
columnNumber) {
                                                 return 
((TableItem)item).getBounds(columnNumber);
                                 }
                                 int getColumnCount() {
                                                 return 
getTable().getColumnCount();
                                 }
                                 Item[] getSelection() {
                                                 return 
getTable().getSelection();
                                 }
                                 void setEditor(Control w, Item item, int 
columnNumber) {
                                                 tableEditor.setEditor(w, 
(TableItem)item, columnNumber);
                                 }
                                 void setSelection(StructuredSelection 
selection, boolean b) {
 NPTableViewer.this.setSelection(selection,b);
                                 }
                                 void showSelection() {
 getTable().showSelection();
                                 }
                                 void setLayoutData(CellEditor.LayoutData 
layoutData) {
 tableEditor.grabHorizontal = layoutData.grabHorizontal;
 tableEditor.horizontalAlignment = layoutData.horizontalAlignment;
                                                 tableEditor.minimumWidth 
= layoutData.minimumWidth;
                                 }
                                 void handleDoubleClickEvent() {
                                                 Viewer viewer = 
getViewer();
                                                 fireDoubleClick (new 
DoubleClickEvent(viewer, viewer.getSelection()));
                                                 fireOpen (new 
OpenEvent(viewer, viewer.getSelection()));
                                 }
                 };
}
/* (non-Javadoc)
 * Method declared on Viewer.
 */
protected void inputChanged(Object input, Object oldInput) {
                 getControl().setRedraw(false);
                 try {
                                 // refresh() attempts to preserve 
selection, which we want here
                                 refresh();
                 }
                 finally {
                                 getControl().setRedraw(true);
                 }
}
/**
 * Inserts the given element into this table viewer at the given position.
 * If this viewer has a sorter, the position is ignored and the element is 
inserted
 * at the correct position in the sort order.
 * <p>
 * This method should be called (by the content provider) when elements 
 * have 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.
 * </p>
 *
 * @param element the element
 * @param position a 0-based position relative to the model, or -1 to 
indicate the last position
 */
public void insert(Object element, int position) {
                 tableViewerImpl.applyEditorValue();
                 if (getSorter() != null || hasFilters()) {
                                 add(element);
                                 return;
                 }
                 if (position == -1)
                                 position = table.getItemCount();
                 updateItem(new TableItem(table, SWT.NONE, position), 
element);
}
/* (non-Javadoc)
 * Method declared on StructuredViewer.
 */
protected void internalRefresh(Object element) {
                 internalRefresh(element, true);
}

/* (non-Javadoc)
 * Method declared on StructuredViewer.
 */
protected void internalRefresh(Object element, boolean updateLabels) {
                 tableViewerImpl.applyEditorValue();
                 if (element == null || equals(element, getRoot())) {
                                 // the parent

                                 // in the code below, it is important to 
do all disassociates
                                 // before any associates, since a later 
disassociate can undo an earlier associate
                                 // e.g. if (a, b) is replaced by (b, a), 
the disassociate of b to item 1 could undo
                                 // the associate of b to item 0.
 
                                 Object[] children = 
getSortedChildren(getRoot());
                                 TableItem[] items = table.getItems();
                                 int min = Math.min(children.length, 
items.length);
                                 for (int i = 0; i < min; ++i) {
                                                 // if the element is 
unchanged, update its label if appropriate
                                                 if (equals(children[i], 
items[i].getData())) {
                                                                 if 
(updateLabels) {
  updateItem(items[i], children[i]);
                                                                 }
                                                                 else {
  // associate the new element, even if equal to the old one,
  // to remove stale references (see bug 31314)
  associate(children[i], items[i]);
                                                                 }
                                                 }
                                                 else {
                                                                 // 
updateItem does an associate(...), which can mess up
                                                                 // the 
associations if the order of elements has changed.
                                                                 // E.g. 
(a, b) -> (b, a) first replaces a->0 with b->0, then replaces b->1 with 
a->1, but this actually removes b->0.
                                                                 // So, if 
the object associated with this item has changed,
                                                                 // just 
disassociate it for now, and update it below.
 items[i].setText(""); //$NON-NLS-1$
 items[i].setImage(new Image[0]);
 disassociate(items[i]);
                                                 }
                                 }
 
                                 // dispose of all items beyond the end of 
the current elements
                                 if (min < items.length) {
                                                 for (int i = 
items.length; --i >= min;) {
 disassociate(items[i]);
                                                 }
                                                 table.remove(min, 
items.length-1);
                                 }
 
                                 // Workaround for 1GDGN4Q: ITPUI:WIN2000 
- TableViewer icons get scrunched
                                 if (table.getItemCount() == 0) {
                                                 table.removeAll();
                                 }

                                 // Update items which were removed above
                                 for (int i = 0; i < min; ++i) {
                                                 if (items[i].getData() == 
null) {
 updateItem(items[i], children[i]);
                                                 }
                                 }
 
                                 // add any remaining elements
                                 for (int i = min; i < children.length; 
++i) {
                                                 updateItem(new 
TableItem(table, SWT.NONE, i), children[i]);
                                 }
                 }
                 else {
                                 Widget w = findItem(element);
                                 if (w != null) {
                                                 updateItem(w, element);
                                 }
                 }
}
/**
 * Removes the given elements from this table viewer.
 *
 * @param elements the elements to remove
 */
private void internalRemove(final Object[] elements) {
                 Object input = getInput();
                 for (int i = 0; i < elements.length; ++i) {
                                 if (equals(elements[i], input)) {
                                                 setInput(null);
                                                 return;
                                 }
                 }
                 // use remove(int[]) rather than repeated 
TableItem.dispose() calls
                 // to allow SWT to optimize multiple removals
                 int[] indices = new int[elements.length];
                 int count = 0;
                 for (int i = 0; i < elements.length; ++i) {
                                 Widget w = findItem(elements[i]);
                                 if (w instanceof TableItem) {
                                                 TableItem item = 
(TableItem) w;
                                                 disassociate(item);
                                                 indices[count++] = 
table.indexOf(item);
                                 }
                 }
                 if (count < indices.length) {
                                 System.arraycopy(indices, 0, indices = 
new int[count], 0, count);
                 }
                 table.remove(indices);
 
                 // Workaround for 1GDGN4Q: ITPUI:WIN2000 - TableViewer 
icons get scrunched
                 if (table.getItemCount() == 0) {
                                 table.removeAll();
                 }
}
/**
 * Returns whether there is an active cell editor.
 *
 * @return <code>true</code> if there is an active cell editor, and 
 *   <code>false</code> otherwise
 */
public boolean isCellEditorActive() {
                 return tableViewerImpl.isCellEditorActive();
}
/**
 * Removes the given elements from this table viewer.
 * The selection is updated if required.
 * <p>
 * This method should be called (by the content provider) when elements 
 * have been removed from the model, in order to cause the viewer to 
accurately
 * reflect the model. This method only affects the viewer, not the model.
 * </p>
 *
 * @param elements the elements to remove
 */
public void remove(final Object[] elements) {
                 assertElementsNotNull(elements);
                 preservingSelection(new Runnable() {
                                 public void run() {
                                                 internalRemove(elements);
                                 }
                 });
}
/**
 * Removes the given element from this table viewer.
 * The selection is updated if necessary.
 * <p>
 * This method should be called (by the content provider) when a single 
element 
 * has been removed from 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
 * removal of multiple elements.
 * </p>
 *
 * @param element the element
 */
public void remove(Object element) {
                 remove(new Object[] { element });
}
/*
 * Non-Javadoc.
 * Method defined on StructuredViewer.
 */
public void reveal(Object element) {
                 Assert.isNotNull(element);
                 Widget w = findItem(element);
                 if (w instanceof TableItem)
                                 getTable().showItem((TableItem) w);
}
/**
 * Sets the cell editors of this table viewer.
 *
 * @param editors the list of cell editors
 */
public void setCellEditors(CellEditor[] editors) {
                 tableViewerImpl.setCellEditors(editors);
}
/**
 * Sets the cell modifier of this table viewer.
 *
 * @param modifier the cell modifier
 */
public void setCellModifier(INPCellModifier modifier) {
                 tableViewerImpl.setCellModifier(modifier);
}
/**
 * Sets the column properties of this table viewer.
 * The properties must correspond with the columns of the table control.
 * They are used to identify the column in a cell modifier.
 *
 * @param columnProperties the list of column properties
 */
public void setColumnProperties(String[] columnProperties) {
                 tableViewerImpl.setColumnProperties(columnProperties);
}
/**
 * The table viewer implementation of this <code>Viewer</code> framework
 * method ensures that the given label provider is an instance
 * of either <code>ITableLabelProvider</code> or 
<code>ILabelProvider</code>.
 * If it is an <code>ITableLabelProvider</code>, then it provides a
 * separate label text and image for each column. If it is an 
 * <code>ILabelProvider</code>, then it provides only the label text 
 * and image for the first column, and any remaining columns are blank.
 */
public void setLabelProvider(IBaseLabelProvider labelProvider) {
                 Assert.isTrue(labelProvider instanceof 
ITableLabelProvider || labelProvider instanceof ILabelProvider );
                 super.setLabelProvider(labelProvider);
}
/* (non-Javadoc)
 * Method declared on StructuredViewer.
 */
protected void setSelectionToWidget(List list, boolean reveal) {
                 if (list == null) {
                                 table.deselectAll();
                                 return;
                 }
                 int size = list.size();
                 TableItem[] items = new TableItem[size];
                 TableItem firstItem = null;
                 int count = 0;
                 for (int i = 0; i < size; ++i) {
                                 Object o = list.get(i);
                                 Widget w = findItem(o);
                                 if (w instanceof TableItem) {
                                                 TableItem item = 
(TableItem) w;
                                                 items[count++] = item;
                                                 if (firstItem == null)
                                                                 firstItem 
= item;
                                 }
                 }
                 if (count < size) {
                                 System.arraycopy(items, 0, items = new 
TableItem[count], 0, count);
                 }
                 table.setSelection(items);
 
                 if (reveal && firstItem != null) {
                                 table.showItem(firstItem);
                 }
}
}

package com.kenati.npeint.tools.cliide.ui.widgets;

/**
 * @author abeer
 * We are using all the code from the TableViewerImpl class as is since 
 * access to the TableViewerImpl class is restricted to its package only 
 * We are using INPCellModifier instead of ICellModifier
 * We need to change only one line of code:
 * in method activateCellEditor(), 
 * instead of "cellEditor = cellEditors[columnNumber];"
 * we are using "cellEditor = cellModifier.getCellEditor(element, 
property);"
 * We need maintain to this class in sync with future releases of Eclipse
 */

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellEditorListener;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Item;

/* package */ abstract class NPTableViewerImpl {
 
                 private CellEditor cellEditor;
                 private CellEditor[] cellEditors;
                 private INPCellModifier cellModifier;
                 private String[] columnProperties;
                 private Item tableItem;
                 private int columnNumber;
                 private ICellEditorListener cellEditorListener;
                 private FocusListener focusListener;
                 private MouseListener mouseListener;
                 private int doubleClickExpirationTime;
                 private StructuredViewer viewer;
 

                 NPTableViewerImpl(StructuredViewer viewer) {
                 this.viewer = viewer;
                 initCellEditorListener();
}

/**
 * Returns this <code>TableViewerImpl</code> viewer
 * 
 * @return the viewer
 */
public StructuredViewer getViewer() {
                 return viewer;
}

private void activateCellEditor() {
                 if(cellModifier != null) {
                                 Object element = tableItem.getData();
                                 String property = 
columnProperties[columnNumber];
                                 if (cellModifier.canModify(element, 
property)) {
/*****************************
 * Abeer :) - this is the only diff between TableViewerImpl and 
NPTableViewerImpl
 * instead of "cellEditor = cellEditors[columnNumber];"
 * we are using "cellEditor = cellModifier.getCellEditor(element, 
property);"
 *****************************/
                                                 //cellEditor = 
cellEditors[columnNumber];
                                     cellEditor = 
cellModifier.getCellEditor(element, property);
                                                 //table.showSelection();
 cellEditor.addListener(cellEditorListener);
                                                 Object value = 
cellModifier.getValue(element, property);
 cellEditor.setValue(value);
                                                 // Tricky flow of control 
here:
                                                 // activate() can trigger 
callback to cellEditorListener which will clear cellEditor
                                                 // so must get control 
first, but must still call activate() even if there is no control.
                                                 final Control control = 
cellEditor.getControl();
                                                 cellEditor.activate();
                                                 if (control == null)
                                                                 return;
 setLayoutData(cellEditor.getLayoutData());
                                                 setEditor(control, 
tableItem, columnNumber); 
                                                 cellEditor.setFocus();
                                                 if(focusListener == null) 
{
 focusListener = new FocusAdapter() {
  public void focusLost(FocusEvent e) {
                 applyEditorValue();
  }
                                                                 };
                                                 }
 control.addFocusListener(focusListener);
                                                 mouseListener = new 
MouseAdapter() {
                                                                 public 
void mouseDown(MouseEvent e) {
  // time wrap? 
  // check for expiration of doubleClickTime
  if (e.time <= doubleClickExpirationTime ) {
                 control.removeMouseListener(mouseListener);
                 cancelEditing();
                 handleDoubleClickEvent();
  } else if (mouseListener != null) {
                 control.removeMouseListener(mouseListener);
  }
                                                                 } 
                                                 };   
 control.addMouseListener(mouseListener);
                                 }
                 } 
}
/**
 * Activate a cell editor for the given mouse position.
 */
private void activateCellEditor(MouseEvent event) {
                 if (tableItem == null || tableItem.isDisposed()) {
                                 //item no longer exists
                                 return;
                 }
                 int columnToEdit;
                 int columns = getColumnCount();
                 if (columns == 0) {
                                 // If no TableColumn, Table acts as if it 
has a single column
                                 // which takes the whole width.
                                 columnToEdit = 0;
                 }
                 else {
                                 columnToEdit = -1;
                                 for (int i = 0; i < columns; i++) {
                                                 Rectangle bounds = 
getBounds(tableItem, i);
                                                 if 
(bounds.contains(event.x, event.y)) {
 columnToEdit = i;
                                                                 break;
                                                 }
                                 }
                                 if (columnToEdit == -1) {
                                                 return;
                                 }
                 }
 
                 columnNumber = columnToEdit;
                 activateCellEditor();
}
/**
 * Deactivates the currently active cell editor.
 */
public void applyEditorValue() {
                 CellEditor c = this.cellEditor;
                 if (c != null) {
                                 // null out cell editor before calling 
save
                                 // in case save results in 
applyEditorValue being re-entered
                                 // see 1GAHI8Z: ITPUI:ALL - How to code 
event notification when using cell editor ?
                                 this.cellEditor = null;
                                 Item t = this.tableItem;
                                 // don't null out table item -- same item 
is still selected
                                 if (t != null && !t.isDisposed()) {
                                                 saveEditorValue(c, t);
                                 }
                                 setEditor(null, null, 0);
                                 c.removeListener(cellEditorListener);
                                 Control control = c.getControl();
                                 if (control != null) {
                                                 if (mouseListener != 
null) {
 control.removeMouseListener(mouseListener);
                                                 }
                                                 if (focusListener != 
null) {
 control.removeFocusListener(focusListener);
                                                 }
                                 }
                                 c.deactivate();
                 }
}
/**
 * Cancels the active cell editor, without saving the value 
 * back to the domain model.
 */
public void cancelEditing() {
                 if (cellEditor != null) {
                                 setEditor(null, null, 0);
 cellEditor.removeListener(cellEditorListener);
                                 CellEditor oldEditor = cellEditor;
                                 cellEditor = null;
                                 oldEditor.deactivate();
                 }
}
/**
 * Start editing the given element. 
 */
public void editElement(Object element, int column) {
                 if (cellEditor != null)
                                 applyEditorValue();

                 setSelection(new StructuredSelection(element), true);
                 Item[] selection = getSelection();
                 if (selection.length != 1)
                                 return;

                 tableItem = selection[0];

                 // Make sure selection is visible
                 showSelection();
                 columnNumber = column;
                 activateCellEditor();

}
abstract Rectangle getBounds(Item item, int columnNumber);
public CellEditor[] getCellEditors() {
                 return cellEditors;
}
public ICellModifier getCellModifier() {
                 return cellModifier; 
}
abstract int getColumnCount();
public Object[] getColumnProperties() {
                 return columnProperties;
}
abstract Item[] getSelection();
/**
 * Handles the mouse down event; activates the cell editor.
 */
public void handleMouseDown(MouseEvent event) {
                 if (event.button != 1)
                                 return;

                 if (cellEditor != null)
                                 applyEditorValue();
 
                 // activate the cell editor immediately.  If a second 
mouseDown
                 // is received prior to the expiration of the doubleClick 
time then
                 // the cell editor will be deactivated and a doubleClick 
event will
                 // be processed.
                 //
                 doubleClickExpirationTime = event.time + 
Display.getCurrent().getDoubleClickTime();    

                 Item[] items = getSelection();
                 // Do not edit if more than one row is selected.
                 if (items.length != 1) {
                                 tableItem = null;
                                 return;
                 }
                 tableItem = items[0];
                 activateCellEditor(event);
}
private void initCellEditorListener() {
                 cellEditorListener = new ICellEditorListener() {
                                 public void editorValueChanged(boolean 
oldValidState, boolean newValidState) {
                                                 // Ignore.
                                 }
 
                                 public void cancelEditor() {
 NPTableViewerImpl.this.cancelEditing();
                                 }
 
                                 public void applyEditorValue() {
 NPTableViewerImpl.this.applyEditorValue();
                                 }
                 };
}
/**
 * Returns <code>true</code> if there is an active cell editor; otherwise
 * <code>false</code> is returned.
 */
public boolean isCellEditorActive() {
                 return cellEditor != null;
}
/**
 * Saves the value of the currently active cell editor,
 * by delegating to the cell modifier.
 */
private void saveEditorValue(CellEditor cellEditor, Item tableItem) {
                 if (cellModifier != null) {
                                 if (!cellEditor.isValueValid()) {
                                                 ///Do what ???
                                 }
                                 String property = null;
                                 if (columnProperties != null && 
columnNumber < columnProperties.length)
                                                 property = 
columnProperties[columnNumber];
                                 cellModifier.modify(tableItem, property, 
cellEditor.getValue());
                 }
}
public void setCellEditors(CellEditor[] editors) {
                 this.cellEditors = editors;
}
public void setCellModifier(INPCellModifier modifier) {
                 this.cellModifier = modifier; 
}
public void setColumnProperties(String[] columnProperties) {
                 this.columnProperties = columnProperties;
}
abstract void setEditor(Control w, Item item, int fColumnNumber);
abstract void setLayoutData(CellEditor.LayoutData layoutData);
abstract void setSelection(StructuredSelection selection, boolean b);
abstract void showSelection();
abstract void handleDoubleClickEvent();
}

package com.kenati.npeint.tools.cliide.ui.dialogs;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.TableItem;

import com.kenati.npeint.tools.cliide.ui.model.PromptElementList;
import com.kenati.npeint.tools.cliide.ui.model.PromptElementTO;
import com.kenati.npeint.tools.cliide.ui.widgets.INPCellModifier;
import com.kenati.npeint.tools.cliide.ui.widgets.NPTableViewer;
import com.kenati.npeint.tools.common.Constants;

public class PromptElementCellModifier implements INPCellModifier 
{
                 private NPTableViewer tableViewer;
                 private PromptElementList elementList; 
//                column indices
                 private static final int COL_TYPE = 0;
                 private static final int COL_VALUE = 1;

//               column 1 : type (Combo box)
                 private ComboBoxCellEditor typeEditor;
                 private String noItems[] = {""};
//               column 2 : value - use prompt names (Combo box)
                 private ComboBoxCellEditor usePromptNameEditor;
//OR
//  column 2 : value - string / function name (Free text)
                 private TextCellEditor stringValueEditor;

                 PromptElementCellModifier(NPTableViewer tableViewer)
                 {
                                 this.tableViewer = tableViewer;
//                               column 1 : filter criterias (Combo box)   
 
                                 typeEditor = new 
ComboBoxCellEditor(tableViewer.getTable(), noItems, SWT.READ_ONLY);
//                               column 2 : value - use prompt names 
(Combo box) 
                                 usePromptNameEditor = new 
ComboBoxCellEditor(tableViewer.getTable(), noItems, SWT.READ_ONLY);
//                                Column 2 : string / function name (Free 
text)
                                 stringValueEditor = new 
TextCellEditor(tableViewer.getTable()); 
                 }
 
                 public void setParamList(PromptElementList elementList)
                 {
                                 this.elementList = elementList;
                 }
 
                 public CellEditor getCellEditor(Object element, String 
property)
                 {
//                               get the index of the column
                                 int colIndex = -1;
                                 for(int i=0; 
i<tableViewer.getTable().getColumnCount(); i++)
                                                 if 
(property.equalsIgnoreCase(tableViewer.getTable().getColumn(i).getText()))
                                                 {
                                                                 colIndex 
= i;
                                                                 break;
                                                 }
 
                                 switch(colIndex)
                                 {
                                                 case COL_TYPE:
                                                     if (noItems != null)
                                                     {
 typeEditor.setItems(elementList.getTypes());
 noItems = null;
                                                     }
                                                     return typeEditor;
                                                 case COL_VALUE:
                                                     PromptElementTO 
elementTO = (PromptElementTO) element;
                                                     if 
(elementTO.getType().equals(Constants.ATTR_PROMPTELEMENT_STRING) || 
elementTO.getType().equals(Constants.ATTR_PROMPTELEMENT_FUNCTION))
                                                         return 
stringValueEditor;
                                                     else if 
(elementTO.getType().equals(Constants.ATTR_PROMPTELEMENT_USEPROMPT))
                                                     {
                                                         String[] 
usePromptNames  = elementList.getUsePromptNames();
                                                         if 
(usePromptNames != null)
 usePromptNameEditor.setItems(usePromptNames);
                                                         return 
usePromptNameEditor; 
                                                     }
                                                  default:
                                                      return null;
                                 }
                 }

                 public boolean canModify(Object element, String property)
                 {
                                 //get the selected TO obj
                                 PromptElementTO selElement = 
(PromptElementTO) element;
  
                                 //check if the element is a new or saved 
one
                                 if (selElement.isNew())
                                                 return true;
                                 else
                                 {
//                                               get the index of the 
column
                                                 int colIndex = -1;
                                                 for(int i=0; 
i<tableViewer.getTable().getColumnCount(); i++)
                                                                 if 
(property.equalsIgnoreCase(tableViewer.getTable().getColumn(i).getText()))
                                                                 {
  colIndex = i;
  break;
                                                                 }
                                                 //can only change the 
value but not the type
                                                 if (colIndex == 1)
                                                                 return 
true;
                                                 else
                                                                 return 
false;
                                 }
                 }

                 public Object getValue(Object element, String property)
                 {
//                               get the index of the column
                                 int colIndex = -1;
                                 for(int i=0; 
i<tableViewer.getTable().getColumnCount(); i++)
                                                 if 
(property.equalsIgnoreCase(tableViewer.getTable().getColumn(i).getText()))
                                                 {
                                                                 colIndex 
= i;
                                                                 break;
                                                 }

                                 Object result = null;
                                 PromptElementTO elementTO = 
(PromptElementTO) element;

                                 switch(colIndex)
                                 {
                                                 case COL_VALUE: //value
                                                     if 
(elementTO.getType() == Constants.ATTR_PROMPTELEMENT_USEPROMPT)
                                                     {
//                                                               get the 
current use prompt name
                                                         String promptName 
= elementTO.getValue();
//                                                               get the 
list of all prompt names in the combo box
                                                         String[] 
usePromptNames  = elementList.getUsePromptNames();
                                                         if 
(usePromptNames == null)
                                                             result = "";
                                                         else
                                                         {
                 //get the index of the current use prompt
                 int index = 0;
                 for (index=0; index<usePromptNames.length; index++)
                 {
                                 if 
(usePromptNames[index].equals(promptName))
                                                 break;
                 }
                 if (index == usePromptNames.length)
                                 index = 0;
                 result = new Integer(index);  
                                                         }
                                                     }
                                                     else
                                                     {
  result = elementTO.getValue();
  if (result == null)
                 result = "";
                                                     }
                                                                 break;
                                                 case COL_TYPE: //type
                                                                 //get the 
current type
                                                                 String 
type = elementTO.getType();
                                                                 //get the 
list of all criterias in the combo box
                                                                 String[] 
allTypes = elementList.getTypes();
                                                                 //get the 
index of the current criteria
                                                                 int index 
= 0;
                                                                 for 
(index=0; index<allTypes.length; index++)
                                                                 {
  if (allTypes[index].equals(type))
                 break;
                                                                 }
                                                                 if (index 
== allTypes.length)
  index = 0;
                                                                 result = 
new Integer(index); 
                                                                 break;
                                 }
 
                                 return result;
                 }
 
                 public void modify(Object element, String property, 
Object value)
                 {
                                 //get the index of the column
                                 int colIndex = -1;
                                 for(int i=0; 
i<tableViewer.getTable().getColumnCount(); i++)
                                                 if 
(property.equalsIgnoreCase(tableViewer.getTable().getColumn(i).getText()))
                                                 {
                                                                 colIndex 
= i;
                                                                 break;
                                                 }
 
                                 TableItem item = (TableItem) element;
                                 PromptElementTO elementTO = 
(PromptElementTO) item.getData();
 
                                 boolean isColWidthValid = true;
                                 switch(colIndex)
                                 {
                                                 case COL_TYPE: //type
                                                                 if 
(((Integer)value).intValue() == -1)
  elementTO.setType("");
                                                                 else
  elementTO.setType((String) 
elementList.getTypes()[((Integer)value).intValue()]);
 elementTO.setValue("");
                                                                 break;
                                                 case COL_VALUE: //value
                                                     if 
(elementTO.getType() == Constants.ATTR_PROMPTELEMENT_USEPROMPT)
                                                     {
  if (((Integer)value).intValue() == -1)
      elementTO.setValue("");
  else
      elementTO.setValue((String) 
elementList.getUsePromptNames()[((Integer)value).intValue()]);
                                                     }
                                                     else
                                                     {
 elementTO.setValue(((String)value).trim());
                                                     }
                                 }
                                 ((PromptElementList) 
tableViewer.getInput()).elementChanged(elementTO);
                 }
}





Back to the top