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 TimeLineGraph(String title, Dim dim)26 public TimeLineGraph (String title, Dim dim) { 27 super(title, dim); 28 this.fItemGroups=new Hashtable(); 29 } 30 paint(Image im)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 addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp)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 addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp,boolean isSpecial)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 addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp,boolean isSpecial,boolean drawBaseline)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 getMaxItem()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 getMinItem()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 getMostRecent(Hashtable lineGraphGroups)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 setCoordinates(int width, int xOffset, int height, int yOffset, int yValueRange)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 setRelativeXPosition(TimeLineGraphItem thisItem, List items)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