Home | History | Annotate | Download | only in ui
      1 /*******************************************************************************
      2  * Copyright (c) 2000, 2009 IBM Corporation and others.
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *     IBM Corporation - initial API and implementation
     10  *******************************************************************************/
     11 package org.eclipse.test.performance.ui;
     12 
     13 import java.util.*;
     14 
     15 import org.eclipse.swt.graphics.Color;
     16 import org.eclipse.swt.graphics.GC;
     17 import org.eclipse.swt.graphics.Image;
     18 import org.eclipse.swt.graphics.Point;
     19 import org.eclipse.swt.graphics.Rectangle;
     20 import org.eclipse.test.internal.performance.data.Dim;
     21 
     22 public class TimeLineGraph extends LineGraph{
     23 
     24     Hashtable fItemGroups;
     25 
     26     public TimeLineGraph (String title, Dim dim) {
     27         super(title, dim);
     28         this.fItemGroups=new Hashtable();
     29     }
     30 
     31     public void paint(Image im) {
     32 
     33         Rectangle bounds= im.getBounds();
     34 
     35         GC g= new GC(im);
     36 
     37         Point ee= g.stringExtent(this.fTitle);
     38         int titleHeight= ee.y;
     39 
     40         double maxItem= getMaxItem();
     41         double minItem= getMinItem();
     42 
     43         int max= (int) (Math.ceil(maxItem * (maxItem < 0 ? 0.8 : 1.2)));
     44         int min= (int) (Math.floor(minItem * (minItem < 0 ? 1.2 : 0.8)));
     45 
     46         String smin= this.fDimension.getDisplayValue(min);
     47         Point emin= g.stringExtent(smin);
     48 
     49         String smax= this.fDimension.getDisplayValue(max);
     50         Point emax= g.stringExtent(smax);
     51 
     52         int labelWidth= Math.max(emin.x, emax.x) + 2;
     53 
     54         int top= PADDING;
     55         int bottom= bounds.height - titleHeight - PADDING;
     56         int left= PADDING + labelWidth;
     57 
     58         //getMostRecent
     59         TimeLineGraphItem lastItem= getMostRecent(this.fItemGroups);
     60         int right=bounds.width - PADDING/2;
     61         if (lastItem!=null)
     62         	right= bounds.width - lastItem.getSize(g).x - PADDING/2;
     63 
     64         // draw the max and min values
     65         g.drawString(smin, PADDING/2+labelWidth-emin.x, bottom-titleHeight, true);
     66         g.drawString(smax, PADDING/2+labelWidth-emax.x, top, true);
     67         g.drawString("TIME (not drawn to scale)", (right-left)/3+PADDING+titleHeight,bottom-PADDING+(titleHeight*2), true);
     68 
     69         // draw the vertical and horizontal lines
     70         g.drawLine(left, top, left, bottom);
     71         g.drawLine(left, bottom, right, bottom);
     72 
     73         Color oldbg= g.getBackground();
     74         Color oldfg= g.getForeground();
     75 
     76         setCoordinates(right-left,left,bottom-top,bottom,max-min);
     77 
     78         Enumeration _enum=this.fItemGroups.elements();
     79         Comparator comparator=new TimeLineGraphItem.GraphItemComparator();
     80 
     81         while (_enum.hasMoreElements()) {
     82  			List items = (List) _enum.nextElement();
     83 			Object[] fItemsArray=items.toArray();
     84 			Arrays.sort(fItemsArray,comparator);
     85 			int lastx = 0;
     86 			int lasty = 0;
     87 
     88 			int n = fItemsArray.length;
     89 
     90 			for (int i = 0; i < n; i++) {
     91 				TimeLineGraphItem thisItem = (TimeLineGraphItem) fItemsArray[i];
     92 
     93 				int yposition = thisItem.y;
     94 				int xposition = thisItem.x;
     95 				g.setLineWidth(1);
     96 
     97 				g.setBackground(thisItem.color);
     98 				g.setForeground(thisItem.color);
     99 
    100 				if (thisItem.drawAsBaseline){
    101 					g.setLineWidth(0);
    102 					g.drawLine(xposition, yposition,right,yposition);
    103 					g.drawLine(left,yposition,xposition, yposition);
    104     		    }
    105 
    106 				if (i > 0) // don't draw for first segment
    107 					g.drawLine(lastx, lasty, xposition, yposition);
    108 
    109 				g.setBackground(thisItem.color);
    110 				g.setForeground(thisItem.color);
    111 			//	g.fillOval(xposition - 2, yposition - 2, 6, 6);
    112 				g.fillRectangle(xposition - 2, yposition - 2, 5, 5);
    113 
    114 				if (thisItem.isSpecial)
    115 					g.drawRectangle(xposition -4, yposition - 4, 8, 8);
    116 
    117 				if (this.fAreaBuffer == null)
    118 					this.fAreaBuffer = new StringBuffer();
    119 
    120 				this.fAreaBuffer.append("\r<area shape=\"circle\" coords=\""
    121 						+ (xposition - 2) + ',' + (yposition - 2) + ',' + 5
    122 						+ " alt=\"" + thisItem.title + ": "
    123 						+ thisItem.description + "\"" + " title=\""
    124 						+ thisItem.title + ": " + thisItem.description + "\">");
    125 
    126 				int shift;
    127 				if (i > 0 && yposition < lasty)
    128 					shift = 3; // below dot
    129 				else
    130 					shift = -(2 * titleHeight + 3); // above dot
    131 				if (thisItem.displayDescription) {
    132 					g.drawString(thisItem.title, xposition + 2, yposition
    133 							+ shift, true);
    134 					g.drawString(thisItem.description, xposition + 2, yposition
    135 							+ shift + titleHeight, true);
    136 				}
    137 				g.setBackground(oldbg);
    138 				g.setForeground(oldfg);
    139 
    140 				lastx = xposition;
    141 				lasty = yposition;
    142 			}
    143 		}
    144 
    145         g.dispose();
    146     }
    147 
    148     public void addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp) {
    149     	addItem(groupName, name, description, value, col, display,	timestamp,false);
    150     }
    151 
    152     public void addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp,boolean isSpecial) {
    153  		addItem(groupName, name,description, value, col, display,
    154  				timestamp,isSpecial,false);
    155 	}
    156 
    157     public void addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp,boolean isSpecial,boolean drawBaseline) {
    158       	List items = (List) this.fItemGroups.get(groupName);
    159   		if (this.fItemGroups.get(groupName) == null) {
    160   			items=new ArrayList();
    161   			this.fItemGroups.put(groupName, items);
    162   		}
    163   		items.add(new TimeLineGraphItem(name, description, value, col, display,
    164   				timestamp,isSpecial,drawBaseline));
    165     }
    166 
    167     public double getMaxItem() {
    168     	Enumeration _enum=this.fItemGroups.elements();
    169         double maxItem= 0;
    170     	while (_enum.hasMoreElements()) {
    171 			List items = (List) _enum.nextElement();
    172 			for (int i = 0; i < items.size(); i++) {
    173 				TimeLineGraphItem graphItem = (TimeLineGraphItem) items.get(i);
    174 				if (graphItem.value > maxItem)
    175 					maxItem = graphItem.value;
    176 			}
    177 		}
    178         if (maxItem == 0)
    179             return 1;
    180         return maxItem;
    181     }
    182 
    183     public double getMinItem() {
    184        	Enumeration _enum = this.fItemGroups.elements();
    185 		double minItem = getMaxItem();
    186 
    187 		while (_enum.hasMoreElements()) {
    188 			List items = (List) _enum.nextElement();
    189 			for (int i = 0; i < items.size(); i++) {
    190 				TimeLineGraphItem graphItem = (TimeLineGraphItem) items.get(i);
    191 				if (graphItem.value < minItem)
    192 					minItem = graphItem.value;
    193 			}
    194 		}
    195         if (minItem == 0)
    196             return -1;
    197         return minItem;
    198     }
    199 
    200     private TimeLineGraphItem getMostRecent(Hashtable lineGraphGroups) {
    201 		Enumeration _enum = lineGraphGroups.elements();
    202 		long mostRecentTimestamp = 0;
    203 		TimeLineGraphItem mostRecentItem = null;
    204 
    205 		while (_enum.hasMoreElements()) {
    206 			List items = (List) _enum.nextElement();
    207 			for (int i = 0; i < items.size(); i++) {
    208 				if (items.size() == 1)
    209 					return (TimeLineGraphItem) items.get(i);
    210 				else {
    211 					TimeLineGraphItem graphItem = (TimeLineGraphItem) items.get(i);
    212 					if (graphItem.timestamp > mostRecentTimestamp) {
    213 						mostRecentTimestamp = graphItem.timestamp;
    214 						mostRecentItem = (TimeLineGraphItem) items.get(i);
    215 					}
    216 				}
    217 			}
    218 		}
    219 		return mostRecentItem;
    220 	}
    221 
    222     private void setCoordinates(int width, int xOffset, int height, int yOffset, int yValueRange){
    223 
    224         List mainGroup=(ArrayList)this.fItemGroups.get("main");
    225         List referenceGroup=(ArrayList)this.fItemGroups.get("reference");
    226 
    227         Comparator comparator=new TimeLineGraphItem.GraphItemComparator();
    228 
    229  		Object[] fItemsArray=mainGroup.toArray();
    230 		Arrays.sort(fItemsArray,comparator);
    231 
    232 		int n = mainGroup.size();
    233 		int xIncrement=width/n;
    234 		double max=getMaxItem()*1.2;
    235 //		double min=getMinItem()*0.8;
    236 
    237 		for (int i = 0; i < n; i++) {
    238 			TimeLineGraphItem thisItem = (TimeLineGraphItem) fItemsArray[i];
    239 			thisItem.setX(xOffset + (i * xIncrement));
    240 			thisItem.setY((int)(PADDING+((max-thisItem.value) * (height)/(yValueRange))));
    241 
    242 			}
    243 
    244 		if (referenceGroup==null)
    245 			return;
    246 
    247 		n = referenceGroup.size();
    248 		for (int i = 0; i < n; i++) {
    249 			 TimeLineGraphItem thisItem = (TimeLineGraphItem) referenceGroup.get(i);
    250 			 if (thisItem.timestamp==-1)
    251 				 thisItem.setX(xOffset + (i * (width/n)));
    252 			 else
    253 				 setRelativeXPosition(thisItem,mainGroup);
    254 
    255 			 thisItem.setY((int)(PADDING+((max-thisItem.value) * (height)/(yValueRange))));
    256 
    257 		}
    258     }
    259 
    260 
    261 	private void setRelativeXPosition (TimeLineGraphItem thisItem, List items){
    262 			Comparator comparator=new TimeLineGraphItem.GraphItemComparator();
    263 			Object[] fItemsArray=items.toArray();
    264 			Arrays.sort(fItemsArray,comparator);
    265 
    266 			TimeLineGraphItem closestPrecedingItem=null;
    267 			long minimumTimeDiffPreceding=thisItem.timestamp;
    268 
    269 			TimeLineGraphItem closestFollowingItem=null;
    270 			long minimumTimeDiffFollowing=thisItem.timestamp;
    271 
    272 			for (int i=0;i<fItemsArray.length;i++){
    273 				TimeLineGraphItem anItem=(TimeLineGraphItem)fItemsArray[i];
    274 				long timeDiff=thisItem.timestamp-anItem.timestamp;
    275 
    276 				 if (timeDiff>0&&timeDiff<minimumTimeDiffPreceding){
    277 					 closestPrecedingItem=anItem;
    278 				 	minimumTimeDiffPreceding=thisItem.timestamp-anItem.timestamp;
    279 				 }
    280 				 if (timeDiff<=0&&Math.abs(timeDiff)<=minimumTimeDiffFollowing){
    281 					 closestFollowingItem=anItem;
    282 					 minimumTimeDiffFollowing=thisItem.timestamp-anItem.timestamp;
    283 				 }
    284 			}
    285 			if (closestFollowingItem==null && closestPrecedingItem!=null)
    286 				thisItem.setX(closestPrecedingItem.x);
    287 
    288 			else if (closestFollowingItem!=null && closestPrecedingItem==null)
    289 				thisItem.setX(closestFollowingItem.x);
    290 			else{
    291 				long timeRange=closestFollowingItem.timestamp-closestPrecedingItem.timestamp;
    292 
    293 				int xRange=closestFollowingItem.x-closestPrecedingItem.x;
    294 				double increments=(xRange*1.0)/timeRange;
    295 
    296 				thisItem.setX((int)(Math.round((thisItem.timestamp-closestPrecedingItem.timestamp)*increments)+closestPrecedingItem.x));
    297 			}
    298 	}
    299 }
    300