Java tutorial
/******************************************************************************* * Copyright (c) 2010 Oak Ridge National Laboratory. * 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 ******************************************************************************/ package org.csstudio.opibuilder.visualparts; import java.util.Arrays; import java.util.List; import java.util.Set; import org.csstudio.opibuilder.OPIBuilderPlugin; import org.csstudio.opibuilder.model.AbstractContainerModel; import org.csstudio.opibuilder.model.AbstractPVWidgetModel; import org.csstudio.opibuilder.model.AbstractWidgetModel; import org.csstudio.opibuilder.properties.AbstractWidgetProperty; import org.csstudio.opibuilder.script.Expression; import org.csstudio.opibuilder.script.PVTuple; import org.csstudio.opibuilder.script.RuleData; import org.csstudio.ui.util.CustomMediaFactory; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CellEditor; 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.viewers.TextCellEditor; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolBar; /**The dialog for rule data editing. * @author Xihui Chen * */ public class RuleDataEditDialog extends HelpTrayDialog { private Action addAction; private Action copyAction; private Action removeAction; private Action moveUpAction; private Action moveDownAction; private TableViewer expressionViewer; private PVTupleTableEditor pvsEditor; private Text nameText; private Combo propCombo; private Button outPutExpButton; private RuleData ruleData; private List<Expression> expressionList; private List<String> propIDList; private TableViewerColumn valueColumn; private static String[] UNCHANGEABLE_PROPERTIES = new String[] { AbstractWidgetModel.PROP_ACTIONS, AbstractWidgetModel.PROP_WIDGET_TYPE, AbstractWidgetModel.PROP_SCRIPTS, AbstractWidgetModel.PROP_RULES, AbstractContainerModel.PROP_MACROS }; public RuleDataEditDialog(Shell parentShell, RuleData ruleData) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); this.ruleData = ruleData.getCopy(); this.expressionList = this.ruleData.getExpressionList(); Set<String> propIDSet = ruleData.getWidgetModel().getAllPropertyIDs(); for (String p : UNCHANGEABLE_PROPERTIES) { propIDSet.remove(p); } for (String id : propIDSet.toArray(new String[0])) { AbstractWidgetProperty prop = ruleData.getWidgetModel().getProperty(id); if (prop.configurableByRule()) continue; else propIDSet.remove(id); } String[] propArray = propIDSet.toArray(new String[0]); Arrays.sort(propArray); propIDList = Arrays.asList(propArray); } @Override protected String getHelpResourcePath() { return "/" + OPIBuilderPlugin.PLUGIN_ID + "/html/Rules.html"; //$NON-NLS-1$; //$NON-NLS-2$ } @Override protected void okPressed() { boolean hasTrigger = false; for (PVTuple pvTuple : ruleData.getPVList()) { hasTrigger |= pvTuple.trigger; } if (!hasTrigger) { MessageDialog.openWarning(getShell(), "Warning", NLS.bind("At least one trigger PV must be selected for the rule:\n{0}", ruleData.getName())); return; } super.okPressed(); } /** * @return the ruleData. */ public final RuleData getOutput() { return ruleData; } /** * {@inheritDoc} */ @Override protected void configureShell(final Shell shell) { super.configureShell(shell); shell.setText("Edit Rule"); } /** * Creates 'wrapping' label with the given text. * * @param parent * The parent for the label * @param text * The text for the label */ private void createLabel(final Composite parent, final String text) { Label label = new Label(parent, SWT.WRAP); label.setText(text); label.setLayoutData(new GridData(SWT.FILL, 0, false, false)); } @Override protected Control createDialogArea(Composite parent) { final Composite parent_Composite = (Composite) super.createDialogArea(parent); // Parent composite has GridLayout with 1 columns. // Create embedded composite w/ 2 columns final Composite mainComposite = new Composite(parent_Composite, SWT.None); mainComposite.setLayout(new GridLayout(2, false)); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); gridData.heightHint = 500; mainComposite.setLayoutData(gridData); final Composite topComposite = new Composite(mainComposite, SWT.None); topComposite.setLayout(new GridLayout(2, false)); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false); gd.horizontalSpan = 2; topComposite.setLayoutData(gd); createLabel(topComposite, "Rule Name: "); nameText = new Text(topComposite, SWT.BORDER); nameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); nameText.setText(ruleData.getName()); nameText.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { ruleData.setName(nameText.getText()); } }); createLabel(topComposite, "Property: "); propCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); propCombo.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); String[] comboItems = new String[propIDList.size()]; int i = 0; for (String id : propIDList) { comboItems[i++] = ruleData.getWidgetModel().getProperty(id).getDescription() + " (" + id + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } propCombo.setItems(comboItems); propCombo.select(propIDList.indexOf(ruleData.getPropId())); propCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (propIDList.get(propCombo.getSelectionIndex()).equals(AbstractPVWidgetModel.PROP_PVVALUE)) { MessageDialog.openWarning(propCombo.getShell(), "Warning", "Note: Changing pv_value property with rule or " + "script will not write value to the PV. " + "It only change the graphical value on the widget! " + "If you need to write a PV, please call PV.setValue() from script."); } ruleData.setPropId(propIDList.get(propCombo.getSelectionIndex())); if (ruleData.getProperty().getPropertyDescriptor() == null || ruleData.getProperty().onlyAcceptExpressionInRule()) { ruleData.setOutputExpValue(true); outPutExpButton.setSelection(true); outPutExpButton.setEnabled(false); for (Expression exp : expressionList) exp.setValue(""); //$NON-NLS-1$ valueColumn.getColumn().setText("Output Expression"); } else outPutExpButton.setEnabled(true); if (!ruleData.isOutputExpValue()) { for (Expression exp : expressionList) exp.setValue(ruleData.isOutputExpValue() ? "" : ruleData.getProperty().getDefaultValue()); //$NON-NLS-1$ } expressionViewer.refresh(); } }); outPutExpButton = new Button(topComposite, SWT.CHECK); gd = new GridData(); gd.horizontalSpan = 2; outPutExpButton.setLayoutData(gd); outPutExpButton.setText("Output Expression"); if (ruleData.getProperty().getPropertyDescriptor() == null || ruleData.getProperty().onlyAcceptExpressionInRule()) { ruleData.setOutputExpValue(true); outPutExpButton.setEnabled(false); } outPutExpButton.setSelection(ruleData.isOutputExpValue()); outPutExpButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { ruleData.setOutputExpValue(outPutExpButton.getSelection()); for (Expression exp : expressionList) exp.setValue(ruleData.isOutputExpValue() ? "" : ruleData.getProperty().getDefaultValue()); //$NON-NLS-1$ valueColumn.getColumn().setText(ruleData.isOutputExpValue() ? "Output Expression" : "Output Value"); expressionViewer.refresh(); } }); // Left Panel: List of scripts final Composite leftComposite = new Composite(mainComposite, SWT.NONE); leftComposite.setLayout(new GridLayout(1, false)); gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.widthHint = 350; leftComposite.setLayoutData(gd); createLabel(leftComposite, "Expressions"); Composite toolBarComposite = new Composite(leftComposite, SWT.BORDER); GridLayout gridLayout = new GridLayout(1, false); gridLayout.marginLeft = 0; gridLayout.marginRight = 0; gridLayout.marginBottom = 0; gridLayout.marginTop = 0; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; toolBarComposite.setLayout(gridLayout); gd = new GridData(SWT.FILL, SWT.FILL, true, true); toolBarComposite.setLayoutData(gd); ToolBarManager toolbarManager = new ToolBarManager(SWT.FLAT); ToolBar toolBar = toolbarManager.createControl(toolBarComposite); GridData grid = new GridData(); grid.horizontalAlignment = GridData.FILL; grid.verticalAlignment = GridData.BEGINNING; toolBar.setLayoutData(grid); createActions(); toolbarManager.add(addAction); toolbarManager.add(copyAction); toolbarManager.add(removeAction); toolbarManager.add(moveUpAction); toolbarManager.add(moveDownAction); toolbarManager.update(true); expressionViewer = createExpressionsTableViewer(toolBarComposite); expressionViewer.setInput(expressionList); expressionViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { refreshActionBarOnSelection(); } }); // Right panel: Input PVs for selected script final Composite rightComposite = new Composite(mainComposite, SWT.NONE); gridLayout = new GridLayout(1, false); rightComposite.setLayout(gridLayout); gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.minimumWidth = 250; // Account for the StringTableEditor's minimum size rightComposite.setLayoutData(gd); this.createLabel(rightComposite, "Input PVs"); pvsEditor = new PVTupleTableEditor(rightComposite, ruleData.getPVList(), SWT.BORDER); pvsEditor.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); if (expressionList.size() > 0) setExpressionViewerSelection(expressionList.get(0)); final Composite bottomComposite = new Composite(mainComposite, SWT.None); bottomComposite.setLayout(new GridLayout(1, false)); gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.horizontalSpan = 2; bottomComposite.setLayoutData(gd); Button generateScriptButton = new Button(bottomComposite, SWT.PUSH); generateScriptButton.setText("See Generated Script"); gd = new GridData(SWT.LEFT, SWT.TOP, false, false); generateScriptButton.setLayoutData(gd); final Text scriptText = new Text(bottomComposite, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.READ_ONLY); gd = new GridData(SWT.FILL, SWT.FILL, true, true); scriptText.setLayoutData(gd); generateScriptButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { scriptText.setText(ruleData.generateScript()); } }); return parent_Composite; } /** * Refreshes the enabled-state of the actions. */ private void refreshActionBarOnSelection() { IStructuredSelection selection = (IStructuredSelection) expressionViewer.getSelection(); boolean enabled = !selection.isEmpty() && selection.getFirstElement() instanceof Expression; copyAction.setEnabled(enabled); removeAction.setEnabled(enabled); moveUpAction.setEnabled(enabled); moveDownAction.setEnabled(enabled); } private void setExpressionViewerSelection(Expression expression) { expressionViewer.refresh(); if (expression == null) expressionViewer.setSelection(StructuredSelection.EMPTY); else { expressionViewer.setSelection(new StructuredSelection(expression)); } } /** * Creates and configures a {@link TableViewer}. * * @param parent * The parent for the table * @return The {@link TableViewer} */ private TableViewer createExpressionsTableViewer(final Composite parent) { final TableViewer viewer = new TableViewer(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.FULL_SELECTION); viewer.getTable().setLinesVisible(true); viewer.getTable().setHeaderVisible(true); TableViewerColumn expressionColumn = new TableViewerColumn(viewer, SWT.NONE); expressionColumn.getColumn().setText("Boolean Expression"); expressionColumn.getColumn().setMoveable(false); expressionColumn.getColumn().setWidth(200); expressionColumn.setEditingSupport(new EditingSupport(viewer) { @Override protected void setValue(Object element, Object value) { if (element instanceof Expression) ((Expression) element).setBooleanExpression(value.toString()); viewer.refresh(); } @Override protected Object getValue(Object element) { if (element instanceof Expression) return ((Expression) element).getBooleanExpression(); return null; } @Override protected CellEditor getCellEditor(Object element) { return new TextCellEditor(viewer.getTable()); } @Override protected boolean canEdit(Object element) { return true; } }); valueColumn = new TableViewerColumn(viewer, SWT.NONE); valueColumn.getColumn().setText(ruleData.isOutputExpValue() ? "Output Expression" : "Output Value"); valueColumn.getColumn().setMoveable(false); valueColumn.getColumn().setWidth(200); EditingSupport editingSupport = new EditingSupport(viewer) { @Override protected void setValue(Object element, Object value) { if (element instanceof Expression) { ((Expression) element).setValue(value); } viewer.refresh(); } @Override protected Object getValue(Object element) { if (element instanceof Expression) { if (((Expression) element).getValue() == null) return ""; //$NON-NLS-1$ return ((Expression) element).getValue(); } return null; } @Override protected CellEditor getCellEditor(Object element) { if (element instanceof Expression) { if (ruleData.isOutputExpValue() || ruleData.getProperty().getPropertyDescriptor() == null) return new TextCellEditor(viewer.getTable()); else return ruleData.getProperty().getPropertyDescriptor() .createPropertyEditor(viewer.getTable()); } return null; } @Override protected boolean canEdit(Object element) { return true; } }; valueColumn.setEditingSupport(editingSupport); viewer.setContentProvider(new ArrayContentProvider()); viewer.setLabelProvider(new ExpressionLabelProvider()); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); viewer.getTable().setLayoutData(gd); return viewer; } /** * Creates the actions. */ private void createActions() { addAction = new Action("Add") { @Override public void run() { Expression expression = new Expression("", ruleData.isOutputExpValue() ? "" : ruleData.getProperty().getDefaultValue()); expressionList.add(expression); expressionViewer.refresh(); setExpressionViewerSelection(expression); } }; addAction.setToolTipText("Add an Expression"); addAction.setImageDescriptor(CustomMediaFactory.getInstance() .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/add.gif")); //$NON-NLS-1$ copyAction = new Action() { @Override public void run() { IStructuredSelection selection = (IStructuredSelection) expressionViewer.getSelection(); if (!selection.isEmpty() && selection.getFirstElement() instanceof Expression) { Expression expression = ((Expression) selection.getFirstElement()).getCopy(); expressionList.add(expression); setExpressionViewerSelection(expression); } } }; copyAction.setText("Copy"); copyAction.setToolTipText("Copy selected expression"); copyAction.setImageDescriptor(CustomMediaFactory.getInstance() .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/copy.gif")); //$NON-NLS-1$ copyAction.setEnabled(false); removeAction = new Action() { @Override public void run() { IStructuredSelection selection = (IStructuredSelection) expressionViewer.getSelection(); if (!selection.isEmpty() && selection.getFirstElement() instanceof Expression) { expressionList.remove((Expression) selection.getFirstElement()); setExpressionViewerSelection(null); this.setEnabled(false); } } }; removeAction.setText("Remove Expression"); removeAction.setToolTipText("Remove the selected expression from the list"); removeAction.setImageDescriptor(CustomMediaFactory.getInstance() .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/delete.gif")); //$NON-NLS-1$ removeAction.setEnabled(false); moveUpAction = new Action() { @Override public void run() { IStructuredSelection selection = (IStructuredSelection) expressionViewer.getSelection(); if (!selection.isEmpty() && selection.getFirstElement() instanceof Expression) { Expression expression = (Expression) selection.getFirstElement(); int i = expressionList.indexOf(expression); if (i > 0) { expressionList.remove(expression); expressionList.add(i - 1, expression); setExpressionViewerSelection(expression); } } } }; moveUpAction.setText("Move Expression Up"); moveUpAction.setToolTipText("Move selected expression up"); moveUpAction.setImageDescriptor(CustomMediaFactory.getInstance() .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/search_prev.gif")); //$NON-NLS-1$ moveUpAction.setEnabled(false); moveDownAction = new Action() { @Override public void run() { IStructuredSelection selection = (IStructuredSelection) expressionViewer.getSelection(); if (!selection.isEmpty() && selection.getFirstElement() instanceof Expression) { Expression expression = (Expression) selection.getFirstElement(); int i = expressionList.indexOf(expression); if (i < expressionList.size() - 1) { expressionList.remove(expression); expressionList.add(i + 1, expression); setExpressionViewerSelection(expression); } } } }; moveDownAction.setText("Move Expression Down"); moveDownAction.setToolTipText("Move selected expression down"); moveDownAction.setImageDescriptor(CustomMediaFactory.getInstance() .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/search_next.gif")); //$NON-NLS-1$ moveDownAction.setEnabled(false); } class ExpressionLabelProvider extends LabelProvider implements ITableLabelProvider { /** * {@inheritDoc} */ @Override public Image getColumnImage(final Object element, final int columnIndex) { if (columnIndex == 1 && !ruleData.isOutputExpValue() && element instanceof Expression) { Expression expression = (Expression) element; if (ruleData.getProperty().getPropertyDescriptor() == null) return null; if (ruleData.getProperty().getPropertyDescriptor().getLabelProvider() != null) return ruleData.getProperty().getPropertyDescriptor().getLabelProvider() .getImage(expression.getValue()); } return null; } /** * {@inheritDoc} */ @Override public String getColumnText(final Object element, final int columnIndex) { if (element != null && element instanceof Expression) { Expression expression = (Expression) element; if (columnIndex == 0) { return expression.getBooleanExpression(); } if (ruleData.getProperty().getPropertyDescriptor() != null && !ruleData.isOutputExpValue() && ruleData.getProperty().getPropertyDescriptor().getLabelProvider() != null) { return ruleData.getProperty().getPropertyDescriptor().getLabelProvider() .getText(expression.getValue()); } else if (expression.getValue() == null) return ""; else return expression.getValue().toString(); } if (element != null) { return element.toString(); } return "error"; } } }