/******************************************************************************* * 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.eclipse.nebula.visualization.widgets.figures; import java.beans.BeanInfo; import java.beans.IntrospectionException; import org.eclipse.draw2d.AbstractLayout; import org.eclipse.draw2d.FigureListener; import org.eclipse.draw2d.FigureUtilities; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.Polygon; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Insets; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PointList; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.nebula.visualization.internal.widgets.introspection.MeterIntrospector; import org.eclipse.nebula.visualization.widgets.figureparts.RoundScale; import org.eclipse.nebula.visualization.widgets.figureparts.RoundScaledRamp; import org.eclipse.nebula.visualization.widgets.util.PointsUtil; import org.eclipse.nebula.visualization.xygraph.util.XYGraphMediaFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; /** * The figure of Express Meter * @author Xihui Chen * */ public class MeterFigure extends AbstractRoundRampedFigure { private final static Font DEFAULT_LABEL_FONT = XYGraphMediaFactory.getInstance().getFont( new FontData("Arial", 12, SWT.BOLD)); // private Ellipse needleCenter; private Needle needle; private Label valueLabel; private final static double SPACE_ANGLE = 45; public static final int NEEDLE_WIDTH = 16; public final static double ALPHA = SPACE_ANGLE * Math.PI/180; public final static double HW_RATIO = (1- Math.sin(ALPHA)/2)/(2*Math.cos(ALPHA)); public MeterFigure() { super(); //TODO, remove this if clip is supported by RAP if(SWT.getPlatform().startsWith("rap"))//$NON-NLS-1$ ramp.setVisible(false); setTransparent(false); scale.setScaleLineVisible(false); ((RoundScale)scale).setStartAngle(180-SPACE_ANGLE); ((RoundScale)scale).setEndAngle(SPACE_ANGLE); ramp.setRampWidth(12); setLoColor(XYGraphMediaFactory.getInstance().getColor(XYGraphMediaFactory.COLOR_YELLOW)); setHiColor(XYGraphMediaFactory.getInstance().getColor(XYGraphMediaFactory.COLOR_YELLOW)); valueLabel = new Label(); valueLabel.setFont(DEFAULT_LABEL_FONT); needle = new Needle(); needle.setFill(true); needle.setOutline(false); // needleCenter = new Ellipse(); // needleCenter.setOutline(false); setLayoutManager(new XMeterLayout()); add(ramp, XMeterLayout.RAMP); add(scale, XMeterLayout.SCALE); add(needle, XMeterLayout.NEEDLE); // add(needleCenter, XMeterLayout.NEEDLE_CENTER); add(valueLabel, XMeterLayout.VALUE_LABEL); addFigureListener(new FigureListener() { public void figureMoved(IFigure source) { ramp.setDirty(true); revalidate(); } }); } @Override public void setBounds(Rectangle rect) { super.setBounds(rect); } @Override public void setShowMarkers(boolean showMarkers) { super.setShowMarkers(showMarkers); //TODO: this should be removed if RAP supports clip if(SWT.getPlatform().startsWith("rap"))//$NON-NLS-1$ ramp.setVisible(false); else ramp.setVisible(showMarkers); } @Override public void setValue(double value) { super.setValue(value); valueLabel.setText(getValueText()); } public void setValueLabelVisibility(boolean visible) { valueLabel.setVisible(visible); } /** * @param needleColor the needleColor to set */ public void setNeedleColor(Color needleColor) { needle.setBackgroundColor(needleColor); } /** * @return color of the needle. */ public Color getNeedleColor(){ return needle.getBackgroundColor(); } @Override public BeanInfo getBeanInfo() throws IntrospectionException { return new MeterIntrospector().getBeanInfo(this.getClass()); } static class Needle extends Polygon { public Needle() { setBackgroundColor(XYGraphMediaFactory.getInstance().getColor( XYGraphMediaFactory.COLOR_RED)); } @Override protected void fillShape(Graphics g) { g.setAntialias(SWT.ON); super.fillShape(g); } } class XMeterLayout extends AbstractLayout { private static final int GAP_BTW_NEEDLE_SCALE = -5; int M = 0; /** Used as a constraint for the scale. */ public static final String SCALE = "scale"; //$NON-NLS-1$ /** Used as a constraint for the Needle. */ public static final String NEEDLE = "needle"; //$NON-NLS-1$ /** Used as a constraint for the Ramp */ public static final String RAMP = "ramp"; //$NON-NLS-1$ /** Used as a constraint for the needleCenter */ //public static final String NEEDLE_CENTER = "needleCenter"; //$NON-NLS-1$ /** Used as a constraint for the value label*/ public static final String VALUE_LABEL = "valueLabel"; //$NON-NLS-1$ private RoundScale scale; private RoundScaledRamp ramp; private Polygon needle; // private Ellipse needleCenter; private Label valueLabel; private PointList needlePoints = new PointList(new int[] {0,0,0,0,0,0}); @Override public void setConstraint(IFigure child, Object constraint) { if(constraint.equals(SCALE)) scale = (RoundScale)child; else if (constraint.equals(RAMP)) ramp = (RoundScaledRamp) child; else if (constraint.equals(NEEDLE)) needle = (Polygon) child; // else if (constraint.equals(NEEDLE_CENTER)) // needleCenter = (Ellipse) child; else if (constraint.equals(VALUE_LABEL)) valueLabel = (Label)child; } @Override protected Dimension calculatePreferredSize(IFigure container, int w, int h) { Insets insets = container.getInsets(); Dimension d = new Dimension(256, 256); d.expand(insets.getWidth(), insets.getHeight()); return d; } public void layout(IFigure container) { Rectangle area = container.getClientArea(); // calculate a virtual area if(scale != null && scale.isDirty()) M = Math.max(FigureUtilities.getTextWidth( scale.format(scale.getRange().getLower()), scale.getFont()), FigureUtilities.getTextWidth( scale.format(scale.getRange().getUpper()), scale.getFont()))/2; int h = area.height; int w = area.width; if(h > HW_RATIO * (w - 2*M)) h = (int) (HW_RATIO * (w - 2*M)); //else if (w > h/HW_RATIO + 2*M) // w = (int) (h/HW_RATIO + 2*M); double r = h/(1- Math.sin(ALPHA)/2); int x = (int) (area.x - r * (1.0 - Math.cos(ALPHA)) + M); int y = area.y; area = new Rectangle(x, y, (int)(2*r), (int)(2*r)); Point center = area.getCenter(); if(scale != null) { scale.setBounds(area); } if(ramp != null && ramp.isVisible()) { Rectangle rampBounds = area.getCopy(); ramp.setBounds(rampBounds.shrink(area.width/4 -ramp.getRampWidth(), area.height/4 - ramp.getRampWidth())); } if(valueLabel != null) { Dimension labelSize = valueLabel.getPreferredSize(); valueLabel.setBounds(new Rectangle(area.x + area.width/2 - labelSize.width/2, area.y + area.height/2 - area.height/4 -(scale.getInnerRadius() - area.height/4)/2 - labelSize.height/2, labelSize.width, labelSize.height)); } if(needle != null && scale != null) { needlePoints.setPoint ( new Point(center.x + area.width/4, center.y - NEEDLE_WIDTH/2 + 3), 0); scale.getScaleTickMarks(); needlePoints.setPoint( new Point(center.x + scale.getInnerRadius() - GAP_BTW_NEEDLE_SCALE, center.y), 1); needlePoints.setPoint( new Point(center.x + area.width/4, center.y + NEEDLE_WIDTH/2 - 3), 2); double valuePosition = 360 - scale.getValuePosition(getCoercedValue(), false); if(maximum > minimum){ if(value > maximum) valuePosition += 8; else if(value < minimum) valuePosition -=8; }else{ if(value > minimum) valuePosition -= 8; else if(value < maximum) valuePosition +=8; } needlePoints.setPoint( PointsUtil.rotate(needlePoints.getPoint(0), valuePosition, center), 0); needlePoints.setPoint( PointsUtil.rotate(needlePoints.getPoint(1), valuePosition, center), 1); needlePoints.setPoint( PointsUtil.rotate(needlePoints.getPoint(2), valuePosition, center),2); needle.setPoints(needlePoints); } // if(needleCenter != null){ // needleCenter.setBounds(new Rectangle(center.x - area.width/4, // center.y - area.height/4, // area.width/2, area.height/2)); // } } } }