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 TimeLineGraph extends LineGraph{
23402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
24402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    Hashtable fItemGroups;
25402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
26402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public TimeLineGraph (String title, Dim dim) {
27402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        super(title, dim);
28402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        this.fItemGroups=new Hashtable();
29402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
30402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
31402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public void paint(Image im) {
32402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
33402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Rectangle bounds= im.getBounds();
34402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
35402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        GC g= new GC(im);
36402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
37402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Point ee= g.stringExtent(this.fTitle);
38402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int titleHeight= ee.y;
39402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
40402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        double maxItem= getMaxItem();
41402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        double minItem= getMinItem();
42402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
43402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int max= (int) (Math.ceil(maxItem * (maxItem < 0 ? 0.8 : 1.2)));
44402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int min= (int) (Math.floor(minItem * (minItem < 0 ? 1.2 : 0.8)));
45402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
46402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        String smin= this.fDimension.getDisplayValue(min);
47402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Point emin= g.stringExtent(smin);
48402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
49402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        String smax= this.fDimension.getDisplayValue(max);
50402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Point emax= g.stringExtent(smax);
51402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
52402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int labelWidth= Math.max(emin.x, emax.x) + 2;
53402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
54402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int top= PADDING;
55402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int bottom= bounds.height - titleHeight - PADDING;
56402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int left= PADDING + labelWidth;
57402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
58402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        //getMostRecent
59402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        TimeLineGraphItem lastItem= getMostRecent(this.fItemGroups);
60402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        int right=bounds.width - PADDING/2;
61402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        if (lastItem!=null)
62402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        	right= bounds.width - lastItem.getSize(g).x - PADDING/2;
63402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
64402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        // draw the max and min values
65402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.drawString(smin, PADDING/2+labelWidth-emin.x, bottom-titleHeight, true);
66402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.drawString(smax, PADDING/2+labelWidth-emax.x, top, true);
67402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.drawString("TIME (not drawn to scale)", (right-left)/3+PADDING+titleHeight,bottom-PADDING+(titleHeight*2), true);
68402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
69402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        // draw the vertical and horizontal lines
70402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.drawLine(left, top, left, bottom);
71402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.drawLine(left, bottom, right, bottom);
72402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
73402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Color oldbg= g.getBackground();
74402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Color oldfg= g.getForeground();
75402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
76402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        setCoordinates(right-left,left,bottom-top,bottom,max-min);
77402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
78402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Enumeration _enum=this.fItemGroups.elements();
79402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Comparator comparator=new TimeLineGraphItem.GraphItemComparator();
80402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
81402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        while (_enum.hasMoreElements()) {
82402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll 			List items = (List) _enum.nextElement();
83402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Object[] fItemsArray=items.toArray();
84402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Arrays.sort(fItemsArray,comparator);
85402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			int lastx = 0;
86402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			int lasty = 0;
87402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
88402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			int n = fItemsArray.length;
89402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
90402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			for (int i = 0; i < n; i++) {
91402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				TimeLineGraphItem thisItem = (TimeLineGraphItem) fItemsArray[i];
92402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
93402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				int yposition = thisItem.y;
94402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				int xposition = thisItem.x;
95402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				g.setLineWidth(1);
96402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
97402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				g.setBackground(thisItem.color);
98402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				g.setForeground(thisItem.color);
99402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
100402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (thisItem.drawAsBaseline){
101402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					g.setLineWidth(0);
102402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					g.drawLine(xposition, yposition,right,yposition);
103402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					g.drawLine(left,yposition,xposition, yposition);
104402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    		    }
105402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
106402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (i > 0) // don't draw for first segment
107402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					g.drawLine(lastx, lasty, xposition, yposition);
108402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
109402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				g.setBackground(thisItem.color);
110402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				g.setForeground(thisItem.color);
111402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			//	g.fillOval(xposition - 2, yposition - 2, 6, 6);
112402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				g.fillRectangle(xposition - 2, yposition - 2, 5, 5);
113402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
114402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (thisItem.isSpecial)
115402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					g.drawRectangle(xposition -4, yposition - 4, 8, 8);
116402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
117402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (this.fAreaBuffer == null)
118402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					this.fAreaBuffer = new StringBuffer();
119402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
120402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				this.fAreaBuffer.append("\r<area shape=\"circle\" coords=\""
121402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						+ (xposition - 2) + ',' + (yposition - 2) + ',' + 5
122402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						+ " alt=\"" + thisItem.title + ": "
123402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						+ thisItem.description + "\"" + " title=\""
124402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						+ thisItem.title + ": " + thisItem.description + "\">");
125402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
126402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				int shift;
127402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (i > 0 && yposition < lasty)
128402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					shift = 3; // below dot
129402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				else
130402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					shift = -(2 * titleHeight + 3); // above dot
131402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (thisItem.displayDescription) {
132402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					g.drawString(thisItem.title, xposition + 2, yposition
133402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll							+ shift, true);
134402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					g.drawString(thisItem.description, xposition + 2, yposition
135402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll							+ shift + titleHeight, true);
136402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				}
137402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				g.setBackground(oldbg);
138402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				g.setForeground(oldfg);
139402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
140402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				lastx = xposition;
141402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				lasty = yposition;
142402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
143402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
144402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
145402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        g.dispose();
146402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
147402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
148402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public void addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp) {
149402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    	addItem(groupName, name, description, value, col, display,	timestamp,false);
150402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
151402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
152402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public void addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp,boolean isSpecial) {
153402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll 		addItem(groupName, name,description, value, col, display,
154402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll 				timestamp,isSpecial,false);
155402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
156402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
157402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public void addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp,boolean isSpecial,boolean drawBaseline) {
158402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll      	List items = (List) this.fItemGroups.get(groupName);
159402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll  		if (this.fItemGroups.get(groupName) == null) {
160402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll  			items=new ArrayList();
161402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll  			this.fItemGroups.put(groupName, items);
162402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll  		}
163402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll  		items.add(new TimeLineGraphItem(name, description, value, col, display,
164402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll  				timestamp,isSpecial,drawBaseline));
165402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
166402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
167402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public double getMaxItem() {
168402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    	Enumeration _enum=this.fItemGroups.elements();
169402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        double maxItem= 0;
170402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    	while (_enum.hasMoreElements()) {
171402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			List items = (List) _enum.nextElement();
172402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			for (int i = 0; i < items.size(); i++) {
173402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				TimeLineGraphItem graphItem = (TimeLineGraphItem) items.get(i);
174402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (graphItem.value > maxItem)
175402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					maxItem = graphItem.value;
176402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
177402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
178402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        if (maxItem == 0)
179402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            return 1;
180402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        return maxItem;
181402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
182402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
183402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    public double getMinItem() {
184402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll       	Enumeration _enum = this.fItemGroups.elements();
185402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		double minItem = getMaxItem();
186402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
187402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		while (_enum.hasMoreElements()) {
188402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			List items = (List) _enum.nextElement();
189402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			for (int i = 0; i < items.size(); i++) {
190402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				TimeLineGraphItem graphItem = (TimeLineGraphItem) items.get(i);
191402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (graphItem.value < minItem)
192402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					minItem = graphItem.value;
193402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
194402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
195402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        if (minItem == 0)
196402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll            return -1;
197402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        return minItem;
198402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
199402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
200402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    private TimeLineGraphItem getMostRecent(Hashtable lineGraphGroups) {
201402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		Enumeration _enum = lineGraphGroups.elements();
202402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		long mostRecentTimestamp = 0;
203402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		TimeLineGraphItem mostRecentItem = null;
204402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
205402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		while (_enum.hasMoreElements()) {
206402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			List items = (List) _enum.nextElement();
207402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			for (int i = 0; i < items.size(); i++) {
208402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (items.size() == 1)
209402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					return (TimeLineGraphItem) items.get(i);
210402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				else {
211402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					TimeLineGraphItem graphItem = (TimeLineGraphItem) items.get(i);
212402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					if (graphItem.timestamp > mostRecentTimestamp) {
213402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						mostRecentTimestamp = graphItem.timestamp;
214402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						mostRecentItem = (TimeLineGraphItem) items.get(i);
215402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					}
216402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				}
217402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
218402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
219402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return mostRecentItem;
220402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
221402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
222402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    private void setCoordinates(int width, int xOffset, int height, int yOffset, int yValueRange){
223402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
224402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        List mainGroup=(ArrayList)this.fItemGroups.get("main");
225402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        List referenceGroup=(ArrayList)this.fItemGroups.get("reference");
226402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
227402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll        Comparator comparator=new TimeLineGraphItem.GraphItemComparator();
228402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
229402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll 		Object[] fItemsArray=mainGroup.toArray();
230402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		Arrays.sort(fItemsArray,comparator);
231402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
232402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int n = mainGroup.size();
233402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int xIncrement=width/n;
234402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		double max=getMaxItem()*1.2;
235402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll//		double min=getMinItem()*0.8;
236402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
237402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		for (int i = 0; i < n; i++) {
238402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			TimeLineGraphItem thisItem = (TimeLineGraphItem) fItemsArray[i];
239402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			thisItem.setX(xOffset + (i * xIncrement));
240402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			thisItem.setY((int)(PADDING+((max-thisItem.value) * (height)/(yValueRange))));
241402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
242402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
243402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
244402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (referenceGroup==null)
245402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			return;
246402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
247402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		n = referenceGroup.size();
248402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		for (int i = 0; i < n; i++) {
249402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			 TimeLineGraphItem thisItem = (TimeLineGraphItem) referenceGroup.get(i);
250402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			 if (thisItem.timestamp==-1)
251402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				 thisItem.setX(xOffset + (i * (width/n)));
252402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			 else
253402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				 setRelativeXPosition(thisItem,mainGroup);
254402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
255402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			 thisItem.setY((int)(PADDING+((max-thisItem.value) * (height)/(yValueRange))));
256402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
257402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
258402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    }
259402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
260402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
261402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private void setRelativeXPosition (TimeLineGraphItem thisItem, List items){
262402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Comparator comparator=new TimeLineGraphItem.GraphItemComparator();
263402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Object[] fItemsArray=items.toArray();
264402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Arrays.sort(fItemsArray,comparator);
265402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
266402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			TimeLineGraphItem closestPrecedingItem=null;
267402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			long minimumTimeDiffPreceding=thisItem.timestamp;
268402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
269402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			TimeLineGraphItem closestFollowingItem=null;
270402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			long minimumTimeDiffFollowing=thisItem.timestamp;
271402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
272402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			for (int i=0;i<fItemsArray.length;i++){
273402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				TimeLineGraphItem anItem=(TimeLineGraphItem)fItemsArray[i];
274402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				long timeDiff=thisItem.timestamp-anItem.timestamp;
275402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
276402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				 if (timeDiff>0&&timeDiff<minimumTimeDiffPreceding){
277402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					 closestPrecedingItem=anItem;
278402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				 	minimumTimeDiffPreceding=thisItem.timestamp-anItem.timestamp;
279402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				 }
280402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				 if (timeDiff<=0&&Math.abs(timeDiff)<=minimumTimeDiffFollowing){
281402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					 closestFollowingItem=anItem;
282402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					 minimumTimeDiffFollowing=thisItem.timestamp-anItem.timestamp;
283402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				 }
284402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
285402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (closestFollowingItem==null && closestPrecedingItem!=null)
286402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				thisItem.setX(closestPrecedingItem.x);
287402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
288402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			else if (closestFollowingItem!=null && closestPrecedingItem==null)
289402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				thisItem.setX(closestFollowingItem.x);
290402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			else{
291402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				long timeRange=closestFollowingItem.timestamp-closestPrecedingItem.timestamp;
292402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
293402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				int xRange=closestFollowingItem.x-closestPrecedingItem.x;
294402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				double increments=(xRange*1.0)/timeRange;
295402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
296402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				thisItem.setX((int)(Math.round((thisItem.timestamp-closestPrecedingItem.timestamp)*increments)+closestPrecedingItem.x));
297402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
298402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
299402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
300