From b0d3496e8d43ff6d195551af3b311d8f16b9a848 Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Mon, 31 May 2010 19:26:26 +0000 Subject: [PATCH] --- org.eclipse.linuxtools.tmf.ui/.classpath | 7 + org.eclipse.linuxtools.tmf.ui/.project | 28 + .../META-INF/MANIFEST.MF | 20 + .../build.properties | 6 + .../icons/events_view.gif | Bin 0 -> 97 bytes .../icons/filter_items.gif | Bin 0 -> 220 bytes .../icons/home_nav.gif | Bin 0 -> 583 bytes .../icons/next_event.gif | Bin 0 -> 556 bytes .../icons/next_item.gif | Bin 0 -> 345 bytes .../icons/prev_event.gif | Bin 0 -> 554 bytes .../icons/prev_item.gif | Bin 0 -> 339 bytes .../icons/project_view.gif | Bin 0 -> 144 bytes .../icons/synced.gif | Bin 0 -> 160 bytes .../icons/zoomin_nav.gif | Bin 0 -> 560 bytes .../icons/zoomout_nav.gif | Bin 0 -> 560 bytes .../plugin.properties | 3 + .../linuxtools/tmf/ui/TmfUiPlugin.java | 82 + .../linuxtools/tmf/ui/viewers/ITmfViewer.java | 23 + .../tmf/ui/viewers/TmfViewerFactory.java | 38 + .../tmf/ui/viewers/timeAnalysis/GridUtil.java | 45 + .../timeAnalysis/ITimeAnalysisViewer.java | 167 ++ .../ITmfTimeFilterSelectionListener.java | 19 + .../ITmfTimeScaleSelectionListener.java | 24 + .../ITmfTimeSelectionListener.java | 24 + .../tmf/ui/viewers/timeAnalysis/Messages.java | 54 + .../timeAnalysis/TmfTimeAnalysisProvider.java | 327 +++ .../timeAnalysis/TmfTimeAnalysisViewer.java | 836 +++++++ .../TmfTimeFilterSelectionEvent.java | 39 + .../TmfTimeScaleSelectionEvent.java | 79 + .../timeAnalysis/TmfTimeSelectionEvent.java | 49 + .../dialogs/TmfTimeFilterDialog.java | 214 ++ .../timeAnalysis/dialogs/TmfTimeLegend.java | 293 +++ .../viewers/timeAnalysis/messages.properties | 39 + .../timeAnalysis/model/ITimeEvent.java | 30 + .../model/ITmfTimeAnalysisEntry.java | 30 + .../viewers/timeAnalysis/model/TimeEvent.java | 32 + .../widgets/ITimeDataProvider.java | 68 + .../timeAnalysis/widgets/PlainSelection.java | 65 + .../timeAnalysis/widgets/TimeScaleCtrl.java | 787 ++++++ .../widgets/TmfTimeStatesCtrl.java | 2214 +++++++++++++++++ .../widgets/TmfTimeTipHandler.java | 244 ++ .../widgets/TraceColorScheme.java | 378 +++ .../timeAnalysis/widgets/TraceCtrl.java | 67 + .../viewers/timeAnalysis/widgets/Utils.java | 538 ++++ .../tmf/ui/views/TmfEventsView.java | 305 +++ .../linuxtools/tmf/ui/views/TmfView.java | 72 + 46 files changed, 7246 insertions(+) create mode 100644 org.eclipse.linuxtools.tmf.ui/.classpath create mode 100644 org.eclipse.linuxtools.tmf.ui/.project create mode 100644 org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF create mode 100644 org.eclipse.linuxtools.tmf.ui/build.properties create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/events_view.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/filter_items.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/home_nav.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/next_event.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/next_item.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/prev_event.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/prev_item.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/project_view.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/synced.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/zoomin_nav.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/icons/zoomout_nav.gif create mode 100644 org.eclipse.linuxtools.tmf.ui/plugin.properties create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/TmfUiPlugin.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ITmfViewer.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/TmfViewerFactory.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/GridUtil.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITimeAnalysisViewer.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeFilterSelectionListener.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeScaleSelectionListener.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeSelectionListener.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/Messages.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisProvider.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisViewer.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeFilterSelectionEvent.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeScaleSelectionEvent.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeSelectionEvent.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/dialogs/TmfTimeFilterDialog.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/dialogs/TmfTimeLegend.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/messages.properties create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/ITimeEvent.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/ITmfTimeAnalysisEntry.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/TimeEvent.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/ITimeDataProvider.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/PlainSelection.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TimeScaleCtrl.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeStatesCtrl.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeTipHandler.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceColorScheme.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceCtrl.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/Utils.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfEventsView.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfView.java diff --git a/org.eclipse.linuxtools.tmf.ui/.classpath b/org.eclipse.linuxtools.tmf.ui/.classpath new file mode 100644 index 0000000000..64c5e31b7a --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.eclipse.linuxtools.tmf.ui/.project b/org.eclipse.linuxtools.tmf.ui/.project new file mode 100644 index 0000000000..87f2a6bf14 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/.project @@ -0,0 +1,28 @@ + + + org.eclipse.linuxtools.tmf.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..192c41e9b8 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF @@ -0,0 +1,20 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.linuxtools.tmf.ui +Bundle-Version: 0.2.0.qualifier +Bundle-Activator: org.eclipse.linuxtools.tmf.ui.TmfUiPlugin +Bundle-Vendor: %Bundle-Vendor +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.linuxtools.tmf;bundle-version="0.2.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Export-Package: org.eclipse.linuxtools.tmf.ui, + org.eclipse.linuxtools.tmf.ui.viewers, + org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis, + org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.dialogs, + org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model, + org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets, + org.eclipse.linuxtools.tmf.ui.views +Bundle-Localization: plugin diff --git a/org.eclipse.linuxtools.tmf.ui/build.properties b/org.eclipse.linuxtools.tmf.ui/build.properties new file mode 100644 index 0000000000..ae84c65aec --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + icons/,\ + plugin.properties diff --git a/org.eclipse.linuxtools.tmf.ui/icons/events_view.gif b/org.eclipse.linuxtools.tmf.ui/icons/events_view.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ef74cf98f4f2b07ad4af73f0af65049a3cf0e5a GIT binary patch literal 97 zcmZ?wbhEHb6krfwSj4~(Q?)9gZf#og#)(Uh=X7l^ny{;E%D(^q|117vVPs%nXV75) z0+3n;X0?i4cm5ezIXq=zmO0EV=;)jorWvNXtgwxJ-V)9JWxGn_Ph2R9S7WdS0HyOH A^Z)<= literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.tmf.ui/icons/filter_items.gif b/org.eclipse.linuxtools.tmf.ui/icons/filter_items.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef51bd544fbdc7395428d67995ff9a9b881b4b66 GIT binary patch literal 220 zcmZ?wbhEHb6krfwIKseS;S!r)))JmlQ{FNwwRTEO>(Y?!&Aw5w|Ng%J`{~%3g*@Ep*Y~U{NvkRFU9fRo-~QE2#gB^W=jGQoZbjC7BTgs)7ZZU%s^16P^?H_|6-h Ox@?)krsix#25SI#S5~_K literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.tmf.ui/icons/home_nav.gif b/org.eclipse.linuxtools.tmf.ui/icons/home_nav.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd0c66950972e9fd6b4eee2a45293db7b0402a95 GIT binary patch literal 583 zcmZ?wbhEHb6krfwc*ek>=hf;IH{B?(Il6LneC_)9y7e)Ys}kzgCpT_NZrqsBx;3M1 zYfjfr^Oy#Un1=ILZ(q4_=gaqB7ao7P|N7gr_usES|9bEBw__J?ox6Jb!jmu8UwnP~ z{`vgb@~XsXFsG`()# z)P`jC{<4g|#s1N)K&pC%tK(wV?&6UV6I0Yt5EGW+>Ef1>5|vq# o@xi~D$(7S6WrD(k7KT&hOx ziFIxpXNCQ~+k9s4lr0miR`fWno8+;e-E~5Z`@~w0OGg)9Kegi4*|qmBZn}Mb)Ah4k zwoI_uI?;AZzulIJ_G^3WS9d$jYjNM*B)YdnY-hd5o+cnEy1PkiMXtc=0>RaVf~yJy zSL6wCM5XhhdauFy_7}z@-0-Ks!TATQ7HQTyH zjr47-t?jy-#1-urI63UK9P|a-Gz?gnnb_GJg}O~8xEOhjO{N5z%S#D!Z*Df^Yjt++ z){)%DdZ1NZJJ8kXj608jQ>%iNn}~>*(zR}Ix8Y0QUu0d11${8!&)HNl9JEWMHg}o(NS=qQJOb~Zd tV&|B}#l_CfspP82&$onsIiG^JoUELT3@?vNu#3E)^cELoWfw;VYXHBReU|_L literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.tmf.ui/icons/prev_event.gif b/org.eclipse.linuxtools.tmf.ui/icons/prev_event.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed3e7c26eeda82c0dec1a9ca0776df484a740cb9 GIT binary patch literal 554 zcmZ?wbhEHb6krfwc*el+=lkM6Kezq;Qu^=v-2cB0{QLX<|7-jI@1y^}OZfk}`Tws= zjg{Vif808?#lNw__u%%nzu#}2+T?e7vww4i_n!}Yj_;d#`SkKBO)ec(o~;$$zaLNd z{ba)L#}j`)nb=h3b7*tTksW=1-tYN+ul4u+w%-pre?RQpxisU1_**ej7 zOTXQgiS}!{?bi0#ukLo5*W$jnMQme*@UBMDU5#QZ^8{9akl@-Pp-tt&%d!Rj|NqZ0 zh=Jly7DfgJZw4KZ8$ofxz~0{A-PGLD+Qe_I(bg?$q;F+uY17>#reMRs$zi8yuP@l9 zZotCK#Lng*)NLxx#mH-HGR50mPEweAbF(2|i=*Qd9f@W~)&t#Y+D(oEJp0eL$ZL7K zh+GpE&b4`+0544Lq+wy$~#q$ZdWB`cQ^Ono4s_sc5!GjdT0nR GSOWmYUAo)= literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.tmf.ui/icons/prev_item.gif b/org.eclipse.linuxtools.tmf.ui/icons/prev_item.gif new file mode 100644 index 0000000000000000000000000000000000000000..c16474aad48a749eedc27dad7b0158aaeaee5cf8 GIT binary patch literal 339 zcmZ?wbhEHb6krfwxXQrr|Ns1df8YQ8aqI8*TmSFJ|M{@z_u~n_pG^4uc;fFT6aT#5 z^ZQ=w@B3}PA9VhH*tvhc{qMWY|9^kj+amUVzx}M<;*Ax;yBbAzHHxjw6IcO4f@_O} zHkAu6%NDpl-#*V*_2`Zj*AMTWlMxnTVetR|e+Fs;#h)yU3=Ap^Iv|5VeqvxNaF|r! zp(Ez1JaOZXpFIqVp9TG>6j;}PUc_@jk4DRrB9oatN-3X(EI$UFS(tg%xxPVVQfl!N z$-B&z(aMTK%uE#>-r}r1tX#cft}+~KY@D3z>{CVEq*IQghNsY+tXkpKpcfp)vCJ_O*fz()`; OzdrMMtX{Vt5db^*GD&v; literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.tmf.ui/icons/zoomin_nav.gif b/org.eclipse.linuxtools.tmf.ui/icons/zoomin_nav.gif new file mode 100644 index 0000000000000000000000000000000000000000..31441e34e438f640b7b35268c758c016440093fd GIT binary patch literal 560 zcmZ?wbhEHb6krfwc*elcnv?(H+4KMZ{y%;E?8Cdy{rxlFz5o9D&Bvd={(b)P7G<>+Wmo$< z^%Q3Hl;+RvX#Vl#^T)Sux(ajJOAG)1|Nr~Fz1UmpySorVO4JkL7CJ0C{u=27pF<1it6s-XG literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.tmf.ui/icons/zoomout_nav.gif b/org.eclipse.linuxtools.tmf.ui/icons/zoomout_nav.gif new file mode 100644 index 0000000000000000000000000000000000000000..1f874009adf2835898ea0dd034adcbe41777815b GIT binary patch literal 560 zcmZ?wbhEHb6krfwc*elcnv?(H+4KMZ{y%;E?8Cdy{rxjvzxnv{*T2tSe!P19{?X&- z+jk%9pSJAD^LI;DZQFnJ;-A0&fBpXZ^VgrxU%owi{<3H4vKOyEJbC`+(bHG!w;yWi znQ`m>(@i@MPMW>w>aBZ^pTD~M@X4)v4;k||FlMY|Oj*iMx|OkX8)N?Z14mEXe(;!~ za@X$t2VTB?_u|dl$IoBfdGN5ItNZfJn=jtI`}zCVw;$g>fBmw3-}bHBw@jHn;qtZ9 z8@J4yzhK6{e}67rx^VI0`MrBq?b$JP-SXna^C}k3Z8~*q<+3GHx2~vB!>pOp|Nr~*`O}BFGpEh#s;>;ND-Uq&EXryt z%C7cz>M6|XDb1hT(fs4f=Z|mSbQR{bmlpp2|Nr;z-$0Uq+CcFq3nK$V3WE;FU{IVe zu=h5kG&Q%hwzxaG`FgsvH9Pn*2b&7}d-wTxFfs|)1SQ8iwK*pV8Vd=r3z=AXwYny$ zs3TmfUiPlugin + *

