/* * This file is part of the OpenSCADA project * Copyright (C) 2006-2012 TH4 SYSTEMS GmbH (http://th4-systems.com) * * OpenSCADA is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenSCADA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenSCADA. If not, see * <http://opensource.org/licenses/lgpl-3.0.html> for a copy of the LGPLv3 License. */ package org.openscada.da.client.test.wizards; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ComboBoxCellEditor; import org.eclipse.jface.viewers.ICellModifier; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; 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.TableLayout; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolBar; import org.openscada.core.Variant; import org.openscada.da.client.base.browser.ValueType; import org.openscada.da.ui.connection.data.Item; import org.openscada.da.ui.connection.data.ItemSelectionHelper; import org.openscada.da.ui.widgets.realtime.AttributePair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; class WriteAttributesOperationWizardValuePage extends WizardPage implements IWizardPage { private final static Logger logger = LoggerFactory.getLogger ( WriteAttributesOperationWizardValuePage.class ); private Text itemIdText; private TableViewer table; private class AttributeEntry { private String name = ""; private ValueType valueType = ValueType.STRING; private String valueString = ""; private Variant value = Variant.NULL; private Throwable valueError = null; public AttributeEntry ( final String name, final ValueType valueType, final String value ) { super (); this.name = name; this.valueType = valueType; setValue ( value ); } public String getName () { return this.name; } public void setName ( final String name ) { this.name = name; } public Variant getValue () { return this.value; } public String getValueString () { return this.valueString; } public void setValue ( final String value ) { try { this.valueString = value; this.value = this.valueType.convertTo ( value ); this.valueError = null; } catch ( final Exception e ) { this.valueError = e; } } public ValueType getValueType () { return this.valueType; } public void setValueType ( final ValueType valueType ) { this.valueType = valueType; setValue ( this.valueString ); } public Throwable getValueError () { return this.valueError; } } private class Attributes { private final List<AttributeEntry> entries = new ArrayList<AttributeEntry> (); public void add ( final AttributeEntry entry ) { this.entries.add ( entry ); } public void remove ( final AttributeEntry entry ) { this.entries.remove ( entry ); } public List<AttributeEntry> getEntries () { return this.entries; } } private class MyLabelProvider extends LabelProvider implements ITableLabelProvider { @Override public Image getColumnImage ( final Object element, final int columnIndex ) { return getImage ( element ); } @Override public String getColumnText ( final Object element, final int columnIndex ) { logger.debug ( "Label for: {} - {}", element, columnIndex ); if ( element instanceof AttributeEntry ) { final AttributeEntry entry = (AttributeEntry)element; logger.debug ( "Label: {}", entry.getName () ); switch ( columnIndex ) { case 0: return entry.getName (); case 1: return entry.getValueType ().toString (); case 2: return entry.getValue ().asString ( "<null>" ); case 3: { if ( entry.getValueError () != null ) { return entry.getValueError ().getMessage (); } return ""; } } } return getText ( element ); } } private class MyContentProvider implements IStructuredContentProvider { @Override public Object[] getElements ( final Object inputElement ) { if ( inputElement instanceof Attributes ) { final Attributes attributes = (Attributes)inputElement; return attributes.getEntries ().toArray ( new AttributeEntry[0] ); } return new Object[0]; } @Override public void dispose () { } @Override public void inputChanged ( final Viewer viewer, final Object oldInput, final Object newInput ) { } } private ComboBoxCellEditor valueTypeEditor; private final String[] PROPERTIES = new String[] { "name", "value-type", "value", "value-error" }; private class MyCellModifier implements ICellModifier { private TableViewer viewer = null; public MyCellModifier ( final TableViewer viewer ) { this.viewer = viewer; } @Override public boolean canModify ( final Object element, final String property ) { logger.debug ( "Can modify: {}:{}", element, property ); if ( element instanceof AttributeEntry ) { if ( property.equals ( "value" ) ) { return true; } if ( property.equals ( "name" ) ) { return true; } if ( property.equals ( "value-type" ) ) { return true; } } return false; } @Override public Object getValue ( final Object element, final String property ) { logger.debug ( "Get Value: " + element + ":" + property ); if ( element instanceof AttributeEntry ) { final AttributeEntry entry = (AttributeEntry)element; if ( property.equals ( "value" ) ) { return entry.getValueString (); } if ( property.equals ( "name" ) ) { return entry.getName (); } if ( property.equals ( "value-type" ) ) { return entry.getValueType ().index (); } } return null; } @Override public void modify ( final Object element, final String property, final Object value ) { logger.debug ( "Modify Value: {}:{}:{}", new Object[] { element, property, value } ); final TableItem tableItem = (TableItem)element; if ( tableItem.getData () instanceof AttributeEntry ) { final AttributeEntry entry = (AttributeEntry)tableItem.getData (); if ( property.equals ( "value" ) ) { entry.setValue ( value.toString () ); } else if ( property.equals ( "name" ) ) { entry.setName ( value.toString () ); } else if ( property.equals ( "value-type" ) ) { final Integer i = (Integer)value; final String valueType = WriteAttributesOperationWizardValuePage.this.valueTypeEditor.getItems ()[i]; for ( final ValueType vt : ValueType.values () ) { if ( vt.label ().equals ( valueType ) ) { entry.setValueType ( vt ); } } } this.viewer.update ( entry, WriteAttributesOperationWizardValuePage.this.PROPERTIES ); dialogChanged (); } } } private final Attributes attributes = new Attributes (); private class AddAction extends Action { public AddAction () { super ( "Add Entry", IAction.AS_PUSH_BUTTON ); setEnabled ( true ); } @Override public void run () { final AttributeEntry entry = new AttributeEntry ( "", ValueType.STRING, "" ); WriteAttributesOperationWizardValuePage.this.attributes.add ( entry ); WriteAttributesOperationWizardValuePage.this.table.add ( entry ); dialogChanged (); } } private class RemoveAction extends Action implements ISelectionChangedListener { private ISelection selection; public RemoveAction () { super ( "Remove Entry", IAction.AS_PUSH_BUTTON ); } @Override public void run () { if ( this.selection instanceof IStructuredSelection ) { final IStructuredSelection selection = (IStructuredSelection)this.selection; final Iterator<?> i = selection.iterator (); while ( i.hasNext () ) { final Object o = i.next (); if ( o instanceof AttributeEntry ) { WriteAttributesOperationWizardValuePage.this.attributes.remove ( (AttributeEntry)o ); WriteAttributesOperationWizardValuePage.this.table.remove ( o ); } } dialogChanged (); } } @Override public void selectionChanged ( final SelectionChangedEvent event ) { this.selection = event.getSelection (); } } private final AddAction addAction = new AddAction (); private final RemoveAction removeAction = new RemoveAction (); private Item item; protected WriteAttributesOperationWizardValuePage () { super ( "wizardPage" ); setTitle ( "Write Attributes" ); setDescription ( "Configure the attributes to write" ); } @Override public void createControl ( final Composite parent ) { final Composite container = new Composite ( parent, SWT.NONE ); final GridLayout layout = new GridLayout (); container.setLayout ( layout ); layout.numColumns = 3; layout.verticalSpacing = 9; Label label = new Label ( container, SWT.NONE ); label.setText ( "&Item:" ); this.itemIdText = new Text ( container, SWT.BORDER | SWT.SINGLE ); GridData gd = new GridData ( GridData.FILL_HORIZONTAL ); this.itemIdText.setLayoutData ( gd ); this.itemIdText.addModifyListener ( new ModifyListener () { @Override public void modifyText ( final ModifyEvent e ) { dialogChanged (); } } ); label = new Label ( container, SWT.NONE ); // row 2 gd = new GridData ( GridData.FILL_HORIZONTAL ); gd.horizontalSpan = 3; gd.grabExcessHorizontalSpace = true; final ToolBar toolbar = new ToolBar ( container, SWT.NONE ); toolbar.setLayoutData ( gd ); final ToolBarManager tbm = new ToolBarManager ( toolbar ); tbm.add ( this.addAction ); tbm.add ( this.removeAction ); tbm.update ( true ); // row 3 gd = new GridData ( GridData.FILL_BOTH ); gd.horizontalSpan = 3; gd.grabExcessHorizontalSpace = true; gd.grabExcessVerticalSpace = true; this.table = new TableViewer ( container, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL ); TableColumn col; col = new TableColumn ( this.table.getTable (), SWT.NONE ); col.setText ( "Name" ); col = new TableColumn ( this.table.getTable (), SWT.NONE ); col.setText ( "Value Type" ); col = new TableColumn ( this.table.getTable (), SWT.NONE ); col.setText ( "Value" ); col = new TableColumn ( this.table.getTable (), SWT.NONE ); col.setText ( "Value Error" ); this.table.getTable ().setHeaderVisible ( true ); try { this.table.setLabelProvider ( new MyLabelProvider () ); this.table.setContentProvider ( new MyContentProvider () ); this.table.setColumnProperties ( this.PROPERTIES ); this.table.setCellModifier ( new MyCellModifier ( this.table ) ); final TextCellEditor nameEditor = new TextCellEditor ( this.table.getTable () ); final List<String> values = new LinkedList<String> (); for ( final ValueType vt : ValueType.values () ) { values.add ( vt.label () ); } this.valueTypeEditor = new ComboBoxCellEditor ( this.table.getTable (), values.toArray ( new String[0] ) ); final TextCellEditor valueEditor = new TextCellEditor ( this.table.getTable () ); this.table.setCellEditors ( new CellEditor[] { nameEditor, this.valueTypeEditor, valueEditor, new TextCellEditor ( this.table.getTable () ) } ); final TableLayout tableLayout = new TableLayout (); tableLayout.addColumnData ( new ColumnWeightData ( 50, 75, true ) ); tableLayout.addColumnData ( new ColumnWeightData ( 50, 75, true ) ); tableLayout.addColumnData ( new ColumnWeightData ( 50, 75, true ) ); tableLayout.addColumnData ( new ColumnWeightData ( 50, 75, true ) ); this.table.getTable ().setLayout ( tableLayout ); this.table.setInput ( this.attributes ); } catch ( final Exception e ) { logger.warn ( "Unable to create control", e ); } this.table.getTable ().setLayoutData ( gd ); this.table.addSelectionChangedListener ( this.removeAction ); setControl ( container ); updateSelection (); dialogChanged (); } private void updateSelection () { this.itemIdText.setText ( this.item.getId () ); } private void dialogChanged () { // connection if ( this.item == null ) { updateStatus ( "No item selection" ); return; } // item if ( this.itemIdText.getText ().length () <= 0 ) { updateStatus ( "Item name must not be empty" ); return; } if ( this.attributes.entries.size () <= 0 ) { updateStatus ( "No attributes" ); return; } for ( final AttributeEntry entry : this.attributes.entries ) { if ( entry.name.equals ( "" ) ) { updateStatus ( "Attribute with an empty name is not allowed" ); return; } } updateStatus ( null ); } private void updateStatus ( final String message ) { setErrorMessage ( message ); setPageComplete ( message == null ); } public Item getItem () { return new Item ( this.item.getConnectionString (), this.itemIdText.getText (), this.item.getType () ); } public Map<String, Variant> getAttributes () { final Map<String, Variant> attributes = new HashMap<String, Variant> (); for ( final AttributeEntry entry : this.attributes.entries ) { attributes.put ( entry.getName (), entry.getValue () ); } return attributes; } public void setSelection ( final IStructuredSelection selection ) { this.item = ItemSelectionHelper.getFirstFromSelection ( selection ); findAttributes ( selection ); } private void findAttributes ( final IStructuredSelection selection ) { final Iterator<?> i = selection.iterator (); while ( i.hasNext () ) { final Object o = i.next (); if ( o instanceof AttributePair ) { final AttributePair pair = (AttributePair)o; final AttributeEntry entry = new AttributeEntry ( pair.key, ValueType.fromVariantType ( pair.value.getType () ), pair.value.asString ( "" ) ); this.attributes.add ( entry ); if ( this.table != null ) { this.table.add ( entry ); } } } } }