package org.objectstyle.wolips.baseforuiplugins.plist; import java.util.List; import java.util.Set; import org.eclipse.jface.viewers.ColumnViewerEditor; import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent; import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy; import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.TreeViewerColumn; import org.eclipse.jface.viewers.TreeViewerEditor; import org.eclipse.jface.viewers.TreeViewerFocusCellManager; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.objectstyle.woenvironment.plist.ParserDataStructureFactory; import org.objectstyle.woenvironment.plist.PropertyListParserException; import org.objectstyle.woenvironment.plist.WOLPropertyListSerialization; import org.objectstyle.wolips.baseforuiplugins.utils.WOTreeCellNavigationStrategy; public class PropertyListEditor extends Viewer implements IPropertyListChangeListener, KeyListener { private IPropertyListChangeListener _listener; private ParserDataStructureFactory _parserDataStructureFactory; private TreeViewer _propertyListTree; public PropertyListEditor(Composite parent, boolean rootVisible, boolean canEditRootType, Set<String> filteredKeyPaths) { _propertyListTree = new TreeViewer(parent, SWT.BORDER | SWT.FULL_SELECTION | SWT.BACKGROUND | SWT.SINGLE | SWT.NO_SCROLL | SWT.V_SCROLL); _propertyListTree.getTree().setHeaderVisible(true); _propertyListTree.getTree().setLinesVisible(true); _propertyListTree.setAutoExpandLevel(2); TreeViewerFocusCellManager focusCellManager = new TreeViewerFocusCellManager(_propertyListTree, new FocusCellOwnerDrawHighlighter(_propertyListTree), new WOTreeCellNavigationStrategy()); ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(_propertyListTree) { protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) { ViewerCell cell = (ViewerCell) event.getSource(); boolean isEditorActivationEvent; if (cell.getColumnIndex() == 1) { isEditorActivationEvent = event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_CLICK_SELECTION || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == ' ') || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC; //isEditorActivationEvent = event.eventType == ColumnViewerEditorActivationEvent.MOUSE_CLICK_SELECTION || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == ' ') || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC; } else { isEditorActivationEvent = event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == ' ') || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC; //isEditorActivationEvent = event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC; } return isEditorActivationEvent; } }; TreeViewerEditor.create(_propertyListTree, focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION | ColumnViewerEditor.KEEP_EDITOR_ON_DOUBLE_CLICK); TreeViewerColumn keyColumn = new TreeViewerColumn(_propertyListTree, SWT.NONE); keyColumn.getColumn().setWidth(120); keyColumn.getColumn().setText("Key"); keyColumn.setLabelProvider(new PropertyListKeyLabelProvider()); keyColumn.setEditingSupport(new PropertyListKeyEditingSupport(_propertyListTree, this)); TreeViewerColumn typeColumn = new TreeViewerColumn(_propertyListTree, SWT.NONE); typeColumn.getColumn().setWidth(75); typeColumn.getColumn().setText("Type"); typeColumn.setLabelProvider(new PropertyListTypeLabelProvider()); typeColumn.setEditingSupport(new PropertyListTypeEditingSupport(_propertyListTree, this, canEditRootType)); TreeViewerColumn valueColumn = new TreeViewerColumn(_propertyListTree, SWT.NONE); valueColumn.getColumn().setWidth(250); valueColumn.getColumn().setText("Value"); valueColumn.setLabelProvider(new PropertyListValueLabelProvider()); valueColumn.setEditingSupport(new PropertyListValueEditingSupport(_propertyListTree, this)); _propertyListTree.getTree().addKeyListener(this); _parserDataStructureFactory = new StableDataStructureFactory(); _propertyListTree.setContentProvider(new PropertyListContentProvider(_parserDataStructureFactory, rootVisible, filteredKeyPaths)); } public void setListener(IPropertyListChangeListener listener) { _listener = listener; } public IPropertyListChangeListener getListener() { return _listener; } @Override public Control getControl() { return _propertyListTree.getTree(); } @Override public Object getInput() { try { return WOLPropertyListSerialization.propertyListFromString(WOLPropertyListSerialization.stringFromPropertyList(_propertyListTree.getInput()), new StableDataStructureFactory()); } catch (PropertyListParserException e) { throw new IllegalArgumentException("Failed to parse property list.", e); } } @Override public ISelection getSelection() { return _propertyListTree.getSelection(); } @Override public void refresh() { _propertyListTree.refresh(); } @Override public void setInput(Object input) { try { _propertyListTree.setInput(WOLPropertyListSerialization.propertyListFromString(WOLPropertyListSerialization.stringFromPropertyList(input), new StableDataStructureFactory())); } catch (PropertyListParserException e) { throw new IllegalArgumentException("Failed to parse property list.", e); } } @Override public void setSelection(ISelection selection, boolean reveal) { _propertyListTree.setSelection(selection); } public void pathRenamed(String oldPath, String newPath) { if (_listener != null) { _listener.pathRenamed(oldPath, newPath); } } public void pathChanged(String path, Object oldValue, Object newValue) { if (_listener != null) { _listener.pathChanged(path, oldValue, newValue); } } public void pathAdded(String path, Object value) { if (_listener != null) { _listener.pathAdded(path, value); } } public void pathRemoved(String path, Object value) { if (_listener != null) { _listener.pathRemoved(path, value); } } public void addRow() { PropertyListPath parentPath; PropertyListPath selectedPath = (PropertyListPath) ((IStructuredSelection) _propertyListTree.getSelection()).getFirstElement(); if (selectedPath.isCollectionValue()) { if (_propertyListTree.getExpandedState(selectedPath) || selectedPath.getParent() == null) { parentPath = selectedPath; } else { parentPath = selectedPath.getParent(); } } else { parentPath = selectedPath.getParent(); } PropertyListPath newChild = parentPath.addRow(); _propertyListTree.refresh(parentPath); _propertyListTree.setSelection(new StructuredSelection(newChild), true); if (_listener != null) { _listener.pathAdded(newChild.getKeyPath(), newChild.getValue()); } _propertyListTree.editElement(newChild, 0); } public void deleteRow() { PropertyListPath selectedPath = (PropertyListPath) ((IStructuredSelection) _propertyListTree.getSelection()).getFirstElement(); String keyPath = selectedPath.getKeyPath(); PropertyListPath parentPath = selectedPath.getParent(); int index = parentPath.getIndexOf(selectedPath); if (selectedPath.delete()) { _propertyListTree.refresh(parentPath); if (_listener != null) { _listener.pathRemoved(keyPath, selectedPath.getValue()); } List<PropertyListPath> children = parentPath.getChildren(); if (children.size() == 0) { _propertyListTree.setSelection(new StructuredSelection(parentPath), true); } else if (index == children.size()) { _propertyListTree.setSelection(new StructuredSelection(parentPath.getChildAtIndex(index - 1)), true); } else { _propertyListTree.setSelection(new StructuredSelection(parentPath.getChildAtIndex(index)), true); } } } public void moveRowUp() { PropertyListPath selectedPath = (PropertyListPath) ((IStructuredSelection) _propertyListTree.getSelection()).getFirstElement(); PropertyListPath parentPath = selectedPath.getParent(); int index = parentPath.getIndexOf(selectedPath); if (selectedPath.moveUp()) { _propertyListTree.refresh(parentPath); if (_listener != null) { _listener.pathChanged(parentPath.getKeyPath(), null, null); } _propertyListTree.setSelection(new StructuredSelection(parentPath.getChildAtIndex(index - 1)), true); } } public void moveRowDown() { PropertyListPath selectedPath = (PropertyListPath) ((IStructuredSelection) _propertyListTree.getSelection()).getFirstElement(); PropertyListPath parentPath = selectedPath.getParent(); int index = parentPath.getIndexOf(selectedPath); if (selectedPath.moveDown()) { _propertyListTree.refresh(parentPath); if (_listener != null) { _listener.pathChanged(parentPath.getKeyPath(), null, null); } _propertyListTree.setSelection(new StructuredSelection(parentPath.getChildAtIndex(index + 1)), true); } } public void keyPressed(KeyEvent e) { if (!_propertyListTree.isCellEditorActive()) { if (e.keyCode == SWT.CR) { addRow(); } else if (e.keyCode == SWT.DEL) { deleteRow(); } else if (e.keyCode == SWT.ARROW_UP && (e.stateMask & SWT.COMMAND) != 0) { moveRowUp(); e.doit = false; } else if (e.keyCode == SWT.ARROW_DOWN && (e.stateMask & SWT.COMMAND) != 0) { moveRowDown(); e.doit = false; } } } public void keyReleased(KeyEvent e) { // IGNORE } }