package org.csstudio.sds.ui.internal.editor.newproperties; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.csstudio.sds.internal.model.ActionDataProperty; import org.csstudio.sds.model.ActionData; import org.csstudio.sds.model.ActionType; import org.csstudio.sds.model.WidgetProperty; import org.csstudio.sds.model.properties.actions.AbstractWidgetActionModel; import org.csstudio.sds.ui.SdsUiPlugin; import org.csstudio.sds.ui.internal.editor.newproperties.table.ColumnConfig; import org.csstudio.sds.ui.internal.editor.newproperties.table.ConvenienceTableWrapper; import org.csstudio.sds.ui.internal.editor.newproperties.table.ITableRow; import org.csstudio.sds.ui.internal.properties.PropertyDescriptorFactoryService; import org.csstudio.sds.ui.properties.IPropertyDescriptor; import org.csstudio.sds.ui.properties.IPropertyDescriptorFactory; import org.csstudio.ui.util.CustomMediaFactory; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent; import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener; import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableEditor; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; 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.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.Hyperlink; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; /** * Section for {@link ActionDataProperty}. * * @author Kai Meyer (C1 WPS) * */ public class ActionDataSection extends AbstractBaseSection<ActionDataProperty> { private TableViewer tableViewer; private List<TableEditor> tableEditors = new ArrayList<TableEditor>(); public ActionDataSection(String propertyId) { super(propertyId); } /** *{@inheritDoc} */ @Override public int getMinimumHeight() { return 150; } /** *{@inheritDoc} */ @Override protected void doCreateControls(final Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage) { GridLayoutFactory.swtDefaults().numColumns(5).applyTo(parent); // .. table for viewing and editing the entries Composite tableComposite = new Composite(parent, SWT.NONE); GridDataFactory.fillDefaults().hint(STANDARD_WIDGET_WIDTH * 3, 100) .span(5, 1).applyTo(tableComposite); TableColumnLayout tableColumnLayout = new TableColumnLayout(); tableComposite.setLayout(tableColumnLayout); Table table = getWidgetFactory().createTable(tableComposite, SWT.FULL_SELECTION | SWT.DOUBLE_BUFFERED | SWT.SCROLL_PAGE); table.setLinesVisible(true); table.setHeaderVisible(false); tableViewer = ConvenienceTableWrapper.equip(table, new ColumnConfig("action", "Action", 100, 10, false), new ColumnConfig("remove", "Remove", 30, -1, true), new ColumnConfig("up", "Up", 30, -1, true)); // .. button to add new entries to the table final Hyperlink addHyperLink = getWidgetFactory().createHyperlink(parent, "Add Action...", SWT.NONE); addHyperLink.setUnderlined(false); addHyperLink.addHyperlinkListener(new HyperlinkAdapter() { @Override public void linkActivated(HyperlinkEvent e) { ActionDataProperty property = getMainWidgetProperty(); if (property != null) { ActionData data = property.<ActionData>getPropertyValue().clone(); if (data != null) { AbstractWidgetActionModel widgetAction = ActionType.OPEN_DISPLAY .getActionFactory().createWidgetActionModel(); ActionDataDialog dialog = new ActionDataDialog( addHyperLink.getShell(), widgetAction); if (Window.OK == dialog.open()) { widgetAction = dialog.getActionModel(); printAction(widgetAction); data.addAction(widgetAction); applyPropertyChange(data); } } } } }); } private void printAction(AbstractWidgetActionModel widgetAction) { System.out.println("WidgetAction:"); System.out.println(" "+ widgetAction.getActionLabel()); for (WidgetProperty prop : widgetAction.getProperties()) { System.out.println(" " + prop.getDescription() + ": " + prop.getPropertyValue()); } } /** *{@inheritDoc} */ @Override protected void doRefreshControls(ActionDataProperty widgetProperty) { // .. (re)create the table editors used for removing single lines of the // table if (tableEditors != null) { // .. dispose existing editors for (TableEditor editor : tableEditors) { if (editor.getEditor() != null) { editor.getEditor().dispose(); } editor.dispose(); } tableEditors.clear(); } // .. create new editors if (widgetProperty != null && tableViewer.getContentProvider() != null) { ActionData original = widgetProperty.getPropertyValue(); ActionData data = original.clone(); List<ITableRow> rows = new ArrayList<ITableRow>(); for (AbstractWidgetActionModel action : data.getWidgetActions()) { rows.add(new ActionDataRowAdapter(data, action)); } tableViewer.setInput(rows); TableItem[] items = tableViewer.getTable().getItems(); for (int i = 0; i < items.length; i++) { final TableItem item = items[i]; TableEditor deleteTableEditor = new TableEditor(tableViewer .getTable()); Button deleteButton = new Button(tableViewer.getTable(), SWT.FLAT); deleteButton.setImage(CustomMediaFactory.getInstance() .getImageFromPlugin(SdsUiPlugin.PLUGIN_ID, "icons/delete.gif")); deleteButton.pack(); deleteTableEditor.minimumWidth = deleteButton.getSize().x; deleteTableEditor.horizontalAlignment = SWT.LEFT; deleteTableEditor.setEditor(deleteButton, item, 1); deleteButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { ActionDataRowAdapter data = (ActionDataRowAdapter) item .getData(); data.setValue(1, "true"); } }); tableEditors.add(deleteTableEditor); TableEditor upTableEditor = new TableEditor(tableViewer .getTable()); final Button upButton = new Button(tableViewer.getTable(), SWT.FLAT); upButton.setImage(CustomMediaFactory.getInstance() .getImageFromPlugin(SdsUiPlugin.PLUGIN_ID, "icons/search_prev.gif")); upButton.pack(); upTableEditor.minimumWidth = upButton.getSize().x; upTableEditor.horizontalAlignment = SWT.LEFT; upTableEditor.setEditor(upButton, item, 2); upButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { ActionDataRowAdapter data = (ActionDataRowAdapter) item .getData(); data.setValue(2, "true"); } }); tableEditors.add(upTableEditor); } } } /** * * @author Kai Meyer (C1 WPS) * */ private class ActionDataRowAdapter implements ITableRow { private final AbstractWidgetActionModel _actionModel; private final ActionData _actionData; public ActionDataRowAdapter(ActionData actionData, AbstractWidgetActionModel action) { _actionData = actionData; _actionModel = action; } @Override public boolean canModify(int column) { return true; } @Override public RGB getBackgroundColor(int column) { return null; } @Override public CellEditor getCellEditor(int column, Composite parent) { switch (column) { case 0: return new ActionDataCellEditor(parent, _actionModel); default: return null; } } @Override public String getDisplayValue(int column) { switch (column) { case 0: return _actionModel.getActionLabel(); default: return null; } } @Override public String getEditingValue(int column) { return _actionModel.getActionLabel(); } @Override public Font getFont(int column) { return CustomMediaFactory.getInstance().getFont("Arial", 10, SWT.NORMAL); } @Override public RGB getForegroundColor(int column) { return null; } @Override public Image getImage(int column) { if (column == 0) { ImageDescriptor imageDescriptor = CustomMediaFactory .getInstance().getImageDescriptorFromPlugin( SdsUiPlugin.PLUGIN_ID, _actionModel.getType().getIcon()); return imageDescriptor.createImage(); } return null; } @Override public String getTooltip() { return null; } @Override public void setValue(int column, Object value) { switch (column) { case 0: AbstractWidgetActionModel newModel = (AbstractWidgetActionModel) value; _actionData.replaceActionModels(_actionModel, newModel); applyPropertyChange(_actionData); break; case 1: _actionData.removeAction(_actionModel); applyPropertyChange(_actionData); break; case 2: _actionData.upAction(_actionModel); applyPropertyChange(_actionData); break; default: break; } } @Override public int compareTo(ITableRow o) { return 0; } } /** * * @author Kai Meyer (C1 WPS) * */ private class ActionDataCellEditor extends CellEditor { private final Shell _shell; private AbstractWidgetActionModel _actionModel; public ActionDataCellEditor(Composite parent, AbstractWidgetActionModel actionModel) { super(parent, SWT.NONE); _actionModel = actionModel; _shell = parent.getShell(); } @Override protected Control createControl(Composite parent) { return null; } @Override public void activate() { ActionDataDialog dialog = new ActionDataDialog(_shell, _actionModel); dialog.open(); _actionModel = dialog.getActionModel(); fireApplyEditorValue(); } @Override protected Object doGetValue() { return _actionModel; } @Override protected void doSetFocus() { // nothing to do } @Override protected void doSetValue(Object value) { // nothing to do } } /** * * @author Kai Meyer (C1 WPS) * */ private class ActionDataDialog extends Dialog { private TableViewer _propertyViewer; private CellEditor _openedCellEditor = null; private AbstractWidgetActionModel _actionModel; private final HashMap<IPropertyDescriptor, WidgetProperty> _descriptorPropertyMap; protected ActionDataDialog(Shell parentShell, AbstractWidgetActionModel actionModel) { super(parentShell); _actionModel = actionModel; _descriptorPropertyMap = new HashMap<IPropertyDescriptor, WidgetProperty>(); parentShell.setText("Action Properties"); } public AbstractWidgetActionModel getActionModel() { return _actionModel; } @Override protected Control createDialogArea(Composite parent) { Composite area = (Composite) super.createDialogArea(parent); ComboViewer typeCombo = new ComboViewer(area, SWT.READ_ONLY); typeCombo.setContentProvider(new ArrayContentProvider()); typeCombo.setLabelProvider(new LabelProvider()); typeCombo.setInput(ActionType.values()); StructuredSelection selection = new StructuredSelection( _actionModel.getType()); typeCombo.setSelection(selection, true); typeCombo .addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event .getSelection(); ActionType newType = (ActionType) selection .getFirstElement(); _actionModel = newType.getActionFactory() .createWidgetActionModel(); _propertyViewer .setInput(generateInputProperties(_actionModel)); } }); _propertyViewer = createPropertyTableViewer(area); _propertyViewer.setInput(generateInputProperties(_actionModel)); return area; } /** * Creates and configures a {@link TableViewer}. * * @param parent * The parent for the table * @return The {@link TableViewer} */ private TableViewer createPropertyTableViewer(final Composite parent) { final Table table = new Table(parent, SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); table.setLinesVisible(true); table.setHeaderVisible(true); TableViewer viewer = new TableViewer(table); TableViewerColumn tvColumn = new TableViewerColumn(viewer, SWT.NONE); tvColumn.getColumn().setText("first"); tvColumn.getColumn().setMoveable(false); tvColumn.getColumn().setWidth(0); tvColumn.getColumn().setResizable(false); tvColumn = new TableViewerColumn(viewer, SWT.NONE); tvColumn.getColumn().setText("Property"); tvColumn.getColumn().setMoveable(false); tvColumn.getColumn().setWidth(100); tvColumn = new TableViewerColumn(viewer, SWT.NONE); tvColumn.getColumn().setText("Value"); tvColumn.getColumn().setMoveable(false); tvColumn.getColumn().setWidth(300); EditingSupport editingSupport = new CustomEditingSupport(viewer, table); tvColumn.setEditingSupport(editingSupport); viewer.getColumnViewerEditor().addEditorActivationListener( new ColumnViewerEditorActivationListener() { private boolean _deactivationDone = false; @Override public void afterEditorActivated( final ColumnViewerEditorActivationEvent event) { // do nothing } @Override public void afterEditorDeactivated( final ColumnViewerEditorDeactivationEvent event) { if (!_deactivationDone) { _deactivationDone = true; getButton(IDialogConstants.CANCEL_ID) .setEnabled(true); getButton(IDialogConstants.OK_ID).setEnabled( true); _openedCellEditor = null; } } @Override public void beforeEditorActivated( final ColumnViewerEditorActivationEvent event) { getButton(IDialogConstants.CANCEL_ID).setEnabled( false); getButton(IDialogConstants.OK_ID).setEnabled(false); _deactivationDone = false; } @Override public void beforeEditorDeactivated( final ColumnViewerEditorDeactivationEvent event) { // do nothing } }); viewer.setColumnProperties(new String[] { "first", "Property", "Value" }); viewer.setUseHashlookup(true); viewer.setContentProvider(new ArrayContentProvider()); viewer.setLabelProvider(new TableLabelProvider()); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1); gridData.heightHint = 100; table.setLayoutData(gridData); return viewer; } /** * {@inheritDoc} */ @Override public boolean close() { if (_openedCellEditor == null) { return super.close(); } return false; } /** * Calculates the input for the table depending on the type of the * {@link ActionData}. * * @param action * The {@link AbstractWidgetActionModel} for the input */ private IPropertyDescriptor[] generateInputProperties( final AbstractWidgetActionModel action) { IPropertyDescriptor[] descriptors = new IPropertyDescriptor[0]; if (action != null) { Set<String> propertyKeys = action.getPropertyKeys(); descriptors = new IPropertyDescriptor[propertyKeys.size()]; int i = 0; for (String propertyKey : propertyKeys) { WidgetProperty property = action.getProperty(propertyKey); IPropertyDescriptorFactory factory = PropertyDescriptorFactoryService .getInstance().getPropertyDescriptorFactory( property.getPropertyType()); descriptors[i] = factory.createPropertyDescriptor( propertyKey, property); i++; } } return descriptors; } /** * Returns the {@link WidgetProperty} of the {@link IPropertyDescriptor} * . * * @param descriptor * The {@link IPropertyDescriptor} * @return The {@link WidgetProperty} for the given descriptor */ private WidgetProperty getWidgetProperty( final IPropertyDescriptor descriptor) { if (!_descriptorPropertyMap.containsKey(descriptor)) { for (String propertyKey : _actionModel.getPropertyKeys()) { if (descriptor.getId().equals(propertyKey)) { WidgetProperty widgetProperty = _actionModel .getProperty(propertyKey); _descriptorPropertyMap.put(descriptor, widgetProperty); return widgetProperty; } } return null; } else { return _descriptorPropertyMap.get(descriptor); } } /** * The {@link EditingSupport} for the columns of the property table. * * @author Kai Meyer * */ private final class CustomEditingSupport extends EditingSupport { /** * The {@link Table} where this {@link EditingSupport} is embedded. */ private final Table _table; /** * A {@link Map} of the already known CllEditors. */ private Map<Object, CellEditor> _cellEditors = new HashMap<Object, CellEditor>(); /** * Constructor. * * @param viewer * The {@link ColumnViewer} for this * {@link EditingSupport}. * @param table * The {@link Table} */ private CustomEditingSupport(final ColumnViewer viewer, final Table table) { super(viewer); _table = table; } /** * {@inheritDoc} */ @Override protected boolean canEdit(final Object element) { return true; } /** * {@inheritDoc} */ @Override protected CellEditor getCellEditor(final Object element) { if (!_cellEditors.containsKey(element)) { IStructuredSelection selection = (IStructuredSelection) this .getViewer().getSelection(); IPropertyDescriptor descriptor = (IPropertyDescriptor) selection .getFirstElement(); if (descriptor != null) { CellEditor editor = descriptor .createPropertyEditor(_table); if (editor != null) { _cellEditors.put(element, editor); } } } if (_cellEditors.containsKey(element)) { _openedCellEditor = _cellEditors.get(element); return _cellEditors.get(element); } return null; } /** * {@inheritDoc} */ @Override protected Object getValue(final Object element) { if (element instanceof IPropertyDescriptor) { WidgetProperty prop = getWidgetProperty((IPropertyDescriptor) element); if (prop != null) { return prop.getPropertyValue(); } } return null; } /** * {@inheritDoc} */ @Override protected void setValue(final Object element, final Object value) { if (element instanceof IPropertyDescriptor) { WidgetProperty prop = getWidgetProperty((IPropertyDescriptor) element); if (prop != null) { prop.setPropertyValue(value); _propertyViewer.refresh(); } } } } /** * The {@link LabelProvider} for the table. * * @author Kai Meyer * */ private final class TableLabelProvider extends LabelProvider implements ITableLabelProvider { /** * {@inheritDoc} */ @Override public Image getColumnImage(final Object element, final int columnIndex) { if (columnIndex == 2 && element instanceof IPropertyDescriptor) { IPropertyDescriptor descriptor = (IPropertyDescriptor) element; Object value = getWidgetProperty(descriptor); if (value != null) { if (descriptor.getLabelProvider() != null) { try { return descriptor.getLabelProvider().getImage( value); } catch (Exception e) { e.printStackTrace(); } } } } return null; } /** * {@inheritDoc} */ @Override public String getColumnText(final Object element, final int columnIndex) { if (element instanceof IPropertyDescriptor) { IPropertyDescriptor descriptor = (IPropertyDescriptor) element; if (columnIndex == 0) { return ""; } if (columnIndex == 1) { return descriptor.getDisplayName(); } WidgetProperty widgetProperty = getWidgetProperty(descriptor); if (widgetProperty != null && descriptor.getLabelProvider() != null) { return descriptor.getLabelProvider().getText( widgetProperty.getPropertyValue()); } } if (element != null) { return element.toString(); } return "Fehler"; } } } }