/*
* This file is part of the OpenSCADA project
* Copyright (C) 2006-2011 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.dataitem.details.extra.part;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.draw2d.BendpointConnectionRouter;
import org.eclipse.draw2d.BorderLayout;
import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionLayer;
import org.eclipse.draw2d.ConnectionRouter;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.GridData;
import org.eclipse.draw2d.GridLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.Layer;
import org.eclipse.draw2d.LayeredPane;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.Triangle;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.jface.resource.ColorDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.statushandlers.StatusManager;
import org.openscada.core.Variant;
import org.openscada.core.ui.styles.Style;
import org.openscada.core.ui.styles.StyleInformation;
import org.openscada.da.client.dataitem.details.extra.Activator;
import org.openscada.ui.utils.blink.Blinker;
import org.openscada.ui.utils.blink.Blinker.Handler;
import org.openscada.ui.utils.blink.Blinker.State;
public abstract class GenericLevelPresets extends AbstractBaseDraw2DDetailsPart
{
private final class HandlerImplementation implements Handler
{
private final Shape tri;
public HandlerImplementation ( final Shape tri )
{
this.tri = tri;
}
@Override
public void setState ( final State state )
{
blink ( this.tri, state );
}
}
private static final String TAG_FLOOR = "floor"; //$NON-NLS-1$
private static final String TAG_LL = "lowlow"; //$NON-NLS-1$
private static final String TAG_L = "low"; //$NON-NLS-1$
private static final String TAG_H = "high"; //$NON-NLS-1$
private static final String TAG_HH = "highhigh"; //$NON-NLS-1$
private static final String TAG_CEIL = "ceil"; //$NON-NLS-1$
private Triangle triHH;
private Triangle triH;
private Triangle triL;
private Triangle triLL;
private Label presetHH;
private Label presetH;
private Label presetL;
private Label presetLL;
private Label currentLabel;
private RectangleFigure rectCeil;
private RectangleFigure rectFloor;
private Label presetCeil;
private Label presetFloor;
private Blinker blinkerHH;
private Blinker blinkerCeil;
private Blinker blinkerH;
private Blinker blinkerL;
private Blinker blinkerLL;
private Blinker blinkerFloor;
private static final Dimension TRI_DIMENSION = new Dimension ( 50, 50 );
@Override
protected IFigure createMain ()
{
final Figure baseFigure = new LayeredPane ();
final Layer rootFigure = new Layer ();
this.connLayer = new ConnectionLayer ();
this.connLayer.setAntialias ( 1 );
this.connLayer.setConnectionRouter ( ConnectionRouter.NULL );
baseFigure.add ( this.connLayer );
baseFigure.add ( rootFigure );
rootFigure.setLayoutManager ( new BorderLayout () );
rootFigure.setBackgroundColor ( ColorConstants.white );
rootFigure.add ( createArrowFigure (), BorderLayout.RIGHT );
rootFigure.add ( createEntryGrid ( this.connLayer ), BorderLayout.CENTER );
return baseFigure;
}
private IFigure createEntryGrid ( final Figure connLayer )
{
final Figure figure = new Figure ();
figure.setLayoutManager ( new GridLayout ( 1, false ) );
figure.add ( this.presetCeil = new Label ( Messages.LevelPresets_InitialLabel ), new GridData ( GridData.CENTER, GridData.FILL, true, true ) );
figure.add ( this.presetHH = new Label ( Messages.LevelPresets_InitialLabel ), new GridData ( GridData.CENTER, GridData.FILL, true, true ) );
figure.add ( this.presetH = new Label ( Messages.LevelPresets_InitialLabel ), new GridData ( GridData.CENTER, GridData.FILL, true, true ) );
figure.add ( this.currentLabel = new Label ( Messages.LevelPresets_InitialLabel ), new GridData ( GridData.CENTER, GridData.FILL, true, true ) );
figure.add ( this.presetL = new Label ( Messages.LevelPresets_InitialLabel ), new GridData ( GridData.CENTER, GridData.FILL, true, true ) );
figure.add ( this.presetLL = new Label ( Messages.LevelPresets_InitialLabel ), new GridData ( GridData.CENTER, GridData.FILL, true, true ) );
figure.add ( this.presetFloor = new Label ( Messages.LevelPresets_InitialLabel ), new GridData ( GridData.CENTER, GridData.FILL, true, true ) );
createConnection ( connLayer, this.presetCeil, this.rectCeil );
createConnection ( connLayer, this.presetHH, this.triHH );
createConnection ( connLayer, this.presetH, this.triH );
createConnection ( connLayer, this.presetL, this.triL );
createConnection ( connLayer, this.presetLL, this.triLL );
createConnection ( connLayer, this.presetFloor, this.rectFloor );
this.blinkerCeil = new Blinker ( new HandlerImplementation ( this.rectCeil ) );
this.blinkerHH = new Blinker ( new HandlerImplementation ( this.triHH ) );
this.blinkerH = new Blinker ( new HandlerImplementation ( this.triH ) );
this.blinkerL = new Blinker ( new HandlerImplementation ( this.triL ) );
this.blinkerLL = new Blinker ( new HandlerImplementation ( this.triLL ) );
this.blinkerFloor = new Blinker ( new HandlerImplementation ( this.rectFloor ) );
return figure;
}
protected void blink ( final Shape shape, final State state )
{
final StyleInformation style;
switch ( state )
{
case DISCONNECTED:
case ERROR:
style = org.openscada.core.ui.styles.Activator.getStyle ( Style.ERROR );
break;
case ALARM:
style = org.openscada.core.ui.styles.Activator.getStyle ( Style.ALARM );
break;
case ALARM_1:
style = org.openscada.core.ui.styles.Activator.getStyle ( Style.ALARM );
break;
case OK:
case ALARM_0:
default:
style = new StyleInformation ( null, ColorDescriptor.createFrom ( ColorConstants.lightGray ), null );
break;
}
shape.setForegroundColor ( style.createForeground ( Activator.getResources () ) );
shape.setBackgroundColor ( style.createBackground ( Activator.getResources () ) );
shape.setFont ( style.createFont ( Activator.getResources () ) );
}
private void createConnection ( final Figure connLayer, final Label label, final Figure figure )
{
final Connection c = new PolylineConnection ();
c.setSourceAnchor ( new ChopboxAnchor ( label ) );
c.setTargetAnchor ( new ChopboxAnchor ( figure ) );
c.setConnectionRouter ( new BendpointConnectionRouter () );
connLayer.add ( c );
}
@Override
public void dispose ()
{
this.blinkerHH.dispose ();
this.blinkerH.dispose ();
this.blinkerLL.dispose ();
this.blinkerL.dispose ();
this.blinkerCeil.dispose ();
this.blinkerFloor.dispose ();
super.dispose ();
}
private static final Dimension RECT_DIMENSION = new Dimension ( 50, 15 );
private ConnectionLayer connLayer;
public GenericLevelPresets ()
{
super ();
}
private IFigure createArrowFigure ()
{
final Figure figure = new Figure ();
final Figure innerFigure = new Figure ();
final Figure outerFigure = new Figure ();
outerFigure.setLayoutManager ( new BorderLayout () );
figure.setLayoutManager ( new BorderLayout () );
innerFigure.setLayoutManager ( new BorderLayout () );
RectangleFigure rect;
// create ceil
this.rectCeil = rect = new RectangleFigure ();
rect.setBackgroundColor ( ColorConstants.black );
rect.setSize ( RECT_DIMENSION );
rect.setLineWidth ( 3 );
rect.setCursor ( Display.getDefault ().getSystemCursor ( SWT.CURSOR_HAND ) );
outerFigure.add ( rect, BorderLayout.TOP );
activate ( TAG_CEIL, rect );
// create HH
this.triHH = createTri ( figure, TAG_HH, BorderLayout.TOP, PositionConstants.NORTH );
this.triH = createTri ( innerFigure, TAG_H, BorderLayout.TOP, PositionConstants.NORTH );
this.triL = createTri ( innerFigure, TAG_L, BorderLayout.BOTTOM, PositionConstants.SOUTH );
this.triLL = createTri ( figure, TAG_LL, BorderLayout.BOTTOM, PositionConstants.SOUTH );
// create floor
this.rectFloor = rect = new RectangleFigure ();
rect.setBackgroundColor ( ColorConstants.black );
rect.setSize ( RECT_DIMENSION );
rect.setLineWidth ( 3 );
rect.setCursor ( Display.getDefault ().getSystemCursor ( SWT.CURSOR_HAND ) );
outerFigure.add ( rect, BorderLayout.BOTTOM );
activate ( TAG_FLOOR, rect );
figure.add ( innerFigure, BorderLayout.CENTER );
outerFigure.add ( figure, BorderLayout.CENTER );
// create inner
final PolylineConnection c;
c = new PolylineConnection ();
c.setSourceAnchor ( new ChopboxAnchor ( this.triH ) );
c.setTargetAnchor ( new ChopboxAnchor ( this.triL ) );
c.setLineWidth ( 5 );
innerFigure.add ( c );
return outerFigure;
}
private Triangle createTri ( final Figure figure, final String tag, final Object constraint, final int direction )
{
final Triangle tri;
tri = new Triangle ();
tri.setDirection ( direction );
tri.setBackgroundColor ( ColorConstants.black );
tri.setSize ( TRI_DIMENSION );
tri.setLineWidth ( 3 );
tri.setCursor ( Display.getDefault ().getSystemCursor ( SWT.CURSOR_HAND ) );
figure.add ( tri, constraint );
activate ( tag, tri );
return tri;
}
private void activate ( final String tag, final Shape shape )
{
shape.addMouseListener ( new MouseListener.Stub () {
@Override
public void mouseReleased ( final MouseEvent me )
{
GenericLevelPresets.this.triggerAction ( tag );
}
} );
}
protected void toggle ( final String tag )
{
setActive ( !isActive ( tag ), tag );
}
protected void triggerAction ( final String string )
{
try
{
Variant value = Variant.valueOf ( getPreset ( string ) );
if ( !value.isNull () )
{
value = new VariantEntryDialog ( this.shell, value ).getValue ();
}
else
{
value = new VariantEntryDialog ( this.shell ).getValue ();
}
if ( value != null )
{
setPreset ( value, string );
setActive ( !value.isNull (), string );
}
}
catch ( final Throwable e )
{
StatusManager.getManager ().handle ( new Status ( IStatus.ERROR, Activator.PLUGIN_ID, Messages.GenericLevelPresets_ErrorMessage_Dialog, e ) );
}
}
@Override
protected void update ()
{
super.update ();
if ( this.value == null )
{
return;
}
setTri ( this.rectCeil, TAG_CEIL );
setTri ( this.triHH, TAG_HH );
setTri ( this.triH, TAG_H );
setTri ( this.triL, TAG_L );
setTri ( this.triLL, TAG_LL );
setTri ( this.rectFloor, TAG_FLOOR );
setBlinker ( this.blinkerCeil, TAG_CEIL );
setBlinker ( this.blinkerHH, TAG_HH );
setBlinker ( this.blinkerH, TAG_H );
setBlinker ( this.blinkerL, TAG_L );
setBlinker ( this.blinkerLL, TAG_LL );
setBlinker ( this.blinkerFloor, TAG_FLOOR );
setLabel ( this.presetCeil, TAG_CEIL );
setLabel ( this.presetHH, TAG_HH );
setLabel ( this.presetH, TAG_H );
setLabel ( this.presetL, TAG_L );
setLabel ( this.presetLL, TAG_LL );
setLabel ( this.presetFloor, TAG_FLOOR );
this.currentLabel.setText ( "" + this.value.getValue () ); //$NON-NLS-1$
}
private void setBlinker ( final Blinker blinker, final String tag )
{
blinker.setState ( isAlarm ( tag ), isAckRequired ( tag ), false, isUnsafe ( tag ), isError ( tag ), false );
}
private void setLabel ( final Label preset, final String string )
{
final Number num = getPreset ( string );
if ( num != null )
{
preset.setText ( String.format ( Messages.LevelPresets_NumFormat, num.toString () ) );
}
else
{
preset.setText ( Messages.LevelPresets_EmtyNum );
}
}
private void setTri ( final Shape tri, final String string )
{
tri.setOutline ( isActive ( string ) );
}
protected abstract void setPreset ( final Variant value, final String string );
protected abstract void setActive ( final boolean state, final String tag );
protected abstract boolean isError ( final String string );
protected abstract boolean isAlarm ( final String string );
protected abstract boolean isAckRequired ( final String string );
protected abstract Number getPreset ( final String string );
protected abstract boolean isActive ( final String string );
protected abstract boolean isUnsafe ( final String string );
}