--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.utils.ui.workbench.dialogs;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.eclipse.jface.viewers.CellEditor;\r
+import org.eclipse.jface.viewers.ICellModifier;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.jface.viewers.TableViewer;\r
+import org.eclipse.jface.viewers.TextCellEditor;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.VerifyEvent;\r
+import org.eclipse.swt.events.VerifyListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.swt.widgets.Table;\r
+import org.eclipse.swt.widgets.TableItem;\r
+import org.eclipse.swt.widgets.Text;\r
+\r
+\r
+/**\r
+ * EditablePropertyDialog is a property dialog where dialog cells can be\r
+ * modified\r
+ * \r
+ */\r
+public class PropertyEditorDialog extends PropertyDialog {\r
+\r
+ public static final int ADD_PROPERTY_ID = -5000;\r
+\r
+ public static final int REMOVE_PROPERTY_ID = -5000 + 1;\r
+\r
+ /** Fields that are read-only */\r
+ protected Set<String> readOnlyKeys = new HashSet<String>();\r
+ \r
+ protected List<PropertyLineVerifyListener> verifyListeners = new ArrayList<PropertyLineVerifyListener>();\r
+\r
+ public PropertyEditorDialog(Shell parent) {\r
+ super(parent);\r
+ }\r
+\r
+ @Override\r
+ protected Control createDialogArea(Composite container) {\r
+ Control composite = super.createDialogArea(container);\r
+ TableViewer viewer = getTableViewer();\r
+ Table table = viewer.getTable();\r
+\r
+ viewer.setInput(getTableViewer().getInput());\r
+\r
+ CellEditor keyEditor = new TextCellEditor(table, SWT.NORMAL);\r
+ TextCellEditor valueEditor = new TextCellEditor(table, SWT.NORMAL);\r
+ ((Text)valueEditor.getControl()).addVerifyListener(new VerifyListener() {\r
+ public void verifyText(VerifyEvent e) {\r
+ String sel[] = getSelection();\r
+ if (sel==null) return;\r
+ Text w = (Text)e.widget;\r
+ String newText = w.getText();\r
+ // deleting text\r
+ if (e.text.length()==0)\r
+ newText = newText.substring(0,e.start) + newText.substring(e.end, newText.length());\r
+ else \r
+ // inserting text\r
+ newText = newText.substring(0,e.start) + e.text + newText.substring(e.end );\r
+ \r
+ e.doit = verifyValueModification(sel[0], newText );\r
+ }});\r
+ viewer.setCellEditors(new CellEditor[] { keyEditor, valueEditor });\r
+\r
+ viewer.setCellModifier(new ICellModifier() {\r
+ public boolean canModify(Object element, String property) {\r
+ int column = columnNameToColumn(property);\r
+ if (column < 0)\r
+ return false;\r
+ String line[] = (String[]) element;\r
+ String key = line[0];\r
+ boolean keyReadOnly = isKeyReadonly(key);\r
+ \r
+ return !keyReadOnly;\r
+ }\r
+\r
+ public Object getValue(Object element, String property) {\r
+ int column = columnNameToColumn(property);\r
+ String line[] = (String[]) element;\r
+ return line[column];\r
+ }\r
+\r
+ public void modify(Object element, String property, Object value) {\r
+ // Some kind of bug? This returns TableItem object sometimes\r
+ if (element instanceof TableItem)\r
+ element = ((TableItem) element).getData();\r
+ int column = columnNameToColumn(property);\r
+ String line[] = (String[]) element;\r
+ String key = line[0];\r
+ \r
+ // Cannot have two values with same key\r
+ if (column==0 && containsKey(value.toString()))\r
+ return;\r
+ if (column==0 && isKeyReadonly(key))\r
+ return;\r
+ if (column==0 && !verifyValueModification(value.toString(), line[1]))\r
+ return;\r
+ \r
+ line[column] = value.toString();\r
+ labelProvider.elementChanged(element);\r
+ }\r
+ });\r
+\r
+ return composite;\r
+ }\r
+\r
+ protected boolean containsKey(String key) {\r
+ for (String[] line : data)\r
+ if (line[0].equals(key))\r
+ return true;\r
+ return false; \r
+ }\r
+ \r
+ @Override\r
+ protected void createButtonsForButtonBar(Composite parent) {\r
+ // Add property button\r
+ createButton(parent, ADD_PROPERTY_ID, "Add property", false);\r
+ // Remove property button\r
+ createButton(parent, REMOVE_PROPERTY_ID, "Remove property", false);\r
+\r
+ setAddCancelButton(true);\r
+ super.createButtonsForButtonBar(parent);\r
+ // Having this true enables double-click listener later\r
+ // Which is annoying\r
+ setAddCancelButton(false);\r
+ }\r
+\r
+ @Override\r
+ protected void buttonPressed(int buttonId) {\r
+ if (buttonId == ADD_PROPERTY_ID)\r
+ addPropertyPressed();\r
+ else if (buttonId == REMOVE_PROPERTY_ID)\r
+ removePropertyPressed();\r
+ else\r
+ super.buttonPressed(buttonId);\r
+ }\r
+\r
+ protected String[] getSelection() {\r
+ IStructuredSelection sel = (IStructuredSelection) this.getTableViewer().getSelection();\r
+ if (sel==null) return null;\r
+ Object o = sel.getFirstElement();\r
+ if (o==null) return null;\r
+ return (String[]) o;\r
+ }\r
+ \r
+ private void removePropertyPressed() {\r
+ String o[] = getSelection();\r
+ if (o==null) return;\r
+ if (readOnlyKeys.contains(o[0]))\r
+ return;\r
+ if (!data.remove(o)) return;\r
+ labelProvider.refreshAll();\r
+ }\r
+\r
+ private void addPropertyPressed() {\r
+ String newElement[] = new String[] {"<new property>", "<value>"}; \r
+ data.add(newElement); \r
+ labelProvider.refreshAll();\r
+ getTableViewer().setSelection(new StructuredSelection(newElement));\r
+ }\r
+\r
+ /**\r
+ * Set fields that are read-only (These are 1st column key names)\r
+ * \r
+ * @param readOnlyFields fields that are read only\r
+ */\r
+ public void setReadOnlyFields(String[] readOnlyFields) {\r
+ for (String key : readOnlyFields)\r
+ readOnlyKeys.add(key); \r
+ }\r
+ \r
+ /**\r
+ * Set a key read-only / writable\r
+ * @param key key name\r
+ * @param readOnly true = readonly, false = writable\r
+ */\r
+ public void setFieldReadOnlyStatus(String key, boolean readOnly) {\r
+ if (readOnly)\r
+ readOnlyKeys.add(key);\r
+ else \r
+ readOnlyKeys.remove(key);\r
+ }\r
+ \r
+ protected boolean isKeyReadonly(String key) {\r
+ return readOnlyKeys.contains(key);\r
+ }\r
+\r
+ /**\r
+ * Get result data\r
+ * @return result data\r
+ */\r
+ public List<String[]> getData() {\r
+ return data;\r
+ }\r
+ \r
+ public void addVerifyListener(PropertyLineVerifyListener listener) {\r
+ verifyListeners.add(listener);\r
+ }\r
+ \r
+ public void removeVerifyListener(PropertyLineVerifyListener listener) {\r
+ verifyListeners.remove(listener);\r
+ }\r
+ \r
+ protected boolean verifyValueModification(String key, String value) {\r
+ boolean result = true;\r
+ for (PropertyLineVerifyListener l : verifyListeners)\r
+ result = result & l.verifyValue(key, value);\r
+ return result;\r
+ }\r
+}\r