/*******************************************************************************
* Copyright (c) 2010 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
******************************************************************************/
package org.csstudio.swt.widgets.figures;
import org.csstudio.swt.widgets.util.GraphicsUtil;
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.swt.xygraph.util.XYGraphMediaFactory;
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 TankFigure extends AbstractLinearMarkedFigure {
private final Color WHITE_COLOR = XYGraphMediaFactory.getInstance().getColor(
XYGraphMediaFactory.COLOR_WHITE);
private final Color GRAY_COLOR = XYGraphMediaFactory.getInstance().getColor(
XYGraphMediaFactory.COLOR_GRAY);
private final Color BLUE_COLOR = XYGraphMediaFactory.getInstance().getColor(
XYGraphMediaFactory.COLOR_BLUE);
private boolean effect3D = true;
private Tank tank;
private Color fillColor= BLUE_COLOR;
private Color fillBackgroundColor= GRAY_COLOR;
public TankFigure() {
super();
((LinearScale) scale).setOrientation(Orientation.VERTICAL);
scale.setScaleLineVisible(false);
tank = new Tank();
setLayoutManager(new TankLayout());
add(scale, TankLayout.SCALE);
add(marker, TankLayout.MARKERS);
add(tank, TankLayout.TANK);
}
/**
* @return the fillBackgroundColor
*/
public Color getFillBackgroundColor() {
return fillBackgroundColor;
}
/**
* @return the fillColor
*/
public Color getFillColor() {
return fillColor;
}
/**
* @return the effect3D
*/
public boolean isEffect3D() {
return effect3D;
}
@Override
public boolean isOpaque() {
return false;
}
/**
* @param effect3D the effect3D to set
*/
public void setEffect3D(boolean effect3D) {
if(this.effect3D == effect3D)
return;
this.effect3D = effect3D;
repaint();
}
/**
* @param fillBackgroundColor the fillBackgroundColor to set
*/
public void setFillBackgroundColor(Color fillBackgroundColor) {
if(this.fillBackgroundColor != null && this.fillBackgroundColor.equals(fillBackgroundColor))
return;
this.fillBackgroundColor = fillBackgroundColor;
repaint();
}
/**
* @param fillColor the fillColor to set
*/
public void setFillColor(Color fillColor) {
if(this.fillColor != null && this.fillColor.equals(fillColor))
return;
this.fillColor = fillColor;
repaint();
}
@Override
public void setForegroundColor(Color fg) {
super.setForegroundColor(fg);
}
class Tank extends RoundedRectangle {
private final Color EFFECT3D_OUTLINE_COLOR = XYGraphMediaFactory.getInstance().getColor(
new RGB(160, 160, 160));
private static final int DEFAULT_CORNER = 15;
public Tank() {
super();
setOutline(true);
}
@Override
protected void fillShape(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(getCoercedValue(), false);
boolean support3D = GraphicsUtil.testPatternSupported(graphics);
// Pattern pattern = null;
// //just test if pattern is supported on the platform.
// try {
// graphics.pushState();
// pattern = new Pattern(Display.getCurrent(),
// 0, 0, 0, 0, fillBackgroundColor,WHITE_COLOR);
// graphics.setBackgroundPattern(pattern);
// } catch (Exception e) {
// support3D= false;
// if(pattern != null)
// pattern.dispose();
// }finally{
// graphics.popState();
// }
if(effect3D && support3D) {
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);
}
}
}
static 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
protected Dimension calculatePreferredSize(IFigure container, int w,
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(IFigure container) {
Rectangle area = container.getClientArea();
area.height-=1;
Dimension scaleSize = new Dimension(0, 0);
Dimension markerSize = new Dimension(0, 0);
if(scale != null) {
if(scale.isVisible()){
scaleSize = scale.getPreferredSize(-1, area.height);
scale.setBounds(new Rectangle(area.x, area.y,
scaleSize.width, scaleSize.height));
}else{
scaleSize = scale.getPreferredSize(-1, area.height+2*scale.getMargin());
scale.setBounds(new Rectangle(area.x, area.y-scale.getMargin(),
scaleSize.width, scaleSize.height));
scaleSize.height=0;
scaleSize.width=0;
}
}
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),
area.width - scaleSize.width - markerSize.width,
scale.getTickLength()+ tank.getLineWidth()));
}
}
@Override
public void setConstraint(IFigure child, 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;
}
}
}