/*
* This file is part of the OpenSCADA project
* Copyright (C) 2006-2010 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.ae.ui.views.dialog;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.openscada.ae.Event;
import org.openscada.ae.Event.Fields;
import org.openscada.ae.ui.views.Messages;
import org.openscada.utils.filter.Assertion;
import org.openscada.utils.filter.Filter;
import org.openscada.utils.filter.FilterAssertion;
import org.openscada.utils.filter.FilterExpression;
import org.openscada.utils.filter.Operator;
public class FilterAdvancedComposite extends Composite
{
private final List<OrCondition> orConditions = new ArrayList<OrCondition> ();
private final CTabFolder tabFolder;
private final Button addOrConditionButton;
private enum Type
{
Text,
Number,
DateTime
}
/**
* @author jrose
*
*/
private static class AddAssertionComposite extends Composite
{
// fields
private final OrCondition orCondition;
// widgets
private final Combo attributeCombo;
public AddAssertionComposite ( final OrCondition orCondition, final Composite parent )
{
// fields
super ( parent, SWT.NONE );
this.orCondition = orCondition;
// widgets
this.attributeCombo = createAttributeCombo ();
createTypeCombo ();
createAddButton ();
// layout
final RowLayout layout = new RowLayout ();
this.setLayout ( layout );
}
private Combo createAttributeCombo ()
{
final Combo c = new Combo ( this, SWT.NONE );
c.add ( "sourceTimestamp" ); //$NON-NLS-1$
c.add ( "entryTimestamp" ); //$NON-NLS-1$
for ( final Event.Fields field : Event.Fields.values () )
{
c.add ( field.getName () );
}
c.add ( Messages.custom_field );
c.select ( 0 );
return c;
}
private Combo createTypeCombo ()
{
final Combo c = new Combo ( this, SWT.NONE );
for ( final Type type : Type.values () )
{
c.add ( type.name () );
}
c.select ( 0 );
return c;
}
private Button createAddButton ()
{
final Button b = new Button ( this, SWT.PUSH );
b.setText ( Messages.add_assertion );
b.addSelectionListener ( new SelectionAdapter () {
@Override
public void widgetSelected ( final SelectionEvent e )
{
AddAssertionComposite.this.orCondition.addAssertion ();
}
} );
return b;
}
}
/**
*
* @author jrose
*/
private static class AssertionComposite extends Composite
{
// fields
private final OrCondition orCondition;
// widgets
private final Button notCheck;
private final Text attributeText;
private final Text valueText;
private final Combo assertionCombo;
public AssertionComposite ( final OrCondition orCondition, final Composite parent, final String attribute, final Type type )
{
// final fields
super ( parent, SWT.NONE );
this.orCondition = orCondition;
// widgets
this.notCheck = createNotCheck ();
this.attributeText = createAttributeText ( attribute );
createFieldTypeLabel ( type );
this.assertionCombo = createAssertionCombo ();
this.valueText = createValueText ();
createRemoveButton ();
// layout
final RowLayout layout = new RowLayout ();
layout.center = true;
this.setLayout ( layout );
parent.notifyListeners ( SWT.Resize, new org.eclipse.swt.widgets.Event () );
}
private Button createNotCheck ()
{
final Button b = new Button ( this, SWT.CHECK );
b.setText ( Messages.not );
b.addSelectionListener ( new SelectionAdapter () {
@Override
public void widgetSelected ( final SelectionEvent e )
{
AssertionComposite.this.orCondition.updateFilter ();
}
} );
return b;
}
private Text createAttributeText ( final String attribute )
{
final Text t = new Text ( this, SWT.BORDER );
final Fields field = Fields.byField ( attribute );
if ( field == null )
{
t.setEditable ( true );
t.setMessage ( Messages.custom_field );
}
else
{
t.setEditable ( false );
t.setText ( field.getName () );
}
t.addKeyListener ( new KeyAdapter () {
@Override
public void keyReleased ( final KeyEvent e )
{
AssertionComposite.this.orCondition.updateFilter ();
};
} );
final RowData rowData = new RowData ();
rowData.width = 132;
t.setLayoutData ( rowData );
return t;
}
private Label createFieldTypeLabel ( final Type type )
{
final Label l = new Label ( this, SWT.NONE );
l.setText ( type.name () );
return l;
}
private Combo createAssertionCombo ()
{
final Combo c = new Combo ( this, SWT.NONE );
for ( final Assertion assertion : Assertion.values () )
{
c.add ( assertion.toString () );
}
c.select ( 0 );
c.addSelectionListener ( new SelectionAdapter () {
@Override
public void widgetSelected ( final SelectionEvent e )
{
AssertionComposite.this.orCondition.updateFilter ();
}
} );
final RowData rowData = new RowData ();
rowData.width = 75;
c.setLayoutData ( rowData );
return c;
}
private Text createValueText ()
{
final Text t = new Text ( this, SWT.BORDER );
t.setMessage ( Messages.argument );
t.addKeyListener ( new KeyAdapter () {
@Override
public void keyReleased ( final KeyEvent e )
{
AssertionComposite.this.orCondition.updateFilter ();
}
} );
final RowData rowData = new RowData ();
rowData.width = 132;
t.setLayoutData ( rowData );
return t;
}
private Button createRemoveButton ()
{
final Button b = new Button ( this, SWT.PUSH );
b.setText ( Messages.remove );
b.addSelectionListener ( new SelectionAdapter () {
@Override
public void widgetSelected ( final SelectionEvent e )
{
AssertionComposite.this.orCondition.removeAssertion ( AssertionComposite.this );
}
} );
return b;
}
public Filter getExpression ()
{
final String attr = this.attributeText.getText ();
final String ass = this.assertionCombo.getText ();
final String val = this.valueText.getText ();
final FilterAssertion assertion = new FilterAssertion ( attr, Assertion.fromString ( ass ), val );
if ( val.contains ( "*" ) ) //$NON-NLS-1$
{
assertion.setAssertion ( Assertion.SUBSTRING );
assertion.setValue ( val.split ( "\\*" ) ); //$NON-NLS-1$
}
if ( this.notCheck.getSelection () )
{
return FilterExpression.negate ( assertion );
}
return assertion;
}
}
/**
* @author jrose
*
*/
private static class OrCondition
{
private final FilterAdvancedComposite filterAdvancedComposite;
private final CTabItem tabItem;
private final Composite tabContent;
private final List<AssertionComposite> assertionComposites = new ArrayList<AssertionComposite> ();
private final AddAssertionComposite addAssertionComposite;
private final ScrolledComposite assertionScrolledComposite;
private final Composite assertionComposite;
public OrCondition ( final FilterAdvancedComposite filterAdvancedComposite, final CTabFolder tabFolder )
{
// fields
this.filterAdvancedComposite = filterAdvancedComposite;
this.tabItem = new CTabItem ( tabFolder, SWT.NULL );
this.tabItem.setText ( Messages.a_condition );
this.tabContent = new Composite ( tabFolder, SWT.NONE );
this.tabItem.setControl ( this.tabContent );
// widgets
this.addAssertionComposite = new AddAssertionComposite ( this, this.tabContent );
this.assertionScrolledComposite = new ScrolledComposite ( this.tabContent, SWT.V_SCROLL | SWT.NONE );
this.assertionComposite = new Composite ( this.assertionScrolledComposite, SWT.NONE );
this.assertionScrolledComposite.setContent ( this.assertionComposite );
// layout
final GridLayout layout = new GridLayout ();
layout.marginLeft = 6;
layout.marginRight = 6;
layout.marginTop = 6;
layout.marginBottom = 6;
layout.verticalSpacing = 12;
this.tabContent.setLayout ( layout );
final GridData addAssertionCompositeLayoutData = new GridData ();
addAssertionCompositeLayoutData.grabExcessHorizontalSpace = true;
addAssertionCompositeLayoutData.horizontalAlignment = GridData.FILL;
this.addAssertionComposite.setLayoutData ( addAssertionCompositeLayoutData );
final GridData assertionCompositeLayoutData = new GridData ();
assertionCompositeLayoutData.grabExcessHorizontalSpace = true;
assertionCompositeLayoutData.horizontalAlignment = GridData.FILL;
assertionCompositeLayoutData.grabExcessVerticalSpace = true;
assertionCompositeLayoutData.verticalAlignment = GridData.FILL;
this.assertionScrolledComposite.setLayoutData ( assertionCompositeLayoutData );
this.assertionScrolledComposite.setExpandHorizontal ( true );
final RowLayout innerlayout = new RowLayout ( SWT.VERTICAL );
innerlayout.wrap = false;
this.assertionComposite.setLayout ( innerlayout );
this.assertionComposite.addListener ( SWT.Resize, new Listener () {
public void handleEvent ( final org.eclipse.swt.widgets.Event event )
{
final Point s = OrCondition.this.assertionComposite.computeSize ( SWT.DEFAULT, SWT.DEFAULT );
OrCondition.this.assertionComposite.setSize ( s.x, s.y );
refreshGUI ();
}
} );
}
private void refreshGUI ()
{
this.filterAdvancedComposite.refreshGUI ();
}
public void addAssertion ()
{
this.assertionComposites.add ( new AssertionComposite ( this, this.assertionComposite, this.addAssertionComposite.attributeCombo.getText (), Type.Text ) );
refreshGUI ();
updateFilter ();
}
public void removeAssertion ( final AssertionComposite assertion )
{
this.assertionComposites.remove ( assertion );
assertion.dispose ();
refreshGUI ();
if ( this.assertionComposites.size () == 0 )
{
this.tabItem.setText ( Messages.a_condition );
}
}
public FilterExpression getExpression ()
{
final FilterExpression expression = new FilterExpression ();
expression.setOperator ( Operator.AND );
for ( final AssertionComposite assertionComposite : this.assertionComposites )
{
expression.getFilterSet ().add ( assertionComposite.getExpression () );
}
return expression;
}
private void updateFilter ()
{
this.tabItem.setText ( getExpression ().toString ().replace ( "&", "&&" ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public FilterAdvancedComposite ( final FilterChangedListener filterChangedListener, final Composite parent, final int style )
{
// fields
super ( parent, style );
// widgets
this.tabFolder = new CTabFolder ( this, SWT.TOP | SWT.BORDER | SWT.CLOSE );
this.addOrConditionButton = creteAddOrConditionButton ();
addOrCondition ();
// layout
final GridLayout layout = new GridLayout ( 1, true );
layout.marginLeft = 6;
layout.marginRight = 6;
layout.marginTop = 6;
layout.marginBottom = 6;
layout.verticalSpacing = 12;
this.setLayout ( layout );
final GridData tabFolderLayoutData = new GridData ();
tabFolderLayoutData.horizontalAlignment = GridData.FILL;
tabFolderLayoutData.grabExcessHorizontalSpace = true;
tabFolderLayoutData.verticalAlignment = GridData.FILL;
tabFolderLayoutData.grabExcessVerticalSpace = true;
this.tabFolder.setLayoutData ( tabFolderLayoutData );
this.tabFolder.setBackgroundMode ( SWT.INHERIT_FORCE );
final GridData addOrConditionButtonLayoutdata = new GridData ();
addOrConditionButtonLayoutdata.horizontalAlignment = GridData.END;
this.addOrConditionButton.setLayoutData ( addOrConditionButtonLayoutdata );
}
private Button creteAddOrConditionButton ()
{
final Button b = new Button ( this, SWT.PUSH );
b.setText ( Messages.add_or_condition );
b.addSelectionListener ( new SelectionAdapter () {
@Override
public void widgetSelected ( final SelectionEvent e )
{
addOrCondition ();
}
} );
b.addDisposeListener ( new DisposeListener () {
public void widgetDisposed ( final DisposeEvent e )
{
final int i = FilterAdvancedComposite.this.tabFolder.getSelectionIndex ();
FilterAdvancedComposite.this.orConditions.remove ( i );
}
} );
return b;
}
private void addOrCondition ()
{
this.orConditions.add ( new OrCondition ( this, this.tabFolder ) );
this.tabFolder.setSelection ( this.tabFolder.getItemCount () - 1 );
refreshGUI ();
}
private void refreshGUI ()
{
this.layout ( true, true );
}
}