|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 package com.nokia.s60tools.swmtanalyser.ui.graphs; |
|
18 |
|
19 import java.util.ArrayList; |
|
20 |
|
21 import org.eclipse.draw2d.ColorConstants; |
|
22 import org.eclipse.draw2d.FigureCanvas; |
|
23 import org.eclipse.draw2d.FlowLayout; |
|
24 import org.eclipse.draw2d.Graphics; |
|
25 import org.eclipse.draw2d.Panel; |
|
26 import org.eclipse.jface.action.Action; |
|
27 import org.eclipse.jface.action.IAction; |
|
28 import org.eclipse.jface.action.IMenuListener; |
|
29 import org.eclipse.jface.action.IMenuManager; |
|
30 import org.eclipse.jface.action.MenuManager; |
|
31 import org.eclipse.jface.action.Separator; |
|
32 import org.eclipse.swt.SWT; |
|
33 import org.eclipse.swt.events.ControlAdapter; |
|
34 import org.eclipse.swt.events.ControlEvent; |
|
35 import org.eclipse.swt.events.MouseEvent; |
|
36 import org.eclipse.swt.events.MouseMoveListener; |
|
37 import org.eclipse.swt.events.PaintEvent; |
|
38 import org.eclipse.swt.events.PaintListener; |
|
39 import org.eclipse.swt.events.SelectionEvent; |
|
40 import org.eclipse.swt.events.SelectionListener; |
|
41 import org.eclipse.swt.graphics.Color; |
|
42 import org.eclipse.swt.graphics.Drawable; |
|
43 import org.eclipse.swt.graphics.Image; |
|
44 import org.eclipse.swt.graphics.RGB; |
|
45 import org.eclipse.swt.layout.FormAttachment; |
|
46 import org.eclipse.swt.layout.FormData; |
|
47 import org.eclipse.swt.layout.FormLayout; |
|
48 import org.eclipse.swt.widgets.Composite; |
|
49 import org.eclipse.swt.widgets.Control; |
|
50 import org.eclipse.swt.widgets.Display; |
|
51 import org.eclipse.swt.widgets.Menu; |
|
52 import org.eclipse.swt.widgets.ScrollBar; |
|
53 |
|
54 import com.nokia.s60tools.swmtanalyser.data.ChunksData; |
|
55 import com.nokia.s60tools.swmtanalyser.data.DiskOverview; |
|
56 import com.nokia.s60tools.swmtanalyser.data.GlobalDataChunks; |
|
57 import com.nokia.s60tools.swmtanalyser.data.KernelElements; |
|
58 import com.nokia.s60tools.swmtanalyser.data.ParsedData; |
|
59 import com.nokia.s60tools.swmtanalyser.data.SystemData; |
|
60 import com.nokia.s60tools.swmtanalyser.data.ThreadData; |
|
61 import com.nokia.s60tools.ui.IImageProvider; |
|
62 import com.nokia.s60tools.ui.actions.CopyImageToClipboardAction; |
|
63 import com.nokia.s60tools.util.debug.DbgUtility; |
|
64 /** |
|
65 * Graph to be shown in Graphs tab. |
|
66 * |
|
67 */ |
|
68 public class SwmtGraph extends ZoomableGraph implements MouseMoveListener, IImageProvider { |
|
69 |
|
70 private FigureCanvas figureCanvas; |
|
71 private FigureCanvas yAxis; |
|
72 private ParsedData logData; |
|
73 private Composite parentComposite; |
|
74 |
|
75 private boolean scaleNeedsUpdation = true; |
|
76 private GenericGraph graph; |
|
77 /** |
|
78 * Constructor |
|
79 * @param parent |
|
80 */ |
|
81 public SwmtGraph(Composite parent) |
|
82 { |
|
83 this.parentComposite = parent; |
|
84 } |
|
85 |
|
86 /** |
|
87 * Set parsed data |
|
88 * @param parsedData |
|
89 */ |
|
90 public void setInputCyclesData(ParsedData parsedData) |
|
91 { |
|
92 this.logData = parsedData; |
|
93 } |
|
94 |
|
95 /** |
|
96 * Draw graph area |
|
97 */ |
|
98 public void constructGraphArea() |
|
99 { |
|
100 if(this.logData == null || this.logData.getLogData() == null || parentComposite == null) |
|
101 return; |
|
102 |
|
103 Control [] children = parentComposite.getChildren(); |
|
104 |
|
105 if(children != null) |
|
106 { |
|
107 for(Control child:children) |
|
108 child.dispose(); |
|
109 } |
|
110 |
|
111 Composite parent = new Composite(parentComposite, SWT.NONE); |
|
112 parent.setLayout(new FormLayout()); |
|
113 |
|
114 yAxis = new FigureCanvas(parent); |
|
115 figureCanvas = new FigureCanvas(parent); |
|
116 //figureCanvas.setSize(500, 450); |
|
117 |
|
118 FormData formData = new FormData(); |
|
119 formData.top = new FormAttachment(0); |
|
120 formData.bottom = new FormAttachment(100); |
|
121 formData.left = new FormAttachment(0); |
|
122 formData.width = 60; |
|
123 yAxis.setLayoutData(formData); |
|
124 |
|
125 formData = new FormData(); |
|
126 formData.top = new FormAttachment(0); |
|
127 formData.bottom = new FormAttachment(100); |
|
128 formData.left = new FormAttachment(yAxis, 0, SWT.RIGHT); |
|
129 formData.right = new FormAttachment(100); |
|
130 figureCanvas.setLayoutData(formData); |
|
131 |
|
132 yAxis.setBackground(ColorConstants.white); |
|
133 yAxis.addPaintListener(new PaintListener() |
|
134 { |
|
135 |
|
136 public void paintControl(PaintEvent event) { |
|
137 |
|
138 if(graph != null) |
|
139 graph.paintYAxis(event.gc); |
|
140 else |
|
141 event.gc.dispose(); |
|
142 |
|
143 } |
|
144 }); |
|
145 |
|
146 yAxis.addControlListener(new ControlAdapter(){ |
|
147 public void controlResized(ControlEvent e) { |
|
148 } |
|
149 }); |
|
150 |
|
151 figureCanvas.setBackground(new Color(Display.getDefault(), new RGB(255,255,255))); |
|
152 |
|
153 Panel panel = new Panel() |
|
154 { |
|
155 public void paint(Graphics graphics) |
|
156 { |
|
157 DbgUtility.println(DbgUtility.PRIORITY_LOOP, "SwmtGraph/Panel/paint START"); |
|
158 |
|
159 if(graph != null){ |
|
160 graph.drawBackGroundLines(figureCanvas, graphics); |
|
161 graph.paint(graphics); |
|
162 } |
|
163 else{ |
|
164 erase(); |
|
165 } |
|
166 DbgUtility.println(DbgUtility.PRIORITY_LOOP, "SwmtGraph/Panel/paint END"); |
|
167 } |
|
168 |
|
169 |
|
170 }; |
|
171 |
|
172 panel.setLayoutManager(new FlowLayout()); |
|
173 |
|
174 figureCanvas.setContents(panel); |
|
175 |
|
176 figureCanvas.addMouseMoveListener(this); |
|
177 hookContextMenu(); |
|
178 |
|
179 final ScrollBar horizontalBar = figureCanvas.getHorizontalBar(); |
|
180 |
|
181 horizontalBar.addSelectionListener(new SelectionListener() |
|
182 { |
|
183 |
|
184 public void widgetDefaultSelected(SelectionEvent arg0) { |
|
185 |
|
186 } |
|
187 |
|
188 public void widgetSelected(SelectionEvent event) { |
|
189 |
|
190 if(graph != null){ |
|
191 graph.setScrolledXOrigin((figureCanvas.getViewport().getViewLocation().x)); |
|
192 } |
|
193 |
|
194 figureCanvas.redraw(); |
|
195 } |
|
196 |
|
197 }); |
|
198 |
|
199 figureCanvas.addControlListener(new ControlAdapter() |
|
200 { |
|
201 public void controlResized(ControlEvent e) { |
|
202 horizontalBar.setPageIncrement(figureCanvas.getBounds().width); |
|
203 |
|
204 if(graph != null) |
|
205 graph.setVisualSize(figureCanvas.getClientArea().height); |
|
206 if(scaleNeedsUpdation) |
|
207 { |
|
208 zoomGraph(); |
|
209 scaleNeedsUpdation = false; |
|
210 } |
|
211 |
|
212 yAxis.redraw(); |
|
213 figureCanvas.redraw(); |
|
214 |
|
215 } |
|
216 }); |
|
217 parentComposite.layout(); |
|
218 |
|
219 } |
|
220 |
|
221 /** |
|
222 * Add Pop-Up Menus on Graph area. |
|
223 * |
|
224 */ |
|
225 private void hookContextMenu() { |
|
226 MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ |
|
227 menuMgr.setRemoveAllWhenShown(true); |
|
228 menuMgr.addMenuListener(new IMenuListener() { |
|
229 public void menuAboutToShow(IMenuManager manager) { |
|
230 fillContextMenu(manager); |
|
231 } |
|
232 }); |
|
233 Menu menu = menuMgr.createContextMenu(figureCanvas); |
|
234 figureCanvas.setMenu(menu); |
|
235 } |
|
236 |
|
237 protected void fillContextMenu(IMenuManager manager) { |
|
238 |
|
239 zoomIn = new Action() |
|
240 { |
|
241 public void run() |
|
242 { |
|
243 zoomIn(); |
|
244 } |
|
245 { |
|
246 this.setText(ZOOM_IN_CONTEXT_MENU_TITLE); |
|
247 } |
|
248 }; |
|
249 |
|
250 zoomOut = new Action() |
|
251 { |
|
252 public void run() |
|
253 { |
|
254 zoomOut(); |
|
255 } |
|
256 { |
|
257 this.setText(ZOOM_OUT_CONTEXT_MENU_TITLE); |
|
258 } |
|
259 }; |
|
260 IAction showEntireGraph = new Action() |
|
261 { |
|
262 public void run() |
|
263 { |
|
264 zoomGraph(); |
|
265 } |
|
266 { |
|
267 this.setText(CommonGraphConstants.SHOW_ENTIRE_GRAPH_CONTEXT_MENU_ITEM_TITLE); |
|
268 } |
|
269 }; |
|
270 |
|
271 IAction saveGraph = new Action() |
|
272 { |
|
273 public void run() |
|
274 { |
|
275 GraphsUtils.saveGraph(parentComposite); |
|
276 } |
|
277 { |
|
278 this.setText(CommonGraphConstants.SAVE_GRAPH_CONTEXT_MENU_ITEM_TITLE); |
|
279 } |
|
280 }; |
|
281 |
|
282 copy = new CopyImageToClipboardAction(this); |
|
283 |
|
284 manager.add(zoomIn); |
|
285 manager.add(new Separator()); |
|
286 manager.add(zoomOut); |
|
287 manager.add(new Separator()); |
|
288 manager.add(showEntireGraph); |
|
289 manager.add(saveGraph); |
|
290 manager.add(copy); |
|
291 |
|
292 // Finally updating action states |
|
293 updateViewActionEnabledStates(); |
|
294 } |
|
295 |
|
296 /** |
|
297 * This method acts as an interface for redrawig graphs |
|
298 * @param graph |
|
299 */ |
|
300 public void redraw(GenericGraph graph) |
|
301 { |
|
302 this.graph = graph; |
|
303 |
|
304 try{ |
|
305 |
|
306 graph.setVisualSize(figureCanvas.getClientArea().height); |
|
307 graph.prepareData(); |
|
308 int [] timeSamples = graph.calculateTimeIntervals(); |
|
309 graph.lastSampleTime = timeSamples[timeSamples.length -1]; |
|
310 |
|
311 //Zooms Graph to fit last sample value |
|
312 zoomGraph(); |
|
313 yAxis.redraw(); |
|
314 figureCanvas.redraw(); |
|
315 }catch(Exception e){ |
|
316 e.printStackTrace(); |
|
317 } |
|
318 } |
|
319 |
|
320 /* (non-Javadoc) |
|
321 * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent) |
|
322 */ |
|
323 public void mouseMove(MouseEvent event) { |
|
324 |
|
325 if(this.graph != null) |
|
326 { |
|
327 this.figureCanvas.setToolTipText(this.graph.getToolTipText(event.x, event.y)); |
|
328 this.figureCanvas.redraw(); |
|
329 } |
|
330 } |
|
331 |
|
332 /** |
|
333 * Clear graph |
|
334 */ |
|
335 public void clearGraph() |
|
336 { |
|
337 this.graph = null; |
|
338 try{ |
|
339 yAxis.redraw(); |
|
340 figureCanvas.redraw(); |
|
341 |
|
342 }catch(NullPointerException e){ |
|
343 |
|
344 } |
|
345 } |
|
346 |
|
347 /** |
|
348 * This method stores data corresponding to given item, so that it can be |
|
349 * used in Graphed items view. |
|
350 * @param itemName |
|
351 * @param allEventsGraph |
|
352 */ |
|
353 public void storeClearedEventValues(String itemName, GraphForAllEvents allEventsGraph) |
|
354 { |
|
355 if(this.graph != null) |
|
356 { |
|
357 if(graph instanceof ThreadsGraph){ |
|
358 ArrayList<ThreadData> values = ((ThreadsGraph)(graph)).getDataForThread(itemName); |
|
359 |
|
360 allEventsGraph.setHeapSizeForThread(itemName, values); |
|
361 |
|
362 } |
|
363 else if(graph instanceof ChunksGraph) |
|
364 { |
|
365 if(graph.getEvent().equals(GenericGraph.EventTypes.GLOBAL_DATA_SIZE)) |
|
366 { |
|
367 ArrayList<GlobalDataChunks> values = ((ChunksGraph)(graph)).getGlobalChunkData(itemName); |
|
368 |
|
369 allEventsGraph.setGlobalChunkSizeForChunk(itemName, values); |
|
370 } |
|
371 else if(graph.getEvent().equals(GenericGraph.EventTypes.NON_HEAP_CHUNK_SIZE)) |
|
372 { |
|
373 ArrayList<ChunksData> values = ((ChunksGraph)(graph)).getNonHeapChunkData(itemName); |
|
374 |
|
375 allEventsGraph.setNonHeapChunkSizeForChunk(itemName, values); |
|
376 } |
|
377 |
|
378 } |
|
379 else if(graph instanceof DisksGraph) |
|
380 { |
|
381 if(graph.getEvent().equals(GenericGraph.EventTypes.DISK_USED_SIZE) || |
|
382 graph.getEvent().equals(GenericGraph.EventTypes.DISK_TOTAL_SIZE)) |
|
383 { |
|
384 ArrayList<DiskOverview> values = ((DisksGraph)(graph)).getDiskData(itemName); |
|
385 |
|
386 allEventsGraph.setDiskData(itemName, values); |
|
387 } |
|
388 |
|
389 else if(graph.getEvent().equals(GenericGraph.EventTypes.RAM_USED)|| |
|
390 graph.getEvent().equals(GenericGraph.EventTypes.RAM_TOTAL)) |
|
391 { |
|
392 ArrayList<SystemData> sysData = ((DisksGraph)(graph)).getSystemData(); |
|
393 |
|
394 allEventsGraph.setSystemData(sysData); |
|
395 } |
|
396 } |
|
397 else if(graph instanceof SystemDataGraph) |
|
398 { |
|
399 ArrayList<KernelElements> kernelData = ((SystemDataGraph)(graph)).getKernelData(); |
|
400 |
|
401 allEventsGraph.setKernelData(kernelData); |
|
402 } |
|
403 } |
|
404 } |
|
405 |
|
406 /** |
|
407 * Sets enabled/disabled states for actions commands |
|
408 * on this view, based on the current application state. |
|
409 * This method should be called whenever an operation is |
|
410 * started or stopped that might have effect on action |
|
411 * button states. |
|
412 */ |
|
413 private void updateViewActionEnabledStates() { |
|
414 //Zoom In |
|
415 setEnableState(zoomIn, !(this.graph != null && graph.getScale() == GraphsUtils.nextScale(graph.getScale(), false))); |
|
416 |
|
417 //Zoom Out |
|
418 if(this.graph != null) |
|
419 { |
|
420 boolean zoomOutEnableCondition1 = !(graph.getScale() == GraphsUtils.nextScale(graph.getScale(), true)); |
|
421 int width = figureCanvas.getClientArea().width; |
|
422 boolean zoomOutEnableCondition2 = !(graph.lastSampleTime / graph.getScale() <= width); |
|
423 setEnableState(zoomOut, zoomOutEnableCondition1 && zoomOutEnableCondition2); |
|
424 } |
|
425 else{ |
|
426 setEnableState(zoomOut, false); |
|
427 } |
|
428 |
|
429 } |
|
430 |
|
431 /* (non-Javadoc) |
|
432 * @see com.nokia.s60tools.swmtanalyser.ui.graphs.ZoomableGraph#zoomIn() |
|
433 */ |
|
434 protected void zoomIn() |
|
435 { |
|
436 DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "SwmtGraph - Zoom In"); |
|
437 //Preconditions checked already in updateViewActionEnabledStates |
|
438 graph.setScale(GraphsUtils.nextScale(graph.getScale(), false)); |
|
439 setNewSize(); |
|
440 } |
|
441 |
|
442 /* (non-Javadoc) |
|
443 * @see com.nokia.s60tools.swmtanalyser.ui.graphs.ZoomableGraph#zoomOut() |
|
444 */ |
|
445 protected void zoomOut() |
|
446 { |
|
447 DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "SwmtGraph - Zoom Out"); |
|
448 //Preconditions checked already in updateViewActionEnabledStates |
|
449 graph.setScale(GraphsUtils.nextScale(graph.getScale(), true)); |
|
450 setNewSize(); |
|
451 } |
|
452 |
|
453 /** |
|
454 * This method first zooms in graph to the maximum possible scale |
|
455 * and zooms out so that it fits in the canvas area. |
|
456 * |
|
457 */ |
|
458 public void zoomGraph() |
|
459 { |
|
460 int width = figureCanvas.getClientArea().width; |
|
461 |
|
462 if(width <=0 || this.graph == null) |
|
463 return; |
|
464 |
|
465 double new_scale = graph.getScale(); |
|
466 |
|
467 double prevNew = new_scale; |
|
468 |
|
469 //first zoom in until it is too big to fit |
|
470 while (graph.lastSampleTime / new_scale <= width){ |
|
471 new_scale = GraphsUtils.nextScale(new_scale, false); |
|
472 |
|
473 if(prevNew == new_scale) |
|
474 break; |
|
475 |
|
476 prevNew = new_scale; |
|
477 |
|
478 } |
|
479 // now zoom out until it just fits |
|
480 while (graph.lastSampleTime / new_scale > width){ |
|
481 new_scale = GraphsUtils.nextScale(new_scale, true); |
|
482 |
|
483 if(prevNew == new_scale) |
|
484 break; |
|
485 |
|
486 prevNew = new_scale; |
|
487 } |
|
488 |
|
489 if (new_scale == graph.getScale()) |
|
490 return; |
|
491 |
|
492 graph.setScale(new_scale); |
|
493 setNewSize(); |
|
494 } |
|
495 |
|
496 /** |
|
497 * This method sets the size of the panel, when scale is changed. |
|
498 * When graph extends beyond visible area, horizontal scroll bar appears automatically. |
|
499 * |
|
500 */ |
|
501 private void setNewSize() |
|
502 { |
|
503 if(graph == null) |
|
504 return; |
|
505 |
|
506 graph.setScrolledXOrigin(0); |
|
507 double scale = graph.getScale(); |
|
508 int lastSample = graph.lastSampleTime; |
|
509 |
|
510 int prefSize = (int)(lastSample/scale); |
|
511 |
|
512 Panel panel = (Panel)(figureCanvas.getContents()); |
|
513 panel.setPreferredSize(prefSize + 100, 0); |
|
514 |
|
515 if (prefSize >= figureCanvas.getClientArea().width) { |
|
516 graph.setScrolledXOrigin(figureCanvas.getViewport().getViewLocation().x); |
|
517 panel.setSize(prefSize + 100, 0); |
|
518 } |
|
519 |
|
520 } |
|
521 |
|
522 /* (non-Javadoc) |
|
523 * @see com.nokia.s60tools.swmtanalyser.ui.actions.IImageProvider#getImage() |
|
524 */ |
|
525 public Image getImage() { |
|
526 return new Image(Display.getCurrent(), parentComposite.getClientArea().width, parentComposite.getClientArea().height); |
|
527 } |
|
528 |
|
529 /* (non-Javadoc) |
|
530 * @see com.nokia.s60tools.swmtanalyser.ui.actions.IImageProvider#getDrawable() |
|
531 */ |
|
532 public Drawable getDrawable() { |
|
533 return parentComposite; |
|
534 } |
|
535 |
|
536 |
|
537 } |