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