/*******************************************************************************
* 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.xygraph.figures;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import org.csstudio.swt.xygraph.Preferences;
import org.csstudio.swt.xygraph.figures.Trace.TraceType;
import org.csstudio.swt.xygraph.util.XYGraphMediaFactory;
import org.eclipse.draw2d.FigureUtilities;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
/**The legend to indicate the style and size of the trace line and point.
* The border color of the legend is same as the traces' Y-Axis color.
* @author Xihui Chen
*
*/
public class Legend extends RectangleFigure {
private final static int ICON_WIDTH = 15;//Edited by scouter.project@gmail.com 25->15;
private final static int INNER_GAP = 2;
private final static int OUT_GAP = 5;
// private final static Font LEGEND_FONT = XYGraphMediaFactory.getInstance().getFont(
// XYGraphMediaFactory.FONT_ARIAL);
//
// private final Color WHITE_COLOR = XYGraphMediaFactory.getInstance().getColor(
// XYGraphMediaFactory.COLOR_WHITE);
private final Color BLACK_COLOR = XYGraphMediaFactory.getInstance().getColor(
XYGraphMediaFactory.COLOR_BLACK);
private final List<Trace> traceList = new ArrayList<Trace>();
public Legend(XYGraph xyGraph) {
// setFont(LEGEND_FONT);
xyGraph.getPlotArea().addPropertyChangeListener(PlotArea.BACKGROUND_COLOR, new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
setBackgroundColor((Color) evt.getNewValue());
}
});
setBackgroundColor(xyGraph.getPlotArea().getBackgroundColor());
setForegroundColor(BLACK_COLOR);
setOpaque(false);
setOutline(false); // Edited by scouter.project true -> false
addListenerToBoldline(); // Added by scouter.project
}
/**Add a trace to the axis.
* @param trace the trace to be added.
*/
public void addTrace(Trace trace){
traceList.add(trace);
}
/**Remove a trace from the axis.
* @param trace
* @return true if this axis contained the specified trace
*/
public boolean removeTrace(Trace trace){
return traceList.remove(trace);
}
@Override
protected void outlineShape(Graphics graphics) {
graphics.setForegroundColor(traceList.get(0).getYAxis().getForegroundColor());
super.outlineShape(graphics);
}
@Override
protected void fillShape(Graphics graphics) {
if(!((XYGraph)getParent()).isTransparent())
super.fillShape(graphics);
int hPos = bounds.x +INNER_GAP;
int vPos = bounds.y - INNER_GAP; // up little
int i = 0;
// Added by scouter.project
positionList.clear();
for(Trace trace : traceList){
int hwidth = OUT_GAP + ICON_WIDTH + INNER_GAP +
+ FigureUtilities.getTextExtents(trace.getName(), getFont()).width;
int hEnd = hPos + hwidth;
if(hEnd > (bounds.x + bounds.width) && i>0){
hPos= bounds.x + INNER_GAP;
vPos += ICON_WIDTH + INNER_GAP;
hEnd = hPos + hwidth;
}
// graphics.setForegroundColor(trace.getYAxis().getForegroundColor());
// Rectangle rect = new Rectangle(hPos, vPos-INNER_GAP/2, hwidth - OUT_GAP,ICON_WIDTH-INNER_GAP);
// graphics.fillRectangle(rect);
// graphics.drawRectangle(rect);
drawTraceLagend(trace, graphics, hPos, vPos);
hPos = hEnd;
i++;
}
}
private void drawTraceLagend(Trace trace, Graphics graphics, int hPos, int vPos){
graphics.pushState();
if (Preferences.useAdvancedGraphics())
graphics.setAntialias(SWT.ON);
graphics.setForegroundColor(trace.getTraceColor());
///********************************** Removed by scouter.project
// draw symbol
// switch (trace.getTraceType()) {
// case BAR:
// trace.drawLine(graphics, new Point(hPos + ICON_WIDTH / 2, vPos + trace.getPointSize() / 2), new Point(hPos + ICON_WIDTH / 2, vPos + ICON_WIDTH));
// trace.drawPoint(graphics, new Point(hPos + ICON_WIDTH / 2, vPos + trace.getPointSize() / 2));
// break;
// case AREA:
// graphics.setBackgroundColor(trace.getTraceColor());
// if (Preferences.useAdvancedGraphics())
// graphics.setAlpha(trace.getAreaAlpha());
// graphics.fillPolygon(new int[] { hPos, vPos + ICON_WIDTH / 2, hPos + ICON_WIDTH / 2, vPos + trace.getPointSize() / 2, hPos + ICON_WIDTH, vPos + ICON_WIDTH / 2, hPos + ICON_WIDTH,
// vPos + ICON_WIDTH, hPos, vPos + ICON_WIDTH });
// if (Preferences.useAdvancedGraphics())
// graphics.setAlpha(255);
// trace.drawPoint(graphics, new Point(hPos + ICON_WIDTH / 2, vPos + trace.getPointSize() / 2));
// break;
// default:
// trace.drawLine(graphics, new Point(hPos, vPos + ICON_WIDTH / 2), new Point(hPos + ICON_WIDTH, vPos + ICON_WIDTH / 2));
// trace.drawPoint(graphics, new Point(hPos + ICON_WIDTH / 2, vPos + ICON_WIDTH / 2));
// break;
// }
//**************************************/
// Added by scouter.project
// Draw rectangle and name
graphics.setBackgroundColor(trace.getTraceColor());
int rectangleX = hPos+ INNER_GAP*2;
int rectangleY = vPos+ INNER_GAP;
graphics.fillRectangle(rectangleX, rectangleY ,10 ,10 );
int textX = hPos + ICON_WIDTH + INNER_GAP;
int textY = vPos + ICON_WIDTH / 2 - FigureUtilities.getTextExtents(trace.getName(), getFont()).height / 2;
graphics.drawText(trace.getName(), textX, textY);
int x2 = textX + FigureUtilities.getTextExtents(trace.getName(), getFont()).width;
int y2 = textY + FigureUtilities.getTextExtents(trace.getName(), getFont()).height;
positionList.add(new LegendPosition(rectangleX, rectangleY, x2, y2));
graphics.popState();
}
@Override
public Dimension getPreferredSize(int wHint, int hHint) {
int maxWidth =0;
int hEnd = INNER_GAP;
int height = ICON_WIDTH + INNER_GAP;
// int i=0;
for(Trace trace : traceList){
hEnd = hEnd + OUT_GAP + ICON_WIDTH + INNER_GAP +
+ FigureUtilities.getTextExtents(trace.getName(), getFont()).width;
if(hEnd > wHint){
hEnd= INNER_GAP + OUT_GAP + ICON_WIDTH + INNER_GAP +
+ FigureUtilities.getTextExtents(trace.getName(), getFont()).width;
height += ICON_WIDTH + INNER_GAP;
}
if(maxWidth < hEnd)
maxWidth = hEnd;
// i++;
}
return new Dimension(maxWidth, height);
}
/**
* @return the traceList
*/
public List<Trace> getTraceList() {
return traceList;
}
//Added by scouter.project
private final List<LegendPosition> positionList = new ArrayList<LegendPosition>();
/**
* Added by scouter.project
* When mouse pressed/released event occurs, trace is highlighted/normal
*/
private void addListenerToBoldline() {
addMouseListener(new MouseListener.Stub() {
Trace holdingTrace;
int originalWidth;
public void mousePressed(MouseEvent me) {
mouseReleased(me);
for (int i = 0; i < positionList.size(); i++) {
LegendPosition pos = positionList.get(i);
if (pos.isContained(me.x, me.y)) {
holdingTrace = traceList.get(i);
if (holdingTrace.getTraceType() == TraceType.SOLID_LINE) {
originalWidth = holdingTrace.getLineWidth();
holdingTrace.setLineWidth(originalWidth * 2);
} else {
holdingTrace = null;
}
break;
}
}
}
public void mouseReleased(MouseEvent me) {
if (holdingTrace != null) {
if (originalWidth > 0) {
holdingTrace.setLineWidth(originalWidth);
} else {
holdingTrace.setLineWidth(1);
}
originalWidth = 0;
holdingTrace = null;
}
}
});
}
/**
* Added by scouter.project@gmail.com
* Value object to remember rectangle area of legend.
*/
static class LegendPosition {
int x1, x2, y1, y2;
public LegendPosition (int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public boolean isContained(int x, int y) {
boolean result = false;
if(x1 <= x && x <= x2 && y1 <= y && y <= y2) {
result = true;
}
return result;
}
}
}