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