package org.csstudio.sds.components.ui.internal.figures;
import org.csstudio.swt.xygraph.linearscale.LinearScale;
import org.csstudio.swt.xygraph.linearscale.LinearScale.Orientation;
import org.csstudio.swt.xygraph.linearscale.LinearScaledMarker;
import org.csstudio.ui.util.CustomMediaFactory;
import org.eclipse.draw2d.AbstractLayout;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.RoundedRectangle;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Pattern;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
/**
* A tank figure
*
* @author Xihui Chen
*
*/
public class RefreshableTankFigure extends AbstractLinearMarkedFigure {
private Color fillColor;
private Color fillBackgroundColor;
private Color outlineColor;
private final static Color WHITE_COLOR = CustomMediaFactory.getInstance()
.getColor(CustomMediaFactory.COLOR_WHITE);
private boolean effect3D = true;
private final Tank tank;
public RefreshableTankFigure() {
super();
((LinearScale) scale).setOrientation(Orientation.VERTICAL);
scale.setScaleLineVisible(false);
scale.setForegroundColor(outlineColor);
tank = new Tank();
setLayoutManager(new TankLayout());
add(scale, TankLayout.SCALE);
add(marker, TankLayout.MARKERS);
add(tank, TankLayout.TANK);
}
@Override
public void paint(final Graphics graphics) {
super.paint(graphics);
Rectangle figureBounds = getBounds().getCopy();
paintAdapter(graphics);
}
@Override
public boolean isOpaque() {
return false;
}
@Override
public void setForegroundColor(final Color fg) {
super.setForegroundColor(fg);
outlineColor = fg;
}
public void setFillColor(final Color fillColor) {
this.fillColor = fillColor;
}
public void setFillBackgroundColor(final Color fillBackgroundColor) {
this.fillBackgroundColor = fillBackgroundColor;
}
/**
* @param effect3D
* the effect3D to set
*/
public void setEffect3D(final boolean effect3D) {
this.effect3D = effect3D;
}
class Tank extends RoundedRectangle {
private final Color EFFECT3D_OUTLINE_COLOR = CustomMediaFactory.getInstance()
.getColor(new RGB(160, 160, 160));
private static final int DEFAULT_CORNER = 15;
public Tank() {
super();
setOutline(true);
}
@Override
protected void fillShape(final Graphics graphics) {
int fill_corner = DEFAULT_CORNER;
// If this is more close to 1/2, more light the tank will be.
double intersectFactor = 11d / 20d;
if (bounds.width < 2 * DEFAULT_CORNER) {
intersectFactor = 12d / 20d;
}
int rectWidth = (int) (bounds.width * intersectFactor);
if (fill_corner > (2 * rectWidth - (bounds.width - 2 * getLineWidth()))) {
fill_corner = 2 * rectWidth - bounds.width;
}
corner.height = fill_corner;
corner.width = fill_corner;
graphics.setAntialias(SWT.ON);
int valuePosition = ((LinearScale) scale).getValuePosition(value, false);
if (effect3D) {
graphics.setBackgroundColor(WHITE_COLOR);
super.fillShape(graphics);
// fill background
Rectangle leftRectangle = new Rectangle(bounds.x,
bounds.y,
rectWidth,
bounds.height);
Pattern leftGradientPattern = new Pattern(Display.getCurrent(),
leftRectangle.x,
leftRectangle.y,
leftRectangle.x + leftRectangle.width,
leftRectangle.y,
fillBackgroundColor,
255,
WHITE_COLOR,
0);
graphics.setBackgroundPattern(leftGradientPattern);
graphics.fillRoundRectangle(leftRectangle, corner.width, corner.height);
Rectangle rightRectangle = new Rectangle(bounds.x + bounds.width - rectWidth,
bounds.y,
rectWidth,
bounds.height);
Pattern rightGradientPattern = new Pattern(Display.getCurrent(),
rightRectangle.x,
rightRectangle.y,
rightRectangle.x + rightRectangle.width,
rightRectangle.y,
WHITE_COLOR,
0,
fillBackgroundColor,
255);
graphics.setBackgroundPattern(rightGradientPattern);
graphics.fillRoundRectangle(rightRectangle, corner.width, corner.height);
leftGradientPattern.dispose();
rightGradientPattern.dispose();
// fill value
graphics.setBackgroundColor(WHITE_COLOR);
int fillHeight = bounds.height - (valuePosition - bounds.y) - getLineWidth();
graphics.fillRoundRectangle(new Rectangle(bounds.x,
valuePosition,
bounds.width,
fillHeight), fill_corner, fill_corner);
leftRectangle = new Rectangle(bounds.x, valuePosition, rectWidth, fillHeight);
leftGradientPattern = new Pattern(Display.getCurrent(),
leftRectangle.x,
leftRectangle.y,
leftRectangle.x + leftRectangle.width,
leftRectangle.y,
fillColor,
255,
WHITE_COLOR,
0);
graphics.setBackgroundPattern(leftGradientPattern);
graphics.fillRoundRectangle(leftRectangle, fill_corner, fill_corner);
rightRectangle = new Rectangle(bounds.x + bounds.width - rectWidth,
valuePosition,
rectWidth,
fillHeight);
rightGradientPattern = new Pattern(Display.getCurrent(),
rightRectangle.x,
rightRectangle.y,
rightRectangle.x + rightRectangle.width,
rightRectangle.y,
WHITE_COLOR,
0,
fillColor,
255);
graphics.setBackgroundPattern(rightGradientPattern);
graphics.fillRoundRectangle(rightRectangle, fill_corner, fill_corner);
leftGradientPattern.dispose();
rightGradientPattern.dispose();
graphics.setForegroundColor(EFFECT3D_OUTLINE_COLOR);
} else {
graphics.setBackgroundColor(fillBackgroundColor);
super.fillShape(graphics);
graphics.setBackgroundColor(fillColor);
graphics.fillRoundRectangle(new Rectangle(bounds.x + lineWidth,
valuePosition,
bounds.width - 2 * lineWidth,
bounds.height
- (valuePosition - bounds.y)),
fill_corner,
fill_corner);
graphics.setForegroundColor(outlineColor);
}
}
}
class TankLayout extends AbstractLayout {
/** Used as a constraint for the scale. */
public static final String SCALE = "scale"; //$NON-NLS-1$
/** Used as a constraint for the pipe indicator. */
public static final String TANK = "tank"; //$NON-NLS-1$
/** Used as a constraint for the alarm ticks */
public static final String MARKERS = "markers"; //$NON-NLS-1$
private LinearScale scale;
private LinearScaledMarker marker;
private Tank tank;
@Override
public void setConstraint(final IFigure child, final Object constraint) {
if (constraint.equals(SCALE)) {
scale = (LinearScale) child;
} else if (constraint.equals(MARKERS)) {
marker = (LinearScaledMarker) child;
} else if (constraint.equals(TANK)) {
tank = (Tank) child;
}
}
@Override
protected Dimension calculatePreferredSize(final IFigure container, final int w, final int h) {
Insets insets = container.getInsets();
Dimension d = new Dimension(64, 4 * 64);
d.expand(insets.getWidth(), insets.getHeight());
return d;
}
@Override
public void layout(final IFigure container) {
Rectangle area = container.getClientArea();
Dimension scaleSize = new Dimension(0, 0);
Dimension markerSize = new Dimension(0, 0);
if (scale != null) {
scaleSize = scale.getPreferredSize(-1, area.height);
scale.setBounds(new Rectangle(area.x, area.y, scaleSize.width, scaleSize.height));
}
if ((marker != null) && marker.isVisible()) {
markerSize = marker.getPreferredSize();
marker.setBounds(new Rectangle(area.x + area.width - markerSize.width, marker
.getScale().getBounds().y, markerSize.width, markerSize.height));
}
if (tank != null) {
tank.setBounds(new Rectangle(area.x + scaleSize.width,
scale.getValuePosition(scale.getRange().getUpper(),
false)
- tank.getLineWidth(),
area.width - scaleSize.width - markerSize.width,
scale.getTickLength() + 2 * tank.getLineWidth()));
}
}
}
}