+ * The activator class controls the plug-in life cycle + */ +public class TmfUiPlugin extends AbstractUIPlugin { + + // ======================================================================== + // Attributes + // ======================================================================== + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.linuxtools.tmf.ui"; + + // The shared instance + private static TmfUiPlugin plugin; + + // ======================================================================== + // Constructors + // ======================================================================== + + /** + * The constructor + */ + public TmfUiPlugin() { + } + + // ======================================================================== + // Accessors + // ======================================================================== + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static TmfUiPlugin getDefault() { + return plugin; + } + + // ======================================================================== + // Operators + // ======================================================================== + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ITmfViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ITmfViewer.java new file mode 100644 index 0000000000..7ce82bb300 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ITmfViewer.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers; + +/** + * ITmfWidget + *

+ * + * TODO: Implement me. Please. + */ +public interface ITmfViewer { + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/TmfViewerFactory.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/TmfViewerFactory.java new file mode 100644 index 0000000000..b30f8d44e9 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/TmfViewerFactory.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisViewer; +import org.eclipse.swt.widgets.Composite; + +/** + * TmfWidgetFactory + *

+ * + * TODO: Generalize when extension points are introduced + * TODO: Today, it is specific for the TimeAnalysis widget + */ +public class TmfViewerFactory { + +// public static ITmfWidget createWidget(String id, Composite parent) { +// return null; +// } + + public static ITimeAnalysisViewer createViewer(Composite parent, + TmfTimeAnalysisProvider provider) { + return new TmfTimeAnalysisViewer(parent, provider); + } + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/GridUtil.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/GridUtil.java new file mode 100644 index 0000000000..95e1250e92 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/GridUtil.java @@ -0,0 +1,45 @@ +/********************************************************************** + * Copyright (c) 2005, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * $Id: GridUtil.java,v 1.3 2006/09/20 19:49:13 ewchan Exp $ + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; + +/** + * A utility class to create convenient grid data objects. + */ +public class GridUtil +{ + /** + * Creates a grid data object that occupies vertical and horizontal + * space. + */ + static public GridData createFill() + { + return new GridData(SWT.FILL, SWT.FILL, true, true); + } + /** + * Creates a grid data object that occupies horizontal space. + */ + static public GridData createHorizontalFill() + { + return new GridData(SWT.FILL, SWT.DEFAULT, true, false); + } + /** + * Creates a grid data object that occupies vertical space. + */ + static public GridData createVerticalFill() + { + return new GridData(SWT.DEFAULT, SWT.FILL, false, true); + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITimeAnalysisViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITimeAnalysisViewer.java new file mode 100644 index 0000000000..d1bb5ada04 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITimeAnalysisViewer.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + + package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.linuxtools.tmf.ui.viewers.ITmfViewer; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.TimeEvent; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.widgets.Control; + +/** + * ITimeAnalysisWidget + *

+ * + * TODO: Implement me. Please. + */ +public interface ITimeAnalysisViewer extends ITmfViewer { + + public enum TimeFormat { + RELATIVE, ABSOLUTE + }; + + /** + * @param e + */ + public void controlResized(ControlEvent e); + + /** + * + * @param traceArr + * @param start + * Specifies a fixed start time to the information to be + * displayed + * @param end + * Specifies a fixed end time to the information to be displayed + * @param updateTimeBounds + * If True - Time Range boundaries update is required + */ + public abstract void display(ITmfTimeAnalysisEntry[] traceArr, long start, + long end, boolean updateTimeBounds); + + /** + * The start and End time are taken from the limits used by the children + * events + * + * @param traceArr + */ + public abstract void display(ITmfTimeAnalysisEntry[] traceArr); + + public void addWidgetSelectionListner(ITmfTimeSelectionListener listener); + + public void addWidgetTimeScaleSelectionListner( + ITmfTimeScaleSelectionListener listener); + + public void filterTraces(); + + public ITmfTimeAnalysisEntry getSelectedTrace(); + + public ISelection getSelection(); + + public void groupTraces(boolean on); + + public boolean isInFocus(); + + public void removeWidgetSelectionListner(ITmfTimeSelectionListener listener); + + public void removeWidgetTimeScaleSelectionListner( + ITmfTimeScaleSelectionListener listener); + + public void resetStartFinishTime(); + + public void selectNextEvent(); + + public void selectPrevEvent(); + + public void selectNextTrace(); + + public void selectPrevTrace(); + + public void showLegend(); + + public void zoomIn(); + + public void zoomOut(); + + public void setSelectedTime(long time, boolean ensureVisible, Object source); + + public void setSelectedEvent(ITimeEvent event, Object Source); + + public void setSelectedTraceTime(ITmfTimeAnalysisEntry trace, long time, Object Source); + + public void setSelectVisTimeWindow(long time0, long time1, Object Source); + + public void setAcceptSelectionAPIcalls(boolean acceptCalls); + + public void setTimeCalendarFormat(boolean toAbsoluteCaltime); + + public boolean isCalendarFormat(); + + public boolean isVisibleVerticalScroll(); + + public void setVisibleVerticalScroll(boolean visibleVerticalScroll); + + public int getBorderWidth(); + + public void setBorderWidth(int borderWidth); + + public int getHeaderHeight(); + + public void setHeaderHeight(int headerHeight); + + public int getItemHeight(); + + public void setItemHeight(int rowHeight); + + public void resizeControls(); + + public void setSelectedTrace(ITmfTimeAnalysisEntry trace); + + public ISelection getSelectionTrace(); + + public void setNameWidthPref(int width); + + public int getNameWidthPref(int width); + + public void addFilterSelectionListner(ITmfTimeFilterSelectionListener listener); + + public void removeFilterSelectionListner( + ITmfTimeFilterSelectionListener listener); + + public int getTimeSpace(); + + public void itemUpdate(ITmfTimeAnalysisEntry parent, TimeEvent item); + + public Control getControl(); + + public ISelectionProvider getSelectionProvider(); + + /** + *

+ * Provide the possibility to control the wait cursor externally + *

+ *

+ * e.g. data requests in progress + *

+ * + * @param waitInd + * - true change to wait cursor + */ + public void waitCursor(boolean waitInd); + + public void setFocus(); + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeFilterSelectionListener.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeFilterSelectionListener.java new file mode 100644 index 0000000000..0b102038f6 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeFilterSelectionListener.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import java.util.EventListener; + +public interface ITmfTimeFilterSelectionListener extends EventListener { + public void tmfTaProcessFilterSelection(TmfTimeFilterSelectionEvent event); +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeScaleSelectionListener.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeScaleSelectionListener.java new file mode 100644 index 0000000000..f73845bcaa --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeScaleSelectionListener.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import java.util.EventListener; + +/** + * Implemented by any user of TmfTime in order to be notified of available events, + * upon registration + * + */ +public interface ITmfTimeScaleSelectionListener extends EventListener { + public void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event); +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeSelectionListener.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeSelectionListener.java new file mode 100644 index 0000000000..77d7b828ba --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/ITmfTimeSelectionListener.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import java.util.EventListener; + +/** + * Implemented by any user of TsfTm in order to be notified of available events, + * upon registration + * + */ +public interface ITmfTimeSelectionListener extends EventListener { + public void tsfTmProcessSelEvent(TmfTimeSelectionEvent event); +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/Messages.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/Messages.java new file mode 100644 index 0000000000..32e1dd3ff7 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/Messages.java @@ -0,0 +1,54 @@ +/********************************************************************** + * Copyright (c) 2005, 2008, 2009, 2010 IBM Corporation, Intel Corporation, Ericsson + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * $Id: UIMessages.java,v 1.18 2008/06/03 16:53:41 aalexeev Exp $ + * + * Contributors: + * IBM - Initial API and implementation + * Alvaro Sanchez-Leon - Stripped down for TMF + **********************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import org.eclipse.osgi.util.NLS; + +public class Messages { + + private static final String BUNDLE_NAME = "org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.messages"; //$NON-NLS-1$ + public static String TRACE_STATES_TITLE; + + public static String _TRACE_ID; + public static String _TRACE_NAME; + public static String _TRACE_CLASS_NAME; + public static String _TRACE_GROUP_NAME; + public static String _TRACE_START_TIME; + public static String _TRACE_EVENT_TIME; + public static String _TRACE_DATE; + public static String _TRACE_STOP_TIME; + public static String _TRACE_STATE; + public static String _NUMBER_OF_TRACES; + public static String _TRACE_FILTER; + public static String _TRACE_FILTER_DESC; + // misc + public static String _Timescale; + public static String _DURATION; + public static String _UNDEFINED_GROUP; + public static String _TRACE_GROUP_LABEL; + public static String _EDIT_PROFILING_OPTIONS; + + public static String _LEGEND; + public static String _TRACE_STATES; + public static String _WINDOW_TITLE; + + private Messages() { + // Do not instantiate + } + + static { + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisProvider.java new file mode 100644 index 0000000000..ce95945b14 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisProvider.java @@ -0,0 +1,327 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import java.util.List; +import java.util.Map; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.TimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.TraceColorScheme; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; + +public abstract class TmfTimeAnalysisProvider { + + static public final int IMG_THREAD_RUNNING = 0; + static public final int IMG_THREAD_SUSPENDED = 1; + static public final int IMG_THREAD_STOPPED = 2; + static public final int IMG_METHOD_RUNNING = 3; + static public final int IMG_METHOD = 4; + static public final int IMG_NUM = 5; + + public enum StateColor { + GREEN, DARK_BLUE, RED, GOLD, ORANGE, GRAY, BLACK, DARK_GREEN, DARK_YELLOW, MAGENTA3, PURPLE1, PINK1, AQUAMARINE, LIGHT_BLUE, CADET_BLUE, OLIVE; + + private String stateName; + + StateColor() { + String undef = new String("Undefined"); + this.stateName = undef; + } + + public String getStateName() { + return stateName; + } + + public void setStateName(String stateName) { + this.stateName = stateName; + } + } + + // static private String _externalPath[] = { + // "icons/full/obj16/thread_obj.gif", // running thread + // "icons/full/obj16/threads_obj.gif", // suspended + // "icons/full/obj16/threadt_obj.gif", // stopped + // "icons/full/obj16/stckframe_running_obj.gif", // running stack frame + // "icons/full/obj16/stckframe_obj.gif", // stack frame + // }; + // + // static private String _externalPlugin[] = { "org.eclipse.debug.ui", + // "org.eclipse.debug.ui", "org.eclipse.debug.ui", + // "org.eclipse.debug.ui", "org.eclipse.debug.ui", }; + // + // static private Image getImage(int idx) { + // if (idx < 0 || idx >= IMG_NUM) + // SWT.error(SWT.ERROR_INVALID_ARGUMENT); + // String key = "trace.img." + idx; + // Image img = TmfUiPlugin.getDefault().getImageRegistry().get(key); + // if (null == img) { + // ImageDescriptor desc = AbstractUIPlugin.imageDescriptorFromPlugin( + // _externalPlugin[idx], _externalPath[idx]); + // TmfUiPlugin.getDefault().getImageRegistry().put(key, desc); + // img = TmfUiPlugin.getDefault().getImageRegistry().get(key); + // } + // return img; + // } + + public void drawState(TraceColorScheme colors, ITimeEvent event, + Rectangle rect, GC gc, boolean selected, boolean rectBound, + boolean timeSelected) { + int colorIdx = getEventColorVal(event); + drawState(colors, colorIdx, rect, gc, selected, rectBound, timeSelected); + + } + + public void drawState(TraceColorScheme colors, int colorIdx, + Rectangle rect, GC gc, boolean selected, boolean rectBound, + boolean timeSelected) { + + boolean visible = rect.width == 0 ? false : true; + int colorIdx1 = colorIdx; + + timeSelected = timeSelected && selected; + if (timeSelected) { + colorIdx1 = colorIdx + TraceColorScheme.STATES_SEL0 + - TraceColorScheme.STATES0; + } + + if (visible) { + // fill all rect area + if (rect.isEmpty()) + return; + + gc.setBackground(colors.getColor(colorIdx1)); + gc.fillRectangle(rect); + colorIdx1 = colorIdx + TraceColorScheme.STATES_BORDER0 + - TraceColorScheme.STATES0; + gc.setForeground(colors.getColor(colorIdx1)); + + // draw bounds + if (!timeSelected) { + if (rectBound && rect.width >= 3) { + gc.drawRectangle(rect.x, rect.y, rect.width - 1, + rect.height - 1); + } else { + // Draw the top and bottom borders i.e. no side borders + // top + gc + .drawLine(rect.x, rect.y, rect.x + rect.width - 1, + rect.y); + // bottom + gc.drawLine(rect.x, rect.y + rect.height - 1, rect.x + + rect.width - 1, rect.y + rect.height - 1); + } + } + // draw decoration middle line + // int mindy = rect.y + rect.height / 2; + // if (TraceColorScheme.GOLD_STATE == colorIdx + // || TraceColorScheme.ORANGE_STATE == colorIdx) { + // int s = gc.getLineStyle(); + // int w = gc.getLineWidth(); + // gc.setLineStyle(SWT.LINE_DOT); + // gc.setLineWidth(2); + // gc.drawLine(rect.x, mindy, rect.x + rect.width, mindy); + // gc.setLineStyle(s); + // gc.setLineWidth(w); + // } else if (TraceColorScheme.RED_STATE == colorIdx + // || TraceColorScheme.GRAY_STATE == colorIdx) { + // int w = gc.getLineWidth(); + // gc.setLineWidth(2); + // gc.drawLine(rect.x, mindy, rect.x + rect.width, mindy); + // gc.setLineWidth(w); + // } + // // draw selection bounds + // if (timeSelected) { + // gc.setForeground(colors + // .getColor(TraceColorScheme.SELECTED_TIME)); + // if (rect.width >= 3) { + // gc.drawRectangle(rect.x, rect.y, rect.width - 1, + // rect.height - 1); + // // gc.drawRectangle(rect.x + 1, rect.y + 1, rect.width - 3, + // // rect.height - 3); + // } else { + // gc + // .drawLine(rect.x, rect.y, rect.x + rect.width - 1, + // rect.y); + // gc.drawLine(rect.x, rect.y + rect.height - 1, rect.x + // + rect.width - 1, rect.y + rect.height - 1); + // } + // gc.drawLine(rect.x, rect.y + 1, rect.x + rect.width - 1, + // rect.y + 1); + // gc.drawLine(rect.x, rect.y + rect.height - 2, rect.x + // + rect.width - 1, rect.y + rect.height - 2); + // } + } else { + // selected rectangle area is not visible but can be represented + // with a broken vertical line of specified width. + int width = 2; + rect.width = width; + // check if height is greater than zero. + if (rect.isEmpty()) + return; + // colorIdx1 = TraceColorScheme.BLACK; + gc.setForeground(colors.getColor(colorIdx)); + int s = gc.getLineStyle(); + int w = gc.getLineWidth(); + gc.setLineStyle(SWT.LINE_DOT); + gc.setLineWidth(width); + // Trace.debug("Reactangle not visible, drawing vertical line with: " + // + rect.x + "," + rect.y + "," + rect.x + "," + rect.y + // + rect.height); + gc.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height); + gc.setLineStyle(s); + gc.setLineWidth(w); + } + } + + /** + * Uses the abstract method getEventcolor to obtain an enum value and + * convert it to an internal color index + * + * @param event + * @return + */ + public int getEventColorVal(ITimeEvent event) { + StateColor colors = getEventColor(event); + if (colors == StateColor.GREEN) { + return TraceColorScheme.GREEN_STATE; + } else if (colors == StateColor.DARK_BLUE) { + return TraceColorScheme.DARK_BLUE_STATE; + } else if (colors == StateColor.RED) { + return TraceColorScheme.RED_STATE; + } else if (colors == StateColor.GOLD) { + return TraceColorScheme.GOLD_STATE; + } else if (colors == StateColor.ORANGE) { + return TraceColorScheme.ORANGE_STATE; + } else if (colors == StateColor.GRAY) { + return TraceColorScheme.GRAY_STATE; + } else if (colors == StateColor.DARK_GREEN) { + return TraceColorScheme.DARK_GREEN_STATE; + } else if (colors == StateColor.DARK_YELLOW) { + return TraceColorScheme.DARK_YELLOW_STATE; + } else if (colors == StateColor.MAGENTA3) { + return TraceColorScheme.MAGENTA3_STATE; + } else if (colors == StateColor.PURPLE1) { + return TraceColorScheme.PURPLE1_STATE; + } else if (colors == StateColor.PINK1) { + return TraceColorScheme.PINK1_STATE; + } else if (colors == StateColor.AQUAMARINE) { + return TraceColorScheme.AQUAMARINE_STATE; + } else if (colors == StateColor.LIGHT_BLUE) { + return TraceColorScheme.LIGHT_BLUE_STATE; + } else if (colors == StateColor.CADET_BLUE) { + return TraceColorScheme.CADET_BLUE_STATE_SEL; + } else if (colors == StateColor.OLIVE) { + return TraceColorScheme.OLIVE_STATE; + } + + return TraceColorScheme.BLACK_STATE; + } + + /** + * Select the color for the different internal variants of events. + * + * @param event + * @return + */ + public abstract StateColor getEventColor(ITimeEvent event); + + /** + * This values is appended between braces to the right of Trace Name e.g. + * Trace And Error Log [Board 17] or for a Thread trace e.g. State Server + * [java.lang.Thread] + * + * @param trace + * @return + */ + public abstract String getTraceClassName(ITmfTimeAnalysisEntry trace); + + public String getEventName(ITimeEvent event) { + return getEventName(event, true, false); + } + + /** + * Specify a Name for the event depending on its type or state e.g. blocked, + * running, etc.. + * + * @param event + * @param upper + * True return String value in Upper case + * @param extInfo + * Verbose, add additional information if applicable + * @return + */ + public abstract String getEventName(ITimeEvent event, boolean upper, + boolean extInfo); + + public String composeTraceName(ITmfTimeAnalysisEntry trace, boolean inclState) { + String name = trace.getName(); + String threadClass = getTraceClassName(trace); + if (threadClass != null && threadClass.length() > 0) { + name += " [" + threadClass + "]"; + } + if (inclState) { + List list = trace.getTraceEvents(); + if (null != list && list.size() > 0) { + ITimeEvent event = (ITimeEvent) list.get(list.size() - 1); + name += " (" + getEventName(event, false, true) + ")"; + } + } + return name; + } + + public String composeEventName(ITimeEvent event) { + String name = event.getEntry().getName(); + String threadClass = getTraceClassName(event.getEntry()); + if (threadClass != null && threadClass.length() > 0) { + name += " [" + threadClass + "]"; + } + name += " (" + getEventName(event, false, true) + ")"; + return name; + } + + public abstract Map getEventHoverToolTipInfo( + ITimeEvent event); + + /** + * Provides the image icon for a given Event or Trace e.g. customize to use + * different icons according to specific event /state combination + * + * @param obj + * @return + */ + public Image getItemImage(Object obj) { + /* + if (obj instanceof ITmfTimeAnalysisEntry) { + List list = ((ITmfTimeAnalysisEntry) obj).getTraceEvents(); + if (null != list && list.size() > 0) + obj = list.get(list.size() - 1); + else if (((ITmfTimeAnalysisEntry) obj).getStopTime() > 0) + return getImage(IMG_THREAD_STOPPED); + else + return getImage(IMG_THREAD_RUNNING); + } + if (obj instanceof TimeEvent) { + return getImage(IMG_THREAD_RUNNING); + } + */ + return null; + } + + public abstract String getStateName(StateColor color); + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisViewer.java new file mode 100644 index 0000000000..1de16d6d00 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeAnalysisViewer.java @@ -0,0 +1,836 @@ +/***************************************************************************** + * Copyright (c) 2007, 2008, 2009, 2010 Intel Corporation, Ericsson + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * Ruslan A. Scherbakov, Intel - Initial API and implementation + * Alexander N. Alexeev, Intel - Add monitors statistics support + * Alvaro Sanchez-Leon - Adapted for TMF + * + * $Id: ThreadStatesView.java,v 1.7 2008/05/19 15:07:21 jkubasta Exp $ + *****************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.dialogs.TmfTimeFilterDialog; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.dialogs.TmfTimeLegend; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.TimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.ITimeDataProvider; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.TimeScaleCtrl; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.TmfTimeStatesCtrl; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.TmfTimeTipHandler; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.TraceColorScheme; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.Utils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +public class TmfTimeAnalysisViewer implements ITimeAnalysisViewer, ITimeDataProvider, SelectionListener { + + /** vars */ + private long _minTimeInterval; + private long _selectedTime; + private long _beginTime; + private long _endTime; + private long _time0; + private long _time1; + private long _time0_; + private long _time1_; + private long _time0_extSynch = 0; + private long _time1_extSynch = 0; + private boolean _timeRangeFixed; + private int _nameWidthPref = 200; + private int _minNameWidth = 6; + private int _nameWidth; + private Composite _dataViewer; + + private TmfTimeStatesCtrl _stateCtrl; + private TimeScaleCtrl _timeScaleCtrl; + private TmfTimeTipHandler _threadTip; + private TraceColorScheme _colors; + private TmfTimeAnalysisProvider _utilImplm; + + private boolean _acceptSetSelAPICalls = false; + Vector widgetSelectionListners = new Vector(); + Vector widgetTimeScaleSelectionListners = new Vector(); + Vector widgetFilterSelectionListeners = new Vector(); + + // Calender Time format, using Epoch reference or Relative time + // format(default + private boolean calendarTimeFormat = false; + private int borderWidth = 4; + private int timeScaleHeight = 22; + + /** ctor */ + public TmfTimeAnalysisViewer(Composite parent, TmfTimeAnalysisProvider provider) { + createDataViewer(parent, provider); + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.ui.widgets.timeAnalysis.api.ITimeAnalysisWidget#display(org.eclipse.linuxtools.tmf.ui.widgets.timeAnalysis.model.TmfTaTrace[]) + */ + public void display(ITmfTimeAnalysisEntry[] traceArr) { + modelUpdate(traceArr); + } + + public void display(ITmfTimeAnalysisEntry[] traceArr, long start, long end, + boolean updateTimeBounds) { + modelUpdate(traceArr, start, end, updateTimeBounds); + } + + public void controlMoved(ControlEvent e) { + } + + public void controlResized(ControlEvent e) { + resizeControls(); + } + + // called from the display order in the API + public void modelUpdate(ITmfTimeAnalysisEntry[] traces) { + if (null != _stateCtrl) { + loadOptions(); + updateInternalData(traces); + _stateCtrl.redraw(); + _timeScaleCtrl.redraw(); + } + } + + // called from the display order in the API + public void modelUpdate(ITmfTimeAnalysisEntry[] traces, long start, + long end, boolean updateTimeBounds) { + if (null != _stateCtrl) { + loadOptions(); + updateInternalData(traces, start, end); + if (updateTimeBounds) { + _timeRangeFixed = true; + // set window to match limits + setStartFinishTime(_time0_, _time1_); + } else { + _stateCtrl.redraw(); + _timeScaleCtrl.redraw(); + } + } + } + + public void itemUpdate(ITmfTimeAnalysisEntry parent, TimeEvent item) { + if (null != parent && null != item) { + _stateCtrl.refreshPartial(parent, item); + _stateCtrl.redraw(); + _timeScaleCtrl.redraw(); + } + } + + public void selectionChanged() { + } + + protected String getViewTypeStr() { + return "viewoption.threads"; + } + + int getMarginWidth(int idx) { + return 0; + } + + int getMarginHeight(int idx) { + return 0; + } + + void loadOptions() { + _minTimeInterval = 1; + _selectedTime = -1; + _nameWidth = Utils.loadIntOption(getPreferenceString("namewidth"), + _nameWidthPref, _minNameWidth, 1000); + } + + void saveOptions() { + Utils.saveIntOption(getPreferenceString("namewidth"), _nameWidth); + } + + protected Control createDataViewer(Composite parent, + TmfTimeAnalysisProvider utilImplm) { + loadOptions(); + _utilImplm = utilImplm; + _colors = new TraceColorScheme(); + _dataViewer = new Composite(parent, SWT.NULL); + _dataViewer.setLayoutData(GridUtil.createFill()); + GridLayout gl = new GridLayout(); + gl.marginHeight = borderWidth; + gl.marginWidth = 0; + gl.verticalSpacing = 0; + gl.horizontalSpacing = 0; + _dataViewer.setLayout(gl); + + _timeScaleCtrl = new TimeScaleCtrl(_dataViewer, _colors); + _timeScaleCtrl.setTimeProvider(this); + _timeScaleCtrl.setLayoutData(GridUtil.createHorizontalFill()); + _timeScaleCtrl.setHeight(timeScaleHeight); + + _stateCtrl = new TmfTimeStatesCtrl(_dataViewer, _colors, _utilImplm); + + _stateCtrl.setTimeProvider(this); + _stateCtrl.addSelectionListener(this); + _stateCtrl.setLayoutData(GridUtil.createFill()); + _dataViewer.addControlListener(new ControlAdapter() { + @Override + public void controlResized(ControlEvent event) { + resizeControls(); + } + }); + resizeControls(); + _dataViewer.update(); + _threadTip = new TmfTimeTipHandler(parent.getShell(), _utilImplm, this); + _threadTip.activateHoverHelp(_stateCtrl); + return _dataViewer; + } + + public void dispose() { + saveOptions(); + _stateCtrl.dispose(); + _dataViewer.dispose(); + _colors.dispose(); + } + + public void resizeControls() { + Rectangle r = _dataViewer.getClientArea(); + if (r.isEmpty()) + return; + + int width = r.width; + if (_nameWidth > width - _minNameWidth) + _nameWidth = width - _minNameWidth; + if (_nameWidth < _minNameWidth) + _nameWidth = _minNameWidth; + } + + /** Tries to set most convenient time range for display. */ + void setTimeRange(Object traces[]) { + _endTime = 0; + _beginTime = -1; + ITimeEvent event; + for (int i = 0; i < traces.length; i++) { + ITmfTimeAnalysisEntry entry = (ITmfTimeAnalysisEntry) traces[i]; + if (entry.getStopTime() >= entry.getStartTime() && entry.getStopTime() > 0) { + if (_beginTime < 0 || entry.getStartTime() < _beginTime) { + _beginTime = entry.getStartTime(); + } + if (entry.getStopTime() > _endTime) { + _endTime = entry.getStopTime(); + } + } + List list = entry.getTraceEvents(); + int len = list.size(); + if (len > 0) { + event = (ITimeEvent) list.get(0); + if (_beginTime < 0 || event.getTime() < _beginTime) { + _beginTime = event.getTime(); + } + event = (ITimeEvent) list.get(list.size() - 1); + long eventEndTime = event.getTime() + (event.getDuration() > 0 ? event.getDuration() : 0); + if (eventEndTime > _endTime) { + _endTime = eventEndTime; + } + } + } + + if (_beginTime < 0) + _beginTime = 0; + } + + void setTimeBounds() { + //_time0_ = _beginTime - (long) ((_endTime - _beginTime) * 0.02); + _time0_ = _beginTime; + if (_time0_ < 0) + _time0_ = 0; + // _time1_ = _time0_ + (_endTime - _time0_) * 1.05; + _time1_ = _endTime; + // _time0_ = Math.floor(_time0_); + // _time1_ = Math.ceil(_time1_); + if (!_timeRangeFixed) { + _time0 = _time0_; + _time1 = _time1_; + } + if (_time1 - _time0 < _minTimeInterval) { + _time1 = _time0 + _minTimeInterval; + } + } + + /** + * @param traces + */ + void updateInternalData(ITmfTimeAnalysisEntry[] traces) { + if (null == traces) + traces = new ITmfTimeAnalysisEntry[0]; + setTimeRange(traces); + refreshAllData(traces); + } + + /** + * @param traces + * @param start + * @param end + */ + void updateInternalData(ITmfTimeAnalysisEntry[] traces, long start, long end) { + if (null == traces) + traces = new ITmfTimeAnalysisEntry[0]; + if ((start == 0 && end == 0) || start < 0 || end < 0) { + // Start and end time are unspecified and need to be determined from + // individual processes + setTimeRange(traces); + } else { + _beginTime = start; + _endTime = end; + } + + refreshAllData(traces); + } + + /** + * @param traces + */ + private void refreshAllData(ITmfTimeAnalysisEntry[] traces) { + setTimeBounds(); + if (_selectedTime < _beginTime) { + _selectedTime = _beginTime; + } else if (_selectedTime > _endTime) { + _selectedTime = _endTime; + } + _stateCtrl.refreshData(traces); + filterOutNotification(); + } + + public void setFocus() { + if (null != _stateCtrl) + _stateCtrl.setFocus(); + } + + public boolean isInFocus() { + return _stateCtrl.isInFocus(); + } + + public ITmfTimeAnalysisEntry getSelectedTrace() { + return _stateCtrl.getSelectedTrace(); + } + + public ISelection getSelection() { + return _stateCtrl.getSelection(); + } + + public ISelection getSelectionTrace() { + return _stateCtrl.getSelectionTrace(); + } + + public long getTime0() { + return _time0; + } + + public long getTime1() { + return _time1; + } + + public long getMinTimeInterval() { + return _minTimeInterval; + } + + public int getNameSpace() { + return _nameWidth; + } + + public void setNameSpace(int width) { + _nameWidth = width; + width = _stateCtrl.getClientArea().width; + if (_nameWidth > width - 6) + _nameWidth = width - 6; + if (_nameWidth < 6) + _nameWidth = 6; + _stateCtrl.adjustScrolls(); + _stateCtrl.redraw(); + _timeScaleCtrl.redraw(); + } + + public int getTimeSpace() { + int w = _stateCtrl.getClientArea().width; + return w - _nameWidth; + } + + public long getSelectedTime() { + return _selectedTime; + } + + public long getBeginTime() { + return _beginTime; + } + + public long getEndTime() { + return _endTime; + } + + public long getMaxTime() { + return _time1_; + } + + public long getMinTime() { + return _time0_; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.ITimeDataProvider + * #setStartFinishTimeNotify(long, long) + */ + public void setStartFinishTimeNotify(long time0, long time1) { + setStartFinishTime(time0, time1); + notifyStartFinishTimeSelectionListeners(time0, time1); + } + + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.ITimeDataProvider#notifyStartFinishTime() + */ + public void notifyStartFinishTime() { + notifyStartFinishTimeSelectionListeners(_time0, _time1); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.ITimeDataProvider + * #setStartFinishTime(long, long) + */ + public void setStartFinishTime(long time0, long time1) { + _time0 = time0; + if (_time0 < _time0_) + _time0 = _time0_; + if (_time0 > _time1_) + _time0 = _time1_; + _time1 = time1; + if (_time1 < _time0_) + _time1 = _time0_; + if (_time1 > _time1_) + _time1 = _time1_; + if (_time1 - _time0 < _minTimeInterval) + _time1 = _time0 + _minTimeInterval; + _timeRangeFixed = true; + _stateCtrl.adjustScrolls(); + _stateCtrl.redraw(); + _timeScaleCtrl.redraw(); + } + + public void resetStartFinishTime() { + setStartFinishTimeNotify(_time0_, _time1_); + _timeRangeFixed = false; + } + + public void setSelectedTimeInt(long time, boolean ensureVisible) { + // Trace.debug("currentTime:" + _selectedTime + " new time:" + time); + _selectedTime = time; + if (_selectedTime > _endTime) + _selectedTime = _endTime; + if (_selectedTime < _beginTime) + _selectedTime = _beginTime; + if (ensureVisible) { + double timeSpace = (_time1 - _time0) * .02; + double timeMid = (_time1 - _time0) * .1; + if (_selectedTime < _time0 + timeSpace) { + double dt = _time0 - _selectedTime + timeMid; + _time0 -= dt; + _time1 -= dt; + } else if (_selectedTime > _time1 - timeSpace) { + double dt = _selectedTime - _time1 + timeMid; + _time0 += dt; + _time1 += dt; + } + if (_time0 < _time0_) { + _time1 += _time0_ - _time0; + _time0 = _time0_; + } else if (_time1 > _time1_) { + _time0 -= _time1 - _time1_; + _time1 = _time1_; + } + } + _stateCtrl.adjustScrolls(); + _stateCtrl.redraw(); + _timeScaleCtrl.redraw(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO: Opening call stack shall be replaced to a configurable view + // new OpenCallStackViewAction().openView(false); + // Replaced by event notification + // updateModelSelection(); + notifySelectionListeners(TmfTimeSelectionEvent.type.WIDGET_DEF_SEL); + } + + public void widgetSelected(SelectionEvent e) { + // Replace by event notification + // updateModelSelection(); + notifySelectionListeners(TmfTimeSelectionEvent.type.WIDGET_SEL); + } + + public void selectNextEvent() { + _stateCtrl.selectNextEvent(); + } + + public void selectPrevEvent() { + _stateCtrl.selectPrevEvent(); + } + + public void selectNextTrace() { + _stateCtrl.selectNextTrace(); + } + + public void selectPrevTrace() { + _stateCtrl.selectPrevTrace(); + } + + public void groupTraces(boolean on) { + _stateCtrl.groupTraces(on); + } + + public void filterTraces() { + if (_dataViewer == null || _dataViewer.isDisposed()) + return; + + if (TmfTimeFilterDialog.getTraceFilter(_dataViewer.getShell(), _stateCtrl + .getTraces(), _stateCtrl.getTraceFilter())) { + _stateCtrl.refreshData(); + filterOutNotification(); + } + } + + public void showLegend() { + if (_dataViewer == null || _dataViewer.isDisposed()) + return; + + TmfTimeLegend.open(_dataViewer.getShell(), _utilImplm); + } + + public void toggleThreadsInteractionDrawing() { + _stateCtrl.toggleTraceInteractionDrawing(); + } + + public void setThreadJoinDrawing(boolean on) { + _stateCtrl.setTraceJoinDrawing(on); + } + + public void setThreadWaitDrawing(boolean on) { + _stateCtrl.setTraceWaitDrawing(on); + } + + public void setThreadReleaseDrawing(boolean on) { + _stateCtrl.setTraceReleaseDrawing(on); + } + + public boolean getThreadInteractionDrawing() { + return _stateCtrl.getTracesInteractionDrawing(); + } + + public boolean getThreadJoinDrawing() { + return _stateCtrl.getTraceJoinDrawing(); + } + + public boolean getThreadWaitDrawing() { + return _stateCtrl.getTraceWaitDrawing(); + } + + public boolean getThreadReleaseDrawing() { + return _stateCtrl.getTraceReleaseDrawing(); + } + + protected void select(Object obj) { + if (obj == null) + return; + // TODO: ThreadDetails Adaption removed, might need replacement + // if (obj instanceof ThreadDetails) { + // obj = ((ThreadDetails) obj).getThread(); + // } + if (obj instanceof ITmfTimeAnalysisEntry) { + // _stateCtrl.selectThread((TsfTmTrace) obj); + } + } + + public void zoomIn() { + _stateCtrl.zoomIn(); + } + + public void zoomOut() { + _stateCtrl.zoomOut(); + } + + private String getPreferenceString(String string) { + return getViewTypeStr() + "." + string; + } + + public void addWidgetSelectionListner(ITmfTimeSelectionListener listener) { + widgetSelectionListners.add(listener); + } + + public void removeWidgetSelectionListner(ITmfTimeSelectionListener listener) { + widgetSelectionListners.removeElement(listener); + } + + public void addWidgetTimeScaleSelectionListner( + ITmfTimeScaleSelectionListener listener) { + widgetTimeScaleSelectionListners.add(listener); + } + + public void removeWidgetTimeScaleSelectionListner( + ITmfTimeScaleSelectionListener listener) { + widgetTimeScaleSelectionListners.removeElement(listener); + } + + public void setSelectedTime(long time, boolean ensureVisible, Object source) { + if (_acceptSetSelAPICalls == false || this == source) { + return; + } + + setSelectedTimeInt(time, ensureVisible); + } + + public void setSelectedEvent(ITimeEvent event, Object source) { + if (_acceptSetSelAPICalls == false || event == null || source == this) { + return; + } + ITmfTimeAnalysisEntry trace = event.getEntry(); + if (trace != null) { + _stateCtrl.selectItem(trace, false); + } + + setSelectedTimeInt(event.getTime(), true); + } + + public void setSelectedTraceTime(ITmfTimeAnalysisEntry trace, long time, Object source) { + if (_acceptSetSelAPICalls == false || trace == null || source == this) { + return; + } + + if (trace != null) { + _stateCtrl.selectItem(trace, false); + } + + setSelectedTimeInt(time, true); + } + + public void setSelectedTrace(ITmfTimeAnalysisEntry trace) { + if (trace == null) { + return; + } + + _stateCtrl.selectItem(trace, false); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer + * #setSelectVisTimeWindow(long, long, java.lang.Object) + */ + public void setSelectVisTimeWindow(long time0, long time1, Object source) { + if (_acceptSetSelAPICalls == false || source == this) { + return; + } + + setStartFinishTime(time0, time1); + + // update notification time values since we are now in synch with the + // external application + updateExtSynchTimers(); + } + + public void setAcceptSelectionAPIcalls(boolean acceptCalls) { + _acceptSetSelAPICalls = acceptCalls; + } + + private synchronized void notifySelectionListeners( + TmfTimeSelectionEvent.type rtype) { + // Any listeners out there ? + if (widgetSelectionListners.size() > 0) { + // Locate the event selected + ISelection selection = getSelection(); + Object sel = null; + if (selection != null && !selection.isEmpty()) { + sel = ((IStructuredSelection) selection).getFirstElement(); + } + + if (sel != null) { + // Notify Selection Listeners + TmfTimeSelectionEvent event = new TmfTimeSelectionEvent(this, + rtype, sel, getSelectedTime()); + + for (Iterator iter = widgetSelectionListners + .iterator(); iter.hasNext();) { + ITmfTimeSelectionListener listener = (ITmfTimeSelectionListener) iter + .next(); + listener.tsfTmProcessSelEvent(event); + } + } + } + } + + public void notifyStartFinishTimeSelectionListeners(long _time0, long _time1) { + if (widgetTimeScaleSelectionListners.size() > 0) { + // Check if the time has actually changed from last notification + if (_time0 != _time0_extSynch || _time1 != _time1_extSynch) { + // Notify Time Scale Selection Listeners + TmfTimeScaleSelectionEvent event = new TmfTimeScaleSelectionEvent( + this, _time0, _time1, getTimeSpace(), getSelectedTime()); + + for (Iterator iter = widgetTimeScaleSelectionListners + .iterator(); iter.hasNext();) { + ITmfTimeScaleSelectionListener listener = (ITmfTimeScaleSelectionListener) iter + .next(); + listener.tsfTmProcessTimeScaleEvent(event); + } + + // update external synch timers + updateExtSynchTimers(); + } + } + } + + /** + * update the cache timers used to identify the need to send a time window + * update to external registered listeners + */ + private void updateExtSynchTimers() { + // last time notification cache + _time0_extSynch = _time0; + _time1_extSynch = _time1; + } + + public void setTimeCalendarFormat(boolean toAbsoluteCaltime) { + calendarTimeFormat = toAbsoluteCaltime; + } + + public boolean isCalendarFormat() { + return calendarTimeFormat; + } + + public int getBorderWidth() { + return borderWidth; + } + + public void setBorderWidth(int borderWidth) { + if (borderWidth > -1) { + this.borderWidth = borderWidth; + GridLayout gl = (GridLayout)_dataViewer.getLayout(); + gl.marginHeight = borderWidth; + } + } + + public int getHeaderHeight() { + return timeScaleHeight; + } + + public void setHeaderHeight(int headerHeight) { + if (headerHeight > -1) { + this.timeScaleHeight = headerHeight; + _timeScaleCtrl.setHeight(headerHeight); + } + } + + public int getItemHeight() { + if (_stateCtrl != null) { + return _stateCtrl.getItemHeight(); + } + return 0; + } + + public void setItemHeight(int rowHeight) { + if (_stateCtrl != null) { + _stateCtrl.setItemHeight(rowHeight); + } + } + + public boolean isVisibleVerticalScroll() { + if (_stateCtrl != null) { + _stateCtrl.isVisibleVerticalScroll(); + } + return false; + } + + public void setVisibleVerticalScroll(boolean visibleVerticalScroll) { + if (_stateCtrl != null) { + _stateCtrl.setVisibleVerticalScroll(visibleVerticalScroll); + } + } + + public void setNameWidthPref(int width) { + _nameWidthPref = width; + if (width == 0) { + _minNameWidth = 0; + } + } + + public int getNameWidthPref(int width) { + return _nameWidthPref; + } + + public void addFilterSelectionListner(ITmfTimeFilterSelectionListener listener) { + widgetFilterSelectionListeners.add(listener); + } + + public void removeFilterSelectionListner( + ITmfTimeFilterSelectionListener listener) { + widgetFilterSelectionListeners.remove(listener); + } + + private void filterOutNotification() { + TmfTimeFilterSelectionEvent event = new TmfTimeFilterSelectionEvent(this); + event.setFilteredOut(_stateCtrl.getFilteredOut()); + for (ITmfTimeFilterSelectionListener listener : widgetFilterSelectionListeners) { + listener.tmfTaProcessFilterSelection(event); + } + } + + /** + * needed in case there's a need to associate a context menu + * + * @return + */ + public Control getControl() { + return _stateCtrl; + } + + /** + * Get the selection provider + * + * @return + */ + public ISelectionProvider getSelectionProvider() { + return _stateCtrl; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer + * #waitCursor(boolean) + */ + public void waitCursor(boolean waitInd) { + _stateCtrl.waitCursor(waitInd); + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeFilterSelectionEvent.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeFilterSelectionEvent.java new file mode 100644 index 0000000000..6cf92f82e9 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeFilterSelectionEvent.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import java.util.EventObject; +import java.util.Vector; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; + +public class TmfTimeFilterSelectionEvent extends EventObject { + /** + * + */ + private static final long serialVersionUID = -150960748016449093L; + + Vector filteredOut = null; + + public TmfTimeFilterSelectionEvent(Object source) { + super(source); + } + + public Vector getFilteredOut() { + return filteredOut; + } + + public void setFilteredOut(Vector rfilteredOut) { + this.filteredOut = rfilteredOut; + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeScaleSelectionEvent.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeScaleSelectionEvent.java new file mode 100644 index 0000000000..27def26d19 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeScaleSelectionEvent.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import java.util.EventObject; + +public class TmfTimeScaleSelectionEvent extends EventObject { + + /** + * + */ + private static final long serialVersionUID = -4177428788761351379L; + + + long time0 = 0; + long time1 = 0; + long selectedTime = 0; + int width = 0; + + /** + * + * @param arg0 + * source of event + * @param time0 + * time0 the start time + * @param time1 + * @param width + * pixels used to draw the width of the time space + * @param selTime + * carries the selected time if available otherwise is 0 + */ + public TmfTimeScaleSelectionEvent(Object arg0, long time0, long time1, + int width, long selTime) { + super(arg0); + this.time0 = time0; + this.time1 = time1; + this.width = width; + this.selectedTime = selTime; + } + + /** + * @return + */ + public long getTime0() { + return time0; + } + + /** + * @return + */ + public long getTime1() { + return time1; + } + + /** + * @return + */ + public int getWidth() { + return width; + } + + /** + * @return + */ + public long getSelectedTime() { + return selectedTime; + } + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeSelectionEvent.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeSelectionEvent.java new file mode 100644 index 0000000000..8fd1264d52 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/TmfTimeSelectionEvent.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis; + +import java.util.EventObject; + +public class TmfTimeSelectionEvent extends EventObject { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public enum type {WIDGET_DEF_SEL, WIDGET_SEL} + type dType; + Object selection = null; + long selTime = 0; + int index = 0; + + public TmfTimeSelectionEvent(Object arg0, type rType, Object sel, long selectedTime) { + super(arg0); + dType = rType; + selection = sel; + selTime = selectedTime; + } + + public type getDType() { + return dType; + } + + public Object getSelection() { + return selection; + } + + public long getSelectedTime() { + return selTime; + } + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/dialogs/TmfTimeFilterDialog.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/dialogs/TmfTimeFilterDialog.java new file mode 100644 index 0000000000..f3bd9eebdc --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/dialogs/TmfTimeFilterDialog.java @@ -0,0 +1,214 @@ +/***************************************************************************** + * Copyright (c) 2008 Intel Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * + * $Id: ThreadFilterDialog.java,v 1.2 2008/03/05 17:31:07 ewchan Exp $ + *****************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.dialogs; + +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.jface.window.Window; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.Messages; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +public class TmfTimeFilterDialog extends TitleAreaDialog { + private CheckboxTableViewer viewer; + private Object[] threads; + private boolean[] filter; + private ViewContentProvider viewContentProvider; + private TraceComparator viewTraceComparator; + private ViewLabelProvider viewViewLabelProvider; + + public TmfTimeFilterDialog(Shell parentShell, Object[] threads, + boolean[] filter) { + super(parentShell); + + this.threads = threads; + if (filter != null) + this.filter = (boolean[]) filter.clone(); + + viewContentProvider = new ViewContentProvider(); + viewTraceComparator = new TraceComparator(); + viewViewLabelProvider = new ViewLabelProvider(); + } + + public static boolean getTraceFilter(Shell parentShell, Object[] threads, + boolean[] filter) { + TmfTimeFilterDialog dlg = new TmfTimeFilterDialog(parentShell, threads, + filter); + if (dlg.open() != Window.OK) + return false; + + boolean f[] = dlg.getFilter(); + if (java.util.Arrays.equals(f, filter)) + return false; + for (int i = f.length - 1; i >= 0; i--) + filter[i] = f[i]; + + return true; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + + viewer = CheckboxTableViewer.newCheckList(composite, SWT.BORDER + | SWT.V_SCROLL); + + Table table = viewer.getTable(); + table.setLayoutData(new GridData(GridData.FILL_BOTH)); + table.setBackground(parent.getBackground()); + createColumns(table); + + //Assign providers to the viewer. + viewer.setContentProvider(viewContentProvider); + viewer.setComparator(viewTraceComparator); + viewer.setLabelProvider(viewViewLabelProvider); + + viewer.setInput(new Object()); + + viewer.addCheckStateListener(new ICheckStateListener() { + public void checkStateChanged(CheckStateChangedEvent event) { + Object o = event.getElement(); + for (int i = threads.length - 1; i >= 0; i--) { + if (threads[i].equals(o)) + filter[i] = event.getChecked(); + } + } + }); + + if (filter != null) { + for (int i = 0; i < filter.length; i++) + viewer.setChecked(threads[i], filter[i]); + } + + setMessage(Messages._TRACE_FILTER_DESC); + setTitle(Messages._TRACE_FILTER); + setDialogHelpAvailable(false); + setHelpAvailable(false); + +// setTitleImage(org.eclipse.hyades.trace.internal.ui.PDPluginImages.DESC_IMG_UI_WZ_EDITPROFSET +// .createImage()); + + return composite; + } + + private void createColumns(Table table) { + table.setHeaderVisible(true); + + String headers[] = { "", Messages._TRACE_ID, Messages._TRACE_NAME }; + int width[] = { 20, 80, 400 }; + + for (int i = 0; i < headers.length; i++) { + TableColumn tc = new TableColumn(table, SWT.NONE, i); + tc.setResizable(true); + tc.setText(headers[i]); + tc.setWidth(width[i]); + } + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText(Messages._EDIT_PROFILING_OPTIONS); + } + + public boolean[] getFilter() { + return filter; + } + + /** + * @param viewContentProvider + */ + public void setViewContentProvider(ViewContentProvider viewContentProvider) { + this.viewContentProvider = viewContentProvider; + } + + /** + * @param viewThreadComparator + */ + public void setViewThreadComparator(TraceComparator viewThreadComparator) { + this.viewTraceComparator = viewThreadComparator; + } + + /** + * @param viewViewLabelProvider + */ + public void setViewViewLabelProvider(ViewLabelProvider viewViewLabelProvider) { + this.viewViewLabelProvider = viewViewLabelProvider; + } + + class ViewContentProvider implements IStructuredContentProvider { + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public Object[] getElements(Object input) { + return threads; + } + } + + class ViewLabelProvider extends LabelProvider implements + ITableLabelProvider { + @Override + public Image getImage(Object obj) { + return null; + } + + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + public String getColumnText(Object element, int columnIndex) { + // TODO: AA: Provide Label Provider externally + ITmfTimeAnalysisEntry t = (ITmfTimeAnalysisEntry) element; + + if (columnIndex == 1) + return String.valueOf(t.getId()); + else if (columnIndex == 2) + return t.getName(); + else + return ""; + } + } + + class TraceComparator extends ViewerComparator { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + // TODO: AA: Provide comparator externally + int id1 = ((ITmfTimeAnalysisEntry) e1).getId(); + int id2 = ((ITmfTimeAnalysisEntry) e2).getId(); + + if (id1 == id2) + return 0; + + return (id1 < id2) ? -1 : 1; + // return 0; + } + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/dialogs/TmfTimeLegend.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/dialogs/TmfTimeLegend.java new file mode 100644 index 0000000000..5d0e54fc67 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/dialogs/TmfTimeLegend.java @@ -0,0 +1,293 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.dialogs; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.Messages; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider.StateColor; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.TraceColorScheme; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; + + +public class TmfTimeLegend extends TitleAreaDialog { + + // public static final String stateNames[] = { + // UIMessages._Unknown, // "Unknown", + // UIMessages._Running, // "Running", + // UIMessages._Sleeping, // "Sleeping", + // UIMessages._Waiting, // "Waiting", + // UIMessages._Blocked, // "Blocked", + // UIMessages._Deadlocked, // "Deadlock", + // UIMessages._Stopped, // "Stopped", + // }; + + // public static final String interactionNames[] = { + // UIMessages._START_THREAD, + // UIMessages._JOIN_TERMINATE, + // UIMessages._WAIT_NOTIFY, + // UIMessages._INTERRUPT, + // UIMessages._RELEASE_ACQUIRE + // }; + + public static final int interactionColors[] = { + TraceColorScheme.TI_START_THREAD, + TraceColorScheme.TI_NOTIFY_JOINED, TraceColorScheme.TI_NOTIFY, + TraceColorScheme.TI_INTERRUPT, TraceColorScheme.TI_HANDOFF_LOCK }; + + protected TraceColorScheme colors; + private TmfTimeAnalysisProvider ifUtil; + + public static void open(Shell parent, TmfTimeAnalysisProvider rifUtil) { + (new TmfTimeLegend(parent, rifUtil)).open(); + } + + public TmfTimeLegend(Shell parent, TmfTimeAnalysisProvider rifUtil) { + super(parent); + colors = new TraceColorScheme(); + this.ifUtil = rifUtil; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite dlgArea = (Composite) super.createDialogArea(parent); + Composite composite = new Composite(dlgArea, SWT.NONE); + + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout(layout); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + composite.setLayoutData(gd); + + createThreadStatesGroup(composite); + // createThreadInteractionsGroup(composite); + + setMessage(Messages._LEGEND); + setTitle(Messages.TRACE_STATES_TITLE); + setDialogHelpAvailable(false); + setHelpAvailable(false); + + // setTitleImage(org.eclipse.hyades.trace.internal.ui.PDPluginImages.DESC_IMG_UI_WZ_EDITPROFSET.createImage()); + + return composite; + } + + private void createThreadStatesGroup(Composite composite) { + Group gs = new Group(composite, SWT.NONE); + gs.setText(Messages._TRACE_STATES); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + gs.setLayoutData(gd); + + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.marginWidth = 20; + layout.marginBottom = 10; + gs.setLayout(layout); + + for (int i = 0; i < 7; i++) { + Bar bar = new Bar(gs, i); + gd = new GridData(); + gd.widthHint = 40; + gd.heightHint = 20; + gd.verticalIndent = 8; + bar.setLayoutData(gd); + + Label name = new Label(gs, SWT.NONE); + //Get the color enum related to the index + StateColor stateColor = TraceColorScheme.getStateColors()[i]; + //Get the given name, provided by the interface to the application + name.setText(ifUtil.getStateName(stateColor)); + gd = new GridData(); + gd.horizontalIndent = 10; + gd.verticalIndent = 8; + name.setLayoutData(gd); + } + } + + // private void createThreadInteractionsGroup(Composite composite) { + // Group g = new Group (composite, SWT.NONE); + // g.setText(UIMessages._THREAD_INTERACTIONS); + // GridData gd = new GridData (SWT.FILL, SWT.FILL, true, true); + // g.setLayoutData(gd); + // + // GridLayout layout = new GridLayout(); + // layout.numColumns = 2; + // layout.marginWidth = 20; + // layout.marginBottom = 10; + // g.setLayout(layout); + // + // for (int i=0; i<5; i++) { + // Arrow a = new Arrow(g, interactionColors[i]); + // gd = new GridData(); + // gd.widthHint = 10; + // gd.heightHint = 20; + // gd.verticalIndent = 8; + // a.setLayoutData(gd); + // + // Label name = new Label (g, SWT.NONE); + // name.setText(interactionNames[i]); + // gd = new GridData (); + // gd.horizontalIndent = 4; + // gd.verticalIndent = 8; + // name.setLayoutData(gd); + // } + // + // Mark m = new Mark(g, TraceColorScheme.TI_WAIT_EXCEEDED); + // gd = new GridData(); + // gd.widthHint = 10; + // gd.heightHint = 20; + // gd.verticalIndent = 8; + // m.setLayoutData(gd); + // + // Label name = new Label (g, SWT.NONE); + // name.setText(UIMessages._WAIT_TIMEOUT_EXCEED); + // gd = new GridData (); + // gd.horizontalIndent = 4; + // gd.verticalIndent = 8; + // name.setLayoutData(gd); + // } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText(Messages._WINDOW_TITLE); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, + true); + } + + class Bar extends Canvas { + private int colorIdx; + private Color color; + + public Bar(Composite parent, int colorIdx) { + super(parent, SWT.NONE); + + this.colorIdx = colorIdx; + color = colors.getColor(colorIdx); + addListener(SWT.Paint, new Listener() { + public void handleEvent(Event event) { + draw(event.gc); + } + }); + } + + private void draw(GC gc) { + Rectangle r = getClientArea(); + gc.setBackground(color); + gc.fillRectangle(r); + + int my = r.height / 2; + + if (TraceColorScheme.GOLD_STATE == colorIdx + || TraceColorScheme.ORANGE_STATE == colorIdx) { + int s = gc.getLineStyle(); + int w = gc.getLineWidth(); + gc.setLineStyle(SWT.LINE_DOT); + gc.setLineWidth(2); + gc.drawLine(0, my, r.width - 1, my); + gc.setLineStyle(s); + gc.setLineWidth(w); + } else if (TraceColorScheme.RED_STATE == colorIdx + || TraceColorScheme.GRAY_STATE == colorIdx) { + int w = gc.getLineWidth(); + gc.setLineWidth(2); + gc.drawLine(0, my, r.width - 1, my); + gc.setLineWidth(w); + } + + gc.setForeground(colors.getColor(TraceColorScheme.BLACK)); + gc.drawRectangle(0, 0, r.width - 1, r.height - 1); + } + } + + class Arrow extends Canvas { + public final static int HEIGHT = 12; + public final static int DX = 3; + + private Color color; + + public Arrow(Composite parent, int colorIdx) { + super(parent, SWT.NONE); + + color = colors.getColor(colorIdx); + addListener(SWT.Paint, new Listener() { + public void handleEvent(Event event) { + draw(event.gc); + } + }); + } + + private void draw(GC gc) { + Rectangle r = getClientArea(); + gc.setForeground(color); + + int y0, y1; + if (r.height > HEIGHT) { + y0 = (r.height - HEIGHT) / 2; + y1 = y0 + HEIGHT; + } else { + y0 = 0; + y1 = r.height; + } + + gc.drawLine(DX, y0, DX, y1); + + gc.drawLine(0, y0 + 3, DX, y0); + gc.drawLine(2 * DX, y0 + 3, DX, y0); + } + } + + class Mark extends Canvas { + public final static int DX = 3; + + private Color color; + + public Mark(Composite parent, int colorIdx) { + super(parent, SWT.NONE); + + color = colors.getColor(colorIdx); + addListener(SWT.Paint, new Listener() { + public void handleEvent(Event event) { + draw(event.gc); + } + }); + } + + private void draw(GC gc) { + Rectangle r = getClientArea(); + gc.setBackground(color); + + int y = (r.height - DX) / 2; + int c[] = { 0, y, DX, y + DX, 2 * DX, y }; + gc.fillPolygon(c); + } + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/messages.properties b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/messages.properties new file mode 100644 index 0000000000..7dac086b5a --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/messages.properties @@ -0,0 +1,39 @@ +#******************************************************************************* +# Copyright (c) 2009, 2010 Ericsson +# +# All rights reserved. This program and the accompanying materials are +# made available under the terms of the Eclipse Public License v1.0 which +# accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +#2Contributors: +# IBM Corporation - initial API and implementation +# Alvaro Sanchez-Leon - Stripped down for TMF +# *******************************************************************************/ + +TRACE_STATES_TITLE = States Transition Visualizer + +# labels +_TRACE_ID = Process Id +_TRACE_DATE = Date +_TRACE_NAME = Process Name +_TRACE_CLASS_NAME = Class Name +_TRACE_GROUP_NAME = Group Name +_TRACE_START_TIME = Start Time +_TRACE_EVENT_TIME = Event Time +_TRACE_STOP_TIME = Stop Time +_DURATION = Duration +_TRACE_STATE = State +_NUMBER_OF_TRACES = Number of processes +_TRACE_FILTER = Process Filter +_TRACE_FILTER_DESC = Define the filter set +_Timescale = Time scale +_UNDEFINED_GROUP = +_TRACE_GROUP_LABEL = Process Group [{0}] +_EDIT_PROFILING_OPTIONS = Edit Profiling Options + +#Monitor statistics view messages +MEM_ALLOCATION_DETAILS_FOR = Allocation details for +_LEGEND = Legend +_TRACE_STATES = Process states +_WINDOW_TITLE = Process Visualizer's Legend diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/ITimeEvent.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/ITimeEvent.java new file mode 100644 index 0000000000..56ca0db2e6 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/ITimeEvent.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model; + +public interface ITimeEvent { + + public ITmfTimeAnalysisEntry getEntry(); + + public long getTime(); + + /** + * Returning
  • -1: Considers duration to be from current event till + * the next
  • 0: Duration is not relevant e.g. a Burst / no state + * associated
  • >0: Valid duration value specified + * + * @return + */ + public long getDuration(); + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/ITmfTimeAnalysisEntry.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/ITmfTimeAnalysisEntry.java new file mode 100644 index 0000000000..d26dcf8fa8 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/ITmfTimeAnalysisEntry.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model; + +import java.util.Vector; + +public interface ITmfTimeAnalysisEntry { + + public String getGroupName(); + + public int getId(); + + public String getName(); + + public long getStartTime(); + + public long getStopTime(); + + public Vector getTraceEvents(); +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/TimeEvent.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/TimeEvent.java new file mode 100644 index 0000000000..05681c9701 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/model/TimeEvent.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model; + +public abstract class TimeEvent implements ITimeEvent { + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tlf.widgets.timeAnalysis.model.TmTaEventI#getTrace() + */ + public abstract ITmfTimeAnalysisEntry getEntry(); + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tlf.widgets.timeAnalysis.model.TmTaEventI#getTime() + */ + public abstract long getTime(); + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tlf.widgets.timeAnalysis.model.TmTaEventI#getDuration() + */ + public long getDuration() { + return -1; + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/ITimeDataProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/ITimeDataProvider.java new file mode 100644 index 0000000000..7dd7712824 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/ITimeDataProvider.java @@ -0,0 +1,68 @@ +/***************************************************************************** + * Copyright (c) 2007, 2010 Intel Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * Ruslan A. Scherbakov, Intel - Initial API and implementation + * Alvaro Sanchex-Leon - Updated for TMF + * + * $Id: ITimeDataProvider.java,v 1.2 2007/02/27 18:37:36 ewchan Exp $ + *****************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; + +public interface ITimeDataProvider { + + long getSelectedTime(); + + long getBeginTime(); + + long getEndTime(); + + long getMinTime(); + + long getMaxTime(); + + long getTime0(); + + long getTime1(); + + long getMinTimeInterval(); + + /** + * Updates the time range and notify registered listeners + * + * @param time0 + * @param time1 + */ + void setStartFinishTimeNotify(long time0, long time1); + + /** + * Update the time range but do not trigger event notification + * + * @param time0 + * @param time1 + */ + void setStartFinishTime(long time0, long time1); + + /** + * Notify registered listeners without updating the time range + */ + void notifyStartFinishTime(); + + void setSelectedTimeInt(long time, boolean ensureVisible); + + void resetStartFinishTime(); + + int getNameSpace(); + + void setNameSpace(int width); + + int getTimeSpace(); + + boolean isCalendarFormat(); +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/PlainSelection.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/PlainSelection.java new file mode 100644 index 0000000000..cd6c0fa274 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/PlainSelection.java @@ -0,0 +1,65 @@ +/***************************************************************************** + * Copyright (c) 2007 Intel Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * Ruslan A. Scherbakov, Intel - Initial API and implementation + * Alvaro Sanchex-Leon - Udpated for TMF + * + * $Id: PlainSelection.java,v 1.1 2007/04/20 13:06:49 ewchan Exp $ + *****************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.viewers.IStructuredSelection; + +public class PlainSelection implements IStructuredSelection { + + List list = new ArrayList(); + + public PlainSelection() { + } + + public PlainSelection(Object sel) { + add(sel); + } + + public void add(Object sel) { + if (null != sel && !list.contains(sel)) + list.add(sel); + } + + public Object getFirstElement() { + if (!list.isEmpty()) + return list.get(0); + return null; + } + + public Iterator iterator() { + return list.iterator(); + } + + public int size() { + return list.size(); + } + + public Object[] toArray() { + return list.toArray(); + } + + public List toList() { + return list; + } + + public boolean isEmpty() { + return list.isEmpty(); + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TimeScaleCtrl.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TimeScaleCtrl.java new file mode 100644 index 0000000000..9c53a4d73d --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TimeScaleCtrl.java @@ -0,0 +1,787 @@ +/***************************************************************************** + * Copyright (c) 2007, 2008, 2010 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * Ruslan A. Scherbakov, Intel - Initial API and implementation + * Alvaro Sanchex-Leon - Udpated for TMF + * + * $Id: TimeScaleCtrl.java,v 1.5 2008/06/16 21:04:49 jkubasta Exp $ + *****************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.Messages; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.Utils.Resolution; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; + +public class TimeScaleCtrl extends TraceCtrl implements MouseListener, + MouseMoveListener { + + public TimeScaleCtrl(Composite parent, TraceColorScheme colors) { + super(parent, colors, SWT.NO_BACKGROUND | SWT.NO_FOCUS + | SWT.DOUBLE_BUFFERED); + addMouseListener(this); + addMouseMoveListener(this); + } + + private static final long SEC_IN_NS = 1000000000; + private static final long MIN_IN_NS = 60 * SEC_IN_NS; + private static final long HOUR_IN_NS = 60 * MIN_IN_NS; + private static final long DAY_IN_NS = 24 * HOUR_IN_NS; + private static final long MONTH_IN_NS = 31 * DAY_IN_NS; // upper limit + private static final long YEAR_IN_NS = 366 * DAY_IN_NS; // upper limit + + private static final double LOG10_1 = Math.log10(1); + private static final double LOG10_2 = Math.log10(2); + private static final double LOG10_3 = Math.log10(3); + private static final double LOG10_5 = Math.log10(5); + + private static final Calendar GREGORIAN_CALENDAR = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT")); + + private ITimeDataProvider _timeProvider; + private int _dragState = 0; + private int _dragX0 = 0; + private int _dragX = 0; + private long _time0bak; + private long _time1bak; + private boolean _isInUpdate; + private Rectangle _rect0 = new Rectangle(0, 0, 0, 0); + private int _height; + + public void setTimeProvider(ITimeDataProvider timeProvider) { + _timeProvider = timeProvider; + } + + private long _timeDelta; + + @Override + public Point computeSize(int wHint, int hHint, boolean changed) { + return super.computeSize(wHint, _height, changed); + } + + public void setHeight(int height) { + this._height = height; + } + + private void calcTimeDelta(int width, double pixelsPerNanoSec) { + double minDelta = (double) ((pixelsPerNanoSec == 0) ? YEAR_IN_NS : width / pixelsPerNanoSec); + long unit = 1; + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + if (minDelta > 6 * MONTH_IN_NS) { + unit = YEAR_IN_NS; + } else if (minDelta > 3 * MONTH_IN_NS) { + unit = 6 * MONTH_IN_NS; + } else if (minDelta > 10 * DAY_IN_NS) { + unit = MONTH_IN_NS; + } else if (minDelta > 12 * HOUR_IN_NS) { + unit = DAY_IN_NS; + } else if (minDelta > 3 * HOUR_IN_NS) { + unit = 6 * HOUR_IN_NS; + } else if (minDelta > 30 * MIN_IN_NS) { + unit = HOUR_IN_NS; + } else if (minDelta > 10 * MIN_IN_NS) { + unit = 15 * MIN_IN_NS; + } else if (minDelta > 30 * SEC_IN_NS) { + unit = MIN_IN_NS; + } else if (minDelta > 20 * SEC_IN_NS) { + unit = 30 * SEC_IN_NS; + } + } + double log = Math.log10((double) minDelta / unit); + long pow10 = (long) log; + double remainder = log - pow10; + if (remainder < LOG10_1) { + _timeDelta = (long) Math.pow(10, pow10) * unit; + } else if (remainder < LOG10_2) { + _timeDelta = 2 * (long) Math.pow(10, pow10) * unit; + } else if (remainder < LOG10_3 && unit >= HOUR_IN_NS && unit < YEAR_IN_NS) { + _timeDelta = 3 * (long) Math.pow(10, pow10) * unit; + } else if (remainder < LOG10_5) { + _timeDelta = 5 * (long) Math.pow(10, pow10) * unit; + } else { + _timeDelta = 10 * (long) Math.pow(10, pow10) * unit; + } + } + + private static TimeDraw TIMEDRAW_NANOSEC = new TimeDrawNanosec(); + private static TimeDraw TIMEDRAW_MICROSEC = new TimeDrawMicrosec(); + private static TimeDraw TIMEDRAW_MILLISEC = new TimeDrawMillisec(); + private static TimeDraw TIMEDRAW_SEC = new TimeDrawSec(); + private static TimeDraw TIMEDRAW_ABS_NANOSEC = new TimeDrawAbsNanoSec(); + private static TimeDraw TIMEDRAW_ABS_MICROSEC = new TimeDrawAbsMicroSec(); + private static TimeDraw TIMEDRAW_ABS_MILLISEC = new TimeDrawAbsMillisec(); + private static TimeDraw TIMEDRAW_ABS_SEC = new TimeDrawAbsSec(); + private static TimeDraw TIMEDRAW_ABS_MIN = new TimeDrawAbsMin(); + private static TimeDraw TIMEDRAW_ABS_HRS = new TimeDrawAbsHrs(); + private static TimeDraw TIMEDRAW_ABS_DAY = new TimeDrawAbsDay(); + private static TimeDraw TIMEDRAW_ABS_MONTH = new TimeDrawAbsMonth(); + private static TimeDraw TIMEDRAW_ABS_YEAR = new TimeDrawAbsYear(); + + TimeDraw getTimeDraw(long timeDelta) { + TimeDraw timeDraw; + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + if (timeDelta >= YEAR_IN_NS) + timeDraw = TIMEDRAW_ABS_YEAR; + else if (timeDelta >= MONTH_IN_NS) + timeDraw = TIMEDRAW_ABS_MONTH; + else if (timeDelta >= DAY_IN_NS) + timeDraw = TIMEDRAW_ABS_DAY; + else if (timeDelta >= HOUR_IN_NS) + timeDraw = TIMEDRAW_ABS_HRS; + else if (timeDelta >= MIN_IN_NS) + timeDraw = TIMEDRAW_ABS_MIN; + else if (timeDelta >= SEC_IN_NS) + timeDraw = TIMEDRAW_ABS_SEC; + else if (timeDelta >= 1000000) + timeDraw = TIMEDRAW_ABS_MILLISEC; + else if (timeDelta >= 1000) + timeDraw = TIMEDRAW_ABS_MICROSEC; + else + timeDraw = TIMEDRAW_ABS_NANOSEC; + return timeDraw; + } + if (timeDelta >= 1000000000) + timeDraw = TIMEDRAW_SEC; + else if (timeDelta >= 1000000) + timeDraw = TIMEDRAW_MILLISEC; + else if (timeDelta >= 1000) + timeDraw = TIMEDRAW_MICROSEC; + else + timeDraw = TIMEDRAW_NANOSEC; + return timeDraw; + } + + @Override + void paint(Rectangle rect, PaintEvent e) { + + if (_isInUpdate || null == _timeProvider) + return; + + GC gc = e.gc; + gc.fillRectangle(rect); + + if (null == _timeProvider) { + return; + } + + long time0 = _timeProvider.getTime0(); + long time1 = _timeProvider.getTime1(); + long selectedTime = _timeProvider.getSelectedTime(); + int leftSpace = _timeProvider.getNameSpace(); + int timeSpace = _timeProvider.getTimeSpace(); + + gc.setBackground(_colors.getColor(TraceColorScheme.TOOL_BACKGROUND)); + gc.setForeground(_colors.getColor(TraceColorScheme.TOOL_FOREGROUND)); + Utils.init(_rect0, rect); + + // draw top left area + _rect0.width = leftSpace; + _rect0.x += 4; + _rect0.width -= 4; + if (_rect0.width > 0) { + Utils.drawText(gc, Messages._Timescale + ":", _rect0, true); + } + int messageWidth = gc.stringExtent(Messages._Timescale + ":").x + 4; + Rectangle absHeaderRect = new Rectangle(_rect0.x + messageWidth, _rect0.y, _rect0.width - messageWidth, _rect0.height); + _rect0.x -= 4; + _rect0.width += 4; + + // prepare and draw right rect of the timescale + _rect0.x += leftSpace; + _rect0.width = rect.width - leftSpace; + + // draw bottom border and erase all other area + gc.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width - 1, + rect.y + rect.height - 1); + _rect0.height--; + gc.fillRectangle(_rect0); + + if (time1 <= time0 || timeSpace < 2) { + return; + } + + int numDigits = calculateDigits(time0, time1); + + int labelWidth = gc.getCharWidth('0') * numDigits; + double pixelsPerNanoSec = (timeSpace <= RIGHT_MARGIN) ? 0 : + (double) (timeSpace - RIGHT_MARGIN) / (time1 - time0); + calcTimeDelta(labelWidth, pixelsPerNanoSec); + + TimeDraw timeDraw = getTimeDraw(_timeDelta); + + // draw zoom rectangle + if (3 == _dragState && null != _timeProvider) { + if (_dragX0 < _dragX) { + gc.drawRectangle(leftSpace + _dragX0, rect.y, _dragX - _dragX0 - 1, rect.height - 8); + } else if (_dragX0 > _dragX) { + gc.drawRectangle(leftSpace + _dragX, rect.y, _dragX0 - _dragX - 1, rect.height - 8); + } + } + + if (_rect0.isEmpty()) + return; + + // draw selected time + int x = _rect0.x + (int) ((double)(selectedTime - time0) * pixelsPerNanoSec); + if (x >= _rect0.x && x < _rect0.x + _rect0.width) { + gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME)); + gc.drawLine(x, _rect0.y + _rect0.height - 6, x, _rect0.y + + _rect0.height); + gc + .setForeground(_colors + .getColor(TraceColorScheme.TOOL_FOREGROUND)); + } + + // draw time scale ticks + _rect0.y = rect.y; + _rect0.height = rect.height - 4; + _rect0.width = labelWidth; + + long time; + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + time = floorToCalendar(time0, _timeDelta); + } else { + time = (long) (Math.ceil((double) time0 / _timeDelta) * _timeDelta); + } + + // long t = (long) (time * 1000000000); + int y = _rect0.y + _rect0.height; + + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + timeDraw.drawAbsHeader(gc, time, absHeaderRect); + } + + while (true) { + x = rect.x + leftSpace + (int) (Math.floor((time - time0) * pixelsPerNanoSec)); + if (x >= rect.x + leftSpace + rect.width - _rect0.width) { + break; + } + if (x >= rect.x + leftSpace) { + gc.drawLine(x, y, x, y + 4); + _rect0.x = x; + if (x + _rect0.width <= rect.x + rect.width) + timeDraw.draw(gc, time, _rect0); + } + if (pixelsPerNanoSec == 0 || time > Long.MAX_VALUE - _timeDelta) { + break; + } + time += _timeDelta; + if (_timeProvider != null && _timeProvider.isCalendarFormat()) { + if (_timeDelta >= YEAR_IN_NS) { + GREGORIAN_CALENDAR.setTime(new Date(time / 1000000)); + GREGORIAN_CALENDAR.set(Calendar.MONTH, 0); // January 1st of year + GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); + time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000; + } else if (_timeDelta >= MONTH_IN_NS) { + GREGORIAN_CALENDAR.setTime(new Date(time / 1000000)); + GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); // 1st of month + time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000; + } + } + } + } + + private long floorToCalendar(long time, long timeDelta) { + if (_timeDelta >= YEAR_IN_NS) { + GREGORIAN_CALENDAR.setTime(new Date(time / 1000000)); + int year = GREGORIAN_CALENDAR.get(Calendar.YEAR); + int yearDelta = (int) (timeDelta / YEAR_IN_NS); + year = (year / yearDelta) * yearDelta; + GREGORIAN_CALENDAR.set(Calendar.YEAR, year); + GREGORIAN_CALENDAR.set(Calendar.MONTH, 0); // January 1st of year + GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); + GREGORIAN_CALENDAR.set(Calendar.HOUR_OF_DAY, 0); + GREGORIAN_CALENDAR.set(Calendar.MINUTE, 0); + GREGORIAN_CALENDAR.set(Calendar.SECOND, 0); + GREGORIAN_CALENDAR.set(Calendar.MILLISECOND, 0); + time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000; + } else if (_timeDelta >= MONTH_IN_NS) { + GREGORIAN_CALENDAR.setTime(new Date(time / 1000000)); + int month = GREGORIAN_CALENDAR.get(Calendar.MONTH); + int monthDelta = (int) (timeDelta / MONTH_IN_NS); + month = (month / monthDelta) * monthDelta; + GREGORIAN_CALENDAR.set(Calendar.MONTH, month); + GREGORIAN_CALENDAR.set(Calendar.DAY_OF_MONTH, 1); // 1st of month + GREGORIAN_CALENDAR.set(Calendar.HOUR_OF_DAY, 0); + GREGORIAN_CALENDAR.set(Calendar.MINUTE, 0); + GREGORIAN_CALENDAR.set(Calendar.SECOND, 0); + GREGORIAN_CALENDAR.set(Calendar.MILLISECOND, 0); + time = GREGORIAN_CALENDAR.getTimeInMillis() * 1000000; + } else { + time = (time / timeDelta) * timeDelta; + } + return time; + } + + private int calculateDigits(long time0, long time1) { + int numDigits = 5; + long timeRange = time1 - time0; + + if (_timeProvider.isCalendarFormat()) { + // Calculate the number of digits to represent the minutes provided + // 11:222 + // HH:mm:ss + numDigits += 8; + if (timeRange < 10000) { + // HH:11:222:333:444__ + numDigits += 10; + } else if (timeRange < 10000000) { + // HH:11:222:333__ + numDigits += 6; + } + } else { + // Calculate the number of digits to represent the minutes provided + long min = (long) ((time1 * 1E-9) / 60); // to sec then to minutes + String strMinutes = String.valueOf(min); + // 11:222 + if (strMinutes != null) { + numDigits += strMinutes.length(); + } else { + numDigits += 2; + } + if (timeRange < 10000) { + // 11:222:333:444__ + numDigits += 8; + } else if (timeRange < 10000000) { + // 11:222:333__ + numDigits += 4; + } + } + +// Trace.debug("timeRange: " + timeRange + " numDigits: " + numDigits); + return numDigits; + } + + public void mouseDown(MouseEvent e) { + if (_dragState == 0 && null != _timeProvider) { + if (1 == e.button) { + setCapture(true); + _dragState = 1; + } else if (3 == e.button) { + _dragState = 3; + } + int x = e.x - _timeProvider.getNameSpace(); + if (x < 0) { + x = 0; + } else if (x > getSize().x - _timeProvider.getNameSpace()) { + x = getSize().x - _timeProvider.getNameSpace(); + } + _dragX = _dragX0 = x; + _time0bak = _timeProvider.getTime0(); + _time1bak = _timeProvider.getTime1(); + } + } + + public void mouseUp(MouseEvent e) { + if (e.button == 1 && _dragState == 1) { + setCapture(false); + _dragState = 0; + + // Notify time provider to check the need for listener notification + if (_dragX != _dragX0) { + _timeProvider.setStartFinishTimeNotify(_timeProvider.getTime0(), _timeProvider.getTime1()); + } + } else if (e.button == 3 && _dragState == 3 && null != _timeProvider) { + _dragState = 0; + if (_dragX0 == _dragX) { + return; + } + int timeSpace = _timeProvider.getTimeSpace(); + int leftSpace = _timeProvider.getNameSpace(); + int x = e.x - leftSpace; + if (timeSpace > 0) { + _dragX = x; + if (_dragX0 > _dragX) { // drag right to left + _dragX = _dragX0; + _dragX0 = x; + } + long time0 = _time0bak + (long) ((_time1bak - _time0bak) * ((double) _dragX0 / timeSpace)); + long time1 = _time0bak + (long) ((_time1bak - _time0bak) * ((double) _dragX / timeSpace)); + + _timeProvider.setStartFinishTimeNotify(time0, time1); + _time0bak = _timeProvider.getTime0(); + _time1bak = _timeProvider.getTime1(); + } + } + } + + public void mouseMove(MouseEvent e) { + if (_dragX0 < 0 || _dragState == 0) { + return; + } + Point size = getSize(); + int leftSpace = _timeProvider.getNameSpace(); + int timeSpace = _timeProvider.getTimeSpace(); + int x = e.x - leftSpace; + if (1 == _dragState && null != _timeProvider) { + if (x > 0 && size.x > leftSpace && _dragX != x) { + _dragX = x; + long time1 = _time0bak + (long) ((_time1bak - _time0bak) * ((double) _dragX0 / _dragX)); + _timeProvider.setStartFinishTime(_time0bak, time1); + } + } else if (3 == _dragState && null != _timeProvider) { + if (x < 0) { + _dragX = 0; + } else if (x > timeSpace) { + _dragX = timeSpace; + } else { + _dragX = x; + } + redraw(); + } + } + + public void mouseDoubleClick(MouseEvent e) { + if (null != _timeProvider) { + _timeProvider.resetStartFinishTime(); + _time0bak = _timeProvider.getTime0(); + _time1bak = _timeProvider.getTime1(); + } + } +} + +abstract class TimeDraw { + static String S = ":"; + static String S0 = ":0"; + static String S00 = ":00"; + protected static final SimpleDateFormat stimeformat = new SimpleDateFormat("HH:mm:ss"); + protected static final SimpleDateFormat stimeformatheader = new SimpleDateFormat("yyyy MMM dd"); + protected static final SimpleDateFormat sminformat = new SimpleDateFormat("HH:mm"); + protected static final SimpleDateFormat sminformatheader = new SimpleDateFormat("yyyy MMM dd"); + protected static final SimpleDateFormat shrsformat = new SimpleDateFormat("MMM dd HH:mm"); + protected static final SimpleDateFormat shrsformatheader = new SimpleDateFormat("yyyy"); + protected static final SimpleDateFormat sdayformat = new SimpleDateFormat("MMM dd"); + protected static final SimpleDateFormat sdayformatheader = new SimpleDateFormat("yyyy"); + protected static final SimpleDateFormat smonthformat = new SimpleDateFormat("yyyy MMM"); + protected static final SimpleDateFormat syearformat = new SimpleDateFormat("yyyy"); + static { + stimeformat.setTimeZone(TimeZone.getTimeZone("GMT")); + stimeformatheader.setTimeZone(TimeZone.getTimeZone("GMT")); + sminformat.setTimeZone(TimeZone.getTimeZone("GMT")); + sminformatheader.setTimeZone(TimeZone.getTimeZone("GMT")); + shrsformat.setTimeZone(TimeZone.getTimeZone("GMT")); + shrsformatheader.setTimeZone(TimeZone.getTimeZone("GMT")); + sdayformat.setTimeZone(TimeZone.getTimeZone("GMT")); + sdayformatheader.setTimeZone(TimeZone.getTimeZone("GMT")); + smonthformat.setTimeZone(TimeZone.getTimeZone("GMT")); + syearformat.setTimeZone(TimeZone.getTimeZone("GMT")); + } + + static String pad(long n) { + String s = S; + if (n < 10) + s = S00; + else if (n < 100) + s = S0; + return s + n; + } + + public abstract void draw(GC gc, long time, Rectangle rect); + + public void drawAbsHeader(GC gc, long time, Rectangle absHeaderRect) { + // Override to draw absolute time header + // This is for the time information not shown in the draw of each tick + } + + public abstract String hint(); +} + +class TimeDrawSec extends TimeDraw { + static String _hint = "sec"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + time /= 1000000000; + Utils.drawText(gc, time + "", rect, true); + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawMillisec extends TimeDraw { + static String _hint = "s:ms"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + time /= 1000000; + long ms = time % 1000; + time /= 1000; + Utils.drawText(gc, time + pad(ms), rect, true); + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawMicrosec extends TimeDraw { + static String _hint = "s:ms:mcs"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + time /= 1000; + long mcs = time % 1000; + time /= 1000; + long ms = time % 1000; + time /= 1000; + Utils.drawText(gc, time + pad(ms) + pad(mcs), rect, true); + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawNanosec extends TimeDraw { + static String _hint = "s:ms:mcs:ns"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + long ns = time % 1000; + time /= 1000; + long mcs = time % 1000; + time /= 1000; + long ms = time % 1000; + time /= 1000; + Utils.drawText(gc, time + pad(ms) + pad(mcs) + pad(ns), rect, true); + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsYear extends TimeDraw { + static String _hint = "YYYY"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = syearformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsMonth extends TimeDraw { + static String _hint = "YYYY Mmm"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = smonthformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsDay extends TimeDraw { + static String _hint = "Mmm dd"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = sdayformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = sdayformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsHrs extends TimeDraw { + static String _hint = "Mmm dd HH:mm"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = shrsformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = shrsformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsMin extends TimeDraw { + static String _hint = "HH:mm"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = sminformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = sminformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsSec extends TimeDraw { + static String _hint = "HH:mm:ss"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = stimeformat.format(new Date((long) (time / 1000000))); + Utils.drawText(gc, stime, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = stimeformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsMillisec extends TimeDraw { + static String _hint = "HH:ss:ms"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = stimeformat.format(new Date((long) (time / 1000000))); + String ns = Utils.formatNs(time, Resolution.MILLISEC); + + Utils.drawText(gc, stime + " " + ns, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = stimeformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsMicroSec extends TimeDraw { + static String _hint = "HH:ss:ms:mcs"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = stimeformat.format(new Date((long) (time / 1000000))); + String micr = Utils.formatNs(time, Resolution.MICROSEC); + Utils.drawText(gc, stime + " " + micr, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = stimeformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + @Override + public String hint() { + return _hint; + } +} + +class TimeDrawAbsNanoSec extends TimeDraw { + static String _hint = "HH:ss:ms:mcs:ns"; + + @Override + public void draw(GC gc, long time, Rectangle rect) { + String stime = stimeformat.format(new Date((long) (time / 1000000))); + String ns = Utils.formatNs(time, Resolution.NANOSEC); + Utils.drawText(gc, stime + " " + ns, rect, true); + } + + @Override + public void drawAbsHeader(GC gc, long time, Rectangle rect) { + String header = stimeformatheader.format(new Date((long) (time / 1000000))); + int headerwidth = gc.stringExtent(header).x + 4; + if (headerwidth <= rect.width) { + rect.x += (rect.width - headerwidth); + Utils.drawText(gc, header, rect, true); + } + } + + @Override + public String hint() { + return _hint; + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeStatesCtrl.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeStatesCtrl.java new file mode 100644 index 0000000000..02729cfdf9 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeStatesCtrl.java @@ -0,0 +1,2214 @@ +/***************************************************************************** + * Copyright (c) 2007, 2008 Intel Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * Ruslan A. Scherbakov, Intel - Initial API and implementation + * Alvaro Sanchex-Leon - Udpated for TMF + * + * $Id: ThreadStatesCtrl.java,v 1.15 2008/07/11 13:49:01 aalexeev Exp $ + *****************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.Messages; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.TimeEvent; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.events.MouseWheelListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.ScrollBar; + +/** + * @author alvaro + * + */ +public class TmfTimeStatesCtrl extends TraceCtrl implements FocusListener, + KeyListener, MouseMoveListener, MouseListener, MouseWheelListener, + ControlListener, SelectionListener, MouseTrackListener, + TraverseListener, ISelectionProvider { + + public static final boolean DEFAULT_DRAW_THREAD_JOIN = true; + public static final boolean DEFAULT_DRAW_THREAD_WAIT = true; + public static final boolean DEFAULT_DRAW_THREAD_RELEASE = true; + public static int H_SCROLLBAR_MAX = Integer.MAX_VALUE - 1; + + private final double zoomCoeff = 1.5; + + private ITimeDataProvider _timeProvider; + private boolean _isInFocus = false; + private boolean _isDragCursor3 = false; + private boolean _isWaitCursor = true; + private boolean _mouseHover = false; + private int _itemHeightDefault = 19; + private int _itemHeight = _itemHeightDefault; + private int _topItem = 0; + private int _dragState = 0; + private int _hitIdx = 0; + private int _dragX0 = 0; + private int _dragX = 0; + private int _idealNameWidth = 0; + // private double _timeStep = 10000000; + private long _time0bak; + private long _time1bak; + private TmfTimeAnalysisProvider utilImpl = null; + private ItemData _data = null; + private List _selectionListeners; + private List _selectionChangedListeners = new ArrayList(); + private Rectangle _rect0 = new Rectangle(0, 0, 0, 0); + private Rectangle _rect1 = new Rectangle(0, 0, 0, 0); + private Cursor _dragCursor3; + private Cursor _WaitCursor; + private boolean drawTracesInteraction = false; + private boolean drawTraceJoins = DEFAULT_DRAW_THREAD_JOIN; + private boolean drawTraceWaits = DEFAULT_DRAW_THREAD_WAIT; + private boolean drawTraceReleases = DEFAULT_DRAW_THREAD_RELEASE; + + // Vertical formatting formatting for the state control view + private boolean _visibleVerticalScroll = true; + private int _borderWidth = 0; + private int _headerHeight = 0; + + private Listener mouseScrollFilterListener; + + public TmfTimeStatesCtrl(Composite parent, TraceColorScheme colors, + TmfTimeAnalysisProvider rutilImp) { + + super(parent, colors, SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL + | SWT.DOUBLE_BUFFERED); + + this.utilImpl = rutilImp; + _data = new ItemData(utilImpl); + + addFocusListener(this); + addMouseListener(this); + addMouseMoveListener(this); + addMouseTrackListener(this); + addMouseWheelListener(this); + addTraverseListener(this); + addKeyListener(this); + addControlListener(this); + ScrollBar scrollVer = getVerticalBar(); + ScrollBar scrollHor = getHorizontalBar(); + if (scrollVer != null) { + scrollVer.addSelectionListener(this); + scrollVer.setVisible(_visibleVerticalScroll); + } + + if (scrollHor != null) { + scrollHor.addSelectionListener(this); + } + mouseScrollFilterListener = new Listener() { + // This filter is used to prevent scrolling of the view when the + // mouse wheel is used to zoom + public void handleEvent(Event event) { + event.doit = false; + } + }; + + _dragCursor3 = new Cursor(super.getDisplay(), SWT.CURSOR_SIZEWE); + _WaitCursor = new Cursor(super.getDisplay(), SWT.CURSOR_WAIT); + } + + @Override + public void dispose() { + super.dispose(); + _dragCursor3.dispose(); + _WaitCursor.dispose(); + } + + public void setTimeProvider(ITimeDataProvider timeProvider) { + _timeProvider = timeProvider; + adjustScrolls(); + redraw(); + } + + public void addSelectionListener(SelectionListener listener) { + if (listener == null) + SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (null == _selectionListeners) + _selectionListeners = new ArrayList(); + _selectionListeners.add(listener); + } + + public void removeSelectionListener(SelectionListener listener) { + if (null != _selectionListeners) + _selectionListeners.remove(listener); + } + + public void fireSelectionChanged() { + if (null != _selectionListeners) { + Iterator it = _selectionListeners.iterator(); + while (it.hasNext()) { + SelectionListener listener = it.next(); + listener.widgetSelected(null); + } + } + } + + public void fireDefaultSelection() { + if (null != _selectionListeners) { + Iterator it = _selectionListeners.iterator(); + while (it.hasNext()) { + SelectionListener listener = it.next(); + listener.widgetDefaultSelected(null); + } + } + } + + public Object[] getTraces() { + return _data.getTraces(); + } + + public boolean[] getTraceFilter() { + return _data.getTraceFilter(); + } + + public void refreshData() { + _data.refreshData(); + adjustScrolls(); + redraw(); + } + + public void refreshData(Object traces[]) { + _data.refreshData(traces); + adjustScrolls(); + redraw(); + } + + public void refreshPartial(ITmfTimeAnalysisEntry parent, TimeEvent item) { + _data.refreshPartial(parent, item); + adjustScrolls(); + redraw(); + } + + public void adjustScrolls() { + if (null == _timeProvider) { + getVerticalBar().setValues(0, 1, 1, 1, 1, 1); + getHorizontalBar().setValues(0, 1, 1, 1, 1, 1); + return; + } + + // Vertical scroll bar + int page = countPerPage(); + if (_topItem + page > _data._items.length) + _topItem = _data._items.length - page; + if (_topItem < 0) + _topItem = 0; + getVerticalBar().setValues(_topItem, 0, _data._items.length, page, 1, + page); + + // HORIZONTAL BAR + // Visible window + long time0 = _timeProvider.getTime0(); + long time1 = _timeProvider.getTime1(); + // Time boundaries + long timeMin = _timeProvider.getMinTime(); + long timeMax = _timeProvider.getMaxTime(); + + long delta = timeMax - timeMin; + + int timePos = 0; + int thumb = H_SCROLLBAR_MAX; + + if (delta != 0) { + // Thumb size (page size) + thumb = Math.max(1, (int) (H_SCROLLBAR_MAX * ((double) (time1 - time0) / delta))); + // At the beginning of visible window + timePos = (int) (H_SCROLLBAR_MAX * ((double) (time0 - timeMin) / delta)); + } + + // position, minimum, maximum, thumb size, increment (half page)t, page + // increment size (full page) + getHorizontalBar().setValues(timePos, 0, H_SCROLLBAR_MAX, thumb, + Math.max(1, thumb / 2), Math.max(2, thumb)); + } + + boolean ensureVisibleItem(int idx, boolean redraw) { + boolean changed = false; + if (idx < 0) { + for (idx = 0; idx < _data._items.length; idx++) { + if (((Item) _data._items[idx])._selected) + break; + } + } + if (idx >= _data._items.length) + return changed; + if (idx < _topItem) { + _topItem = idx; + getVerticalBar().setSelection(_topItem); + if (redraw) + redraw(); + changed = true; + } else { + int page = countPerPage(); + if (idx >= _topItem + page) { + _topItem = idx - page + 1; + getVerticalBar().setSelection(_topItem); + if (redraw) + redraw(); + changed = true; + } + } + return changed; + } + + public ISelection getSelection() { + PlainSelection sel = new PlainSelection(); + ITmfTimeAnalysisEntry trace = getSelectedTrace(); + if (null != trace && null != _timeProvider) { + long selectedTime = _timeProvider.getSelectedTime(); + ITimeEvent event = Utils.findEvent(trace, selectedTime, 0); + if (event != null) + sel.add(event); + else + sel.add(trace); + } + return sel; + } + + public ISelection getSelectionTrace() { + PlainSelection sel = new PlainSelection(); + ITmfTimeAnalysisEntry trace = getSelectedTrace(); + if (null != trace) { + sel.add(trace); + } + return sel; + } + + public void selectTrace(int n) { + if (n != 1 && n != -1) + return; + boolean changed = false; + int lastSelection = -1; + for (int i = 0; i < _data._items.length; i++) { + Item item = (Item) _data._items[i]; + if (item._selected) { + lastSelection = i; + if (1 == n && i < _data._items.length - 1) { + item._selected = false; + if (item._hasChildren) + _data.expandItem(i, true); + item = (Item) _data._items[i + 1]; + if (item._hasChildren) { + _data.expandItem(i + 1, true); + item = (Item) _data._items[i + 2]; + } + item._selected = true; + changed = true; + } else if (-1 == n && i > 0) { + i--; + Item prevItem = (Item) _data._items[i]; + if (prevItem._hasChildren) { + if (prevItem._expanded) { + if (i > 0) { + i--; + prevItem = (Item) _data._items[i]; + } + } + if (!prevItem._expanded) { + int added = _data.expandItem(i, true); + prevItem = (Item) _data._items[i + added]; + item._selected = false; + prevItem._selected = true; + changed = true; + } + } else { + item._selected = false; + prevItem._selected = true; + changed = true; + } + } + break; + } + } + if (lastSelection < 0 && _data._items.length > 0) { + Item item = (Item) _data._items[0]; + if (item._hasChildren) { + _data.expandItem(0, true); + item = (Item) _data._items[1]; + item._selected = true; + changed = true; + } else { + item._selected = true; + changed = true; + } + } + if (changed) { + ensureVisibleItem(-1, false); + redraw(); + fireSelectionChanged(); + } + } + + public void selectEvent(int n) { + if (null == _timeProvider) + return; + ITmfTimeAnalysisEntry trace = getSelectedTrace(); + if (trace == _timeProvider || trace == null) + return; + long selectedTime = _timeProvider.getSelectedTime(); + long endTime = _timeProvider.getEndTime(); + ITimeEvent nextEvent; + if (-1 == n && selectedTime > endTime) + nextEvent = Utils.findEvent(trace, selectedTime, 0); + else + nextEvent = Utils.findEvent(trace, selectedTime, n); + if (null == nextEvent && -1 == n) + nextEvent = Utils.getFirstEvent(trace); + if (null != nextEvent) { + _timeProvider.setSelectedTimeInt(nextEvent.getTime(), true); + fireSelectionChanged(); + } else if (1 == n) { + _timeProvider.setSelectedTimeInt(endTime, true); + fireSelectionChanged(); + } + } + + public void selectNextEvent() { + selectEvent(1); + } + + public void selectPrevEvent() { + selectEvent(-1); + } + + public void selectNextTrace() { + selectTrace(1); + } + + public void selectPrevTrace() { + selectTrace(-1); + } + + /** + * Zooming based on mouse cursor location with mouse scrolling + * + * @param zoomIn + */ + public void zoom(boolean zoomIn) { + int globalX = getDisplay().getCursorLocation().x; + Point p = toControl(globalX, 0); + int nameSpace = _timeProvider.getNameSpace(); + int timeSpace = _timeProvider.getTimeSpace(); + int xPos = Math.max(nameSpace, Math.min(nameSpace + timeSpace, p.x)); + long time0 = _timeProvider.getTime0(); + long time1 = _timeProvider.getTime1(); + long interval = time1 - time0; + if (interval == 0) { + interval = 1; + } // to allow getting out of single point interval + long newInterval; + if (zoomIn) { + newInterval = Math.max(Math.round((double) interval * 0.8), _timeProvider.getMinTimeInterval()); + } else { + newInterval = Math.round((double) interval * 1.25); + } + long center = time0 + Math.round(((double) (xPos - nameSpace) / timeSpace * interval)); + long newTime0 = center - Math.round((double) newInterval * (center - time0) / interval); + long newTime1 = newTime0 + newInterval; + _timeProvider.setStartFinishTime(newTime0, newTime1); + } + + /** + * zoom in using single click + */ + public void zoomIn() { + long _time0 = _timeProvider.getTime0(); + long _time1 = _timeProvider.getTime1(); + long _range = _time1 - _time0; + long selTime = _timeProvider.getSelectedTime(); + if (selTime <= _time0 || selTime >= _time1) { + selTime = (_time0 + _time1) / 2; + } + long time0 = selTime - (long) ((selTime - _time0) / zoomCoeff); + long time1 = selTime + (long) ((_time1 - selTime) / zoomCoeff); + + long inaccuracy = (_timeProvider.getMaxTime() - _timeProvider + .getMinTime()) + - (time1 - time0); + + // Trace.debug("selTime:" + selTime + " time0:" + time0 + " time1:" + // + time1 + " inaccuracy:" + inaccuracy); + + if (inaccuracy > 0 && inaccuracy < 100) { + _timeProvider.setStartFinishTimeNotify(_timeProvider.getMinTime(), + _timeProvider.getMaxTime()); + return; + } + + long m = _timeProvider.getMinTimeInterval(); + if ((time1 - time0) < m) { + time0 = selTime - (long) ((selTime - _time0) * m / _range); + time1 = time0 + m; + } + + _timeProvider.setStartFinishTimeNotify(time0, time1); + } + + /** + * zoom out using single click + */ + public void zoomOut() { + long _time0 = _timeProvider.getTime0(); + long _time1 = _timeProvider.getTime1(); + long selTime = _timeProvider.getSelectedTime(); + if (selTime <= _time0 || selTime >= _time1) { + selTime = (_time0 + _time1) / 2; + } + long time0 = (long) (selTime - (selTime - _time0) * zoomCoeff); + long time1 = (long) (selTime + (_time1 - selTime) * zoomCoeff); + + long inaccuracy = (_timeProvider.getMaxTime() - _timeProvider + .getMinTime()) + - (time1 - time0); + if (inaccuracy > 0 && inaccuracy < 100) { + _timeProvider.setStartFinishTimeNotify(_timeProvider.getMinTime(), + _timeProvider.getMaxTime()); + return; + } + + _timeProvider.setStartFinishTimeNotify(time0, time1); + } + + public void groupTraces(boolean on) { + _data.groupTraces(on); + adjustScrolls(); + redraw(); + } + + public void toggleTraceInteractionDrawing() { + drawTracesInteraction = !drawTracesInteraction; + redraw(); + } + + public void setTraceJoinDrawing(boolean on) { + drawTraceJoins = on; + drawTracesInteraction = true; + redraw(); + } + + public void setTraceWaitDrawing(boolean on) { + drawTraceWaits = on; + drawTracesInteraction = true; + redraw(); + } + + public void setTraceReleaseDrawing(boolean on) { + drawTraceReleases = on; + drawTracesInteraction = true; + redraw(); + } + + public boolean getTracesInteractionDrawing() { + return drawTracesInteraction; + } + + public boolean getTraceJoinDrawing() { + return drawTraceJoins; + } + + public boolean getTraceWaitDrawing() { + return drawTraceWaits; + } + + public boolean getTraceReleaseDrawing() { + return drawTraceReleases; + } + + public ITmfTimeAnalysisEntry getSelectedTrace() { + ITmfTimeAnalysisEntry trace = null; + int idx = getSelectedIndex(); + if (idx >= 0 && _data._items[idx] instanceof TraceItem) + trace = ((TraceItem) _data._items[idx])._trace; + return trace; + } + + public int getSelectedIndex() { + int idx = -1; + for (int i = 0; i < _data._items.length; i++) { + Item item = (Item) _data._items[i]; + if (item._selected) { + idx = i; + break; + } + } + return idx; + } + + boolean toggle(int idx) { + boolean toggled = false; + if (idx >= 0 && idx < _data._items.length) { + Item item = (Item) _data._items[idx]; + if (item._hasChildren) { + item._expanded = !item._expanded; + _data.updateItems(); + adjustScrolls(); + redraw(); + toggled = true; + } + } + return toggled; + } + + int hitTest(int x, int y) { + if (x < 0 || y < 0) + return -1; + int hit = -1; + int idx = y / _itemHeight; + idx += _topItem; + if (idx < _data._items.length) + hit = idx; + return hit; + } + + int hitSplitTest(int x, int y) { + if (x < 0 || y < 0 || null == _timeProvider) + return -1; + int w = 4; + int hit = -1; + int nameWidth = _timeProvider.getNameSpace(); + if (x > nameWidth - w && x < nameWidth + w) + hit = 1; + return hit; + } + + public Item getItem(Point pt) { + int idx = hitTest(pt.x, pt.y); + return idx >= 0 ? (Item) _data._items[idx] : null; + } + + long hitTimeTest(int x, int y) { + if (null == _timeProvider) + return -1; + long hitTime = -1; + Point size = getCtrlSize(); + long time0 = _timeProvider.getTime0(); + long time1 = _timeProvider.getTime1(); + int nameWidth = _timeProvider.getNameSpace(); + x -= nameWidth; + if (x >= 0 && size.x >= nameWidth) { + if (time1 - time0 > size.x - nameWidth - RIGHT_MARGIN) { + // get the last possible time represented by the pixel position + // by taking the time of the next pixel position minus 1 nanosecond + hitTime = time0 + (long) ((time1 - time0) * ((double) (x + 1) / (size.x - nameWidth - RIGHT_MARGIN))) - 1; + } else { + hitTime = time0 + (long) ((time1 - time0) * ((double) (x) / (size.x - nameWidth - RIGHT_MARGIN))); + } + } + return hitTime; + } + + void selectItem(int idx, boolean addSelection) { + if (addSelection) { + if (idx >= 0 && idx < _data._items.length) { + Item item = (Item) _data._items[idx]; + item._selected = true; + } + } else { + for (int i = 0; i < _data._items.length; i++) { + Item item = (Item) _data._items[i]; + item._selected = i == idx; + } + } + boolean changed = ensureVisibleItem(idx, true); + if (!changed) + redraw(); + } + + public void selectItem(ITmfTimeAnalysisEntry trace, boolean addSelection) { + Integer idx = _data.findTraceItemIndex(trace); + selectItem(idx, addSelection); + } + + public int countPerPage() { + int height = getCtrlSize().y; + int count = 0; + if (height > 0) + count = height / _itemHeight; + return count; + } + + public int getTopIndex() { + int idx = -1; + if (_data._items.length > 0) + idx = 0; + return idx; + } + + public int getBottomIndex() { + int idx = _data._items.length - 1; + return idx; + } + + Point getCtrlSize() { + Point size = getSize(); + if (getVerticalBar().isVisible()) { + size.x -= getVerticalBar().getSize().x; + } + if (getHorizontalBar().isVisible()) { + size.y -= getHorizontalBar().getSize().y; + } + return size; + } + + void getNameRect(Rectangle rect, Rectangle bound, int idx, int nameWidth) { + idx -= _topItem; + rect.x = bound.x; + rect.y = bound.y + idx * _itemHeight; + rect.width = nameWidth; + rect.height = _itemHeight; + } + + void getStatesRect(Rectangle rect, Rectangle bound, int idx, int nameWidth) { + idx -= _topItem; + rect.x = bound.x + nameWidth; + rect.y = bound.y + idx * _itemHeight; + rect.width = bound.width - rect.x; + rect.height = _itemHeight; + } + + // private int getTraceNumber(int tid) { + // int num = -1; + // + // Object[] items = _data._items; + // for (int i = _topItem; i < items.length; i++) { + // Item item = (Item) items[i]; + // if ((item instanceof TraceItem)) { + // TsfTmTrace trace = ((TraceItem) item)._trace; + // if (trace != null && trace.getId() == tid) { + // num = i; + // break; + // } + // } + // } + // + // return num; + // } + + // private void drawArrow(GC gc, int x0, int y0, int x1, int y1, Color c) { + // gc.setForeground(c); + // gc.drawLine(x0, y0, x1, y1); + // + // if (y1 > y0) { + // gc.drawLine(x1 - 3, y1 - 3, x1, y1); + // gc.drawLine(x1 + 3, y1 - 3, x1, y1); + // } else { + // gc.drawLine(x1 - 3, y1 + 3, x1, y1); + // gc.drawLine(x1 + 3, y1 + 3, x1, y1); + // } + // } + + // TODO: CC: used in the removed functionality to draw thread interactions. + // private void drawTraceThreadEvent(Rectangle bound, TsfTmEvent e, + // TsfTmTrace trace, int nItem, int color, GC gc) { + // if (trace == null) + // return; + // + // int tid = trace.getId(); + // if (tid < 0 || getTraceNumber(tid) == -1) + // return; + // + // int nameWidth = _timeProvider.getNameSpace(); + // + // double time0 = _timeProvider.getTime0(); + // double time1 = _timeProvider.getTime1(); + // if (time0 == time1) + // return; + // + // int xr = bound.x + nameWidth; + // double K = (double) (bound.width - xr) / (time1 - time0); + // + // int x0 = xr + (int) ((e.getTime() - time0) * K); + // if (x0 < xr) + // x0 = xr; + // + // int x1 = xr + (int) ((trace.getStartTime() - time0) * K); + // if (x1 < xr) + // return; + // + // int y0 = bound.y + (nItem - _topItem) * _itemHeight + 3 + // + (_itemHeight - 6) / 2; + // int y1 = bound.y + (getTraceNumber(tid) - _topItem) * _itemHeight + 3 + // + (_itemHeight - 6) / 2; + // + // drawArrow(gc, x0, y0, x1, y1, _colors.getColor(color)); + // } + + public void drawTraceEvent(Rectangle bound, ITimeEvent e, int nItem, + int color, GC gc) { + int nameWidth = _timeProvider.getNameSpace(); + + long time0 = _timeProvider.getTime0(); + long time1 = _timeProvider.getTime1(); + if (time0 == time1) + return; + + int xr = bound.x + nameWidth; + double pixelsPerNanoSec = (bound.width - xr <= RIGHT_MARGIN) ? 0 + : (double) (bound.width - xr - RIGHT_MARGIN) / (time1 - time0); + + int x0 = xr + (int) ((e.getTime() - time0) * pixelsPerNanoSec); + if (x0 < xr) + return; + + int y0 = bound.y + (nItem - _topItem) * _itemHeight + 3; + + gc.setBackground(_colors.getColor(color)); + int c[] = { x0 - 3, y0 - 3, x0, y0, x0 + 3, y0 - 3 }; + gc.fillPolygon(c); + } + + // TODO: CC: + // private void drawExecEvent(Rectangle bound, TsfTmTraceExecEventImpl e, + // int nitem, int color, GC gc) { + // List runnings = e.getRunningEvents(); + // if (runnings == null) + // return; + // + // int nameWidth = _timeProvider.getNameSpace(); + // + // double time0 = _timeProvider.getTime0(); + // double time1 = _timeProvider.getTime1(); + // if (time0 == time1) + // return; + // + // int xr = bound.x + nameWidth; + // double K = (double) (bound.width - xr) / (time1 - time0); + // + // int x0 = xr + (int) ((e.getTime() - time0) * K); + // if (x0 < xr) + // x0 = xr; + // + // Iterator it = runnings.iterator(); + // while (it.hasNext()) { + // TsfTmTraceRunningEventImpl re = (TsfTmTraceRunningEventImpl) it + // .next(); + // int tid = re.getThread().getId(); + // if (tid < 0 || getThreadNumber(tid) == -1) + // continue; + // + // int x1 = xr + (int) ((re.getTime() - time0) * K); + // if (x1 < xr) + // continue; + // + // int y0 = bound.y + (nitem - _topItem) * _itemHeight + 3 + // + (_itemHeight - 6) / 2; + // int y1 = bound.y + (getThreadNumber(tid) - _topItem) * _itemHeight + // + 3 + (_itemHeight - 6) / 2; + // + // drawArrow(gc, x0, y0, x1, y1, _colors.getColor(color)); + // } + // } + + public void drawTraceInteractions(Rectangle bound, GC gc) { + // int nameWidth = _timeProvider.getNameSpace(); + // Object[] items = _data._items; + // + // double time0 = _timeProvider.getTime0(); + // double time1 = _timeProvider.getTime1(); + // + // if (time0 == time1) + // return; + // + // int xr = bound.x + nameWidth; + // double K = (double) (bound.width - xr) / (time1 - time0); + + // for (int i = 0; i < items.length; i++) { + // Item item = (Item) items[i]; + // if (!(item instanceof TraceItem)) + // continue; + // + // TsfTmTrace trace = ((TraceItem) item)._trace; + // if (trace == null) + // continue; + // + // List list = trace.getTraceEvents(); + // Iterator it = list.iterator(); + // while (it.hasNext()) { + // TsfTmEvent te = (TsfTmEvent) it.next(); + // TODO: CC: Thread Interactions, + // This needs to be accessed externally via a specific + // implementation. + // if (te instanceof TsfTmTraceStartThreadEventImpl) { + // TsfTmTrace child = ((TsfTmTraceStartThreadEventImpl) te) + // .getStartedThread(); + // drawThreadThreadEvent(bound, te, child, i, + // TraceColorScheme.TI_START_THREAD, gc); + // } else if (te instanceof TsfTmTraceHandoffLockEventImpl) { + // if (drawThreadReleases) + // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i, + // TraceColorScheme.TI_HANDOFF_LOCK, gc); + // } else if (te instanceof TsfTmTraceNotifyAllEventImpl) { + // if (drawThreadWaits) + // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i, + // TraceColorScheme.TI_NOTIFY_ALL, gc); + // } else if (te instanceof TsfTmTraceNotifyEventImpl) { + // if (drawThreadWaits) + // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i, + // TraceColorScheme.TI_NOTIFY, gc); + // } else if (te instanceof + // TsfTmTraceDeadAndNotifyJoinedEventImpl) { + // if (drawThreadJoins) + // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i, + // TraceColorScheme.TI_NOTIFY_JOINED, gc); + // } else if (te instanceof TsfTmTraceInterruptThreadEventImpl) + // { + // if (drawThreadWaits) + // drawExecEvent(bound, (TsfTmTraceExecEventImpl) te, i, + // TraceColorScheme.TI_INTERRUPT, gc); + // } else if (te instanceof + // TsfTmTraceWaitTimeoutExceedEventImpl) { + // drawThreadEvent(bound, te, i, + // TraceColorScheme.TI_WAIT_EXCEEDED, gc); + // } + // } + // } + } + + @Override + void paint(Rectangle bound, PaintEvent e) { + GC gc = e.gc; + gc.setBackground(_colors.getColor(TraceColorScheme.BACKGROUND)); + drawBackground(gc, bound.x, bound.y, bound.width, bound.height); + + if (bound.width < 2 || bound.height < 2 || null == _timeProvider) + return; + + _idealNameWidth = 0; + int nameWidth = _timeProvider.getNameSpace(); + long time0 = _timeProvider.getTime0(); + long time1 = _timeProvider.getTime1(); + long endTime = _timeProvider.getEndTime(); + long selectedTime = _timeProvider.getSelectedTime(); + // draw trace states + Object[] items = _data._items; + for (int i = _topItem; i < items.length; i++) { + Item item = (Item) items[i]; + + getNameRect(_rect0, bound, i, nameWidth); + if (_rect0.y >= bound.y + bound.height) + break; + + if (item instanceof GroupItem) { + getStatesRect(_rect1, bound, i, nameWidth); + _rect0.width += _rect1.width; + drawName(item, _rect0, gc); + } else { + drawName(item, _rect0, gc); + } + getStatesRect(_rect0, bound, i, nameWidth); + drawItemDataDurations(item, _rect0, time0, time1, endTime, + selectedTime, gc); + } + + if (drawTracesInteraction) + drawTraceInteractions(bound, e.gc); + + // draw drag line, no line if name space is 0. + if (3 == _dragState) { + gc.setForeground(_colors.getColor(TraceColorScheme.BLACK)); + gc.drawLine(bound.x + nameWidth, bound.y, bound.x + nameWidth, + bound.y + bound.height - 1); + } else if (0 == _dragState && _mouseHover + && _timeProvider.getNameSpace() > 0) { + gc.setForeground(_colors.getColor(TraceColorScheme.RED)); + gc.drawLine(bound.x + nameWidth, bound.y, bound.x + nameWidth, + bound.y + bound.height - 1); + } + } + + void drawName(Item item, Rectangle rect, GC gc) { + // No name to be drawn + if (_timeProvider.getNameSpace() == 0) + return; + boolean group = item instanceof GroupItem; + + int elemHeight = rect.height / 2; + int elemWidth = elemHeight; + String name = item._name; + if (group) { + gc.setBackground(_colors + .getBkColorGroup(item._selected, _isInFocus)); + gc.fillRectangle(rect); + if (item._selected && _isInFocus) { + gc.setForeground(_colors.getBkColor(item._selected, _isInFocus, + false)); + gc.drawRectangle(rect.x, rect.y, rect.width - 2, + rect.height - 2); + } + gc.setForeground(_colors.getBkColor(false, false, false)); + gc.drawLine(rect.x, rect.y + rect.height - 1, rect.width - 1, + rect.y + rect.height - 1); + gc.setForeground(_colors.getFgColorGroup(false, false)); + gc.setBackground(_colors.getBkColor(false, false, false)); + Utils.init(_rect1, rect); + _rect1.x += MARGIN; + _rect1.y += (rect.height - elemHeight) / 2; + _rect1.width = elemWidth; + _rect1.height = elemHeight; + // Get the icon rectangle in the group items + gc.fillRectangle(_rect1); + gc.drawRectangle(_rect1.x, _rect1.y, _rect1.width - 1, + _rect1.height - 1); + int p = _rect1.y + _rect1.height / 2; + gc.drawLine(_rect1.x + 2, p, _rect1.x + _rect1.width - 3, p); + if (!item._expanded) { + p = _rect1.x + _rect1.width / 2; + gc.drawLine(p, _rect1.y + 2, p, _rect1.y + _rect1.height - 3); + } + gc.setForeground(_colors + .getFgColorGroup(item._selected, _isInFocus)); + elemWidth += MARGIN; + } else { + gc.setBackground(_colors.getBkColor(item._selected, _isInFocus, + true)); + gc.setForeground(_colors.getFgColor(item._selected, _isInFocus)); + gc.fillRectangle(rect); + Utils.init(_rect1, rect); + _rect1.x += MARGIN; + // draw icon + ITmfTimeAnalysisEntry trace = ((TraceItem) item)._trace; + Image img = utilImpl.getItemImage(trace); + if (null != img) { + _rect1.y += (rect.height - img.getImageData().height) / 2; + gc.drawImage(img, _rect1.x, _rect1.y); + } + elemWidth = SMALL_ICON_SIZE; + // cut long string with "..." + Point size = gc.stringExtent(name); + if (_idealNameWidth < size.x) + _idealNameWidth = size.x; + int width = rect.width - MARGIN - MARGIN - elemWidth; + int cuts = 0; + while (size.x > width && name.length() > 1) { + cuts++; + name = name.substring(0, name.length() - 1); + size = gc.stringExtent(name + "..."); + } + if (cuts > 0) + name += "..."; + elemWidth += MARGIN; + } + Utils.init(_rect1, rect); + int leftMargin = MARGIN + elemWidth; + _rect1.x += leftMargin; + _rect1.width -= leftMargin; + int textWidth = 0; + // draw text + if (_rect1.width > 0) { + _rect1.y += 2; + textWidth = Utils.drawText(gc, name, _rect1, true) + 8; + _rect1.y -= 2; + } + // draw middle line + if (_rect1.width > 0 && !group) { + Utils.init(_rect1, rect); + _rect1.x += leftMargin + textWidth; + _rect1.width -= textWidth; + gc.setForeground(_colors.getColor(TraceColorScheme.MID_LINE)); + int midy = _rect1.y + _rect1.height / 2; + gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy); + } + // gc.drawLine(_rect1.x + _rect1.width - 1, _rect1.y, _rect1.x + + // _rect1.width - 1, _rect1.y + _rect1.height); + } + + void drawItemData(Item item, Rectangle rect, long time0, long time1, + long endTime, long selectedTime, GC gc) { + if (rect.isEmpty()) + return; + if (time1 <= time0) { + gc.setBackground(_colors.getBkColor(false, false, false)); + gc.fillRectangle(rect); + return; + } + + Utils.init(_rect1, rect); + boolean selected = item._selected; + double pixelsPerNanoSec = (rect.width <= RIGHT_MARGIN) ? 0 + : (double) (rect.width - RIGHT_MARGIN) / (time1 - time0); + boolean group = item instanceof GroupItem; + + if (group) { + // gc.setBackground(_colors.getBkColorGroup(selected, _isInFocus)); + // gc.fillRectangle(rect); + } else if (item instanceof TraceItem) { + ITmfTimeAnalysisEntry trace = ((TraceItem) item)._trace; + + int x0 = rect.x; + List list = trace.getTraceEvents(); + // Iterator it = list.iterator(); + int count = list.size(); + ITimeEvent lastEvent = null; + if (count > 0) { + ITimeEvent currEvent = list.get(0); + ITimeEvent nextEvent = null; + long currEventTime = currEvent.getTime(); + long nextEventTime = currEventTime; + x0 = rect.x + (int) ((currEventTime - time0) * pixelsPerNanoSec); + int xEnd = rect.x + (int) ((time1 - time0) * pixelsPerNanoSec); + int x1 = -1; + int idx = 1; + + // reduce rect + _rect1.y += 3; + _rect1.height -= 6; + fillSpace(rect, gc, selected, _rect1.x, x0, xEnd); + + // draw event states + while (x0 <= xEnd && null != currEvent) { + boolean stopped = false;// currEvent instanceof + // TsfTmTraceDeadEvent; + if (idx < count) { + nextEvent = list.get(idx); + nextEventTime = nextEvent.getTime(); + idx++; + } else if (stopped) { + nextEvent = null; + nextEventTime = time1; + } else { + nextEvent = null; + nextEventTime = endTime; + } + x1 = rect.x + (int) ((nextEventTime - time0) * pixelsPerNanoSec); + if (x1 >= rect.x) { + _rect1.x = x0 >= rect.x ? x0 : rect.x; + _rect1.width = (x1 <= xEnd ? x1 : xEnd) - _rect1.x; + boolean timeSelected = currEventTime <= selectedTime + && selectedTime < nextEventTime; + // Trace.debug("Drawing rectangle: " + _rect1.x + "," + // + _rect1.y + "," + _rect1.height + ", " + // + _rect1.width + "-->" + // + ((int) _rect1.x + (int) _rect1.width)); + utilImpl.drawState(_colors, currEvent, _rect1, gc, + selected, false, timeSelected); + } + lastEvent = currEvent; + currEvent = nextEvent; + currEventTime = nextEventTime; + x0 = x1; + } + } + + // fill space after last event + int xEnd = rect.x + rect.width; + if (x0 < xEnd) { + _rect1.x = x0 >= rect.x ? x0 : rect.x; + _rect1.width = xEnd - _rect1.x; + gc.setBackground(_colors + .getBkColor(selected, _isInFocus, false)); + gc.fillRectangle(_rect1); + // draw middle line + gc.setForeground(_colors.getColor(utilImpl + .getEventColorVal(lastEvent))); + int midy = _rect1.y + _rect1.height / 2; + int lw = gc.getLineWidth(); + gc.setLineWidth(2); + gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy); + gc.setLineWidth(lw); + } + + // draw focus ares + Utils.init(_rect1, rect); + gc.setForeground(_colors.getBkColor(selected, _isInFocus, false)); + int y = _rect1.y; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y++; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y++; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y = _rect1.y + _rect1.height - 1; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y--; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y--; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + } + + // draw selected time + int x = rect.x + (int) ((selectedTime - time0) * pixelsPerNanoSec); + if (x >= rect.x && x < rect.x + rect.width) { + gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME)); + if (group) + gc.drawLine(x, rect.y + rect.height - 1, x, rect.y + + rect.height); + else + gc.drawLine(x, rect.y, x, rect.y + rect.height); + } + } + + /** + * Represent the event in series of bursts rather than sequence of states + * + * @param item + * @param rect + * - The container rectangle to be colored to different states + * @param time0 + * - Base time of all events + * @param time1 + * - End time of all events + * @param endTime + * @param selectedTime + * @param gc + */ + void drawItemDataBurst(Item item, Rectangle rect, long time0, long time1, + long endTime, long selectedTime, GC gc) { + if (rect.isEmpty()) + return; + if (time1 <= time0) { + gc.setBackground(_colors.getBkColor(false, false, false)); + gc.fillRectangle(rect); + return; + } + + // Initialize _rect1 to same values as enclosing rectangle rect + Utils.init(_rect1, rect); + boolean selected = item._selected; + // K pixels per second + double pixelsPerNanoSec = (rect.width <= RIGHT_MARGIN) ? 0 + : (double) (rect.width - RIGHT_MARGIN) / (time1 - time0); + // Trace.debug("Value of K: " + K + " width:" + rect.width + " time0: " + // + time0 + " time1:" + time1 + " endTime: " + endTime); + + boolean group = item instanceof GroupItem; + + if (group) { + // gc.setBackground(_colors.getBkColorGroup(selected, _isInFocus)); + // gc.fillRectangle(rect); + // if (Trace.isDEBUG()) { + // Trace.debug("Group"); + // } + } else if (item instanceof TraceItem) { + ITmfTimeAnalysisEntry trace = ((TraceItem) item)._trace; + + double x0 = rect.x; + List list = trace.getTraceEvents(); + // Iterator it = list.iterator(); + int count = list.size(); + ITimeEvent lastEvent = null; + // Trace.debug("count is: " + count); + if (count > 0) { + ITimeEvent currEvent = list.get(0); + ITimeEvent nextEvent = null; + long currEventTime = currEvent.getTime(); + long nextEventTime = currEventTime; + // x0 - Points to the beginning of the event being drawn + double step = (double) ((currEventTime - time0) * pixelsPerNanoSec); + x0 = rect.x + step; + // xEnd - Points to the end of the events rectangle + double xEnd = rect.x + (double) ((time1 - time0) * pixelsPerNanoSec); + double x1 = -1; + int idx = 1; + double xNext = 0; + + // Drawing rectangle is smaller than reserved space + _rect1.y += 3; + _rect1.height -= 6; + + // Clean up to empty line to draw on top + fillSpace(rect, gc, selected, _rect1.x, xEnd, xEnd); + // draw event states + while (x0 <= xEnd && null != currEvent) { + boolean stopped = false;// currEvent instanceof + // TsfTmTraceDeadEvent; + if (idx < count) { + nextEvent = list.get(idx); + nextEventTime = nextEvent.getTime(); + idx++; + } else if (stopped) { + nextEvent = null; + nextEventTime = time1; + } else { + nextEvent = null; + nextEventTime = endTime; + // Trace + // .debug("nexEventTime is endTime: " + // + nextEventTime); + } + + // Draw it as a burst, one unit of width. + x1 = x0 + (int) 2; + if (x1 >= rect.x && x0 <= xEnd) { + // Fill with space until x0 + _rect1.x = (int) (x0 >= rect.x ? x0 : rect.x); + _rect1.width = (int) ((x1 <= xEnd ? x1 : xEnd) - _rect1.x); + boolean timeSelected = currEventTime <= selectedTime + && selectedTime < nextEventTime; + utilImpl.drawState(_colors, currEvent, _rect1, gc, + selected, false, timeSelected); + // Trace.debug("Drawing rectangle: " + _rect1.x + "," + // + _rect1.y + "," + _rect1.height + ", " + // + _rect1.width + "-->" + // + ((int) _rect1.x + (int) _rect1.width)); + // Advance rectangle to next start position and Fill + // with space until next event + _rect1.x += _rect1.width; + x0 = x1; + xNext = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); + } + // Fill space till next event + fillSpace(rect, gc, selected, x0, xNext, xEnd); + + lastEvent = currEvent; + currEvent = nextEvent; + currEventTime = nextEventTime; + // Move x0 to the beginning of next event + x0 = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); + // Trace.debug("rect.x: " + rect.x + " + " + + // "(nextEvenTime: " + // + nextEventTime + "- time0: " + time0 + ") * K: " + // + K + " = " + x0); + } + } + + // fill space after last event + int xEnd = rect.x + rect.width; + if (x0 < xEnd) { + // Trace.debug("Space after last event, x0: " + x0 + ", xEnd: " + // + xEnd); + _rect1.x = (int) (x0 >= rect.x ? x0 : rect.x); + _rect1.width = xEnd - _rect1.x; + gc.setBackground(_colors + .getBkColor(selected, _isInFocus, false)); + gc.fillRectangle(_rect1); + // draw middle line + gc.setForeground(_colors.getColor(utilImpl + .getEventColorVal(lastEvent))); + int midy = _rect1.y + _rect1.height / 2; + int lw = gc.getLineWidth(); + gc.setLineWidth(2); + gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy); + gc.setLineWidth(lw); + } + + // draw focus area + Utils.init(_rect1, rect); + gc.setForeground(_colors.getBkColor(selected, _isInFocus, false)); + int y = _rect1.y; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y++; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y++; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y = _rect1.y + _rect1.height - 1; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y--; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y--; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + } + + // draw selected time + int x = rect.x + (int) ((selectedTime - time0) * pixelsPerNanoSec); + if (x >= rect.x && x < rect.x + rect.width) { + gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME)); + if (group) + gc.drawLine(x, rect.y + rect.height - 1, x, rect.y + + rect.height); + else + gc.drawLine(x, rect.y, x, rect.y + rect.height); + } + } + + /** + * Represent the series of events with specified durations + * + * @param item + * @param rect + * - The container rectangle to be colored to different states + * @param time0 + * - Base time of all events - start of visible window + * @param time1 + * - End time of visible events - end time of visible window + * @param endTime + * - End time of all events - may not be visible in selected + * visible window + * @param selectedTime + * @param gc + */ + void drawItemDataDurations(Item item, Rectangle rect, long time0, + long time1, long endTime, long selectedTime, GC gc) { + if (rect.isEmpty()) + return; + if (time1 <= time0) { + gc.setBackground(_colors.getBkColor(false, false, false)); + gc.fillRectangle(rect); + return; + } + + // Initialize _rect1 to same values as enclosing rectangle rect + Utils.init(_rect1, rect); + boolean selected = item._selected; + // K pixels per second + double pixelsPerNanoSec = (rect.width <= RIGHT_MARGIN) ? 0 + : (double) (rect.width - RIGHT_MARGIN) / (time1 - time0); + // Trace.debug("Value of K: " + K + " width:" + rect.width + " time0: " + // + time0 + " time1:" + time1 + " endTime: " + endTime); + + boolean group = item instanceof GroupItem; + + if (group) { + // gc.setBackground(_colors.getBkColorGroup(selected, _isInFocus)); + // gc.fillRectangle(rect); + } else if (item instanceof TraceItem) { + ITmfTimeAnalysisEntry trace = ((TraceItem) item)._trace; + + double x0 = rect.x; + List list = trace.getTraceEvents(); + // Iterator it = list.iterator(); + int count = list.size(); + // ITimeEvent lastEvent = null; + // if (Trace.isDEBUG()) { + // Trace.debug("\n\t\t\tTrace: " + trace.getName() + // + utilImpl.getTraceClassName(trace)); + // } + // Trace.debug("count is: " + count); + // Drawing rectangle is smaller than reserved space + _rect1.y += 3; + _rect1.height -= 6; + + // Clean up to empty line to draw on top + int xEnd = rect.x + rect.width; + fillSpace(rect, gc, selected, _rect1.x, xEnd, xEnd); + if (count > 0) { + ITimeEvent currEvent = list.get(0); + ITimeEvent nextEvent = null; + long currEventTime = currEvent.getTime(); + long currEventDuration = currEvent.getDuration(); + // initial value + long nextEventTime = currEventTime; + // x0 - Points to the beginning of the event being drawn + double step = (double) ((currEventTime - time0) * pixelsPerNanoSec); + x0 = rect.x + step; + // xEnd - Points to the end of the events rectangle + double x1 = -1; + int idx = 1; + double xNext = 0; + + // draw event states + while (/* x0 <= xEnd &&*/ null != currEvent) { + boolean stopped = false;// currEvent instanceof + // refresh current event duration as the loop moves + currEventDuration = currEvent.getDuration(); + // TsfTmTraceDeadEvent; + if (idx < count) { + nextEvent = list.get(idx); + nextEventTime = nextEvent.getTime(); + idx++; + } else if (stopped) { + nextEvent = null; + nextEventTime = time1; + } else { + nextEvent = null; + nextEventTime = endTime; + // Trace + // .debug("nexEventTime is endTime: " + // + nextEventTime); + } + + // Calculate position to next event + xNext = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); + + // Calculate end position of current event + if (currEventDuration < 0) { + x1 = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); + } else if (currEventDuration == 0) { + x1 = x0; + } else { + x1 = x0 + (double) ((currEventDuration) * pixelsPerNanoSec); + } + + // If event end position x1 further away than start position + // of + // next event, cut width till next event + // Trace.debug("Next Event Pos: " + xNext + // + " End Of Current at: " + x1 + " Event Duration: " + // + currEventDuration); + if (currEventDuration != 0) { + x1 = x1 > xNext ? xNext : x1; + } + // if event end boundary is within time range + if (x1 >= rect.x && x0 <= xEnd) { + if (currEventDuration != 0) { + x0 = (double) (x0 >= rect.x ? x0 : rect.x); + _rect1.width = (int) ((x1 <= xEnd ? x1 : xEnd) - x0); + } else { + _rect1.width = 2; // make punctual events 2 pixels wide + } + _rect1.x = (int) x0; + boolean timeSelected = currEventTime <= selectedTime + && selectedTime < nextEventTime; + utilImpl.drawState(_colors, currEvent, _rect1, gc, + selected, false, timeSelected); + // Trace.debug("Drawing rectangle: " + _rect1.x + "," + // + _rect1.y + "," + _rect1.height + ", " + // + _rect1.width + "-->" + // + ((int) _rect1.x + (int) _rect1.width)); + // Advance rectangle to next start position and Fill + // with space until next event + _rect1.x += _rect1.width; + x0 = _rect1.x; + } + + // Fill space till next event + // fillSpace(rect, gc, selected, x0, xNext, xEnd); + + // lastEvent = currEvent; + currEvent = nextEvent; + currEventTime = nextEventTime; + // Move x0 to the beginning of next event + x0 = rect.x + (double) ((nextEventTime - time0) * pixelsPerNanoSec); + // Trace.debug("rect.x: " + rect.x + " + " + + // "(nextEvenTime: " + // + nextEventTime + "- time0: " + time0 + ") * K: " + // + K + " = " + x0); + } + } + + // draw focus area + Utils.init(_rect1, rect); + gc.setForeground(_colors.getBkColor(selected, _isInFocus, false)); + int y = _rect1.y; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y++; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y++; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y = _rect1.y + _rect1.height - 1; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y--; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + y--; + gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); + } + + // draw selected time + int x = rect.x + (int) ((double) (selectedTime - time0) * pixelsPerNanoSec); + if (x >= rect.x && x < rect.x + rect.width) { + gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME)); + if (group) + gc.drawLine(x, rect.y + rect.height - 1, x, rect.y + + rect.height); + else + gc.drawLine(x, rect.y, x, rect.y + rect.height); + } + } + + private void fillSpace(Rectangle rect, GC gc, boolean selected, double x0, + double x1, double xEnd) { + // fill space before first event + if (x0 >= rect.x && x0 < xEnd) { + // _rect1.width = (int) ((x1 <= xEnd ? x1 : xEnd) - x0); + // Trace.debug("Drawing Space: " + _rect1.x + "," + _rect1.y + "," + // + _rect1.height + ", " + _rect1.width + "--> " + // + ((int) _rect1.x + (int) _rect1.width)); + + // if (_rect1.width < 0) { + // Trace.debug("Incorrect width:" + _rect1.width); + // } + gc.setBackground(_colors.getBkColor(selected, _isInFocus, false)); + gc.fillRectangle(_rect1); + // draw middle line + gc.setForeground(_colors.getColor(TraceColorScheme.MID_LINE)); + int midy = _rect1.y + _rect1.height / 2; + gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy); + } else { + // Trace.debug("No space added since, x0 is out of range " + x0 + // + " rect.x: " + rect.x + " xEnd: " + xEnd); + } + } + + public void keyTraversed(TraverseEvent e) { + if ((e.detail == SWT.TRAVERSE_TAB_NEXT) + || (e.detail == SWT.TRAVERSE_TAB_PREVIOUS)) + e.doit = true; + } + + public void keyPressed(KeyEvent e) { + int idx = -1; + if (SWT.HOME == e.keyCode) { + idx = getTopIndex(); + } else if (SWT.END == e.keyCode) { + idx = getBottomIndex(); + } else if (SWT.ARROW_DOWN == e.keyCode) { + idx = getSelectedIndex(); + if (idx < 0) + idx = 0; + else if (idx < _data._items.length - 1) + idx++; + } else if (SWT.ARROW_UP == e.keyCode) { + idx = getSelectedIndex(); + if (idx < 0) + idx = 0; + else if (idx > 0) + idx--; + } else if (SWT.ARROW_LEFT == e.keyCode) { + selectPrevEvent(); + } else if (SWT.ARROW_RIGHT == e.keyCode) { + selectNextEvent(); + } else if (SWT.PAGE_DOWN == e.keyCode) { + int page = countPerPage(); + idx = getSelectedIndex(); + if (idx < 0) + idx = 0; + idx += page; + if (idx >= _data._items.length) + idx = _data._items.length - 1; + } else if (SWT.PAGE_UP == e.keyCode) { + int page = countPerPage(); + idx = getSelectedIndex(); + if (idx < 0) + idx = 0; + idx -= page; + if (idx < 0) + idx = 0; + } else if (SWT.CR == e.keyCode) { + idx = getSelectedIndex(); + if (idx >= 0) { + if (_data._items[idx] instanceof TraceItem) + fireDefaultSelection(); + else if (_data._items[idx] instanceof GroupItem) + toggle(idx); + } + idx = -1; + } + if (idx >= 0) { + selectItem(idx, false); + fireSelectionChanged(); + } + } + + public void keyReleased(KeyEvent e) { + } + + public void focusGained(FocusEvent e) { + _isInFocus = true; + redraw(); + getDisplay().addFilter(SWT.MouseWheel, mouseScrollFilterListener); + } + + public void focusLost(FocusEvent e) { + _isInFocus = false; + if (0 != _dragState) { + setCapture(false); + _dragState = 0; + } + redraw(); + getDisplay().removeFilter(SWT.MouseWheel, mouseScrollFilterListener); + } + + public boolean isInFocus() { + return _isInFocus; + } + + public void mouseMove(MouseEvent e) { + if (null == _timeProvider) + return; + Point size = getCtrlSize(); + if (1 == _dragState) { + int nameWidth = _timeProvider.getNameSpace(); + int x = e.x - nameWidth; + if (x > 0 && size.x > nameWidth && _dragX != x) { + _dragX = x; + double pixelsPerNanoSec = (size.x - nameWidth <= RIGHT_MARGIN) ? 0 + : (double) (size.x - nameWidth - RIGHT_MARGIN) / (_time1bak - _time0bak); + long timeDelta = (long) ((pixelsPerNanoSec == 0) ? 0 : ((_dragX - _dragX0) / pixelsPerNanoSec)); + long time1 = _time1bak - timeDelta; + long maxTime = _timeProvider.getMaxTime(); + if (time1 > maxTime) + time1 = maxTime; + long time0 = time1 - (_time1bak - _time0bak); + if (time0 < _timeProvider.getMinTime()) { + time0 = _timeProvider.getMinTime(); + time1 = time0 + (_time1bak - _time0bak); + } + _timeProvider.setStartFinishTime(time0, time1); + } + } else if (3 == _dragState) { + _dragX = e.x; + _timeProvider.setNameSpace(_hitIdx + _dragX - _dragX0); + } else if (0 == _dragState) { + boolean mouseHover = hitSplitTest(e.x, e.y) > 0; + if (_mouseHover != mouseHover) + redraw(); + _mouseHover = mouseHover; + // Make sure any time changes are notified to the application e.g. + // getting back from the horizontal scroll bar or zoomed using the + // mouse wheel + _timeProvider.notifyStartFinishTime(); + } + updateCursor(e.x, e.y); + } + + public void mouseDoubleClick(MouseEvent e) { + if (null == _timeProvider) + return; + if (1 == e.button) { + int idx = hitSplitTest(e.x, e.y); + if (idx >= 0) { + _timeProvider.setNameSpace(_idealNameWidth + 3 * MARGIN + + SMALL_ICON_SIZE); + return; + } + idx = hitTest(e.x, e.y); + if (idx >= 0) { + selectItem(idx, false); + if (_data._items[idx] instanceof TraceItem) { + fireDefaultSelection(); + } + } + } + } + + /** + *

    + * If the x, y position is over the vertical split line (name to time + * ranges), then change the cursor to a drag cursor to indicate the user the + * possibility of resizing + *

    + * + * @param x + * @param y + */ + void updateCursor(int x, int y) { + // if Wait cursor not active, check for the need to change to a drag + // cursor + if (_isWaitCursor == false) { + int idx = hitSplitTest(x, y); + // No dragcursor is name space is fixed to zero + if (idx > 0 && !_isDragCursor3 && _timeProvider.getNameSpace() > 0) { + setCursor(_dragCursor3); + _isDragCursor3 = true; + } else if (idx <= 0 && _isDragCursor3) { + setCursor(null); + _isDragCursor3 = false; + } + } + } + + /** + * Provide the possibilty to control the wait cursor externally e.g. data + * requests in progress + * + * @param waitInd + */ + public void waitCursor(boolean waitInd) { + // Update cursor as indicated + if (waitInd) { + setCursor(_WaitCursor); + _isWaitCursor = true; + } else { + setCursor(null); + _isWaitCursor = false; + } + + // Get ready for next mouse move + _isDragCursor3 = false; + } + + public void mouseDown(MouseEvent e) { + if (null == _timeProvider) + return; + int idx; + if (1 == e.button) { + int namewidth = _timeProvider.getNameSpace(); + if (namewidth != 0) { + idx = hitSplitTest(e.x, e.y); + if (idx > 0) { + _dragState = 3; + _dragX = _dragX0 = e.x; + _hitIdx = _timeProvider.getNameSpace(); + ; + _time0bak = _timeProvider.getTime0(); + _time1bak = _timeProvider.getTime1(); + redraw(); + return; + } + } + + idx = hitTest(e.x, e.y); + if (idx >= 0) { + if (_data._items[idx] instanceof TraceItem) { + long hitTime = hitTimeTest(e.x, e.y); + if (hitTime >= 0) { + _timeProvider.setSelectedTimeInt(hitTime, false); + setCapture(true); + _dragState = 1; + _dragX = _dragX0 = e.x - _timeProvider.getNameSpace(); + _time0bak = _timeProvider.getTime0(); + _time1bak = _timeProvider.getTime1(); + } + } else if (_data._items[idx] instanceof GroupItem) { + _hitIdx = idx; + _dragState = 2; + } + selectItem(idx, false); + fireSelectionChanged(); + } else { + selectItem(idx, false); // clear selection + } + } + } + + public void mouseUp(MouseEvent e) { + if (0 != _dragState) { + setCapture(false); + if (1 == _dragState) { + // Notify time provider to check the need for listener notification + _timeProvider.notifyStartFinishTime(); + } else if (2 == _dragState) { + if (hitTest(e.x, e.y) == _hitIdx) + toggle(_hitIdx); + } else if (3 == _dragState) { + redraw(); + } + _dragState = 0; + } + } + + public void controlMoved(ControlEvent e) { + } + + public void controlResized(ControlEvent e) { + adjustScrolls(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + } + + public void widgetSelected(SelectionEvent e) { + if (e.widget == getVerticalBar()) { + _topItem = getVerticalBar().getSelection(); + if (_topItem < 0) + _topItem = 0; + redraw(); + } else if (e.widget == getHorizontalBar() && null != _timeProvider) { + int start = getHorizontalBar().getSelection(); + long time0 = _timeProvider.getTime0(); + long time1 = _timeProvider.getTime1(); + long timeMin = _timeProvider.getMinTime(); + long timeMax = _timeProvider.getMaxTime(); + long delta = timeMax - timeMin; + + long range = time1 - time0; + // _timeRangeFixed = true; + time0 = timeMin + (long) (delta * ((double) start / H_SCROLLBAR_MAX)); + time1 = time0 + range; + + // TODO: Follow-up with Bug 310310 + // In Linux SWT.DRAG is the only value received + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=310310 + if (e.detail == SWT.DRAG) { + _timeProvider.setStartFinishTime(time0, time1); + } else { + _timeProvider.setStartFinishTimeNotify(time0, time1); + } + } + } + + public void mouseEnter(MouseEvent e) { + } + + public void mouseExit(MouseEvent e) { + if (_mouseHover) { + _mouseHover = false; + redraw(); + } + } + + public void mouseHover(MouseEvent e) { + } + + public void mouseScrolled(MouseEvent e) { + if (!_isInFocus) + return; + if (e.count > 0) { + zoom(true); + } else if (e.count < 0) { + zoom(false); + } + } + + public boolean isVisibleVerticalScroll() { + return _visibleVerticalScroll; + } + + public void setVisibleVerticalScroll(boolean visibleVerticalScroll) { + ScrollBar scrollVer = getVerticalBar(); + if (scrollVer != null) { + scrollVer.setVisible(visibleVerticalScroll); + } + this._visibleVerticalScroll = visibleVerticalScroll; + } + + @Override + public int getBorderWidth() { + return _borderWidth; + } + + public void setBorderWidth(int borderWidth) { + this._borderWidth = borderWidth; + } + + public int getHeaderHeight() { + return _headerHeight; + } + + public void setHeaderHeight(int headerHeight) { + this._headerHeight = headerHeight; + } + + public int getItemHeight() { + return _itemHeight; + } + + public void setItemHeight(int rowHeight) { + this._itemHeight = rowHeight; + } + + public Vector getFilteredOut() { + return _data.getFilteredOut(); + } + +// @Override + public void addSelectionChangedListener(ISelectionChangedListener listener) { + if (listener != null) { + if (!_selectionChangedListeners.contains(listener)) { + _selectionChangedListeners.add(listener); + } + } + } + +// @Override + public void removeSelectionChangedListener( + ISelectionChangedListener listener) { + if (listener != null) { + _selectionChangedListeners.remove(listener); + } + } + +// @Override + public void setSelection(ISelection selection) { + if (selection instanceof PlainSelection) { + PlainSelection sel = (PlainSelection) selection; + Object ob = sel.getFirstElement(); + if (ob instanceof ITmfTimeAnalysisEntry) { + ITmfTimeAnalysisEntry trace = (ITmfTimeAnalysisEntry) ob; + selectItem(trace, false); + } + } + + } +} + +class Item { + public boolean _expanded; + public boolean _selected; + public boolean _hasChildren; + public String _name; + + Item(String name) { + _name = name; + } + + @Override + public String toString() { + return _name; + } +} + +class TraceItem extends Item { + public ITmfTimeAnalysisEntry _trace; + + TraceItem(ITmfTimeAnalysisEntry trace, String name) { + super(name); + _trace = trace; + } +} + +class GroupItem extends Item { + public List _traces; + + GroupItem(String name) { + super(name); + _traces = new ArrayList(); + _hasChildren = true; + } + + void add(ITmfTimeAnalysisEntry trace) { + _traces.add(trace); + } +} + +class ItemData { + public Object[] _items = new Object[0]; + private Object _traces[] = new Object[0]; + private boolean traceFilter[] = new boolean[0]; + private Map _groupTable = new HashMap(); + private boolean _flatList = false; + private TmfTimeAnalysisProvider utilsImp; + private Vector filteredOut = new Vector(); + + public ItemData(TmfTimeAnalysisProvider utils) { + this.utilsImp = utils; + } + + protected void groupTraces(boolean on) { + if (_flatList == on) { + _flatList = !on; + updateItems(); + } + } + + void clearGroups() { + Iterator it = _groupTable.values().iterator(); + while (it.hasNext()) { + GroupItem group = it.next(); + group._traces.clear(); + } + } + + void deleteEmptyGroups() { + Iterator it = _groupTable.values().iterator(); + while (it.hasNext()) { + GroupItem group = it.next(); + if (group._traces.size() == 0) + it.remove(); + } + } + + TraceItem findTraceItem(ITmfTimeAnalysisEntry trace) { + if (trace == null) + return null; + + int traceId = trace.getId(); + TraceItem traceItem = null; + + for (int i = 0; i < _items.length; i++) { + Object item = _items[i]; + if (item instanceof TraceItem) { + TraceItem ti = (TraceItem) item; + if (ti._trace.getId() == traceId) { + traceItem = ti; + break; + } + } + } + + return traceItem; + } + + Integer findTraceItemIndex(ITmfTimeAnalysisEntry trace) { + if (trace == null) + return null; + + int traceId = trace.getId(); + + Integer idx = null; + for (int i = 0; i < _items.length; i++) { + idx = i; + Object item = _items[i]; + if (item instanceof TraceItem) { + TraceItem ti = (TraceItem) item; + if (ti._trace.getId() == traceId) { + break; + } + } + } + + return idx; + } + + public void updateItems() { + List itemList = new ArrayList(); + String name = ""; + + Iterator it = _groupTable.values().iterator(); + while (it.hasNext()) { + GroupItem group = it.next(); + if (!_flatList) + itemList.add(group); + + if (_flatList || group._expanded) { + Iterator it2 = group._traces.iterator(); + while (it2.hasNext()) { + ITmfTimeAnalysisEntry trace = it2.next(); + TraceItem traceItem = findTraceItem(trace); + name = utilsImp.composeTraceName(trace, false); + traceItem = new TraceItem(trace, name); + itemList.add(traceItem); + } + } + } + _items = itemList.toArray(); + } + + public int expandItem(int idx, boolean expand) { + if (idx < 0 || idx >= _items.length) + return 0; + int ret = 0; + Item item = (Item) _items[idx]; + if (item._hasChildren && !item._expanded) { + item._expanded = expand; + ret = _items.length; + updateItems(); + ret = _items.length - ret; + } + return ret; + } + + public void refreshData(Object traces[]) { + if (traces == null || traces.length == 0) { + traceFilter = null; + } else if (traceFilter == null || traces.length != traceFilter.length) { + traceFilter = new boolean[traces.length]; + java.util.Arrays.fill(traceFilter, true); + } + + _traces = traces; + refreshData(); + } + + /** + * Allows to update the GUI from a stream of events handling addition one by + * one over known TmfTaTrace parents. + * + * @param parent + * @param childItem + */ + public void refreshPartial(ITmfTimeAnalysisEntry parent, TimeEvent childItem) { + // Find the Trace item within the current list + TraceItem item = findTraceItem(parent); + +// This method is not used (yet) so this code can be commented out for now +// FIXME: Arrays.copyOf is a Java6 feature +// if (item == null) { +// // If the parent item is not found, make room for it in the current +// // array +// int length = 1; +// Object[] traces; +// if (_traces != null) { +// length = _traces.length + 1; +// traces = Arrays.copyOf(_traces, length); +// } else { +// traces = new Object[length]; +// } +// +// // Add the new parent element to the end of the array. +// traces[length - 1] = parent; +// +// // update the filter array to accomodate a postion to the new +// // element +// traceFilter = new boolean[traces.length]; +// java.util.Arrays.fill(traceFilter, true); +// +// // rebuild internal data +// _traces = traces; +// refreshData(); +// +// // item must be there +// item = findTraceItem(parent); +// } + + ITmfTimeAnalysisEntry localTraceItem = item._trace; + // Local trace found + Vector children = localTraceItem.getTraceEvents(); + TimeEvent lastChildIn = children.lastElement(); + long lastChildSTime = lastChildIn.getTime(); + long newChildSTime = childItem.getTime(); + if (newChildSTime < lastChildSTime) { + // The children are expected to arrive sorted by time + // since the new time is earlier than the last child + // The infomation is being refreshed from start, remove all + // children and start over + children.clear(); + } + // Add the new item + children.add(childItem); + + } + + public void refreshData() { + clearGroups(); + filteredOut.clear(); + String undef = Messages._UNDEFINED_GROUP; + List groupList = new ArrayList(); + for (int i = 0; i < _traces.length; i++) { + ITmfTimeAnalysisEntry trace = (ITmfTimeAnalysisEntry) _traces[i]; + if (!traceFilter[i]) { + filteredOut.add(trace); + continue; + } + + String groupName = trace.getGroupName(); + if (null == groupName) + groupName = undef; + + GroupItem group = _groupTable.get(groupName); + if (null == group) { + group = new GroupItem(NLS.bind(Messages._TRACE_GROUP_LABEL, + groupName)); + group._expanded = !groupName.equalsIgnoreCase("system") + && !groupName.equalsIgnoreCase(undef); + _groupTable.put(groupName, group); + groupList.add(group); + } + group.add(trace); + } + + deleteEmptyGroups(); + updateItems(); + } + + public Object[] getTraces() { + return _traces; + } + + public boolean[] getTraceFilter() { + return traceFilter; + } + + public Vector getFilteredOut() { + return filteredOut; + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeTipHandler.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeTipHandler.java new file mode 100644 index 0000000000..eda2d7992b --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TmfTimeTipHandler.java @@ -0,0 +1,244 @@ +/***************************************************************************** + * Copyright (c) 2007, Intel Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * Vitaly A. Provodin, Intel - Initial API and implementation + * Alvaro Sanchex-Leon - Udpated for TMF + * + * $Id: ThreadsTipHandler.java,v 1.5 2007/06/06 19:16:16 gnagarajan Exp $ + *****************************************************************************/ +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; + +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.Messages; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer.TimeFormat; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets.Utils.Resolution; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseTrackAdapter; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Widget; + + +public class TmfTimeTipHandler { + + private Shell _tipShell; + private Table _tipTable; + private Item _tipItem; + private Point _tipPosition; + private ITimeDataProvider _timeDataProvider; + TmfTimeAnalysisProvider _utilImp = null; + + public TmfTimeTipHandler(Shell parent, TmfTimeAnalysisProvider rUtilImpl, + ITimeDataProvider timeProv) { + final Display display = parent.getDisplay(); + + this._utilImp = rUtilImpl; + this._timeDataProvider = timeProv; + _tipShell = new Shell(parent, SWT.ON_TOP | SWT.TOOL); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 2; + gridLayout.marginWidth = 2; + gridLayout.marginHeight = 2; + _tipShell.setLayout(gridLayout); + GridData data = new GridData(GridData.BEGINNING, GridData.BEGINNING, + true, true); + _tipShell.setLayoutData(data); + _tipShell.setBackground(display + .getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + + _tipTable = new Table(_tipShell, SWT.NONE); + _tipTable.setForeground(display + .getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + _tipTable.setBackground(display + .getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + _tipTable.setHeaderVisible(false); + _tipTable.setLinesVisible(false); + + // tipTable.setLayoutData(new GridData(GridData.FILL_HORIZONTAL + // | GridData.VERTICAL_ALIGN_CENTER)); + } + + public void activateHoverHelp(final Control control) { + control.addMouseListener(new MouseAdapter() { + @Override + public void mouseDown(MouseEvent e) { + if (_tipShell.isVisible()) + _tipShell.setVisible(false); + } + }); + + control.addMouseTrackListener(new MouseTrackAdapter() { + @Override + public void mouseExit(MouseEvent e) { + if (_tipShell.isVisible()) + _tipShell.setVisible(false); + _tipItem = null; + + } + + private void addItem(String name, String value) { + TableItem line = new TableItem(_tipTable, SWT.NONE); + line.setText(0, name); + line.setText(1, value); + } + + private void fillValues(Point pt, TmfTimeStatesCtrl threadStates, + Item item) { + if (item instanceof TraceItem) { + ITmfTimeAnalysisEntry thrd = ((TraceItem) item)._trace; + ITimeEvent threadEvent = Utils.findEvent(thrd, threadStates + .hitTimeTest(pt.x, pt.y), 2); + ITimeEvent nextEvent = Utils.findEvent(thrd, threadStates + .hitTimeTest(pt.x, pt.y), 1); + // thread name + addItem(Messages._TRACE_NAME, thrd.getName()); + // class name + addItem(Messages._TRACE_CLASS_NAME, _utilImp + .getTraceClassName(thrd)); + // thread state + addItem(Messages._TRACE_STATE, _utilImp + .getEventName(threadEvent)); + + // This block receives a + // list of values to be added to the tip + // table + Map eventAddOns = _utilImp + .getEventHoverToolTipInfo(threadEvent); + for (Iterator iter = eventAddOns.keySet() + .iterator(); iter.hasNext();) { + String message = (String) iter.next(); + addItem(message, eventAddOns.get(message)); + } + + long eventStartTime = -1; + long eventDuration = -1; + long eventEndTime = -1; + + if (threadEvent != null) { + eventStartTime = threadEvent.getTime(); + eventDuration = threadEvent.getDuration(); + if (eventDuration < 0 && nextEvent != null) { + eventEndTime = nextEvent.getTime(); + eventDuration = eventEndTime - eventStartTime; + } else { + eventEndTime = eventStartTime + eventDuration; + } + } + +// TODO: Check if we need "format" +// TimeFormat format = TimeFormat.RELATIVE; + Resolution res = Resolution.NANOSEC; + if (_timeDataProvider.isCalendarFormat()) { +// format = TimeFormat.ABSOLUTE; // Absolute format +// // (calendar) + // Add Date + addItem(Messages._TRACE_DATE, eventStartTime > -1 ? + Utils.formatDate(eventStartTime) + : "?"); + if (eventDuration > 0) { + addItem(Messages._TRACE_START_TIME, eventStartTime > -1 ? + Utils.formatTime(eventStartTime, TimeFormat.ABSOLUTE, res) + : "?"); + + addItem(Messages._TRACE_STOP_TIME, eventEndTime > -1 ? + Utils.formatTime(eventEndTime, TimeFormat.ABSOLUTE, res) + : "?"); + } else { + addItem(Messages._TRACE_EVENT_TIME, eventStartTime > -1 ? + Utils.formatTime(eventStartTime, TimeFormat.ABSOLUTE, res) + : "?"); + } + } else { + if (eventDuration > 0) { + addItem(Messages._TRACE_START_TIME, eventStartTime > -1 ? + Utils.formatTime(eventStartTime, TimeFormat.RELATIVE, res) + : "?"); + + addItem(Messages._TRACE_STOP_TIME, eventEndTime > -1 ? + Utils.formatTime(eventEndTime, TimeFormat.RELATIVE, res) + : "?"); + } else { + addItem(Messages._TRACE_EVENT_TIME, eventStartTime > -1 ? + Utils.formatTime(eventStartTime, TimeFormat.RELATIVE, res) + : "?"); + } + } + + if (eventDuration > 0) { + // Duration in relative format in any case + addItem(Messages._DURATION, eventDuration > -1 ? + Utils.formatTime(eventDuration, TimeFormat.RELATIVE, res) + : "?"); + } + + } else if (item instanceof GroupItem) { + addItem(Messages._TRACE_GROUP_NAME, item.toString()); + addItem(Messages._NUMBER_OF_TRACES, "" + + ((GroupItem) item)._traces.size()); + } + } + + @Override + public void mouseHover(MouseEvent event) { + Point pt = new Point(event.x, event.y); + Widget widget = event.widget; + Item item = null; + if (widget instanceof TmfTimeStatesCtrl) { + TmfTimeStatesCtrl threadStates = (TmfTimeStatesCtrl) widget; + item = (Item) threadStates.getItem(pt); + _tipTable.remove(0, _tipTable.getItemCount() - 1); + new TableColumn(_tipTable, SWT.NONE); + new TableColumn(_tipTable, SWT.NONE); + fillValues(pt, threadStates, item); + _tipTable.getColumn(0).setWidth(200); + _tipTable.getColumn(1).pack(); + _tipTable.setSize(_tipTable.computeSize(SWT.DEFAULT, 200)); + _tipShell.pack(); + } else if (widget == null) { + _tipShell.setVisible(false); + _tipItem = null; + return; + } + if (item == _tipItem) + return; + _tipItem = item; + _tipPosition = control.toDisplay(pt); + _tipShell.pack(); + setHoverLocation(_tipShell, _tipPosition); + _tipShell.setVisible(true); + } + }); + } + + private void setHoverLocation(Shell shell, Point position) { + Rectangle displayBounds = shell.getDisplay().getBounds(); + Rectangle shellBounds = shell.getBounds(); + shellBounds.x = Math.max(Math.min(position.x, displayBounds.width + - shellBounds.width), 0); + shellBounds.y = Math.max(Math.min(position.y + 16, displayBounds.height + - shellBounds.height), 0); + shell.setBounds(shellBounds); + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceColorScheme.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceColorScheme.java new file mode 100644 index 0000000000..32c533ceb7 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceColorScheme.java @@ -0,0 +1,378 @@ +/***************************************************************************** + * Copyright (c) 2008 Intel Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * Ruslan A. Scherbakov, Intel - Initial API and implementation + * Alvaro Sanchex-Leon - Udpated for TMF + * + * $Id: TraceColorScheme.java,v 1.3 2008/05/09 16:11:24 jkubasta Exp $ + *****************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider.StateColor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; + + +public class TraceColorScheme { + + // elements color indices + static public final int BLACK_STATE = 0; + static public final int GREEN_STATE = 1; + static public final int DARK_BLUE_STATE = 2; + static public final int ORANGE_STATE = 3; + static public final int GOLD_STATE = 4; + static public final int RED_STATE = 5; + static public final int GRAY_STATE = 6; + static public final int DARK_GREEN_STATE = 7; + static public final int DARK_YELLOW_STATE = 8; + static public final int MAGENTA3_STATE = 9; + static public final int PURPLE1_STATE = 10; + static public final int PINK1_STATE = 11; + static public final int AQUAMARINE_STATE = 12; + static public final int LIGHT_BLUE_STATE = 13; + static public final int CADET_BLUE_STATE = 14; + static public final int OLIVE_STATE = 15; + + static public final int STATES0 = 0; + static public final int STATES1 = 15; + + // State element index to name mapping, must keep the same order as above + public static final StateColor stateColors[] = { StateColor.BLACK, + StateColor.GREEN, StateColor.DARK_BLUE, StateColor.ORANGE, + StateColor.GOLD, StateColor.RED, StateColor.GRAY, StateColor.DARK_GREEN, StateColor.DARK_YELLOW, StateColor.MAGENTA3, StateColor.PURPLE1, + StateColor.PINK1, StateColor.AQUAMARINE, StateColor.LIGHT_BLUE, StateColor.CADET_BLUE, StateColor.OLIVE + }; + + // selected state elements color indices + static public final int BLACK_STATE_SEL = 16; + static public final int GREEN_STATE_SEL = 17; + static public final int DARK_BLUE_STATE_SEL = 18; + static public final int ORANGE_STATE_SEL = 19; + static public final int GOLD_STATE_SEL = 20; + static public final int RED_STATE_SEL = 21; + static public final int GRAY_STATE_SEL = 22; + static public final int DARK_GREEN_STATE_SEL = 23; + static public final int DARK_YELLOW_STATE_SEL = 24; + static public final int MAGENTA3_STATE_SEL = 25; + static public final int PURPLE1_STATE_SEL = 26; + static public final int PINK1_STATE_SEL = 27; + static public final int AQUAMARINE_STATE_SEL = 28; + static public final int LIGHT_BLUE_STATE_SEL = 29; + static public final int CADET_BLUE_STATE_SEL = 30; + static public final int OLIVE_STATE_SEL = 31; + + static public final int STATES_SEL0 = 16; + static public final int STATES_SEL1 = 31; + + // colors indices for viewer controls + static public final int BACKGROUND = 32; + static public final int FOREGROUND = 33; + static public final int BACKGROUND_SEL = 34; + static public final int FOREGROUND_SEL = 35; + static public final int BACKGROUND_SEL_NOFOCUS = 36; + static public final int FOREGROUND_SEL_NOFOCUS = 37; + static public final int TOOL_BACKGROUND = 38; + static public final int TOOL_FOREGROUND = 39; + + // misc colors + static public final int FIX_COLOR = 40; + static public final int WHITE = 41; + static public final int GRAY = 42; + static public final int BLACK = 43; + static public final int DARK_GRAY = 44; + + // selected border color indices + static public final int BLACK_BORDER = 45; + static public final int GREEN_BORDER = 46; + static public final int DARK_BLUE_BORDER = 47; + static public final int ORANGE_BORDER = 48; + static public final int GOLD_BORDER = 49; + static public final int RED_BORDER = 50; + static public final int GRAY_BORDER = 51; + static public final int DARK_GREEN_BORDER1 = 52; + static public final int DARK_YELLOW_BORDER1 = 53; + static public final int MAGENTA3_BORDER1 = 54; + static public final int PURPLE1_BORDER1 = 55; + static public final int PINK1_BORDER1 = 56; + static public final int AQUAMARINE_BORDER1 = 57; + static public final int LIGHT_BLUE_BORDER1 = 58; + static public final int CADET_BLUE_STATE_BORDER = 59; + static public final int OLIVE_BORDER2 = 60; + + static public final int STATES_BORDER0 = 45; + static public final int STATES_BORDER1 = 60; + + static public final int MID_LINE = 61; + static public final int RED = 62; + static public final int GREEN = 63; + static public final int BLUE = 64; + static public final int YELLOW = 65; + static public final int CYAN = 66; + static public final int MAGENTA = 67; + + static public final int SELECTED_TIME = 68; + static public final int LEGEND_BACKGROUND = 69; + static public final int LEGEND_FOREGROUND = 70; + + // group items' colors + static public final int GR_BACKGROUND = 71; + static public final int GR_FOREGROUND = 72; + static public final int GR_BACKGROUND_SEL = 73; + static public final int GR_FOREGROUND_SEL = 74; + static public final int GR_BACKGROUND_SEL_NOFOCUS = 75; + static public final int GR_FOREGROUND_SEL_NOFOCUS = 76; + + static public final int LIGHT_LINE = 77; + static public final int BACKGROUND_NAME = 78; + static public final int BACKGROUND_NAME_SEL = 79; + static public final int BACKGROUND_NAME_SEL_NOFOCUS = 80; + + // Interraction's colors + static public final int TI_START_THREAD = BLACK; + static public final int TI_HANDOFF_LOCK = BLUE; + static public final int TI_NOTIFY_ALL = GREEN; + static public final int TI_NOTIFY = GREEN; + static public final int TI_NOTIFY_JOINED = DARK_GRAY; + static public final int TI_INTERRUPT = RED; + static public final int TI_WAIT_EXCEEDED = BLUE; + + static interface IColorProvider { + public Color get(); + } + + static class SysCol implements IColorProvider { + int syscol; + + SysCol(int syscol) { + this.syscol = syscol; + } + + public Color get() { + return Utils.getSysColor(syscol); + } + } + + static class RGB implements IColorProvider { + int r; + int g; + int b; + + RGB(int r, int g, int b) { + this.r = r; + this.g = g; + this.b = b; + } + + public Color get() { + return new Color(null, r, g, b); + } + } + + static class Mix implements IColorProvider { + IColorProvider cp1; + IColorProvider cp2; + int w1; + int w2; + + Mix(IColorProvider cp1, IColorProvider cp2, int w1, int w2) { + this.cp1 = cp1; + this.cp2 = cp2; + this.w1 = w1; + this.w2 = w2; + } + + Mix(IColorProvider cp1, IColorProvider cp2) { + this.cp1 = cp1; + this.cp2 = cp2; + this.w1 = 1; + this.w2 = 1; + } + + public Color get() { + Color col1 = cp1.get(); + Color col2 = cp2.get(); + Color col = Utils.mixColors(col1, col2, w1, w2); + return col; + } + } + + static private final IColorProvider _providersMap[] = { + // + new RGB(100, 100, 100), // UNKNOWN + new RGB(174, 200, 124), // RUNNING + new Mix(new SysCol(SWT.COLOR_BLUE), new SysCol(SWT.COLOR_GRAY), 1, 3), // SLEEPING + new RGB(210, 150, 60), // WAITING + new RGB(242, 225, 168), // BLOCKED + new Mix(new SysCol(SWT.COLOR_RED), new SysCol(SWT.COLOR_GRAY), 1, 3), // DEADLOCK + new RGB(200, 200, 200), // STOPPED + new RGB(35, 107, 42), // STEEL BLUE + new RGB(205,205,0), // DARK YELLOW + new RGB(205, 0, 205), // MAGENTA + new RGB(171, 130, 255), // PURPLE + new RGB(255, 181, 197), // PINK + new RGB(112, 219, 147), // AQUAMARINE + new RGB(198, 226, 255), // SLATEGRAY + new RGB(95, 158, 160), // CADET BLUE + new RGB(107, 142, 35), // OLIVE + + + //TODO: Does not seem to be used, check during clean-up + new SysCol(SWT.COLOR_WHITE), // UNKNOWN_SEL + new SysCol(SWT.COLOR_GREEN), // RUNNING_SEL + new SysCol(SWT.COLOR_BLUE), // SLEEPING_SEL + new SysCol(SWT.COLOR_CYAN), // WAITING_SEL + new SysCol(SWT.COLOR_YELLOW), // BLOCKED_SEL + new SysCol(SWT.COLOR_RED), // DEADLOCK_SEL + new SysCol(SWT.COLOR_DARK_GRAY), // STOPPED_SEL + new SysCol(SWT.COLOR_WHITE), + new SysCol(SWT.COLOR_GREEN), + new SysCol(SWT.COLOR_BLUE), + new SysCol(SWT.COLOR_CYAN), + new SysCol(SWT.COLOR_YELLOW), + new SysCol(SWT.COLOR_RED), + new SysCol(SWT.COLOR_DARK_GRAY), + new SysCol(SWT.COLOR_WHITE), + new SysCol(SWT.COLOR_GREEN), + + + new SysCol(SWT.COLOR_LIST_BACKGROUND), // BACKGROUND + new SysCol(SWT.COLOR_LIST_FOREGROUND), // FOREGROUND + new RGB(232, 242, 254), // BACKGROUND_SEL + new SysCol(SWT.COLOR_LIST_FOREGROUND), // FOREGROUND_SEL + new SysCol(SWT.COLOR_WIDGET_BACKGROUND), // BACKGROUND_SEL_NOFOCUS + new SysCol(SWT.COLOR_WIDGET_FOREGROUND), // FOREGROUND_SEL_NOFOCUS + new SysCol(SWT.COLOR_WIDGET_BACKGROUND), // TOOL_BACKGROUND + new SysCol(SWT.COLOR_WIDGET_DARK_SHADOW), // TOOL_FOREGROUND + + new SysCol(SWT.COLOR_GRAY), // FIX_COLOR + new SysCol(SWT.COLOR_WHITE), // WHITE + new SysCol(SWT.COLOR_GRAY), // GRAY + new SysCol(SWT.COLOR_BLACK), // BLACK + new SysCol(SWT.COLOR_DARK_GRAY), // DARK_GRAY + + new SysCol(SWT.COLOR_DARK_GRAY), // BLACK_BORDER + new RGB(75, 115, 120), // GREEN_BORDER + new SysCol(SWT.COLOR_DARK_BLUE), // DARK_BLUE_BORDER + new RGB(242, 225, 168), // ORANGE_BORDER + new RGB(210, 150, 60), // GOLD_BORDER + new SysCol(SWT.COLOR_DARK_RED), // RED_BORDER + new SysCol(SWT.COLOR_BLACK), // GRAY_BORDER + new SysCol(SWT.COLOR_DARK_GRAY), // DARK_GREEN_BORDER + new RGB(75, 115, 120), // DARK_YELLOW_BORDER + new SysCol(SWT.COLOR_DARK_BLUE), // MAGENTA3_BORDER + new RGB(242, 225, 168), // PURPLE1_BORDER + new RGB(210, 150, 60), // PINK1_BORDER + new SysCol(SWT.COLOR_DARK_RED), // AQUAMARINE_BORDER + new SysCol(SWT.COLOR_BLACK), // LIGHT_BLUE_BORDER + new SysCol(SWT.COLOR_DARK_GRAY), // BLUE_BORDER + new RGB(75, 115, 120), // OLIVE_BORDER + + + new SysCol(SWT.COLOR_GRAY), // MID_LINE + new SysCol(SWT.COLOR_RED), // RED + new SysCol(SWT.COLOR_GREEN), // GREEN + new SysCol(SWT.COLOR_BLUE), // BLUE + new SysCol(SWT.COLOR_YELLOW), // YELLOW + new SysCol(SWT.COLOR_CYAN), // CYAN + new SysCol(SWT.COLOR_MAGENTA), // MAGENTA + + new SysCol(SWT.COLOR_BLUE), // SELECTED_TIME + new SysCol(SWT.COLOR_WIDGET_BACKGROUND), // LEGEND_BACKGROUND + new SysCol(SWT.COLOR_WIDGET_DARK_SHADOW), // LEGEND_FOREGROUND + + new Mix(new RGB(150, 200, 240), new SysCol( + SWT.COLOR_LIST_BACKGROUND)),// GR_BACKGROUND + new RGB(0, 0, 50), // GR_FOREGROUND + new Mix(new RGB(200, 200, 100), + new SysCol(SWT.COLOR_LIST_SELECTION)), // GR_BACKGROUND_SEL + new Mix(new RGB(150, 200, 240), new SysCol( + SWT.COLOR_LIST_SELECTION_TEXT)), // GR_FOREGROUND_SEL + new Mix(new RGB(222, 222, 155), new SysCol( + SWT.COLOR_WIDGET_BACKGROUND)), // GR_BACKGROUND_SEL_NOFOCUS + new RGB(0, 0, 50), // GR_FOREGROUND_SEL_NOFOCUS + + new Mix(new SysCol(SWT.COLOR_GRAY), new SysCol( + SWT.COLOR_LIST_BACKGROUND), 1, 3), // LIGHT_LINE + + new Mix(new SysCol(SWT.COLOR_GRAY), new SysCol(SWT.COLOR_LIST_BACKGROUND), 1, 6), // BACKGROUND_NAME + new Mix(new SysCol(SWT.COLOR_GRAY), new RGB(232, 242, 254), 1, 6), // BACKGROUND_NAME_SEL + new Mix(new SysCol(SWT.COLOR_GRAY), new SysCol(SWT.COLOR_WIDGET_BACKGROUND), 1, 6), // BACKGROUND_NAME_SEL_NOFOCUS + }; + + private Color _colors[]; + + public TraceColorScheme() { + _colors = new Color[_providersMap.length]; + } + + public void dispose() { + for (int i = 0; i < _colors.length; i++) { + Utils.dispose(_colors[i]); + _colors[i] = null; + } + } + + public Color getColor(int idx) { + if (null == _colors[idx]) { + if (idx >= STATES_SEL0 && idx <= STATES_SEL1) { + Color col1 = getColor(idx - STATES_SEL0); + Color col2 = getColor(BACKGROUND_SEL); + _colors[idx] = Utils.mixColors(col1, col2, 3, 1); + } else { + _colors[idx] = _providersMap[idx].get(); + } + } + return _colors[idx]; + } + + public Color getBkColor(boolean selected, boolean focused, boolean name) { + if (name) { + if (selected && focused) + return getColor(BACKGROUND_NAME_SEL); + if (selected) + return getColor(BACKGROUND_NAME_SEL_NOFOCUS); + return getColor(BACKGROUND_NAME); + } else { + if (selected && focused) + return getColor(BACKGROUND_SEL); + if (selected) + return getColor(BACKGROUND_SEL_NOFOCUS); + return getColor(BACKGROUND); + } + } + + public Color getFgColor(boolean selected, boolean focused) { + if (selected && focused) + return getColor(FOREGROUND_SEL); + if (selected) + return getColor(FOREGROUND_SEL_NOFOCUS); + return getColor(FOREGROUND); + } + + public Color getBkColorGroup(boolean selected, boolean focused) { + if (selected && focused) + return getColor(GR_BACKGROUND_SEL); + if (selected) + return getColor(GR_BACKGROUND_SEL_NOFOCUS); + return getColor(GR_BACKGROUND); + } + + public Color getFgColorGroup(boolean selected, boolean focused) { + if (selected && focused) + return getColor(GR_FOREGROUND_SEL); + if (selected) + return getColor(GR_FOREGROUND_SEL_NOFOCUS); + return getColor(GR_FOREGROUND); + } + + public static StateColor[] getStateColors() { + return stateColors; + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceCtrl.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceCtrl.java new file mode 100644 index 0000000000..bb7cab6b11 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/TraceCtrl.java @@ -0,0 +1,67 @@ +/***************************************************************************** + * Copyright (c) 2007, Intel Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * Ruslan A. Scherbakov, Intel - Initial API and implementation + * Alvaro Sanchex-Leon - Udpated for TMF + * + * $Id: TraceCtrl.java,v 1.2 2007/02/27 18:37:36 ewchan Exp $ + *****************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; + +public abstract class TraceCtrl extends Canvas implements PaintListener { + + static public final int MARGIN = 4; + static public final int RIGHT_MARGIN = 2; // 2 pixels less to make sure end time is visible + static public final int SMALL_ICON_SIZE = 16; + + protected TraceColorScheme _colors; + protected int _fontHeight = 0; + + public TraceCtrl(Composite parent, TraceColorScheme colors) { + this(parent, colors, SWT.NO_BACKGROUND | SWT.NO_FOCUS); + } + + public TraceCtrl(Composite parent, TraceColorScheme colors, int style) { + super(parent, style); + _colors = colors; + addPaintListener(this); + } + + @Override + public void dispose() { + super.dispose(); + } + + public void paintControl(PaintEvent e) { + if (e.widget != this) + return; + _fontHeight = e.gc.getFontMetrics().getHeight(); + Rectangle bound = getClientArea(); + if (!bound.isEmpty()) { + Color colBackup = e.gc.getBackground(); + paint(bound, e); + e.gc.setBackground(colBackup); + } + } + + public int getFontHeight() { + return _fontHeight; + } + + abstract void paint(Rectangle bound, PaintEvent e); +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/Utils.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/Utils.java new file mode 100644 index 0000000000..80680e32fd --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/timeAnalysis/widgets/Utils.java @@ -0,0 +1,538 @@ +/***************************************************************************** + * Copyright (c) 2007, 2008 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + * Ruslan A. Scherbakov, Intel - Initial API and implementation + * Alvaro Sanchex-Leon - Udpated for TMF + * + * $Id: Utils.java,v 1.11 2008/06/16 21:04:49 jkubasta Exp $ + *****************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.widgets; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.TimeZone; +import java.util.Vector; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer.TimeFormat; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.TimeEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Device; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; + +public class Utils { + + static public final int IMG_THREAD_RUNNING = 0; + static public final int IMG_THREAD_SUSPENDED = 1; + static public final int IMG_THREAD_STOPPED = 2; + static public final int IMG_METHOD_RUNNING = 3; + static public final int IMG_METHOD = 4; + static public final int IMG_NUM = 5; + + static public final Object[] _empty = new Object[0]; + + static enum Resolution { + SECONDS, MILLISEC, MICROSEC, NANOSEC + }; + + static private final SimpleDateFormat stimeformat = new SimpleDateFormat("HH:mm:ss"); + static private final SimpleDateFormat sdateformat = new SimpleDateFormat("yyyy-MM-dd"); + static { + stimeformat.setTimeZone(TimeZone.getTimeZone("GMT")); + sdateformat.setTimeZone(TimeZone.getTimeZone("GMT")); + } + +// static private String _externalPlugin[] = { "org.eclipse.debug.ui", +// "org.eclipse.debug.ui", "org.eclipse.debug.ui", +// "org.eclipse.debug.ui", "org.eclipse.debug.ui", }; +// +// static private String _externalPath[] = { +// "icons/full/obj16/thread_obj.gif", // running thread +// "icons/full/obj16/threads_obj.gif", // suspended +// "icons/full/obj16/threadt_obj.gif", // stopped +// "icons/full/obj16/stckframe_running_obj.gif", // running stack frame +// "icons/full/obj16/stckframe_obj.gif", // stack frame +// }; + +// static public Image getImage(int idx) { +// if (idx < 0 || idx >= IMG_NUM) +// SWT.error(SWT.ERROR_INVALID_ARGUMENT); +// String key = "trace.img." + idx; +// Image img = TimeAnalysisPlugin.getDefault().getImageRegistry().get(key); +// if (null == img) { +// ImageDescriptor desc = AbstractUIPlugin.imageDescriptorFromPlugin( +// _externalPlugin[idx], _externalPath[idx]); +// TimeAnalysisPlugin.getDefault().getImageRegistry().put(key, desc); +// img = TimeAnalysisPlugin.getDefault().getImageRegistry().get(key); +// } +// return img; +// } + + static public void init(Rectangle rect) { + rect.x = 0; + rect.y = 0; + rect.width = 0; + rect.height = 0; + } + + static public void init(Rectangle rect, int x, int y, int width, int height) { + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + } + + static public void init(Rectangle rect, Rectangle source) { + rect.x = source.x; + rect.y = source.y; + rect.width = source.width; + rect.height = source.height; + } + + static public void deflate(Rectangle rect, int x, int y) { + rect.x += x; + rect.y += y; + rect.width -= x + x; + rect.height -= y + y; + } + + static public void inflate(Rectangle rect, int x, int y) { + rect.x -= x; + rect.y -= y; + rect.width += x + x; + rect.height += y + y; + } + + static void dispose(Color col) { + if (null != col) + col.dispose(); + } + + static public Color mixColors(Device display, Color c1, Color c2, int w1, + int w2) { + return new Color(display, (w1 * c1.getRed() + w2 * c2.getRed()) + / (w1 + w2), (w1 * c1.getGreen() + w2 * c2.getGreen()) + / (w1 + w2), (w1 * c1.getBlue() + w2 * c2.getBlue()) + / (w1 + w2)); + } + + static public Color getSysColor(int id) { + Color col = Display.getCurrent().getSystemColor(id); + return new Color(col.getDevice(), col.getRGB()); + } + + static public Color mixColors(Color col1, Color col2, int w1, int w2) { + return mixColors(Display.getCurrent(), col1, col2, w1, w2); + } + + static public int drawText(GC gc, String text, Rectangle rect, + boolean transp) { + Point size = gc.stringExtent(text); + gc.drawText(text, rect.x, rect.y, transp); + return size.x; + } + + static public int drawText(GC gc, String text, int x, int y, boolean transp) { + Point size = gc.stringExtent(text); + gc.drawText(text, x, y, transp); + return size.x; + } + + /** + * Formats time in format: MM:SS:NNN + * + * @param v + * @param option + * 0: MMMM:ss:nnnnnnnnn, 1: HH:MM:ss MMM.mmmm.nnn + * @return + */ + static public String formatTime(long v, TimeFormat format, Resolution res) { + // if format is absolute (Calendar) + if (format == TimeFormat.ABSOLUTE) { + return formatTimeAbs(v, res); + } + + StringBuffer str = new StringBuffer(); + boolean neg = v < 0; + if (neg) { + v = -v; + str.append('-'); + } + + long sec = (long) (v * 1E-9); + // TODO: Expand to make it possible to select the minute, second, nanosecond format + //printing minutes is suppressed just sec and ns + // if (sec / 60 < 10) + // str.append('0'); + // str.append(sec / 60); + // str.append(':'); + // sec %= 60; + // if (sec < 10) + // str.append('0'); + str.append(sec); + String ns = formatNs(v, res); + if (!ns.equals("")) { + str.append(':'); + str.append(ns); + } + + return str.toString(); + } + + /** + * From input time in nanoseconds, convert to Date format YYYY-MM-dd + * + * @param absTime + * @return + */ + public static String formatDate(long absTime) { + String sdate = sdateformat.format(new Date((long) (absTime * 1E-6))); + return sdate; + } + + /** + * Formats time in ns to Calendar format: HH:MM:SS MMM.mmm.nnn + * + * @param time + * @return + */ + static public String formatTimeAbs(long time, Resolution res) { + StringBuffer str = new StringBuffer(); + + // format time from nanoseconds to calendar time HH:MM:SS + String stime = stimeformat.format(new Date((long) (time * 1E-6))); + str.append(stime + " "); + // append the Milliseconds, MicroSeconds and NanoSeconds as specified in + // the Resolution + str.append(formatNs(time, res)); + return str.toString(); + } + + /** + * Obtains the remainder fraction on unit Seconds of the entered value in + * nanoseconds. e.g. input: 1241207054171080214 ns The number of fraction + * seconds can be obtained by removing the last 9 digits: 1241207054 the + * fractional portion of seconds, expressed in ns is: 171080214 + * + * @param time + * @param res + * @return + */ + public static String formatNs(long time, Resolution res) { + StringBuffer temp = new StringBuffer(); + boolean neg = time < 0; + if (neg) { + time = -time; + } + + // The following approach could be used although performance + // decreases in half. + // String strVal = String.format("%09d", time); + // String tmp = strVal.substring(strVal.length() - 9); + + // number of segments to be included + int segments = 0; + switch (res) { + case MILLISEC: + segments = 1; + break; + case MICROSEC: + segments = 2; + break; + case NANOSEC: + segments = 3; + break; + default: + break; + } + + long ns = time; + ns %= 1000000000; + if (ns < 10) { + temp.append("00000000"); + } else if (ns < 100) { + temp.append("0000000"); + } else if (ns < 1000) { + temp.append("000000"); + } else if (ns < 10000) { + temp.append("00000"); + } else if (ns < 100000) { + temp.append("0000"); + } else if (ns < 1000000) { + temp.append("000"); + } else if (ns < 10000000) { + temp.append("00"); + } else if (ns < 100000000) { + temp.append("0"); + } + temp.append(ns); + + StringBuffer str = new StringBuffer(); + if (segments > 0) { + // append ms + str.append(temp.substring(0, 3)); + } + if (segments > 1) { + // append Micro secs + str.append("."); + str.append(temp.substring(3, 6)); + } + if (segments > 2) { + // append Nano seconds + str.append("."); + str.append(temp.substring(6)); + } + + return str.toString(); + } + + static public int loadIntOption(String opt, int def, int min, int max) { + // int val = + // TraceUIPlugin.getDefault().getPreferenceStore().getInt(opt); + // if (0 == val) + // val = def; + // if (val < min) + // val = min; + // if (val > max) + // val = max; + return def; + } + + // static public int loadIntOption(String opt) { + // int val = TraceUIPlugin.getDefault().getPreferenceStore().getInt(opt); + // return val; + // } + + static public void saveIntOption(String opt, int val) { + // TraceUIPlugin.getDefault().getPreferenceStore().setValue(opt, val); + } + + static ITimeEvent getFirstEvent(ITmfTimeAnalysisEntry thread) { + if (null == thread) + return null; + Vector list = thread.getTraceEvents(); + ITimeEvent event = null; + if (!list.isEmpty()) + event = (ITimeEvent) list.get(0); + return event; + } + + /** + * N means:
  • -1: Previous Event
  • 0: Current Event
  • + * 1: Next Event
  • 2: Previous Event when located in a non Event Area + * + * + * @param thread + * @param time + * @param n + * @return + */ + static ITimeEvent findEvent(ITmfTimeAnalysisEntry thread, long time, int n) { + if (null == thread) + return null; + List list = thread.getTraceEvents(); + Iterator it = list.iterator(); + ITimeEvent nextEvent = null; + ITimeEvent currEvent = null; + ITimeEvent prevEvent = null; + + while (it.hasNext()) { + nextEvent = (ITimeEvent) it.next(); + long nextStartTime = nextEvent.getTime(); + + if (nextStartTime > time) { + break; + } + + if (currEvent == null || currEvent.getTime() != nextStartTime) { + prevEvent = currEvent; + currEvent = nextEvent; + } + } + + if (n == -1) { //previous + if (currEvent != null && currEvent.getTime() + currEvent.getDuration() >= time) { + return prevEvent; + } else { + return currEvent; + } + } else if (n == 0) { //current + if (currEvent != null && currEvent.getTime() + currEvent.getDuration() >= time) { + return currEvent; + } else { + return null; + } + } else if (n == 1) { //next + return nextEvent; + } else if (n == 2) { //current or previous when in empty space + return currEvent; + } + + return null; + } + + // static public TRCPackage getPackage(Object element) { + // if (element instanceof TRCPackage) + // return (TRCPackage) element; + // if (element instanceof TRCClass) + // return ((TRCClass) element).getPackage(); + // return null; + // } + + // static public TRCObjectAllocationAnnotation getAllocationAnnotation( + // TRCClass cls) { + // TRCObjectAllocationAnnotation aa = null; + // EList list = cls.getAnnotations(); + // int len = list.size(); + // for (int i = 0; i < len; i++) { + // TRCAnnotation annotation = (TRCAnnotation) list.get(i); + // if (annotation instanceof TRCObjectAllocationAnnotation) + // aa = (TRCObjectAllocationAnnotation) annotation; + // } + // return aa; + // } + + static public String fixMethodSignature(String sig) { + int pos = sig.indexOf('('); + if (pos >= 0) { + String ret = sig.substring(0, pos); + sig = sig.substring(pos); + sig = sig + " " + ret; + } + return sig; + } + + static public String restoreMethodSignature(String sig) { + String ret = ""; + int pos = sig.indexOf('('); + if (pos >= 0) { + ret = sig.substring(0, pos); + sig = sig.substring(pos + 1); + } + pos = sig.indexOf(')'); + if (pos >= 0) { + sig = sig.substring(0, pos); + } + String args[] = sig.split(","); + sig = "("; + for (int i = 0; i < args.length; i++) { + String arg = args[i].trim(); + if (arg.length() == 0 && args.length == 1) + break; + sig += getTypeSignature(arg); + } + sig += ")" + getTypeSignature(ret); + return sig; + } + + static public String getTypeSignature(String type) { + int dim = 0; + for (int j = 0; j < type.length(); j++) { + if (type.charAt(j) == '[') + dim++; + } + int pos = type.indexOf('['); + if (pos >= 0) + type = type.substring(0, pos); + String sig = ""; + for (int j = 0; j < dim; j++) + sig += "["; + if (type.equals("boolean")) + sig += "Z"; + else if (type.equals("byte")) + sig += "B"; + else if (type.equals("char")) + sig += "C"; + else if (type.equals("short")) + sig += "S"; + else if (type.equals("int")) + sig += "I"; + else if (type.equals("long")) + sig += "J"; + else if (type.equals("float")) + sig += "F"; + else if (type.equals("double")) + sig += "D"; + else if (type.equals("void")) + sig += "V"; + else + sig += "L" + type.replace('.', '/') + ";"; + return sig; + } + + // static public boolean openSource(Object element) { + // if (element instanceof String) { + // final String pattern = (String) element; + // final int javaType = IJavaSearchConstants.METHOD; + // BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + // public void run() { + // if (!OpenJavaSource.openSource(pattern, javaType, + // SearchEngine.createWorkspaceScope(), true)) { + // MessageDialog.openInformation(UIPlugin.getDefault() + // .getWorkbench().getActiveWorkbenchWindow() + // .getShell(), TraceMessages.TRC_MSGT, NLS.bind( + // TraceUIMessages._68, pattern)); + // } + // } + // }); + // } + // OpenSource.openSource(element); + // return true; + // } + + // static public int getObjAge(TRCFullTraceObject obj, EList listGC) { + // int age = 0; + // double t0 = obj.getCreateTime(); + // double t1 = obj.getCollectTime(); + // int len = listGC.size(); + // for (int j = 0; j < len; j++) { + // TRCGCEvent gcEvent = (TRCGCEvent) listGC.get(j); + // if (gcEvent.getType().equals("finish")) { + // double time = gcEvent.getTime(); + // if (time <= t0) + // continue; + // if (t1 > 0 && time >= t1) + // break; + // age++; + // } + // } + // return age; + // } + + static public int compare(double d1, double d2) { + if (d1 > d2) + return 1; + if (d1 < d2) + return 1; + return 0; + } + + static public int compare(String s1, String s2) { + if (s1 != null && s2 != null) + return s1.compareToIgnoreCase(s2); + if (s1 != null) + return 1; + if (s2 != null) + return -1; + return 0; + } + + // static public String formatPercent(int val, int max) { + // String s = max > 0 && max >= val ? TString + // .formatAsPercentage((double) val / (double) max) : ""; + // return s; + // } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfEventsView.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfEventsView.java new file mode 100644 index 0000000000..99ac6f41b8 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfEventsView.java @@ -0,0 +1,305 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.views; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.request.TmfDataRequest; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; + +/** + * TmfEventsView + *

    + * + * TODO: Implement me. Please. + * TODO: Handle column selection, sort, ... generically (nothing less...) + * TODO: Implement hide/display columns + */ +public class TmfEventsView extends TmfView { + + public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.events"; + + private TmfExperiment fExperiment; + private String fTitlePrefix; + + // ------------------------------------------------------------------------ + // Table data + // ------------------------------------------------------------------------ + + private Table fTable; + + // Table column names + private final String TIMESTAMP_COLUMN = "Timestamp"; + private final String SOURCE_COLUMN = "Source"; + private final String TYPE_COLUMN = "Type"; + private final String REFERENCE_COLUMN = "File"; + private final String CONTENT_COLUMN = "Content"; + private final String[] columnProperties = new String[] { + TIMESTAMP_COLUMN, + SOURCE_COLUMN, + TYPE_COLUMN, + REFERENCE_COLUMN, + CONTENT_COLUMN + }; + + // Column data + private class ColumnData { + public final String header; + public final int width; + public final int alignment; + + public ColumnData(String h, int w, int a) { + header = h; + width = w; + alignment = a; + } + }; + + private ColumnData[] columnData = new ColumnData[] { + new ColumnData(columnProperties[0], 100, SWT.LEFT), + new ColumnData(columnProperties[1], 100, SWT.LEFT), + new ColumnData(columnProperties[2], 100, SWT.LEFT), + new ColumnData(columnProperties[3], 100, SWT.LEFT), + new ColumnData(columnProperties[4], 100, SWT.LEFT) + }; + + // ------------------------------------------------------------------------ + // Event cache + // ------------------------------------------------------------------------ + + private static final int DEFAULT_CACHE_SIZE = 1000; + private final int fCacheSize; + private TmfEvent[] cache = new TmfEvent[1]; + private int cacheStartIndex = 0; + private int cacheEndIndex = 0; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + public TmfEventsView(int cacheSize) { + super("TmfEventsView"); + fCacheSize = cacheSize; + } + + public TmfEventsView() { + this(DEFAULT_CACHE_SIZE); + } + + // ------------------------------------------------------------------------ + // ViewPart + // ------------------------------------------------------------------------ + + @SuppressWarnings("unchecked") + @Override + public void createPartControl(Composite parent) { + + // Create a virtual table + // TODO: change SINGLE to MULTI line selection and adjust the selection listener + final int style = SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.VIRTUAL; + fTable = new Table(parent, style); + + // Set the table layout + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + fTable.setLayoutData(layoutData); + + // Some cosmetic enhancements + fTable.setHeaderVisible(true); + fTable.setLinesVisible(true); + + // Set the columns + createColumnHeaders(fTable); + + // Handle the table item requests + fTable.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + TmfTimestamp ts = (TmfTimestamp) fTable.getSelection()[0].getData(); + broadcast(new TmfTimeSynchSignal(fTable, ts)); + } + }); + + // Handle the table item requests + fTable.addListener(SWT.SetData, new Listener() { + + public void handleEvent(Event event) { + + TableItem item = (TableItem) event.item; + final int index = fTable.indexOf(item); + + // Note: this works because handleEvent() is called once for each row, in sequence + if ((index >= cacheStartIndex ) && (index < cacheEndIndex)) { + int i = index - cacheStartIndex; + item.setText(extractItemFields(cache[i])); + item.setData(new TmfTimestamp(cache[i].getTimestamp())); + return; + } + + TmfDataRequest request = new TmfDataRequest(TmfEvent.class, index, fCacheSize) { + @Override + public void handleData() { + TmfEvent[] tmpEvent = getData(); + if ((tmpEvent != null) && (tmpEvent.length > 0)) { + cache = tmpEvent; + cacheStartIndex = index; + cacheEndIndex = index + tmpEvent.length; + } + } + }; + fExperiment.sendRequest(request); + try { + request.waitForCompletion(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (cache[0] != null && cacheStartIndex == index) { + item.setText(extractItemFields(cache[0])); + item.setData(new TmfTimestamp(cache[0].getTimestamp())); + } + + } + }); + + fTable.setItemCount(0); + fTitlePrefix = getTitle(); + + // If an experiment is already selected, update the table + fExperiment = (TmfExperiment) TmfExperiment.getCurrentExperiment(); + if (fExperiment != null) { + experimentSelected(new TmfExperimentSelectedSignal(fTable, fExperiment)); + } + } + + /** + * @param table + * + * FIXME: Add support for column selection + */ + protected void createColumnHeaders(Table table) { + for (int i = 0; i < columnData.length; i++) { + TableColumn column = new TableColumn(table, columnData[i].alignment, i); + column.setText(columnData[i].header); + column.setWidth(columnData[i].width); + } + } + + /** + * @param event + * @return + * + * FIXME: Add support for column selection + */ + protected String[] extractItemFields(TmfEvent event) { + String[] fields = new String[0]; + if (event != null) { + fields = new String[] { + new Long(event.getTimestamp().getValue()).toString(), + event.getSource().getSourceId().toString(), + event.getType().getTypeId().toString(), + event.getReference().getReference().toString(), + event.getContent().toString() + }; + } + return fields; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "[TmfEventsView]"; + } + + // ------------------------------------------------------------------------ + // Signal handlers + // ------------------------------------------------------------------------ + + @SuppressWarnings("unchecked") + @TmfSignalHandler + public void experimentSelected(TmfExperimentSelectedSignal signal) { + // Update the trace reference + fExperiment = (TmfExperiment) signal.getExperiment(); + setPartName(fTitlePrefix + " - " + fExperiment.getName()); + + // Perform the updates on the UI thread + fTable.getDisplay().asyncExec(new Runnable() { + public void run() { + // TODO: Potentially long operation. Add some feedback for the user + fTable.setSelection(0); + fTable.clearAll(); + cacheStartIndex = cacheEndIndex = 0; // Clear the cache + fTable.setItemCount((int) fExperiment.getNbEvents()); + } + }); + } + + @TmfSignalHandler + public void experimentUpdated(TmfExperimentUpdatedSignal signal) { + // Perform the refresh on the UI thread + fTable.getDisplay().asyncExec(new Runnable() { + public void run() { + if (!fTable.isDisposed() && fExperiment != null) { + fTable.setItemCount((int) fExperiment.getNbEvents()); + } + } + }); + } + +// @TmfSignalHandler +// public void currentTimeUpdated(TmfTimeSynchSignal signal) { +// if (signal.getSource() != fTable && fExperiment != null) { +// final int index = (int) fExperiment.getRank(signal.getCurrentTime()); +// // Perform the updates on the UI thread +// fTable.getDisplay().asyncExec(new Runnable() { +// public void run() { +// fTable.setSelection(index); +// // The timestamp might not correspond to an actual event +// // and the selection will point to the next experiment event. +// // But we would like to display both the event before and +// // after the selected timestamp. +// // This works fine by default except when the selected event +// // is the top displayed event. The following ensures that we +// // always see both events. +// if ((index > 0) && (index == fTable.getTopIndex())) { +// fTable.setTopIndex(index - 1); +// } +// } +// }); +// } +// } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfView.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfView.java new file mode 100644 index 0000000000..cef468ad03 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfView.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.ui.views; + +import org.eclipse.linuxtools.tmf.component.ITmfComponent; +import org.eclipse.linuxtools.tmf.signal.TmfSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalManager; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +/** + * TmfView + *

    + * TODO: Implement me. Please. + */ +public abstract class TmfView extends ViewPart implements ITmfComponent { + + private final String fName; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + public TmfView(String viewName) { + super(); + fName = viewName; + TmfSignalManager.register(this); + } + + @Override + public void dispose() { + TmfSignalManager.deregister(this); + super.dispose(); + } + + // ------------------------------------------------------------------------ + // ITmfComponent + // ------------------------------------------------------------------------ + + public String getName() { + return fName; + } + + public void broadcast(TmfSignal signal) { + TmfSignalManager.dispatchSignal(signal); + } + + // ------------------------------------------------------------------------ + // ViewPart + // ------------------------------------------------------------------------ + + @Override + public void createPartControl(Composite parent) { + // TODO Auto-generated method stub + } + + @Override + public void setFocus() { + // TODO Auto-generated method stub + } + +} \ No newline at end of file -- 2.34.1