1402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*******************************************************************************
2402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Copyright (c) 2000, 2009 IBM Corporation and others.
3402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * All rights reserved. This program and the accompanying materials
4402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * are made available under the terms of the Eclipse Public License v1.0
5402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * which accompanies this distribution, and is available at
6402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * http://www.eclipse.org/legal/epl-v10.html
7402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
8402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Contributors:
9402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *     IBM Corporation - initial API and implementation
10402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *******************************************************************************/
11402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpackage org.eclipse.test.performance.ui;
12402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
13402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.*;
14402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
15402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.Color;
16402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.GC;
17402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.Image;
18402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.Point;
19402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.Rectangle;
20402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.data.Dim;
21402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
22402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic class LineGraph {
23402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
24402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    StringBuffer fAreaBuffer;
25402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
26402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    private static class GraphItem {
27402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
28402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        String title;
29402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        String description=null;
30402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        double value;
31402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Color color;
32402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        boolean displayDescription=false;
33402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
34402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        GraphItem(String title, String description,double value, Color color,boolean display) {
35402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        	this(title, description, value, color);
36402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        	this.displayDescription=display;
37402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        }
38402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
39402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        GraphItem(String title, String description, double value, Color color) {
40402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            this.title= title;
41402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            this.value= value;
42402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            this.color= color;
43402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            this.description= description;
44402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        }
45402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
46402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Point getSize(GC g) {
47402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            Point e1= g.stringExtent(this.description);
48402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            Point e2= g.stringExtent(this.title);
49402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            return new Point(Math.max(e1.x, e2.x), e1.y+e2.y);
50402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        }
51402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
52402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
53402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    static final int PADDING= 15;
54402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
55402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
56402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    String fTitle;
57402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    List fItems;
58402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    Dim fDimension;
59402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
60402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
61402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public LineGraph(String title, Dim dim) {
62402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        this.fTitle= title;
63402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        this.fItems= new ArrayList();
64402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        this.fDimension= dim;
65402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
66402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
67402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public void paint(Image im) {
68402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
69402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Rectangle bounds= im.getBounds();
70402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
71402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        GC g= new GC(im);
72402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
73402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Point ee= g.stringExtent(this.fTitle);
74402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int titleHeight= ee.y;
75402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
76402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        double maxItem= getMaxItem();
77402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        double minItem= getMinItem();
78402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
79402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int max= (int) (Math.ceil(maxItem * (maxItem < 0 ? 0.9 : 1.2)));
80402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int min= (int) (Math.floor(minItem * (minItem < 0 ? 1.2 : 0.9)));
81402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
82402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        String smin= this.fDimension.getDisplayValue(min);
83402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Point emin= g.stringExtent(smin);
84402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
85402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        String smax= this.fDimension.getDisplayValue(max);
86402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Point emax= g.stringExtent(smax);
87402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
88402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int labelWidth= Math.max(emin.x, emax.x) + 2;
89402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
90402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int top= PADDING;
91402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int bottom= bounds.height - titleHeight - PADDING;
92402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int left= PADDING + labelWidth;
93402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
94402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        GraphItem lastItem= (GraphItem) this.fItems.get(this.fItems.size()-1);
95402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int right= bounds.width - lastItem.getSize(g).x - PADDING/2;
96402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
97402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        // draw the title
98402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        //g.drawString(fTitle, (bounds.width - titleWidth) / 2, titleHeight, true);
99402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
100402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        // draw the max and min values
101402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.drawString(smin, PADDING/2+labelWidth-emin.x, bottom-titleHeight, true);
102402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.drawString(smax, PADDING/2+labelWidth-emax.x, top, true);
103402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
104402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        // draw the vertical and horizontal lines
105402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.drawLine(left, top, left, bottom);
106402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.drawLine(left, bottom, right, bottom);
107402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
108402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Color oldbg= g.getBackground();
109402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Color oldfg= g.getForeground();
110402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
111402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int n= this.fItems.size();
112402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int xincrement= n > 1 ? (right-left) / (n-1) : 0;
113402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
114402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int graduations= max - min;
115402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        if (graduations == 0)
116402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            graduations= 1;
117402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
118402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int lastx= 0;
119402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int lasty= 0;
120402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
121402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int xposition= left;
122402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
123402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        for (int i= 0; i < n; i++) {
124402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            GraphItem thisItem= (GraphItem) this.fItems.get(i);
125402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
126402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            int yposition= (int) (bottom - (((thisItem.value-min) * (bottom-top)) / graduations));
127402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
128402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            if (i > 0)	// don't draw for first segment
129402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll                g.drawLine(lastx, lasty, xposition, yposition);
130402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
131402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            g.setBackground(thisItem.color);
132402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            g.setForeground(thisItem.color);
133402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            g.fillOval(xposition-2, yposition-2, 5, 5);
134402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
135402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            if (this.fAreaBuffer == null)
136402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll                this.fAreaBuffer= new StringBuffer();
137402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
138402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            this.fAreaBuffer.append("\r<area shape=\"CIRCLE\" coords=\""+(xposition-2)+','+(yposition-2)+','+5+" alt=\""+ thisItem.title+": "+thisItem.description+"\""+ " title=\""+ thisItem.title+": "+thisItem.description+"\">");
139402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
140402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
141402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            int shift;
142402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            if (i > 0 && yposition < lasty)
143402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll                shift= 3;	 // below dot
144402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            else
145402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll                shift= -(2*titleHeight+3);	// above dot
146402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            if (thisItem.displayDescription){
147402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            	g.drawString(thisItem.title, xposition+2, yposition+shift, true);
148402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            	g.drawString(thisItem.description, xposition+2, yposition+shift+titleHeight, true);
149402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            }
150402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            g.setBackground(oldbg);
151402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            g.setForeground(oldfg);
152402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
153402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            lastx= xposition;
154402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            lasty= yposition;
155402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            xposition+= xincrement;
156402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        }
157402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
158402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.dispose();
159402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
160402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
161402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public void addItem(String name, String description, double value, Color col) {
162402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    	addItem(name, description, value, col,false);
163402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
164402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
165402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public void addItem(String name, String description, double value, Color col, boolean display) {
166402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        this.fItems.add(new GraphItem(name, description, value, col,display));
167402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
168402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
169402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public double getMaxItem() {
170402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        double maxItem= 0;
171402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        for (int i= 0; i < this.fItems.size(); i++) {
172402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            GraphItem graphItem= (GraphItem) this.fItems.get(i);
173402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            if (graphItem.value > maxItem)
174402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll                maxItem= graphItem.value;
175402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        }
176402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        if (maxItem == 0)
177402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            return 1;
178402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        return maxItem;
179402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
180402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
181402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public double getMinItem() {
182402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        double minItem= getMaxItem();
183402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        for (int i= 0; i < this.fItems.size(); i++) {
184402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            GraphItem graphItem= (GraphItem) this.fItems.get(i);
185402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            if (graphItem.value < minItem)
186402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll                minItem= graphItem.value;
187402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        }
188402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        if (minItem == 0)
189402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            return -1;
190402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        return minItem;
191402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
192402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public String getAreas() {
193402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        if (this.fAreaBuffer != null) {
194402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            String s= this.fAreaBuffer.toString();
195402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            this.fAreaBuffer= null;
196402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            return s;
197402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        }
198402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        return null;
199402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
200402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
201