/*
* Copyright (c) 2008 Stiftung Deutsches Elektronen-Synchrotron,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.sds.components.ui.internal.figures;
import java.util.HashMap;
import org.csstudio.sds.components.common.CosySwitch;
import org.csstudio.sds.components.common.SwitchPlugins;
import org.csstudio.sds.components.ui.internal.utils.Trigonometry;
import org.csstudio.sds.ui.figures.BorderAdapter;
import org.csstudio.sds.ui.figures.CrossedOutAdapter;
import org.csstudio.sds.ui.figures.IBorderEquippedWidget;
import org.csstudio.sds.ui.figures.ICrossedFigure;
import org.csstudio.sds.ui.figures.IRhombusEquippedWidget;
import org.csstudio.sds.ui.figures.RhombusAdapter;
import org.csstudio.sds.util.AntialiasingUtil;
import org.csstudio.ui.util.CustomMediaFactory;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A switch figure.
*
* @author jbercic
*
*/
public final class RefreshableSwitchFigure extends Shape implements IAdaptable {
private static final Logger LOG = LoggerFactory.getLogger(RefreshableSwitchFigure.class);
/**
* A border adapter, which covers all border handlings.
*/
private IBorderEquippedWidget _borderAdapter;
/**
* Colors for the defined states.
*/
public static final HashMap<Integer,Color> STATECOLORS;
/**
* static initializer for the color array.
*/
static {
STATECOLORS=new HashMap<Integer,Color>();
/*these colors were taken from the switch adl files*/
STATECOLORS.put(CosySwitch.STATE_AUS,CustomMediaFactory.getInstance().getColor(new RGB(253,0,0)));
STATECOLORS.put(CosySwitch.STATE_EIN,CustomMediaFactory.getInstance().getColor(new RGB(0,216,0)));
STATECOLORS.put(CosySwitch.STATE_GESTOERT,CustomMediaFactory.getInstance().getColor(new RGB(251,243,74)));
STATECOLORS.put(CosySwitch.STATE_SCHALTET,CustomMediaFactory.getInstance().getColor(new RGB(158,158,158)));
}
/**
* Current state of the switch.
*/
private int _switchState=CosySwitch.STATE_AUS;
/**
* The current drawing class.
*/
private CosySwitch _switchPainter = new CosySwitch();
/**
* The current switch type.
*/
private int _switchType=0;
/**
* The rotation (in degrees, use to change horizontal/vertical or any other angle).
*/
private int _rotAngle=0;
/**
* The scaling coefficient (needed because only by rotating, the switch could go out of bounds).
*/
private double _scaling = 1.0;
/**
* True if the switch was resized after last paint event.
*/
private boolean _resized=true;
private boolean _transparent = true;
private CrossedOutAdapter _crossedOutAdapter;
private RhombusAdapter _rhombusAdapter;
public RefreshableSwitchFigure() {
}
/**
* Fills the background.
* @param gfx The {@link Graphics} to use
*/
@Override
protected void fillShape(final Graphics gfx) {
if (!_transparent) {
gfx.setBackgroundColor(getBackgroundColor());
Rectangle figureBounds = getBounds().getCopy();
figureBounds.crop(this.getInsets());
gfx.fillRectangle(figureBounds);
}
_crossedOutAdapter.paint(gfx);
_rhombusAdapter.paint(gfx);
}
/**
* {@inheritDoc}
*/
@Override
public void paintFigure(final Graphics graphics) {
this.fillShape(graphics);
this.outlineShape(graphics);
}
/**
* Draws the outline of the image, i.e. the switch itself.
* @param gfx The {@link Graphics} to use
*/
@Override
protected void outlineShape(final Graphics gfx) {
AntialiasingUtil.getInstance().enableAntialiasing(gfx);
Rectangle figureBounds = getBounds().getCopy().crop(this.getInsets());
gfx.translate(figureBounds.getLocation());
gfx.translate(figureBounds.width/2,figureBounds.height/2);
int scalingDegreeOffset = 90;
if ((_rotAngle >= 90 && _rotAngle < 180) || (_rotAngle >= 270 && _rotAngle < 360)) {
int tmpWidth = figureBounds.width;
figureBounds.width = figureBounds.height;
figureBounds.height = tmpWidth;
scalingDegreeOffset = 0;
}
if (_resized) {
/*some trigonometry to determine the new scaling factor*/
double longSide = (figureBounds.width<figureBounds.height)?(double)figureBounds.width:(double)figureBounds.height;
double shortSide = (figureBounds.width<figureBounds.height)?(double)figureBounds.height:(double)figureBounds.width;
_scaling=longSide / (longSide * Trigonometry.sin(-_rotAngle + scalingDegreeOffset) + shortSide * Trigonometry.cos(-_rotAngle + scalingDegreeOffset));
_scaling=Math.abs(_scaling);
_resized=false;
}
try {
gfx.rotate(_rotAngle);
} catch (RuntimeException e) {
LOG.error("Error occured during ratation");
}
gfx.translate(-(int)(_scaling*figureBounds.width*0.5),-(int)(_scaling*figureBounds.height*0.5));
if (_switchState==CosySwitch.STATE_UNKNOWN) {
gfx.setForegroundColor(getForegroundColor());
} else {
gfx.setForegroundColor(STATECOLORS.get(_switchState));
}
gfx.setBackgroundColor(gfx.getForegroundColor());
gfx.setLineWidth(getLineWidth());
_switchPainter.paintSwitch(gfx,_switchState, (int)(_scaling*figureBounds.width),(int)(_scaling*figureBounds.height));
if (_rotAngle!=0) {
gfx.translate((int)(_scaling*figureBounds.width*0.5),(int)(_scaling*figureBounds.height*0.5));
try {
gfx.rotate(-(float)_rotAngle);
} catch (RuntimeException e) {
LOG.error("Error occured during rotation");
}
gfx.translate(-figureBounds.width/2,-figureBounds.height/2);
}
}
/**
* Resizes this switch.
*/
public void resize() {
_resized=true;
}
/**
* Sets the type of the switch.
* @param newval The new type of the switch
*/
public void setType(final int newval) {
try {
_switchPainter=(CosySwitch)SwitchPlugins.classes_map.get(SwitchPlugins.ids[newval]).createExecutableExtension("Class");
} catch (Exception e) {
_switchPainter=new CosySwitch();
}
_switchType=newval;
}
/**
* Returns the current type of the switch.
* @return the current type
*/
public int getType() {
return _switchType;
}
/**
* Sets, if this widget should have a transparent background.
* @param transparent
* The new value for the transparent property
*/
public void setTransparent(final boolean transparent) {
_transparent = transparent;
}
/**
* {@inheritDoc}
*/
@Override
public void setLineWidth(final int w) {
super.setLineWidth(w);
_switchPainter.setLineWidth(w);
}
/**
* Sets the state of the switch.
* @param newval The new state of the switch
*/
public void setState(final int newval) {
if (!STATECOLORS.containsKey(newval)) {
_switchState=CosySwitch.STATE_UNKNOWN;
return;
}
_switchState=newval;
}
/**
* Returns the current state of the switch.
* @return the current state
*/
public int getState() {
return _switchState;
}
/**
* Sets the rotation angle of the switch.
* @param newval the rotation angle
*/
public void setRotation(final int newval) {
_rotAngle=newval;
_resized=true;
}
/**
* Returns the current rotation angle.
* @return the current rotation angle
*/
public int getRotation() {
return _rotAngle;
}
/**
* {@inheritDoc}
*/
@Override
public Object getAdapter(final Class adapter) {
if (adapter == IBorderEquippedWidget.class) {
if (_borderAdapter == null) {
_borderAdapter = new BorderAdapter(this);
}
return _borderAdapter;
} else if(adapter == ICrossedFigure.class) {
if(_crossedOutAdapter==null) {
_crossedOutAdapter = new CrossedOutAdapter(this);
}
return _crossedOutAdapter;
} else if(adapter == IRhombusEquippedWidget.class) {
if(_rhombusAdapter==null) {
_rhombusAdapter = new RhombusAdapter(this);
}
return _rhombusAdapter;
}
return null;
}
}