/******************************************************************************* * 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.AbstractScale.LabelSide; 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.FigureListener; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.Polygon; import org.eclipse.draw2d.RectangleFigure; 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.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Pattern; import org.eclipse.swt.widgets.Display; /** * A progress bar figure * @author Xihui Chen * */ public class ProgressBarFigure extends AbstractLinearMarkedFigure { private boolean effect3D = true; private boolean horizontal = false; private boolean indicatorMode = false; private final Color WHITE_COLOR = XYGraphMediaFactory.getInstance().getColor( XYGraphMediaFactory.COLOR_WHITE); //border color for track and thumb private final Color GRAY_COLOR = XYGraphMediaFactory.getInstance().getColor( XYGraphMediaFactory.COLOR_GRAY); private final Color BLUE_COLOR = XYGraphMediaFactory.getInstance().getColor( XYGraphMediaFactory.COLOR_BLUE); private Color fillColor = BLUE_COLOR; private Color fillBackgroundColor = GRAY_COLOR; private Track track; private Label label; private Thumb thumb; private double origin = 0; //the start point of the bar. private boolean originIgnored; public ProgressBarFigure() { super(); scale.setScaleLineVisible(false); scale.setTickLabelSide(LabelSide.Secondary); if(horizontal) { ((LinearScale)scale).setOrientation(Orientation.HORIZONTAL); scale.setTickLabelSide(LabelSide.Primary); marker.setLabelSide(LabelSide.Secondary); }else { ((LinearScale)scale).setOrientation(Orientation.VERTICAL); scale.setTickLabelSide(LabelSide.Primary); marker.setLabelSide(LabelSide.Secondary); } track = new Track(); label = new Label(); label.setOpaque(false); thumb = new Thumb(); thumb.setVisible(indicatorMode); setLayoutManager(new ProgressBarLayout()); add(scale, ProgressBarLayout.SCALE); add(marker, ProgressBarLayout.MARKERS); add(track, ProgressBarLayout.TRACK); add(thumb, ProgressBarLayout.THUMB); add(label, ProgressBarLayout.LABEL); addFigureListener(new FigureListener() { @Override public void figureMoved(IFigure source) { revalidate(); } }); } /** * @return the fillBackgroundColor */ public Color getFillBackgroundColor() { return fillBackgroundColor; } /** * @return the fillColor */ public Color getFillColor() { return fillColor; } /** * @return the origin */ public double getOrigin() { return origin; } /** * @return the effect3D */ public boolean isEffect3D() { return effect3D; } /** * @return the horizontal */ public boolean isHorizontal() { return horizontal; } /** * @return the indicatorMode */ public boolean isIndicatorMode() { return indicatorMode; } @Override public boolean isOpaque() { return false; } /** * @return the originIgnored */ public boolean isOriginIgnored() { return originIgnored; } /** * @param effect3D the effect3D to set */ public void setEffect3D(boolean effect3D) { if(this.effect3D == effect3D) return; this.effect3D = effect3D; repaint(); } @Override public void setEnabled(boolean value) { super.setEnabled(value); 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(); } /** * @param horizontal the horizontal to set */ public void setHorizontal(boolean horizontal) { if(this.horizontal == horizontal) return; this.horizontal = horizontal; if(horizontal) { ((LinearScale)scale).setOrientation(Orientation.HORIZONTAL); scale.setTickLabelSide(LabelSide.Primary); marker.setLabelSide(LabelSide.Secondary); }else { ((LinearScale)scale).setOrientation(Orientation.VERTICAL); scale.setTickLabelSide(LabelSide.Primary); marker.setLabelSide(LabelSide.Secondary); } revalidate(); } public void setIndicatorMode(boolean indicatorMode) { if(this.indicatorMode == indicatorMode) return; this.indicatorMode = indicatorMode; thumb.setVisible(indicatorMode); revalidate(); repaint(); } public void setOrigin(double origin) { if(this.origin == origin) return; this.origin = origin; repaint(); } public void setOriginIgnored(boolean originIgnored) { if(this.originIgnored == originIgnored) return; this.originIgnored = originIgnored; repaint(); } @Override public void setRange(double min, double max) { super.setRange(min, max); updateLabelText(); } public void setShowLabel(boolean visible){ label.setVisible(visible); repaint(); } @Override public void setValue(double value) { super.setValue(value); updateLabelText(); revalidate(); } /** * Update the text of the label. */ private void updateLabelText() { label.setText(getValueText()); } class Thumb extends Polygon { public static final int LENGTH = 20; public static final int BREADTH = 13; public final PointList horizontalThumbPointList = new PointList(new int[] { 0,0, 0, BREADTH, LENGTH*4/5, BREADTH, LENGTH, BREADTH/2, LENGTH*4/5, 0}) ; public final PointList verticalThumbPointList = new PointList(new int[] { 0,0, 0, LENGTH*4/5, BREADTH/2, LENGTH, BREADTH, LENGTH*4/5, BREADTH, 0}) ; public Thumb() { super(); //setOutline(true); setFill(true); setForegroundColor(GRAY_COLOR); setLineWidth(1); } @Override protected void fillShape(Graphics g) { g.setAntialias(SWT.ON); g.setClip(new Rectangle(getBounds().x, getBounds().y, getBounds().width, getBounds().height)); g.setBackgroundColor(WHITE_COLOR); super.fillShape(g); Point leftPoint = getPoints().getPoint(0); Point rightPoint; //if(horizontal) rightPoint = getPoints().getPoint(2); //else // rightPoint = getPoints().getPoint(1);//.translate(0, -BREADTH/2); Pattern thumbPattern = null; boolean support3D = GraphicsUtil.testPatternSupported(g); setOutline(effect3D && support3D); if(effect3D && support3D) { thumbPattern = new Pattern(Display.getCurrent(), leftPoint.x, leftPoint.y, rightPoint.x, rightPoint.y, WHITE_COLOR, 0, fillColor, 255); g.setBackgroundPattern(thumbPattern); }else g.setBackgroundColor(fillColor); g.fillPolygon(getPoints()); if(effect3D && support3D) thumbPattern.dispose(); } } class Track extends RectangleFigure { public Track() { super(); setForegroundColor(GRAY_COLOR); setOutline(false); } @Override protected void fillShape(Graphics graphics) { graphics.setAntialias(SWT.ON); int valuePosition = ((LinearScale) scale).getValuePosition(getCoercedValue(), false); double tempOrigin; if(originIgnored) tempOrigin = minimum; else tempOrigin = origin; int originPosition = ((LinearScale) scale).getValuePosition(tempOrigin, false); int fillLength = valuePosition - originPosition; boolean support3D = GraphicsUtil.testPatternSupported(graphics); if(effect3D && support3D) { //fill background graphics.setBackgroundColor(fillBackgroundColor); super.fillShape(graphics); Pattern backGroundPattern; if(horizontal) backGroundPattern= new Pattern(Display.getCurrent(), bounds.x, bounds.y, bounds.x, bounds.y + bounds.height, WHITE_COLOR, 255, fillBackgroundColor, 0); else backGroundPattern= new Pattern(Display.getCurrent(), bounds.x, bounds.y, bounds.x + bounds.width, bounds.y, WHITE_COLOR, 255, fillBackgroundColor, 0); graphics.setBackgroundPattern(backGroundPattern); super.fillShape(graphics); backGroundPattern.dispose(); //fill value if(!indicatorMode){ if(horizontal) backGroundPattern = new Pattern(Display.getCurrent(), bounds.x, bounds.y, bounds.x, bounds.y + bounds.height, WHITE_COLOR, 255, fillColor, 0); else backGroundPattern = new Pattern(Display.getCurrent(), bounds.x, bounds.y, bounds.x + bounds.width, bounds.y, WHITE_COLOR, 255, fillColor, 0); graphics.setBackgroundColor(fillColor); graphics.setForegroundColor(fillColor); if(horizontal){ Rectangle valueRectangle =new Rectangle(originPosition, bounds.y + 1, fillLength, bounds.height-2) ; graphics.fillRectangle(valueRectangle); graphics.setBackgroundPattern(backGroundPattern); graphics.fillRectangle(valueRectangle); }else { Rectangle valueRectangle = new Rectangle(bounds.x +1, originPosition, bounds.width-2, fillLength); graphics.fillRectangle(valueRectangle); graphics.setBackgroundPattern(backGroundPattern); graphics.fillRectangle(valueRectangle); } backGroundPattern.dispose(); } graphics.setForegroundColor(GRAY_COLOR); outlineShape(graphics); }else { graphics.setBackgroundColor(fillBackgroundColor); if(!indicatorMode){ if(horizontal){ graphics.fillRectangle( bounds.x, bounds.y, bounds.width-getLineWidth(), bounds.height); graphics.setBackgroundColor(fillColor); graphics.fillRectangle(new Rectangle(originPosition, bounds.y, fillLength, bounds.height)); } else { graphics.fillRectangle( bounds.x, bounds.y, bounds.width, bounds.height-getLineWidth()); graphics.setBackgroundColor(fillColor); graphics.fillRectangle(new Rectangle(bounds.x, originPosition, bounds.width, fillLength)); } }else graphics.fillRectangle(getBounds()); // graphics.setForegroundColor(outlineColor); // graphics.setForegroundColor(GRAY_COLOR); // outlineShape(graphics); } } } class ProgressBarLayout extends AbstractLayout { private static final int ADDITIONAL_MARGIN = 1; /** 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 TRACK = "track"; //$NON-NLS-1$ /** Used as a constraint for the alarm ticks */ public static final String MARKERS = "markers"; //$NON-NLS-1$ /** Used as a constraint for the thumb */ public static final String THUMB = "thumb"; //$NON-NLS-1$ /** Used as a constraint for the label */ public static final String LABEL = "label"; //$NON-NLS-1$ private LinearScale scale; private LinearScaledMarker marker; private Track track; private Label label; private Thumb thumb; @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; } private void horizontalLayout(IFigure container) { Rectangle area = container.getClientArea().getCopy(); area.x += ADDITIONAL_MARGIN; area.width -= 2*ADDITIONAL_MARGIN; Dimension scaleSize = new Dimension(0, 0); Dimension markerSize = new Dimension(0, 0); Rectangle trackBounds = area; if(scale != null) { if(scale.isVisible()){ scaleSize = scale.getPreferredSize(area.width, -1); scale.setBounds(new Rectangle(area.x, area.y + area.height - scaleSize.height, scaleSize.width, scaleSize.height)); scaleSize.height +=ADDITIONAL_MARGIN; }else{ // scaleSize = scale.getPreferredSize(area.width+2*scale.getMargin(), -1); scaleSize.width=area.width+2*scale.getMargin(); scaleSize.height=0; scale.setBounds(new Rectangle(area.x - scale.getMargin(), area.y + area.height - scaleSize.height, scaleSize.width, scaleSize.height)); scaleSize.width = 0; // scaleSize.height = 0; } } if(marker != null && marker.isVisible()) { markerSize = marker.getPreferredSize(); marker.setBounds(new Rectangle(marker.getScale().getBounds().x, area.y, markerSize.width, markerSize.height)); } if(track != null) { trackBounds = new Rectangle( scale.getValuePosition(scale.getRange().getLower(), false), area.y + markerSize.height, scale.getTickLength()+ track.getLineWidth(), area.height -markerSize.height - scaleSize.height ); track.setBounds(trackBounds); } if(thumb != null && thumb.isVisible()) { int h = track.getBounds().height; int b = Thumb.BREADTH; PointList newPointList = new PointList(new int[]{ b/2, 0, b, h/2, b/2, h-1, 0, h/2 }); newPointList.translate(scale.getValuePosition(getCoercedValue(), false) - Thumb.BREADTH/2, track.getBounds().y ); thumb.setPoints(newPointList); } if(label != null) { Dimension labelSize = label.getPreferredSize(); label.setBounds(new Rectangle(trackBounds.x + trackBounds.width/2 - labelSize.width/2, trackBounds.y + trackBounds.height/2 - labelSize.height/2, labelSize.width, labelSize.height)); } } @Override public void layout(IFigure container) { if(horizontal) horizontalLayout(container); else verticalLayout(container); } @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(TRACK)) track = (Track) child; else if (constraint.equals(THUMB)) thumb = (Thumb)child; else if (constraint.equals(LABEL)) label = (Label) child; } private void verticalLayout(IFigure container) { Rectangle area = container.getClientArea().getCopy(); area.y += ADDITIONAL_MARGIN; area.height -= 2*ADDITIONAL_MARGIN; Dimension scaleSize = new Dimension(0, 0); Dimension markerSize = new Dimension(0, 0); Rectangle trackBounds = area; if(scale != null) { if(scale.isVisible()){ scaleSize = scale.getPreferredSize(-1, area.height); scale.setBounds(new Rectangle(area.x + ADDITIONAL_MARGIN, area.y, scaleSize.width, scaleSize.height)); scaleSize.width += ADDITIONAL_MARGIN; }else{ // scaleSize = scale.getPreferredSize(-1, area.height+2*scale.getMargin()); scaleSize.width = 0; scaleSize.height = area.height+2*scale.getMargin(); scale.setBounds(new Rectangle(area.x, area.y-scale.getMargin(), scaleSize.width, scaleSize.height)); scaleSize.height = 0; } } if(marker != null && marker.isVisible()) { markerSize = marker.getPreferredSize(); marker.setBounds(new Rectangle(area.x + area.width - markerSize.width - ADDITIONAL_MARGIN, marker.getScale().getBounds().y, markerSize.width, markerSize.height)); } if(track != null) { trackBounds = new Rectangle( area.x + scaleSize.width, scale.getValuePosition(scale.getRange().getUpper(), false), area.width -markerSize.width - scaleSize.width, scale.getTickLength()+ track.getLineWidth()); track.setBounds(trackBounds); } if(thumb != null && thumb.isVisible()) { int h = track.getBounds().width; int b = Thumb.BREADTH; PointList newPointList = new PointList(new int[]{ 0, b/2, h/2, 0, h-1, b/2, h/2, b }); newPointList.translate(track.getBounds().x, scale.getValuePosition(getCoercedValue(), false) - Thumb.BREADTH/2); thumb.setPoints(newPointList); } if(label != null && label.isVisible()) { Dimension labelSize = label.getPreferredSize(); label.setBounds(new Rectangle(trackBounds.x + trackBounds.width/2 - labelSize.width/2, trackBounds.y + trackBounds.height/2 - labelSize.height/2, labelSize.width, labelSize.height)); } } } }