/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ui.properties;
import org.eclipse.jface.action.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TreeEditor;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.views.properties.IPropertySource2;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.core.CoreMessages;
import org.jkiss.dbeaver.core.DBeaverUI;
import org.jkiss.dbeaver.model.DBPObject;
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.runtime.properties.IPropertySourceEditable;
import org.jkiss.dbeaver.runtime.properties.PropertyCollector;
import org.jkiss.dbeaver.runtime.properties.PropertySourceCollection;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.actions.navigator.NavigatorHandlerObjectOpen;
import org.jkiss.dbeaver.ui.controls.ObjectViewerRenderer;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.utils.BeanUtils;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.Array;
import java.text.Collator;
import java.util.*;
import java.util.List;
/**
* Driver properties control
*/
public class PropertyTreeViewer extends TreeViewer {
public enum ExpandMode {
NONE,
FIRST,
ALL,
}
private static final String CATEGORY_GENERAL = CoreMessages.ui_properties_tree_viewer_category_general;
private boolean expandSingleRoot = true;
private TreeEditor treeEditor;
private Font boldFont;
private int selectedColumn = -1;
private CellEditor curCellEditor;
private DBPPropertyDescriptor selectedProperty;
private String[] customCategories;
private IBaseLabelProvider extraLabelProvider;
private ObjectViewerRenderer renderer;
private ExpandMode expandMode = ExpandMode.ALL;
public PropertyTreeViewer(Composite parent, int style)
{
super(parent, style | SWT.SINGLE | SWT.FULL_SELECTION);
super.setContentProvider(new PropsContentProvider());
final Tree treeControl = super.getTree();
if (parent.getLayout() instanceof GridLayout) {
GridData gd = new GridData(GridData.FILL_BOTH);
gd.grabExcessHorizontalSpace = true;
gd.grabExcessVerticalSpace = true;
gd.minimumHeight = 120;
gd.minimumWidth = 120;
treeControl.setLayoutData(gd);
}
treeControl.setHeaderVisible(true);
treeControl.setLinesVisible(true);
treeControl.addControlListener(new ControlAdapter() {
private boolean packing = false;
@Override
public void controlResized(ControlEvent e)
{
if (!packing) {
packing = true;
UIUtils.packColumns(treeControl, true, new float[]{0.1f, 0.9f});
}
}
});
treeControl.addListener(SWT.PaintItem, new PaintListener());
this.boldFont = UIUtils.makeBoldFont(treeControl.getFont());
ColumnViewerToolTipSupport.enableFor(this, ToolTip.NO_RECREATE);
TreeViewerColumn column = new TreeViewerColumn(this, SWT.NONE);
//column.getColumn().setWidth(200);
column.getColumn().setMoveable(true);
column.getColumn().setText(CoreMessages.ui_properties_name);
column.setLabelProvider(new PropsLabelProvider(true));
column.getColumn().addListener(SWT.Selection, new SortListener());
column = new TreeViewerColumn(this, SWT.NONE);
//column.getColumn().setWidth(120);
column.getColumn().setMoveable(true);
column.getColumn().setText(CoreMessages.ui_properties_value);
column.setLabelProvider(new PropsLabelProvider(false));
/*
List<? extends DBPProperty> props = ((DBPPropertyGroup) parent).getProperties();
Collections.sort(props, new Comparator<DBPProperty>() {
public int compare(DBPProperty o1, DBPProperty o2)
{
return o1.getName().compareTo(o2.getName());
}
});
return props.toArray();
*/
registerEditor();
registerContextMenu();
renderer = new ObjectViewerRenderer(this) {
@Override
protected Object getCellValue(Object element, int columnIndex)
{
final TreeNode node = (TreeNode) element;
if (columnIndex == 0) {
return node.category != null ?
node.category :
node.property.getDisplayName();
}
return getPropertyValue(node);
}
@Override
public boolean isHyperlink(Object cellValue)
{
return cellValue instanceof DBSObject;
}
@Override
public void navigateHyperlink(Object cellValue)
{
if (cellValue instanceof DBSObject) {
DBNDatabaseNode node = NavigatorHandlerObjectOpen.getNodeByObject((DBSObject) cellValue);
if (node != null) {
NavigatorHandlerObjectOpen.openEntityEditor(node, null, DBeaverUI.getActiveWorkbenchWindow());
}
}
}
};
}
public void loadProperties(DBPPropertySource propertySource)
{
loadProperties(null, null, propertySource);
}
protected void loadProperties(@Nullable DBRProgressMonitor monitor, TreeNode parent, DBPPropertySource propertySource)
{
// Make tree model
customCategories = getCustomCategories();
Map<String, TreeNode> categories = loadTreeNodes(monitor, parent, propertySource);
if (customCategories != null) {
for (String customCategory : customCategories) {
TreeNode node = categories.get(customCategory);
if (node == null) {
node = new TreeNode(parent, propertySource, customCategory);
categories.put(customCategory, node);
}
}
}
Object root;
if (categories.size() == 1 && expandSingleRoot) {
final Collection<TreeNode> values = categories.values();
root = values.iterator().next();
} else {
root = categories.values();
}
super.setInput(root);
switch (expandMode) {
case ALL:
this.expandAll();
break;
case FIRST:
if (root instanceof Collection) {
Collection rootItems = (Collection) root;
if (!rootItems.isEmpty()) {
Object first = rootItems.iterator().next();
this.expandToLevel(first, ALL_LEVELS);
}
} else {
this.expandAll();
}
break;
}
disposeOldEditor();
UIUtils.packColumns(getTree(), true, new float[]{0.5f, 0.5f});
}
private Map<String, TreeNode> loadTreeNodes(@Nullable DBRProgressMonitor monitor, TreeNode parent, DBPPropertySource propertySource)
{
Map<String, TreeNode> categories = new LinkedHashMap<>();
final DBPPropertyDescriptor[] props = propertySource.getPropertyDescriptors2();
for (DBPPropertyDescriptor prop : props) {
String categoryName = prop.getCategory();
if (CommonUtils.isEmpty(categoryName)) {
categoryName = CATEGORY_GENERAL;
}
TreeNode category = (parent != null ? parent : categories.get(categoryName));
if (category == null) {
category = new TreeNode(null, propertySource, categoryName);
categories.put(categoryName, category);
}
TreeNode propNode = new TreeNode(category, propertySource, prop);
// Load nested object's properties
if (!(propertySource instanceof IPropertySourceEditable)) {
Class<?> propType = ((DBPPropertyDescriptor) prop).getDataType();
if (propType != null) {
if (DBPObject.class.isAssignableFrom(propType)) {
Object propertyValue = propertySource.getPropertyValue(monitor, prop.getId());
if (propertyValue != null) {
PropertyCollector nestedCollector = new PropertyCollector(propertyValue, true);
if (nestedCollector.collectProperties()) {
categories.putAll(loadTreeNodes(monitor, propNode, nestedCollector));
}
}
} else if (BeanUtils.isCollectionType(propType)) {
Object propertyValue = propertySource.getPropertyValue(monitor, prop.getId());
if (propertyValue != null) {
Collection<?> collection;
if (BeanUtils.isArrayType(propType)) {
collection = Arrays.asList((Object[]) propertyValue);
} else {
collection = (Collection<?>) propertyValue;
}
PropertySourceCollection psc = new PropertySourceCollection(collection);
for (DBPPropertyDescriptor pd : psc.getPropertyDescriptors2()) {
new TreeNode(propNode, psc, pd);
}
}
}
}
}
}
return categories;
}
public DBPPropertyDescriptor getSelectedProperty() {
return selectedProperty;
}
public void clearProperties()
{
super.setInput(null);
}
protected void addProperty(Object node, DBPPropertyDescriptor property)
{
if (node instanceof TreeNode) {
TreeNode treeNode = (TreeNode) node;
while (treeNode.property != null) {
treeNode = treeNode.parent;
}
final TreeNode newNode = new TreeNode(treeNode, treeNode.propertySource, property);
handlePropertyCreate(newNode);
}
}
protected void removeProperty(Object node)
{
if (node instanceof TreeNode) {
TreeNode treeNode = (TreeNode) node;
if (treeNode.propertySource != null) {
treeNode.propertySource.resetPropertyValueToDefault(treeNode.property.getId());
}
treeNode.parent.children.remove(treeNode);
handlePropertyRemove(treeNode);
}
}
@Override
public void refresh()
{
//disposeOldEditor();
super.refresh();
}
private void disposeOldEditor()
{
if (curCellEditor != null) {
curCellEditor.deactivate();
curCellEditor.dispose();
curCellEditor = null;
selectedProperty = null;
}
Control oldEditor = treeEditor.getEditor();
if (oldEditor != null) oldEditor.dispose();
}
private void registerEditor()
{
// Make an editor
final Tree treeControl = super.getTree();
treeEditor = new TreeEditor(treeControl);
treeEditor.horizontalAlignment = SWT.CENTER;
treeEditor.verticalAlignment = SWT.CENTER;
treeEditor.minimumWidth = 50;
treeControl.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e)
{
//showEditor((TreeItem) e.item, true);
}
@Override
public void widgetSelected(final SelectionEvent e)
{
showEditor((TreeItem) e.item, selectedColumn == 1 && (e.stateMask & SWT.BUTTON_MASK) != 0);
}
});
treeControl.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e)
{
TreeItem item = treeControl.getItem(new Point(e.x, e.y));
if (item != null) {
selectedColumn = UIUtils.getColumnAtPos(item, e.x, e.y);
} else {
selectedColumn = -1;
}
}
});
treeControl.addTraverseListener(new TraverseListener() {
@Override
public void keyTraversed(TraverseEvent e)
{
if (e.detail == SWT.TRAVERSE_RETURN) {
// Set focus on editor
if (curCellEditor != null) {
curCellEditor.setFocus();
} else {
final TreeItem[] selection = treeControl.getSelection();
if (selection.length == 0) {
return;
}
showEditor(selection[0], true);
}
e.doit = false;
e.detail = SWT.TRAVERSE_NONE;
}
}
});
}
private void showEditor(final TreeItem item, boolean isDef)
{
// Clean up any previous editor control
disposeOldEditor();
if (item == null) {
return;
}
// Identify the selected row
if (item.getData() instanceof TreeNode) {
final Tree treeControl = super.getTree();
final TreeNode prop = (TreeNode) item.getData();
if (prop.property == null || !prop.isEditable()) {
return;
}
final CellEditor cellEditor = UIUtils.createPropertyEditor(DBeaverUI.getActiveWorkbenchWindow(), treeControl, prop.propertySource, prop.property);
if (cellEditor == null) {
return;
}
final Object propertyValue = prop.propertySource.getPropertyValue(null, prop.property.getId());
final ICellEditorListener cellEditorListener = new ICellEditorListener() {
@Override
public void applyEditorValue()
{
//editorValueChanged(true, true);
final Object value = cellEditor.getValue();
final Object oldValue = prop.propertySource.getPropertyValue(null, prop.property.getId());
if (!CommonUtils.equalObjects(oldValue, value)) {
prop.propertySource.setPropertyValue(
null,
prop.property.getId(),
value);
handlePropertyChange(prop);
}
}
@Override
public void cancelEditor()
{
disposeOldEditor();
}
@Override
public void editorValueChanged(boolean oldValidState, boolean newValidState)
{
}
};
cellEditor.addListener(cellEditorListener);
if (propertyValue != null) {
cellEditor.setValue(propertyValue);
}
curCellEditor = cellEditor;
selectedProperty = prop.property;
cellEditor.activate();
final Control editorControl = cellEditor.getControl();
if (editorControl != null) {
editorControl.addTraverseListener(new TraverseListener() {
@Override
public void keyTraversed(TraverseEvent e)
{
if (e.detail == SWT.TRAVERSE_RETURN) {
e.doit = false;
e.detail = SWT.TRAVERSE_NONE;
cellEditorListener.applyEditorValue();
disposeOldEditor();
} else if (e.detail == SWT.TRAVERSE_ESCAPE) {
e.doit = false;
e.detail = SWT.TRAVERSE_NONE;
disposeOldEditor();
if (prop.isEditable()) {
new ActionResetProperty(prop, false).run();
}
}
}
});
treeEditor.verticalAlignment = cellEditor.getLayoutData().verticalAlignment;
treeEditor.horizontalAlignment = cellEditor.getLayoutData().horizontalAlignment;
treeEditor.minimumWidth = cellEditor.getLayoutData().minimumWidth;
treeEditor.grabHorizontal = cellEditor.getLayoutData().grabHorizontal;
treeEditor.setEditor(editorControl, item, 1);
}
if (isDef) {
// Selected by mouse
cellEditor.setFocus();
}
}
}
private void registerContextMenu()
{
// Register context menu
{
MenuManager menuMgr = new MenuManager();
menuMgr.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(final IMenuManager manager)
{
final IStructuredSelection selection = PropertyTreeViewer.this.getStructuredSelection();
if (selection.isEmpty()) {
return;
}
final Object object = selection.getFirstElement();
if (object instanceof TreeNode) {
final TreeNode prop = (TreeNode) object;
if (prop.property != null) {
final String stringValue = CommonUtils.toString(getPropertyValue(prop));
if (!CommonUtils.isEmpty(stringValue)) {
manager.add(new Action(CoreMessages.ui_properties_tree_viewer_action_copy_value) {
@Override
public void run()
{
UIUtils.setClipboardContents(
Display.getDefault(),
TextTransfer.getInstance(),
stringValue);
}
});
}
if (isPropertyChanged(prop) && prop.isEditable()) {
if (prop.propertySource instanceof IPropertySource2 && !prop.propertySource.isPropertyResettable(prop.property.getId())) {
// it is not resettable
} else {
manager.add(new ActionResetProperty(prop, false));
if (!isCustomProperty(prop.property)) {
manager.add(new ActionResetProperty(prop, true));
}
}
}
}
manager.add(new Separator());
contributeContextMenu(
manager,
object,
prop.category != null ?
prop.category :
(prop.property == null ? null : prop.property.getCategory()),
prop.property);
}
}
});
menuMgr.setRemoveAllWhenShown(true);
Menu menu = menuMgr.createContextMenu(getTree());
getTree().setMenu(menu);
}
}
private boolean isCustomProperty(DBPPropertyDescriptor property)
{
if (customCategories != null) {
for (String category : customCategories) {
if (category.equals(property.getCategory())) {
return true;
}
}
}
return false;
}
protected String[] getCustomCategories()
{
return null;
}
protected void contributeContextMenu(IMenuManager manager, Object node, String category, DBPPropertyDescriptor property)
{
}
public DBPPropertyDescriptor getPropertyFromElement(Object element) {
if (element instanceof TreeNode) {
return ((TreeNode) element).property;
}
return null;
}
private Object getPropertyValue(TreeNode prop)
{
if (prop.category != null) {
return prop.category;
} else {
final Object propertyValue = prop.propertySource.getPropertyValue(null, prop.property.getId());
return GeneralUtils.makeDisplayString(propertyValue);
}
}
private boolean isPropertyChanged(TreeNode prop)
{
return prop.propertySource.isPropertySet(prop.property.getId());
}
private void handlePropertyChange(TreeNode prop)
{
super.update(prop, null);
// Send modify event
Event event = new Event();
event.data = prop.property;
getTree().notifyListeners(SWT.Modify, event);
}
protected void handlePropertyCreate(TreeNode prop)
{
handlePropertyChange(prop);
super.refresh(prop.parent);
super.expandToLevel(prop.parent, 1);
super.reveal(prop);
super.setSelection(new StructuredSelection(prop));
}
protected void handlePropertyRemove(TreeNode prop)
{
handlePropertyChange(prop);
super.refresh(prop.parent);
}
public void setExpandMode(ExpandMode expandMode) {
this.expandMode = expandMode;
}
public void setExpandSingleRoot(boolean expandSingleRoot) {
this.expandSingleRoot = expandSingleRoot;
}
public void setExtraLabelProvider(IBaseLabelProvider extraLabelProvider)
{
this.extraLabelProvider = extraLabelProvider;
}
private static class TreeNode {
final TreeNode parent;
final DBPPropertySource propertySource;
final DBPPropertyDescriptor property;
final String category;
final List<TreeNode> children = new ArrayList<>();
private TreeNode(TreeNode parent, DBPPropertySource propertySource, DBPPropertyDescriptor property, String category)
{
this.parent = parent;
this.propertySource = propertySource;
this.property = property;
this.category = category;
if (parent != null) {
parent.children.add(this);
}
}
private TreeNode(TreeNode parent, DBPPropertySource propertySource, DBPPropertyDescriptor property)
{
this(parent, propertySource, property, null);
}
private TreeNode(TreeNode parent, DBPPropertySource propertySource, String category)
{
this(parent, propertySource, null, category);
}
boolean isEditable()
{
if (property != null) {
return property.isEditable(propertySource.getEditableValue());
} else {
return false;
}
}
@Override
public String toString() {
return
property == null ?
category :
property.getId() + " (" + property.getDisplayName() + ")";
}
@Override
public boolean equals(Object obj) {
if (obj instanceof TreeNode) {
final TreeNode node = (TreeNode) obj;
if (this == node) return true;
return
propertySource.getEditableValue() == node.propertySource.getEditableValue() &&
(category != null ? CommonUtils.equalObjects(category, node.category) :
property != null && node.property != null &&
CommonUtils.equalObjects(property.getId(), node.property.getId()));
}
return super.equals(obj);
}
}
class PropsContentProvider implements IStructuredContentProvider, ITreeContentProvider {
@Override
public void inputChanged(Viewer v, Object oldInput, Object newInput)
{
}
@Override
public void dispose()
{
}
@Override
public Object[] getElements(Object parent)
{
return getChildren(parent);
}
@Override
public Object getParent(Object child)
{
if (child instanceof TreeNode) {
return ((TreeNode) child).parent;
} else {
return null;
}
}
@Override
public Object[] getChildren(Object parent)
{
if (parent instanceof Collection) {
return ((Collection) parent).toArray();
} else if (parent instanceof TreeNode) {
// Add all available property groups
return ((TreeNode) parent).children.toArray();
} else {
return new Object[0];
}
}
@Override
public boolean hasChildren(Object parent)
{
return getChildren(parent).length > 0;
}
}
private class PropsLabelProvider extends CellLabelProvider {
private final boolean isName;
public PropsLabelProvider(boolean isName)
{
this.isName = isName;
}
public String getText(Object obj, int columnIndex)
{
if (!(obj instanceof TreeNode)) {
return ""; //$NON-NLS-1$
}
TreeNode node = (TreeNode) obj;
if (columnIndex == 0) {
if (node.category != null) {
return node.category;
} else {
return node.property.getDisplayName();
}
} else {
if (node.property != null) {
final Object propertyValue = getPropertyValue(node);
if (propertyValue == null || renderer.isHyperlink(propertyValue)) {
return ""; //$NON-NLS-1$
} else if (BeanUtils.isCollectionType(propertyValue.getClass())) {
StringBuilder str = new StringBuilder();
str.append("[");
if (propertyValue instanceof Collection) {
int i = 0;
for (Object item : (Collection) propertyValue) {
if (i > 0) str.append(",");
str.append(GeneralUtils.makeDisplayString(item));
i++;
}
} else {
int size = Array.getLength(propertyValue);
for (int i = 0; i < size; i++) {
if (i > 0) str.append(",");
str.append(GeneralUtils.makeDisplayString(Array.get(propertyValue, i)));
}
}
str.append("]");
return str.toString();
}
if (propertyValue instanceof Boolean) {
return "";
}
return ObjectViewerRenderer.getCellString(propertyValue, isName);
} else {
return ""; //$NON-NLS-1$
}
}
}
@Override
public String getToolTipText(Object obj)
{
if (!(obj instanceof TreeNode)) {
return null; //$NON-NLS-1$
}
TreeNode node = (TreeNode) obj;
String toolTip;
if (node.category != null) {
toolTip = node.category;
} else {
toolTip = isName ? node.property.getDescription() : getText(obj, 1);
}
if (CommonUtils.isEmpty(toolTip)) {
return null;
}
return toolTip;
}
@Override
public Point getToolTipShift(Object object)
{
return new Point(5, 5);
}
@Override
public void update(ViewerCell cell)
{
Object element = cell.getElement();
cell.setText(getText(element, cell.getColumnIndex()));
if (!(element instanceof TreeNode)) {
return;
}
TreeNode node = (TreeNode) element;
boolean changed = false;
if (node.property != null) {
changed = node.isEditable() && isPropertyChanged(node);
}
if (extraLabelProvider instanceof IFontProvider) {
cell.setFont(((IFontProvider) extraLabelProvider).getFont(node.property));
} else if (changed) {
cell.setFont(boldFont);
} else {
cell.setFont(null);
}
}
}
private class SortListener implements Listener {
int sortDirection = SWT.DOWN;
TreeColumn prevColumn = null;
@Override
public void handleEvent(Event e)
{
disposeOldEditor();
getTree().setRedraw(false);
try {
Collator collator = Collator.getInstance(Locale.getDefault());
TreeColumn column = (TreeColumn) e.widget;
Tree tree = getTree();
if (prevColumn == column) {
// Set reverse order
sortDirection = (sortDirection == SWT.UP ? SWT.DOWN : SWT.UP);
}
prevColumn = column;
tree.setSortColumn(column);
tree.setSortDirection(sortDirection);
PropertyTreeViewer.this.setComparator(new ViewerComparator(collator) {
@Override
public int compare(Viewer viewer, Object e1, Object e2)
{
int mul = (sortDirection == SWT.UP ? 1 : -1);
int result;
TreeNode n1 = (TreeNode) e1, n2 = (TreeNode) e2;
if (n1.property != null && n2.property != null) {
result = n1.property.getDisplayName().compareTo(n2.property.getDisplayName());
} else if (n1.category != null && n2.category != null) {
result = n1.category.compareTo(n2.category);
} else {
result = 0;
}
return result * mul;
}
});
} finally {
getTree().setRedraw(true);
}
}
}
private class ActionResetProperty extends Action {
private final TreeNode prop;
private final boolean toDefault;
public ActionResetProperty(TreeNode prop, boolean toDefault)
{
super(CoreMessages.ui_properties_tree_viewer_action_reset_value + (!toDefault ? "" : CoreMessages.ui_properties_tree_viewer__to_default)); //$NON-NLS-2$
this.prop = prop;
this.toDefault = toDefault;
}
@Override
public void run()
{
if (prop.propertySource != null) {
if (toDefault) {
prop.propertySource.resetPropertyValueToDefault(prop.property.getId());
} else {
prop.propertySource.resetPropertyValue(null, prop.property.getId());
}
}
handlePropertyChange(prop);
PropertyTreeViewer.this.update(prop, null);
disposeOldEditor();
}
}
class PaintListener implements Listener {
@Override
public void handleEvent(Event event)
{
if (getTree().isDisposed()) {
return;
}
switch (event.type) {
case SWT.PaintItem: {
if (event.index == 1) {
if (treeEditor != null && treeEditor.getItem() == event.item && treeEditor.getEditor() != null &&
!treeEditor.getEditor().isDisposed() && treeEditor.getEditor().isVisible())
{
// Do not paint over active editor
return;
}
final TreeNode node = (TreeNode) event.item.getData();
if (node != null && node.property != null) {
renderer.paintCell(event, node, event.item, event.index, node.isEditable());
}
}
break;
}
}
}
}
}