d4d2efe9f6bfeadf094711b1b7bca38af086f2c8
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.ui / src / org / eclipse / linuxtools / lttng / ui / views / controlflow / ControlFlowView.java
1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors: Alvaro Sanchez-Leon - Initial implementation
10 *******************************************************************************/
11 package org.eclipse.linuxtools.lttng.ui.views.controlflow;
12
13 import java.util.Arrays;
14 import java.util.Vector;
15
16 import org.eclipse.jface.action.Action;
17 import org.eclipse.jface.action.IMenuListener;
18 import org.eclipse.jface.action.IMenuManager;
19 import org.eclipse.jface.action.IToolBarManager;
20 import org.eclipse.jface.action.MenuManager;
21 import org.eclipse.jface.action.Separator;
22 import org.eclipse.jface.dialogs.MessageDialog;
23 import org.eclipse.jface.viewers.DoubleClickEvent;
24 import org.eclipse.jface.viewers.IDoubleClickListener;
25 import org.eclipse.jface.viewers.ISelection;
26 import org.eclipse.jface.viewers.ISelectionChangedListener;
27 import org.eclipse.jface.viewers.IStructuredContentProvider;
28 import org.eclipse.jface.viewers.IStructuredSelection;
29 import org.eclipse.jface.viewers.ITableLabelProvider;
30 import org.eclipse.jface.viewers.LabelProvider;
31 import org.eclipse.jface.viewers.SelectionChangedEvent;
32 import org.eclipse.jface.viewers.StructuredViewer;
33 import org.eclipse.jface.viewers.TableViewer;
34 import org.eclipse.jface.viewers.Viewer;
35 import org.eclipse.jface.viewers.ViewerFilter;
36 import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
37 import org.eclipse.linuxtools.lttng.state.IStateDataRequestListener;
38 import org.eclipse.linuxtools.lttng.state.RequestCompletedSignal;
39 import org.eclipse.linuxtools.lttng.state.RequestStartedSignal;
40 import org.eclipse.linuxtools.lttng.state.StateDataRequest;
41 import org.eclipse.linuxtools.lttng.state.StateManager;
42 import org.eclipse.linuxtools.lttng.state.evProcessor.EventProcessorProxy;
43 import org.eclipse.linuxtools.lttng.state.experiment.StateExperimentManager;
44 import org.eclipse.linuxtools.lttng.state.experiment.StateManagerFactory;
45 import org.eclipse.linuxtools.lttng.ui.TraceDebug;
46 import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess;
47 import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeViewerProvider;
48 import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater;
49 import org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor.FlowTRangeUpdateFactory;
50 import org.eclipse.linuxtools.lttng.ui.views.controlflow.model.FlowModelFactory;
51 import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceModelFactory;
52 import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
53 import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
54 import org.eclipse.linuxtools.tmf.signal.TmfSignalManager;
55 import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;
56 import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewerFactory;
57 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer;
58 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeFilterSelectionListener;
59 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeScaleSelectionListener;
60 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeSelectionListener;
61 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeFilterSelectionEvent;
62 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent;
63 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent;
64 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;
65 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
66 import org.eclipse.swt.SWT;
67 import org.eclipse.swt.custom.SashForm;
68 import org.eclipse.swt.custom.ScrolledComposite;
69 import org.eclipse.swt.events.ControlAdapter;
70 import org.eclipse.swt.events.ControlEvent;
71 import org.eclipse.swt.events.ControlListener;
72 import org.eclipse.swt.events.KeyEvent;
73 import org.eclipse.swt.events.KeyListener;
74 import org.eclipse.swt.graphics.Image;
75 import org.eclipse.swt.graphics.Point;
76 import org.eclipse.swt.graphics.Rectangle;
77 import org.eclipse.swt.layout.FillLayout;
78 import org.eclipse.swt.widgets.Composite;
79 import org.eclipse.swt.widgets.Display;
80 import org.eclipse.swt.widgets.Menu;
81 import org.eclipse.swt.widgets.ScrollBar;
82 import org.eclipse.swt.widgets.Table;
83 import org.eclipse.swt.widgets.TableColumn;
84 import org.eclipse.swt.widgets.TableItem;
85 import org.eclipse.ui.IActionBars;
86 import org.eclipse.ui.IWorkbenchActionConstants;
87 import org.eclipse.ui.PlatformUI;
88 import org.eclipse.ui.plugin.AbstractUIPlugin;
89
90 /**
91 * <b><u>ControlFlowView</u></b>
92 * <p>
93 * TODO: Implement me. Please.
94 */
95 public class ControlFlowView extends TmfView implements
96 ITmfTimeSelectionListener, ITmfTimeScaleSelectionListener,
97 ITmfTimeFilterSelectionListener, IStateDataRequestListener {
98
99 public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.controlflow";
100
101 // ========================================================================
102 // Table data
103 // ========================================================================
104 private final String PROCESS_COLUMN = "Process";
105 private final String BRAND_COLUMN = "Brand";
106 private final String PID_COLUMN = "PID";
107 private final String TGID_COLUMN = "TGID";
108 private final String PPID_COLUMN = "PPID";
109 private final String CPU_COLUMN = "CPU";
110 private final String BIRTH_SEC_COLUMN = "Birth sec";
111 private final String BIRTH_NSEC_COLUMN = "Birth nsec";
112 private final String TRACE = "TRACE";
113
114 private final String[] columnNames = new String[] { PROCESS_COLUMN, /* */
115 BRAND_COLUMN,/* */
116 PID_COLUMN,/* */
117 TGID_COLUMN,/* */
118 PPID_COLUMN,/* */
119 CPU_COLUMN, /* */
120 BIRTH_SEC_COLUMN,/* */
121 BIRTH_NSEC_COLUMN,/* */
122 TRACE /* */
123 };
124
125 // ========================================================================
126 // Data
127 // ========================================================================
128 private Vector<StateDataRequest> pendingDataRequests = new Vector<StateDataRequest>();
129
130 private TableViewer tableViewer;
131 // private int totalNumItems = 0;
132 // Actions
133 private Action doubleClickAction;
134 private Action resetScale;
135 private Action nextEvent;
136 private Action prevEvent;
137 private Action nextTrace;
138 private Action prevTrace;
139 private Action showLegend;
140 private Action filterTraces;
141 private Action zoomIn;
142 private Action zoomOut;
143 private Action synch;
144
145 private ITimeAnalysisViewer tsfviewer;
146 private ViewProcessFilter tableFilter = null;
147 private ScrolledComposite scrollFrame = null;
148 private Composite wrapper = null;
149 private Composite top;
150
151 // private static SimpleDateFormat stimeformat = new SimpleDateFormat(
152 // "yy/MM/dd HH:mm:ss");
153
154 // private TraceModelImplFactory fact;
155
156 // ========================================================================
157 // Methods
158 // ========================================================================
159 /*
160 * The content provider class is responsible for providing objects to the
161 * view. It can wrap existing objects in adapters or simply return objects
162 * as-is. These objects may be sensitive to the current input of the view,
163 * or ignore it and always show the same content (like Task List, for
164 * example).
165 */
166
167 class ViewContentProvider implements
168 /* ILazyContentProvider, */IStructuredContentProvider {
169 private TableViewer cviewer = null;
170 private ITmfTimeAnalysisEntry[] elements = null;
171
172 public ViewContentProvider(TableViewer v) {
173 cviewer = v;
174 }
175
176 public void inputChanged(Viewer v, Object oldInput, Object newInput) {
177 this.elements = (ITmfTimeAnalysisEntry[]) newInput;
178 if (elements != null) {
179 TraceDebug
180 .debug("Total number of processes provided to Control Flow view: "
181 + elements.length);
182 } else {
183 TraceDebug.debug("New input = null");
184 }
185 }
186
187 public void dispose() {
188
189 }
190
191 // Needed with the use of virtual tables in order to initialize items
192 // which were not initially visible.
193 public void updateElement(int index) {
194 cviewer.replace(elements[index], index);
195 }
196
197 // @Override
198 public Object[] getElements(Object inputElement) {
199 // TODO Auto-generated method stub
200 return elements;
201 }
202 }
203
204 class ViewLabelProvider extends LabelProvider implements
205 ITableLabelProvider {
206 public String getColumnText(Object obj, int index) {
207 String strRes = ""; //$NON-NLS-1$
208 LttngTimestamp time;
209 if (obj instanceof TimeRangeEventProcess) {
210 TimeRangeEventProcess process = (TimeRangeEventProcess) obj;
211 switch (index) {
212 case 0:
213 strRes = process.getName();
214 break;
215 case 1:
216 strRes = process.getBrand();
217 break;
218 case 2:
219 strRes = process.getPid().toString();
220 break;
221 case 3:
222 strRes = process.getTgid().toString();
223 break;
224 case 4:
225 strRes = process.getPpid().toString();
226 break;
227 case 5:
228 strRes = process.getCpu().toString();
229 break;
230 case 6:
231 time = new LttngTimestamp(process.getCreationTime()
232 .longValue());
233 strRes = time.getSeconds();
234 break;
235 case 7:
236 time = new LttngTimestamp(process.getCreationTime()
237 .longValue());
238 strRes = time.getNanoSeconds();
239 break;
240 case 8:
241 strRes = process.getTraceID();
242 break;
243 default:
244 break;
245 }
246 } else {
247 return getText(obj);
248 }
249
250 return strRes;
251 }
252
253 public Image getColumnImage(Object obj, int index) {
254 return getImage(obj);
255 }
256
257 @Override
258 public Image getImage(Object obj) {
259 // No image needed for the time being
260 // return PlatformUI.getWorkbench().getSharedImages().getImage(
261 // ISharedImages.IMG_OBJ_ELEMENT);
262 return null;
263 }
264 }
265
266 class ViewProcessFilter extends ViewerFilter {
267
268 private Vector<ITmfTimeAnalysisEntry> filteredSet = new Vector<ITmfTimeAnalysisEntry>();
269 StructuredViewer viewer;
270
271 public ViewProcessFilter(StructuredViewer rviewer) {
272 this.viewer = rviewer;
273 }
274
275 public void setFilter(Vector<ITmfTimeAnalysisEntry> filtered) {
276 if (filtered != null) {
277 this.filteredSet = filtered;
278 viewer.refresh();
279 }
280 }
281
282 @Override
283 public boolean select(Viewer viewer, Object parentElement,
284 Object element) {
285 boolean filteredIn = true;
286 if (element instanceof ITmfTimeAnalysisEntry) {
287 ITmfTimeAnalysisEntry process = (ITmfTimeAnalysisEntry) element;
288 if (filteredSet.contains(process)) {
289 // The element is marked to be filtered out
290 return false;
291 }
292 } else {
293 TraceDebug.debug("Unexpected type of filter element received: "
294 + element.toString());
295 }
296 // Compare element versus a list of filtered out
297 return filteredIn;
298 }
299 }
300
301 /**
302 * The constructor.
303 */
304 public ControlFlowView() {
305 }
306
307 /**
308 * This is a callback that will allow us to create the viewer and initialize
309 * it.
310 */
311 @Override
312 public void createPartControl(Composite parent) {
313 top = new Composite(parent, SWT.BORDER);
314
315 top.setLayout(new FillLayout());
316
317 scrollFrame = new ScrolledComposite(top, SWT.V_SCROLL | SWT.H_SCROLL);
318 scrollFrame.setBounds(top.getClientArea());
319
320 wrapper = new Composite(scrollFrame, SWT.NONE);
321 scrollFrame.setEnabled(true);
322 scrollFrame.setRedraw(true);
323 scrollFrame.setExpandVertical(true);
324 scrollFrame.setExpandHorizontal(true);
325 scrollFrame.setContent(wrapper);
326 scrollFrame.setAlwaysShowScrollBars(true);
327 wrapper.setLayout(new FillLayout());
328
329 SashForm sash = new SashForm(wrapper, SWT.NONE);
330 final Composite tableComposite = new Composite(sash, SWT.NO_SCROLL);
331 FillLayout layout = new FillLayout();
332 tableComposite.setLayout(layout);
333 tableViewer = new TableViewer(tableComposite, SWT.FULL_SELECTION
334 | SWT.H_SCROLL);
335 tableViewer.setContentProvider(new ViewContentProvider(tableViewer));
336 tableViewer.setLabelProvider(new ViewLabelProvider());
337 Table table = tableViewer.getTable();
338 tableViewer
339 .addSelectionChangedListener(new ISelectionChangedListener() {
340 public void selectionChanged(SelectionChangedEvent event) {
341 ISelection sel = event.getSelection();
342 if (!sel.isEmpty()) {
343 Object firstSel = null;
344 if (sel instanceof IStructuredSelection) {
345 firstSel = ((IStructuredSelection) sel)
346 .getFirstElement();
347
348 // Make sure the selection is visible
349 updateScrollOrigin();
350
351 if (firstSel instanceof ITmfTimeAnalysisEntry) {
352 ITmfTimeAnalysisEntry trace = (ITmfTimeAnalysisEntry) firstSel;
353 tsfviewer.setSelectedTrace(trace);
354 }
355 }
356 }
357 }
358
359 /**
360 * Make sure the selected item is visible
361 */
362 private void updateScrollOrigin() {
363 Table table = tableViewer.getTable();
364 if (table != null && table.getItemCount() > 0) {
365 TableItem item = table.getSelection()[0];
366 if (item == null) {
367 // no selected reference to go up or down
368 return;
369 }
370
371 Rectangle itemRect = item.getBounds();
372 int step = itemRect.height;
373
374 // calculate height of horizontal bar
375 int hscrolly = 0;
376 ScrollBar hbar = scrollFrame.getHorizontalBar();
377 if (hbar != null) {
378 hscrolly = hbar.getSize().y;
379 }
380
381 int visibleHeight = scrollFrame.getSize().y
382 - hscrolly;
383
384 // the current scrollbar offset to adjust i.e. start
385 // of
386 // the visible window
387 Point origin = scrollFrame.getOrigin();
388 // end of visible window
389 int endy = origin.y + visibleHeight;
390
391 int itemStartPos = itemRect.y
392 + table.getHeaderHeight()
393 + table.getBorderWidth()
394 + table.getParent().getBorderWidth();
395
396 // Item End Position
397 int itemEndPos = itemStartPos + step;
398
399 // check if need to go up
400 if (origin.y >= step && itemStartPos < origin.y) {
401 // one step up
402 scrollFrame
403 .setOrigin(origin.x, origin.y - step);
404
405 }
406
407 // check if it needs to go down
408 if (itemEndPos > endy) {
409 // one step down
410 scrollFrame
411 .setOrigin(origin.x, origin.y + step);
412
413 }
414 }
415 }
416 });
417
418 // Listen to page up /down and Home / Enc keys
419 tableViewer.getTable().addKeyListener(new KeyListener() {
420 public void keyPressed(KeyEvent e) {
421 Table table = tableViewer.getTable();
422 Point origin = scrollFrame.getOrigin();
423 if (table == null || table.getItemCount() < 1) {
424 // nothing to page
425 return;
426 }
427
428 TableItem item;
429 int count;
430
431 switch (e.keyCode) {
432 case SWT.PAGE_DOWN:
433 updateScrollPageDown();
434 break;
435 case SWT.PAGE_UP:
436 updateScrollUp();
437 break;
438 case SWT.HOME:
439 // Home
440 count = table.getItemCount();
441 item = table.getItem(0);
442 // Go to the top
443 scrollFrame.setOrigin(origin.x, 0);
444 break;
445 case SWT.END:
446 // End Selected
447 count = table.getItemCount();
448 item = table.getItem(count - 1);
449 int itemStartPos = item.getBounds().y;
450 // Get to the bottom
451 scrollFrame.setOrigin(origin.x, itemStartPos);
452 break;
453 default:
454 break;
455 }
456 }
457
458 public void keyReleased(KeyEvent e) {
459 // Nothing to do
460
461 }
462
463 /**
464 * Scroll one page down
465 */
466 private void updateScrollPageDown() {
467 // null protection before calling private method
468 Table table = tableViewer.getTable();
469 int step = table.getItemHeight();
470
471 int hscrolly = 0;
472 ScrollBar hbar = scrollFrame.getHorizontalBar();
473 if (hbar != null) {
474 hscrolly = hbar.getSize().y;
475 }
476
477 Point origin = scrollFrame.getOrigin();
478 int visibleHeight = scrollFrame.getSize().y - hscrolly;
479 int endy = origin.y + visibleHeight;
480
481 scrollFrame.setOrigin(origin.x, endy - step);
482 }
483
484 /**
485 * Scroll one page up
486 */
487 private void updateScrollUp() {
488 // null protection before calling private method
489 Table table = tableViewer.getTable();
490 int step = table.getItemHeight();
491
492 int hscrolly = 0;
493 ScrollBar hbar = scrollFrame.getHorizontalBar();
494 if (hbar != null) {
495 hscrolly = hbar.getSize().y;
496 }
497
498 Point origin = scrollFrame.getOrigin();
499 int visibleHeight = scrollFrame.getSize().y - hscrolly;
500 int pageUpPos = origin.y - visibleHeight + step;
501 pageUpPos = pageUpPos > 0 ? pageUpPos : 0;
502 scrollFrame.setOrigin(origin.x, pageUpPos);
503 }
504
505 });
506 // Describe table
507 applyTableLayout(table);
508
509 int borderWidth = table.getBorderWidth();
510
511 int itemHeight = table.getItemHeight();
512 int headerHeight = table.getHeaderHeight();
513 table.getVerticalBar().setVisible(false);
514
515 tsfviewer = TmfViewerFactory.createViewer(sash,
516 new TimeRangeViewerProvider());
517
518 tsfviewer.addWidgetSelectionListner(this);
519 tsfviewer.addWidgetTimeScaleSelectionListner(this);
520
521 // Traces shall not be grouped to allow synchronization
522 tsfviewer.groupTraces(false);
523 tsfviewer.setItemHeight(itemHeight);
524 tsfviewer.setBorderWidth(borderWidth);
525 tsfviewer.setHeaderHeight(headerHeight);
526 tsfviewer.setVisibleVerticalScroll(false);
527 // Names provided by the table
528 tsfviewer.setNameWidthPref(0);
529 tsfviewer.setAcceptSelectionAPIcalls(true);
530
531 // Viewer to notify selection to this class
532 // This class will synchronize selections with table.
533 tsfviewer.addWidgetSelectionListner(this);
534 tsfviewer.addFilterSelectionListner(this);
535 tsfviewer.addWidgetTimeScaleSelectionListner(this);
536
537 sash.setWeights(new int[] { 1, 1 });
538 // Create the help context id for the viewer's control
539 // TODO: Associate with help system
540 PlatformUI.getWorkbench().getHelpSystem().setHelp(
541 tableViewer.getControl(),
542 "org.eclipse.linuxtools.lttnng.ui.views.flow.viewer"); //$NON-NLS-1$
543
544 makeActions();
545 hookContextMenu();
546 hookDoubleClickAction();
547 contributeToActionBars();
548
549 scrollFrame.addControlListener(new ControlAdapter() {
550 @Override
551 public void controlResized(ControlEvent e) {
552 tsfviewer.resizeControls();
553 updateScrolls(scrollFrame, wrapper);
554 }
555 });
556
557 tableComposite.addControlListener(new ControlListener() {
558 public void controlResized(ControlEvent e) {
559 scrollFrame.getParent().update();
560 }
561
562 public void controlMoved(ControlEvent e) {
563
564 }
565 });
566
567 // Register the updater in charge to refresh elements as we update the
568 // time ranges
569 // FlowParamsUpdater listener = FlowModelFactory.getParamsUpdater();
570 // tsfviewer.addWidgetTimeScaleSelectionListner(listener);
571
572 // Register this view to receive updates when the model is updated with
573 // fresh info
574 // ModelListenFactory.getRegister().addFlowModelUpdatesListener(this);
575
576 // Register the event processor factory in charge of event handling
577 EventProcessorProxy.getInstance().addEventProcessorFactory(
578 FlowTRangeUpdateFactory.getInstance());
579
580 // set the initial view parameter values
581 // Experiment start and end time
582 // as well as time space width in pixels, used by the time analysis
583 // widget
584 ParamsUpdater paramUpdater = FlowModelFactory.getParamsUpdater();
585 StateExperimentManager experimentManger = StateManagerFactory
586 .getExperimentManager();
587 // Read relevant values
588 int timeSpaceWidth = tsfviewer.getTimeSpace();
589 TmfTimeRange timeRange = experimentManger.getExperimentTimeRange();
590 if (timeRange != null) {
591 long time0 = timeRange.getStartTime().getValue();
592 long time1 = timeRange.getEndTime().getValue();
593 paramUpdater.update(time0, time1, timeSpaceWidth);
594 }
595
596 experimentManger.readExperiment("flowView", this);
597 }
598
599 private void hookContextMenu() {
600 MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
601 menuMgr.setRemoveAllWhenShown(true);
602 menuMgr.addMenuListener(new IMenuListener() {
603 public void menuAboutToShow(IMenuManager manager) {
604 ControlFlowView.this.fillContextMenu(manager);
605 }
606 });
607 Menu menu = menuMgr.createContextMenu(tableViewer.getControl());
608 tableViewer.getControl().setMenu(menu);
609 getSite().registerContextMenu(menuMgr, tableViewer);
610 }
611
612 private void contributeToActionBars() {
613 IActionBars bars = getViewSite().getActionBars();
614 fillLocalPullDown(bars.getMenuManager());
615 fillLocalToolBar(bars.getToolBarManager());
616 }
617
618 private void fillLocalPullDown(IMenuManager manager) {
619 manager.add(new Separator());
620 // manager.add(showLegend);
621 manager.add(new Separator());
622 manager.add(resetScale);
623 manager.add(nextEvent);
624 manager.add(prevEvent);
625 manager.add(nextTrace);
626 manager.add(prevTrace);
627 // manager.add(filterTraces);
628 manager.add(zoomIn);
629 manager.add(zoomOut);
630 manager.add(synch);
631 manager.add(new Separator());
632 }
633
634 private void fillContextMenu(IMenuManager manager) {
635 // manager.add(showLegend);
636 manager.add(new Separator());
637 manager.add(resetScale);
638 manager.add(nextEvent);
639 manager.add(prevEvent);
640 manager.add(nextTrace);
641 manager.add(prevTrace);
642 // manager.add(showLegend);
643 // manager.add(filterTraces);
644 manager.add(zoomIn);
645 manager.add(zoomOut);
646 manager.add(synch);
647 manager.add(new Separator());
648 manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
649 }
650
651 private void fillLocalToolBar(IToolBarManager manager) {
652 // manager.add(showLegend);
653 manager.add(new Separator());
654 manager.add(resetScale);
655 manager.add(nextEvent);
656 manager.add(prevEvent);
657 manager.add(nextTrace);
658 manager.add(prevTrace);
659 // manager.add(filterTraces);
660 manager.add(zoomIn);
661 manager.add(zoomOut);
662 manager.add(synch);
663 manager.add(new Separator());
664 }
665
666 private void makeActions() {
667 // action4
668 resetScale = new Action() {
669 @Override
670 public void run() {
671 if (tsfviewer != null) {
672 tsfviewer.resetStartFinishTime();
673 }
674
675 }
676 };
677 resetScale.setText(Messages.getString("ControlFlowView.Action.Reset")); //$NON-NLS-1$
678 resetScale.setToolTipText(Messages
679 .getString("ControlFlowView.Action.Reset.ToolTip")); //$NON-NLS-1$
680 resetScale.setImageDescriptor(AbstractUIPlugin
681 .imageDescriptorFromPlugin(Messages
682 .getString("ControlFlowView.tmf.UI"),
683 "icons/home_nav.gif"));
684
685 // action5
686 nextEvent = new Action() {
687 @Override
688 public void run() {
689 if (tsfviewer != null) {
690 tsfviewer.selectNextEvent();
691 }
692 }
693 };
694 nextEvent.setText(Messages
695 .getString("ControlFlowView.Action.NextEvent")); //$NON-NLS-1$
696 nextEvent.setToolTipText(Messages
697 .getString("ControlFlowView.Action.NextEvent.Tooltip")); //$NON-NLS-1$
698 nextEvent.setImageDescriptor(AbstractUIPlugin
699 .imageDescriptorFromPlugin(Messages
700 .getString("ControlFlowView.tmf.UI"),
701 "icons/next_event.gif"));
702
703 // action6
704 prevEvent = new Action() {
705 @Override
706 public void run() {
707 if (tsfviewer != null) {
708 tsfviewer.selectPrevEvent();
709 }
710 }
711 };
712 prevEvent.setText(Messages
713 .getString("ControlFlowView.Action.PrevEvent")); //$NON-NLS-1$
714 prevEvent.setToolTipText(Messages
715 .getString("ControlFlowView.Action.PrevEvent.Tooltip")); //$NON-NLS-1$
716 prevEvent.setImageDescriptor(AbstractUIPlugin
717 .imageDescriptorFromPlugin(Messages
718 .getString("ControlFlowView.tmf.UI"),
719 "icons/prev_event.gif"));
720
721 // action7
722 nextTrace = new Action() {
723 @Override
724 public void run() {
725 if (tsfviewer != null) {
726 tsfviewer.selectNextTrace();
727 }
728 }
729 };
730 nextTrace.setText(Messages
731 .getString("ControlFlowView.Action.NextProcess")); //$NON-NLS-1$
732 nextTrace.setToolTipText(Messages
733 .getString("ControlFlowView.Action.NextProcess.ToolTip")); //$NON-NLS-1$
734 nextTrace.setImageDescriptor(AbstractUIPlugin
735 .imageDescriptorFromPlugin(Messages
736 .getString("ControlFlowView.tmf.UI"),
737 "icons/next_item.gif"));
738
739 // action8
740 prevTrace = new Action() {
741 @Override
742 public void run() {
743 if (tsfviewer != null) {
744 tsfviewer.selectPrevTrace();
745 }
746 }
747 };
748 prevTrace.setText(Messages
749 .getString("ControlFlowView.Action.PreviousProcess")); //$NON-NLS-1$
750 prevTrace.setToolTipText(Messages
751 .getString("ControlFlowView.Action.PreviousProcess.Tooltip")); //$NON-NLS-1$
752 prevTrace.setImageDescriptor(AbstractUIPlugin
753 .imageDescriptorFromPlugin(Messages
754 .getString("ControlFlowView.tmf.UI"),
755 "icons/prev_item.gif"));
756
757 // action9
758 showLegend = new Action() {
759 @Override
760 public void run() {
761 if (tsfviewer != null) {
762 tsfviewer.showLegend();
763 }
764 }
765 };
766 showLegend.setText(Messages.getString("ControlFlowView.Action.Legend")); //$NON-NLS-1$
767 showLegend.setToolTipText(Messages
768 .getString("ControlFlowView.Action.Legend.ToolTip")); //$NON-NLS-1$
769
770 // action10
771 filterTraces = new Action() {
772 @Override
773 public void run() {
774 if (tsfviewer != null) {
775 tsfviewer.filterTraces();
776 }
777 }
778 };
779 filterTraces.setText(Messages
780 .getString("ControlFlowView.Action.Filter")); //$NON-NLS-1$
781 filterTraces.setToolTipText(Messages
782 .getString("ControlFlowView.Action.Filter.ToolTip")); //$NON-NLS-1$
783 filterTraces.setImageDescriptor(AbstractUIPlugin
784 .imageDescriptorFromPlugin(Messages
785 .getString("ControlFlowView.tmf.UI"),
786 "icons/filter_items.gif"));
787
788 // action10
789 zoomIn = new Action() {
790 @Override
791 public void run() {
792 if (tsfviewer != null) {
793 tsfviewer.zoomIn();
794 }
795 }
796 };
797 zoomIn.setText(Messages.getString("ControlFlowView.Action.ZoomIn")); //$NON-NLS-1$
798 zoomIn.setToolTipText(Messages
799 .getString("ControlFlowView.Action.ZoomIn.Tooltip")); //$NON-NLS-1$
800 zoomIn.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
801 Messages.getString("ControlFlowView.tmf.UI"),
802 "icons/zoomin_nav.gif"));
803
804 // action10
805 zoomOut = new Action() {
806 @Override
807 public void run() {
808 if (tsfviewer != null) {
809 tsfviewer.zoomOut();
810 }
811 }
812 };
813 zoomOut.setText(Messages.getString("ControlFlowView.Action.ZoomOut")); //$NON-NLS-1$
814 zoomOut.setToolTipText(Messages
815 .getString("ControlFlowView.Action.ZoomOut.tooltip")); //$NON-NLS-1$
816 zoomOut.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
817 Messages.getString("ControlFlowView.tmf.UI"),
818 "icons/zoomout_nav.gif"));
819
820 // action11
821 synch = new Action() {
822 @Override
823 public void run() {
824 // Note: No action since the synch flag is used by Control flow
825 // view
826 // the actual viewer is set to accept api selections in
827 // createpartcontrol.
828
829 // if (synch.isChecked()) {
830 // tsfviewer.setAcceptSelectionAPIcalls(true);
831 // } else {
832 // tsfviewer.setAcceptSelectionAPIcalls(false);
833 // }
834 }
835 };
836 synch.setText(Messages.getString("ControlFlowView.Action.Synchronize")); //$NON-NLS-1$
837 synch.setToolTipText(Messages
838 .getString("ControlFlowView.Action.Synchronize.ToolTip")); //$NON-NLS-1$
839 synch.setChecked(false);
840 synch.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
841 Messages.getString("ControlFlowView.tmf.UI"),
842 "icons/synced.gif"));
843 // PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ELCL_SYNCED);
844
845 doubleClickAction = new Action() {
846 @Override
847 public void run() {
848 ISelection selection = tableViewer.getSelection();
849 Object obj = ((IStructuredSelection) selection)
850 .getFirstElement();
851 showMessage("Double-click detected on " + obj.toString()); //$NON-NLS-1$
852 }
853 };
854 }
855
856 private void hookDoubleClickAction() {
857 tableViewer.addDoubleClickListener(new IDoubleClickListener() {
858 public void doubleClick(DoubleClickEvent event) {
859 doubleClickAction.run();
860 }
861 });
862 }
863
864 private void showMessage(String message) {
865 MessageDialog.openInformation(tableViewer.getControl().getShell(),
866 Messages.getString("ControlFlowView.msgSlogan"), message); //$NON-NLS-1$
867 }
868
869 /**
870 * Passing the focus request to the viewer's control.
871 */
872 @Override
873 public void setFocus() {
874 tableViewer.getControl().setFocus();
875 }
876
877 public void tsfTmProcessSelEvent(TmfTimeSelectionEvent event) {
878 Object source = event.getSource();
879 if (source == null) {
880 return;
881 }
882
883 // Reselect the table viewer to widget selection
884 ISelection sel = tsfviewer.getSelectionTrace();
885 if (sel != null && !sel.isEmpty()) {
886 tableViewer.setSelection(sel);
887 }
888
889 ParamsUpdater paramUpdater = ResourceModelFactory.getParamsUpdater();
890 Long savedSelTime = paramUpdater.getSelectedTime();
891
892 long selTimens = event.getSelectedTime();
893
894 // make sure the new selected time is different than saved before
895 // executing update
896 if (savedSelTime == null || savedSelTime != selTimens) {
897 // Notify listener views.
898 synchTimeNotification(selTimens);
899
900 // Update the parameter updater to save the selected time
901 paramUpdater.setSelectedTime(selTimens);
902
903 if (TraceDebug.isDEBUG()) {
904 // Object selection = event.getSelection();
905 TraceDebug.debug("Selected Time in control Flow View: "
906 + new LttngTimestamp(selTimens));
907 }
908 }
909 }
910
911 public void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event) {
912 // source needed to keep track of source values
913 Object source = event.getSource();
914
915 if (source != null) {
916 // Update the parameter updater before carrying out a read request
917 ParamsUpdater paramUpdater = FlowModelFactory.getParamsUpdater();
918 boolean newParams = paramUpdater.processTimeScaleEvent(event);
919
920 if (newParams) {
921 // Read the updated time window
922 TmfTimeRange trange = paramUpdater.getTrange();
923 if (trange != null) {
924 StateManagerFactory.getExperimentManager()
925 .readExperimentTimeWindow(trange, "flowView", this);
926 }
927 }
928 }
929 }
930
931 /**
932 * Obtains the remainder fraction on unit Seconds of the entered value in
933 * nanoseconds. e.g. input: 1241207054171080214 ns The number of seconds can
934 * be obtain by removing the last 9 digits: 1241207054 the fractional
935 * portion of seconds, expressed in ns is: 171080214
936 *
937 * @param v
938 * @return
939 */
940 public String formatNs(long v) {
941 StringBuffer str = new StringBuffer();
942 boolean neg = v < 0;
943 if (neg) {
944 v = -v;
945 str.append('-');
946 }
947
948 String strVal = String.valueOf(v);
949 if (v < 1000000000) {
950 return strVal;
951 }
952
953 // Extract the last nine digits (e.g. fraction of a S expressed in ns
954 return strVal.substring(strVal.length() - 9);
955 }
956
957 private void applyTableLayout(Table table) {
958 for (int i = 0; i < columnNames.length; i++) {
959 TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
960 tableColumn.setText(columnNames[i]);
961 tableColumn.pack();
962 }
963 table.setHeaderVisible(true);
964 table.setLinesVisible(true);
965 }
966
967 // @Override
968 public void flowModelUpdates(final ITmfTimeAnalysisEntry[] items,
969 final long startTime, final long endTime) {
970 final Table table = tableViewer.getTable();
971 Display display = table.getDisplay();
972
973 // Perform the updates on the UI thread
974 display.asyncExec(new Runnable() {
975 public void run() {
976 tableViewer.setInput(items); // This shall be the minimal
977 // initial
978 tableFilter = new ViewProcessFilter(tableViewer);
979 tableViewer.setFilters(new ViewerFilter[] { tableFilter });
980
981 resizeTableColumns(table);
982 table.update();
983 tableViewer.refresh();
984
985 tsfviewer.display(items, startTime, endTime);
986 tsfviewer.resizeControls();
987
988 // Adjust the size of the vertical scroll bar to fit the
989 // contents
990 if (scrollFrame != null && wrapper != null) {
991 updateScrolls(scrollFrame, wrapper);
992 // scrollFrame.update();
993 }
994 }
995 });
996 }
997
998 @Override
999 public void dispose() {
1000 // dispose parent resources
1001 super.dispose();
1002 // Remove the event processor factory
1003 EventProcessorProxy.getInstance().removeEventProcessorFactory(
1004 FlowTRangeUpdateFactory.getInstance());
1005
1006 // Remove listener to model updates
1007 // ModelListenFactory.getRegister().removeFlowModelUpdatesListener(this);
1008 tsfviewer.removeFilterSelectionListner(this);
1009 tsfviewer.removeWidgetSelectionListner(this);
1010 tsfviewer.removeWidgetTimeScaleSelectionListner(this);
1011 tableViewer = null;
1012 tsfviewer = null;
1013 }
1014
1015 /**
1016 * @param tableComposite
1017 * @param table
1018 */
1019 private synchronized void resizeTableColumns(Table table) {
1020 if (table != null) {
1021 Composite parent = table.getParent();
1022 int tableWidthSum = parent.getBorderWidth();
1023
1024 TableColumn[] columns = table.getColumns();
1025 for (TableColumn column : columns) {
1026 column.pack();
1027 tableWidthSum += column.getWidth();
1028 }
1029 }
1030 }
1031
1032 // @Override
1033 public void tmfTaProcessFilterSelection(TmfTimeFilterSelectionEvent event) {
1034 if (tableFilter != null) {
1035 Vector<ITmfTimeAnalysisEntry> filteredout = event.getFilteredOut();
1036 if (filteredout != null) {
1037 tableFilter.setFilter(filteredout);
1038 } else {
1039 tableFilter.setFilter(new Vector<ITmfTimeAnalysisEntry>());
1040 }
1041 tableViewer.refresh();
1042 }
1043 }
1044
1045 /*
1046 * (non-Javadoc)
1047 *
1048 * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener#
1049 * processingCompleted(org.eclipse.linuxtools.lttng.state.StateDataRequest)
1050 */
1051 @TmfSignalHandler
1052 public void processingCompleted(RequestCompletedSignal signal) {
1053 StateDataRequest request = signal.getRequest();
1054
1055 if (request == null) {
1056 return;
1057 } else {
1058 // Remove from the pending requests record
1059 pendingDataRequests.remove(request);
1060 }
1061
1062 // No data refresh actions for cancelled requests.
1063 if (request.isCancelled() || request.isFailed()) {
1064 if (TraceDebug.isDEBUG()) {
1065 TmfTimeRange range = request.getRange();
1066 TraceDebug.debug("Request cancelled: "
1067 + range.getStartTime().toString() + " - "
1068 + range.getEndTime().toString());
1069 }
1070
1071 return;
1072 }
1073
1074 long experimentStartTime = -1;
1075 long experimentEndTime = -1;
1076 StateManager smanager = request.getStateManager();
1077 TmfTimeRange experimentTimeRange = smanager.getExperimentTimeWindow();
1078 if (experimentTimeRange != null) {
1079 experimentStartTime = experimentTimeRange.getStartTime().getValue();
1080 experimentEndTime = experimentTimeRange.getEndTime().getValue();
1081 }
1082
1083 // Obtain the current process list
1084 Vector<TimeRangeEventProcess> processList = FlowModelFactory
1085 .getProcContainer().readProcesses();
1086 // convert it to an Array as expected by the widget
1087 TimeRangeEventProcess[] processArr = processList
1088 .toArray(new TimeRangeEventProcess[processList.size()]);
1089 // Sort the array by pid
1090 Arrays.sort(processArr);
1091
1092 // Update the view part
1093 flowModelUpdates(processArr, experimentStartTime, experimentEndTime);
1094
1095 // reselect to original time
1096 ParamsUpdater paramUpdater = ResourceModelFactory.getParamsUpdater();
1097 final Long selTime = paramUpdater.getSelectedTime();
1098 if (selTime != null) {
1099 Display display = tsfviewer.getControl().getDisplay();
1100 display.asyncExec(new Runnable() {
1101 public void run() {
1102 tsfviewer.setSelectedTime(selTime, false, this);
1103 }
1104 });
1105 }
1106
1107 if (TraceDebug.isDEBUG()) {
1108 int eventCount = 0;
1109 Long count = smanager.getEventCount();
1110 for (TimeRangeEventProcess process : processList) {
1111 eventCount += process.getTraceEvents().size();
1112 }
1113
1114 int discarded = FlowModelFactory.getParamsUpdater()
1115 .getEventsDiscarded();
1116 int discardedOutofOrder = ResourceModelFactory.getParamsUpdater()
1117 .getEventsDiscardedWrongOrder();
1118 TraceDebug
1119 .debug("Events handled: "
1120 + count
1121 + " Events loaded in Control Flow view: "
1122 + eventCount
1123 + " Number of events discarded: "
1124 + discarded
1125 + "\n\tNumber of events discarded with start time earlier than next good time: "
1126 + discardedOutofOrder);
1127 }
1128 }
1129
1130 /*
1131 * (non-Javadoc)
1132 *
1133 * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener#
1134 * processingStarted(org.eclipse.linuxtools.lttng.state.StateDataRequest)
1135 */
1136 @TmfSignalHandler
1137 public void processingStarted(RequestStartedSignal signal) {
1138 StateDataRequest request = signal.getRequest();
1139 cancelPendingRequests();
1140 if (request != null) {
1141 // make sure there are no duplicates
1142 if (!pendingDataRequests.contains(request)) {
1143 pendingDataRequests.add(request);
1144 }
1145 pendingDataRequests.add(request);
1146 StateManager smanager = request.getStateManager();
1147 // Clear the children on the Processes related to this manager.
1148 // Leave the GUI in charge of the updated data.
1149 String traceId = smanager.getEventLog().getName();
1150 FlowModelFactory.getProcContainer().clearChildren(traceId);
1151 // Start over
1152 FlowModelFactory.getParamsUpdater().setEventsDiscarded(0);
1153 }
1154 }
1155
1156 /**
1157 * Orders cancellation of any pending data requests
1158 */
1159 private void cancelPendingRequests() {
1160 for (StateDataRequest request : pendingDataRequests) {
1161 request.cancel();
1162 }
1163 pendingDataRequests.clear();
1164 }
1165
1166 /**
1167 * @param scrollFrame
1168 * @param wrapper
1169 */
1170 private void updateScrolls(final ScrolledComposite scrollFrame,
1171 final Composite wrapper) {
1172
1173 Point ptSize = wrapper.computeSize(SWT.DEFAULT, SWT.DEFAULT);
1174 wrapper.setSize(ptSize);
1175 scrollFrame.setMinSize(ptSize);
1176
1177 // calculate the increment area considering the table header height and
1178 // borders
1179 Rectangle area = top.getBounds();
1180 int marginsHeight = tableViewer.getTable().getHeaderHeight();
1181 marginsHeight -= top.getBorderWidth() + wrapper.getBorderWidth();
1182 area.height -= marginsHeight;
1183
1184 // set page vertical increment area
1185 ScrollBar verBar = scrollFrame.getVerticalBar();
1186 ScrollBar horBar = scrollFrame.getHorizontalBar();
1187 if (verBar != null) {
1188 verBar.setPageIncrement(area.height);
1189 }
1190 if (horBar != null) {
1191 horBar.setPageIncrement(area.width);
1192 }
1193
1194 }
1195
1196 /**
1197 * Trigger time synchronisation to other views this method shall be called
1198 * when a check has been performed to note that an actual change of time has
1199 * been performed vs a pure re-selection of the same time
1200 *
1201 * @param time
1202 */
1203 private void synchTimeNotification(long time) {
1204 // if synchronisation selected
1205 if (synch.isChecked()) {
1206 // Notify other views
1207 TmfSignalManager.dispatchSignal(new TmfTimeSynchSignal(this,
1208 new LttngTimestamp(time)));
1209 }
1210 }
1211
1212 /**
1213 * Registers as listener of time selection from other tmf views
1214 *
1215 * @param signal
1216 */
1217 @TmfSignalHandler
1218 public void synchToTime(TmfTimeSynchSignal signal) {
1219 if (synch.isChecked()) {
1220 Object source = signal.getSource();
1221 if (signal != null && source != null && source != this) {
1222 // Internal value is expected in nano seconds.
1223 long selectedTime = signal.getCurrentTime().getValue();
1224 if (tsfviewer != null) {
1225 tsfviewer.setSelectedTime(selectedTime, true, source);
1226 }
1227 }
1228 }
1229 }
1230
1231 }
This page took 0.05606 seconds and 4 git commands to generate.