/*
* 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.ca.ui.editor.forms.common;
import java.util.Map;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.Observables;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.IViewerObservableList;
import org.eclipse.jface.databinding.viewers.ObservableValueEditingSupport;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.openscada.ca.ui.editor.EditorHelper;
import org.openscada.ca.ui.editor.forms.common.internal.Activator;
import org.openscada.ca.ui.editor.input.ConfigurationEditorInput;
import org.openscada.ui.databinding.observable.KeyPrefixMapObservable;
import org.openscada.ui.databinding.observable.ObservableMapContentProvider;
public class ConfigurationFormToolkit
{
private final FormToolkit toolkit;
private final boolean toolkitCreated;
private final DataBindingContext dbc;
public ConfigurationFormToolkit ( final Display display )
{
this.toolkit = new FormToolkit ( display );
this.toolkitCreated = true;
this.dbc = new DataBindingContext ();
}
public ConfigurationFormToolkit ( final FormToolkit providedToolkit )
{
this.toolkit = providedToolkit;
this.toolkitCreated = false;
this.dbc = new DataBindingContext ();
}
public DataBindingContext getDataBindingContext ()
{
return this.dbc;
}
public FormToolkit getFormToolkit ()
{
return this.toolkit;
}
public void dispose ()
{
if ( this.toolkitCreated )
{
this.toolkit.dispose ();
}
}
public ScrolledForm createScrolledForm ( final Composite parent, final String label )
{
final ScrolledForm form = this.toolkit.createScrolledForm ( parent );
form.setText ( label );
this.toolkit.decorateFormHeading ( form.getForm () );
return form;
}
// standard section
public Composite createStandardSection ( final Composite parent, final String sectionLabel )
{
return createStandardSection ( parent, sectionLabel, false );
}
public Composite createStandardSection ( final Composite parent, final String sectionLabel, final boolean fillVeritcal )
{
final Section section = this.toolkit.createSection ( parent, sectionLabel != null ? ExpandableComposite.TITLE_BAR : ExpandableComposite.NO_TITLE );
if ( sectionLabel != null )
{
section.setText ( sectionLabel );
}
final Composite client = createStandardComposite ( section );
section.setClient ( client );
client.setLayout ( new GridLayout ( 3, false ) );
section.setLayoutData ( new GridData ( GridData.FILL, GridData.BEGINNING, true, fillVeritcal ) );
return client;
}
public Composite createStandardComposite ( final Composite parent )
{
final Composite client = this.toolkit.createComposite ( parent, SWT.NONE );
this.toolkit.paintBordersFor ( client );
return client;
}
public void createStandardLinkText ( final Composite parent, final String linkFactory, final String attributeName, final String label, final String textMessage, final ConfigurationEditorInput input, final Object valueType )
{
this.toolkit.createLabel ( parent, label + ":" );
final Text text = this.toolkit.createText ( parent, "" );
text.setMessage ( textMessage );
text.setLayoutData ( new GridData ( GridData.FILL, GridData.BEGINNING, true, true ) );
final IObservableValue value = Observables.observeMapEntry ( input.getDataMap (), attributeName, valueType );
this.dbc.bindValue ( SWTObservables.observeText ( text, SWT.Modify ), value );
final Hyperlink link = this.toolkit.createHyperlink ( parent, "link", SWT.NONE );
link.setLayoutData ( new GridData ( GridData.FILL, GridData.BEGINNING, false, false ) );
link.addHyperlinkListener ( new HyperlinkAdapter () {
@Override
public void linkActivated ( final HyperlinkEvent e )
{
EditorHelper.handleOpen ( PlatformUI.getWorkbench ().getActiveWorkbenchWindow ().getActivePage (), input.getConnectionUri (), linkFactory, text.getText () );
}
} );
}
public void createStandardText ( final Composite parent, final String attributeName, final String label, final String textMessage, final IObservableMap data, final Object valueType )
{
createStandardText ( parent, attributeName, SWT.SINGLE, label, textMessage, data, valueType );
}
public void createStandardMultiText ( final Composite parent, final String attributeName, final String label, final String textMessage, final IObservableMap data, final Object valueType )
{
createStandardText ( parent, attributeName, SWT.MULTI, label, textMessage, data, valueType );
}
public void createStandardText ( final Composite parent, final String attributeName, final int style, final String label, final String textMessage, final IObservableMap data, final Object valueType )
{
final Label labelControl = this.toolkit.createLabel ( parent, label + ":" );
final boolean multi = ( style & SWT.MULTI ) > 0;
if ( multi )
{
labelControl.setLayoutData ( new GridData ( SWT.FILL, SWT.FILL, false, false ) );
}
final Text text = this.toolkit.createText ( parent, "", style );
text.setMessage ( textMessage );
final GridData gd = new GridData ( GridData.FILL, multi ? GridData.FILL : GridData.BEGINNING, true, true );
gd.horizontalSpan = 2;
text.setLayoutData ( gd );
final IObservableValue value = Observables.observeMapEntry ( data, attributeName, valueType );
this.dbc.bindValue ( SWTObservables.observeText ( text, SWT.Modify ), value );
}
public void createStandardCheckbox ( final Composite parent, final String attributeName, final String label, final IObservableMap data, final Object valueType )
{
final Button button = this.toolkit.createButton ( parent, label, SWT.CHECK );
{
final GridData gd = new GridData ( GridData.FILL_HORIZONTAL );
gd.horizontalSpan = 3;
button.setLayoutData ( gd );
final IObservableValue value = Observables.observeMapEntry ( data, attributeName, valueType );
this.dbc.bindValue ( SWTObservables.observeSelection ( button ), value );
}
}
// info table
public void createInfoSection ( final ScrolledForm form, final ConfigurationEditorInput input )
{
// data
final IObservableMap map = KeyPrefixMapObservable.observePrefix ( input.getDataMap (), String.class, "info.", true );
// section
final Section section = this.toolkit.createSection ( form.getBody (), ExpandableComposite.TITLE_BAR );
section.setText ( "Informational Attributes" );
final Composite client = this.toolkit.createComposite ( section, SWT.NONE );
section.setClient ( client );
this.toolkit.paintBordersFor ( client );
client.setLayout ( new GridLayout ( 1, true ) );
final GridData gd = new GridData ( GridData.FILL_BOTH );
gd.horizontalSpan = 2;
section.setLayoutData ( gd );
// fields
final TableViewer viewer = new TableViewer ( client );
final TableLayout tableLayout = new TableLayout ();
viewer.getTable ().setLayout ( tableLayout );
{
final TableViewerColumn col = new TableViewerColumn ( viewer, SWT.NONE );
col.getColumn ().setText ( "Key" );
col.setLabelProvider ( new CellLabelProvider () {
@Override
public void update ( final ViewerCell cell )
{
cell.setText ( String.format ( "%s", ( (Map.Entry<?, ?>)cell.getElement () ).getKey () ) );
}
} );
tableLayout.addColumnData ( new ColumnWeightData ( 50, true ) );
}
{
final TableViewerColumn col = new TableViewerColumn ( viewer, SWT.NONE );
col.getColumn ().setText ( "Value" );
col.setLabelProvider ( new CellLabelProvider () {
@Override
public void update ( final ViewerCell cell )
{
cell.setText ( String.format ( "%s", ( (Map.Entry<?, ?>)cell.getElement () ).getValue () ) );
}
} );
tableLayout.addColumnData ( new ColumnWeightData ( 100, true ) );
col.setEditingSupport ( new InlineEditingSupport ( map, viewer, this.dbc ) );
}
viewer.getTable ().setHeaderVisible ( true );
viewer.setContentProvider ( new ObservableMapContentProvider () );
viewer.setInput ( map );
viewer.getControl ().setLayoutData ( new GridData ( GridData.FILL_BOTH ) );
viewer.setSorter ( new ViewerSorter () );
final ToolBarManager tbm = new ToolBarManager ();
tbm.add ( new AddAction ( map, form.getShell () ) );
tbm.add ( new RemoveAction ( map, ViewersObservables.observeMultiSelection ( viewer ) ) );
section.setTextClient ( tbm.createControl ( section ) );
}
private static class RemoveAction extends Action
{
private final IObservableMap map;
private final IViewerObservableList selectedItems;
public RemoveAction ( final IObservableMap map, final IViewerObservableList selectedItems )
{
this.map = map;
this.selectedItems = selectedItems;
}
@Override
public String getText ()
{
return "-";
}
@Override
public ImageDescriptor getImageDescriptor ()
{
return ImageDescriptor.createFromURL ( Activator.getDefault ().getBundle ().getEntry ( "/icons/delete.gif" ) );
}
@Override
public void run ()
{
for ( final Object o : this.selectedItems )
{
final Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
this.map.remove ( entry.getKey () );
}
}
}
private static class AddAction extends Action
{
private final IObservableMap map;
private final Shell shell;
public AddAction ( final IObservableMap map, final Shell shell )
{
this.map = map;
this.shell = shell;
}
@Override
public String getText ()
{
return "+";
}
@Override
public ImageDescriptor getImageDescriptor ()
{
return ImageDescriptor.createFromURL ( Activator.getDefault ().getBundle ().getEntry ( "/icons/add.png" ) );
}
@Override
public void runWithEvent ( final Event event )
{
final InputDialog dialog = new InputDialog ( this.shell, "Add key", "Enter the name of the key to add", "", null );
if ( dialog.open () == Window.OK )
{
this.map.put ( dialog.getValue (), "" );
}
}
}
private static class InlineEditingSupport extends ObservableValueEditingSupport
{
private final CellEditor cellEditor;
private final IObservableMap map;
public InlineEditingSupport ( final IObservableMap map, final ColumnViewer viewer, final DataBindingContext dbc )
{
super ( viewer, dbc );
this.map = map;
this.cellEditor = new TextCellEditor ( (Composite)viewer.getControl () );
}
@Override
protected CellEditor getCellEditor ( final Object element )
{
return this.cellEditor;
}
@Override
protected IObservableValue doCreateCellEditorObservable ( final CellEditor cellEditor )
{
return SWTObservables.observeText ( cellEditor.getControl (), SWT.Modify );
}
@Override
protected IObservableValue doCreateElementObservable ( final Object element, final ViewerCell cell )
{
final Object key = ( (Map.Entry<?, ?>)element ).getKey ();
if ( key == null )
{
return null;
}
return Observables.observeMapEntry ( this.map, key, String.class );
}
}
}