1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.lttng
.ui
.views
.timeframe
;
15 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEvent
;
16 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimeRange
;
17 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
18 import org
.eclipse
.linuxtools
.tmf
.experiment
.TmfExperiment
;
19 import org
.eclipse
.linuxtools
.tmf
.experiment
.TmfExperimentSelectedSignal
;
20 import org
.eclipse
.linuxtools
.tmf
.experiment
.TmfExperimentUpdatedSignal
;
21 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalHandler
;
22 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfTimeSynchSignal
;
23 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
24 import org
.eclipse
.swt
.SWT
;
25 import org
.eclipse
.swt
.layout
.GridData
;
26 import org
.eclipse
.swt
.layout
.GridLayout
;
27 import org
.eclipse
.swt
.widgets
.Composite
;
28 import org
.eclipse
.swt
.widgets
.Event
;
29 import org
.eclipse
.swt
.widgets
.Listener
;
30 import org
.eclipse
.swt
.widgets
.Slider
;
33 * <b><u>TimeFrameView</u></b>
35 * The TimeFrameView provides a set of spinners to monitor and set the start
36 * time, end time, the current time interval and current time of the trace
37 * set at the nanosecond level.
39 * It ensures that the following relations are always true:
41 * <li>[ startTime >= start time of the trace ]
42 * <li>[ endTime <= end time of the trace ]
43 * <li>[ startTime <= currentTime <= endTime ]
44 * <li>[ interval == (endTime - startTime) ]
47 * It provides a slider to rapidly set the current time within the time range
48 * (i.e. between startTime and endTime).
50 * Finally, it allows modification of the time range and the current time. This
51 * triggers notifications to the other LTTng views.
53 * FIXME: The slider is very jumpy due to the large number of async updates
54 * FIXME: Revisit the control flow between View, Spinners and Slider
56 public class TimeFrameView
extends TmfView
{
58 public static final String ID
= "org.eclipse.linuxtools.lttng.ui.views.timeframe";
60 // ========================================================================
62 // ========================================================================
64 // The event log timestamp characteristics
65 private TmfTimestamp fTraceStartTime
= new TmfTimestamp();
66 private TmfTimestamp fTraceEndTime
= new TmfTimestamp();
68 private TmfTimestamp fCurrentTime
= new TmfTimestamp();
70 private TmfTimeRange fTraceTimeRange
= new TmfTimeRange(fTraceStartTime
, fTraceEndTime
);
71 private TmfTimeRange fTraceSpan
= new TmfTimeRange(fTraceStartTime
, fTraceEndTime
);
72 private byte fScale
= 0;
75 private static final String START_TIME_LABEL
= "Window Start Time";
76 private static final String END_TIME_LABEL
= "Window End Time";
77 private static final String TIME_RANGE_LABEL
= "Window Range";
78 private static final String CURRENT_TIME_LABEL
= "Current Time";
80 private static final int SLIDER_RANGE
= 10000;
82 private SpinnerGroup fStartGroup
;
83 private SpinnerGroup fEndGroup
;
84 private SpinnerGroup fRangeGroup
;
85 private SpinnerGroup fCurrentGroup
;
88 private Slider fSlider
;
90 // The current experiment
91 TmfExperiment
<LttngEvent
> fExperiment
= null;
96 public TimeFrameView() {
97 super("TimeFrameView");
101 * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
104 public void createPartControl(Composite parent
) {
106 // Set the view layout
107 GridLayout layout
= new GridLayout(4, true);
108 parent
.setLayout(layout
);
110 fStartGroup
= new SpinnerGroup(this, parent
, START_TIME_LABEL
, fTraceTimeRange
, fTraceStartTime
);
111 fEndGroup
= new SpinnerGroup(this, parent
, END_TIME_LABEL
, fTraceTimeRange
, fTraceEndTime
);
112 fRangeGroup
= new SpinnerGroup(this, parent
, TIME_RANGE_LABEL
, fTraceTimeRange
, fTraceEndTime
);
113 fCurrentGroup
= new SpinnerGroup(this, parent
, CURRENT_TIME_LABEL
, fTraceTimeRange
, fTraceStartTime
);
116 createSlider(parent
);
120 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
123 public void setFocus() {
124 // TODO Auto-generated method stub
127 // ========================================================================
129 // ========================================================================
132 * One of the spinners has been updated. Synchronize the other widgets.
134 public void synchTimeFrameWidgets(SpinnerGroup trigger
) {
137 TmfTimestamp startTime
= fStartGroup
.getCurrentTime();
138 TmfTimestamp endTime
= fEndGroup
.getCurrentTime();
139 TmfTimestamp timeRange
= fRangeGroup
.getCurrentTime();
140 TmfTimestamp currentTime
= fCurrentGroup
.getCurrentTime();
142 // If startTime was set beyond endTime, adjust endTime and interval
143 if (trigger
== fStartGroup
) {
144 if (startTime
.compareTo(endTime
, false) > 0) {
149 // If endTime was set beyond startTime, adjust startTime and interval
150 if (trigger
== fEndGroup
) {
151 if (endTime
.compareTo(startTime
, false) < 0) {
156 // If timeRange was set, adjust endTime
157 if (trigger
== fRangeGroup
) {
158 long start
= startTime
.getValue();
159 long span
= timeRange
.getValue();
160 TmfTimestamp ts
= new TmfTimestamp(start
+ span
, startTime
.getScale(), 0);
161 if (ts
.compareTo(fTraceEndTime
, false) > 0) {
162 ts
= fTraceEndTime
.synchronize(fTraceEndTime
.getValue(), startTime
.getScale());
167 // Compute the new time range
168 TmfTimeRange subrange
= new TmfTimeRange(startTime
, endTime
);
169 TmfTimestamp interval
= new TmfTimestamp(startTime
.getAdjustment(endTime
), startTime
.getScale(), 0);
171 // Update the spinner groups
172 fStartGroup
.setContent(fTraceTimeRange
, startTime
);
173 fEndGroup
.setContent(fTraceTimeRange
, endTime
);
174 fRangeGroup
.setContent(fTraceSpan
, interval
);
175 fCurrentGroup
.setContent(subrange
, currentTime
);
177 updateSlider(subrange
, currentTime
);
179 // Notify other views
180 if (!fCurrentTime
.equals(currentTime
)) {
181 fCurrentTime
= currentTime
;
182 broadcast(new TmfTimeSynchSignal(this, currentTime
));
186 // ========================================================================
188 // ========================================================================
193 private void createSlider(Composite parent
) {
194 fSlider
= new Slider(parent
, SWT
.SMOOTH
| SWT
.FILL
);
195 fSlider
.setMinimum(0);
196 fSlider
.setMaximum(SLIDER_RANGE
+ fSlider
.getThumb());
197 fSlider
.setIncrement(SLIDER_RANGE
/ 100);
198 fSlider
.setPageIncrement(SLIDER_RANGE
/ 10);
199 fSlider
.setSelection(0);
201 GridData gridData
= new GridData(SWT
.LEFT
, SWT
.TOP
, true, false);
202 gridData
.horizontalAlignment
= SWT
.FILL
;
203 gridData
.horizontalSpan
= 4;
204 fSlider
.setLayoutData(gridData
);
206 fSlider
.addListener(SWT
.Selection
, new Listener() {
207 public void handleEvent(Event event
) {
208 int ratio
= fSlider
.getSelection();
209 TmfTimestamp span
= fCurrentGroup
.getSpan();
210 long value
= span
.getValue() * ratio
/ SLIDER_RANGE
;
211 TmfTimestamp start
= fCurrentGroup
.getStartTime();
212 TmfTimestamp current
= new TmfTimestamp(start
.getValue() + value
, start
.getScale(), 0);
213 fCurrentGroup
.setValue(current
);
223 private void updateSlider(TmfTimeRange range
, TmfTimestamp timestamp
) {
225 // Determine the new relative position
226 long total
= range
.getStartTime().getAdjustment(range
.getEndTime());
227 long relative
= range
.getStartTime().getAdjustment(timestamp
);
229 // Set the slider value
230 final long position
= (total
> 0) ?
(relative
* SLIDER_RANGE
/ total
) : 0;
232 // Update the slider on the UI thread
233 long current
= fSlider
.getSelection();
234 if (position
!= current
) {
235 fSlider
.getDisplay().asyncExec(new Runnable() {
237 fSlider
.setSelection((int) position
);
244 * @see java.lang.Object#toString()
247 public String
toString() {
248 return "[TimeFrameView]";
251 // ========================================================================
252 // TMF Signal Handling
253 // ========================================================================
258 @SuppressWarnings("unchecked")
260 public void experimentSelected(TmfExperimentSelectedSignal
<LttngEvent
> signal
) {
262 // Update the trace reference
263 fExperiment
= (TmfExperiment
<LttngEvent
>) signal
.getExperiment();
265 // Update the time frame
266 fTraceTimeRange
= fExperiment
.getTimeRange();
267 fTraceStartTime
= fTraceTimeRange
.getStartTime();
268 fTraceEndTime
= fTraceTimeRange
.getEndTime();
269 fScale
= fTraceStartTime
.getScale();
271 // Update the widgets
272 fStartGroup
.setContent(fTraceTimeRange
, fTraceStartTime
);
273 fEndGroup
.setContent(fTraceTimeRange
, fTraceEndTime
);
274 fCurrentGroup
.setContent(fTraceTimeRange
, fTraceStartTime
);
276 fCurrentTime
= fTraceStartTime
;
278 TmfTimestamp delta
= new TmfTimestamp(fTraceStartTime
.getAdjustment(fTraceEndTime
), fScale
, 0);
279 fTraceSpan
= new TmfTimeRange(new TmfTimestamp(0, fScale
, 0), delta
);
280 // fRangeGroup.setContent(fTraceSpan, delta);
281 TmfTimestamp start
= new TmfTimestamp(1, (byte) -1, 0);
282 fRangeGroup
.setContent(fTraceSpan
, start
);
289 public void experimentUpdated(TmfExperimentUpdatedSignal signal
) {
291 // Update the time frame
292 fTraceTimeRange
= signal
.getTrace().getTimeRange();
293 fTraceStartTime
= fTraceTimeRange
.getStartTime();
294 fTraceEndTime
= fTraceTimeRange
.getEndTime();
295 fScale
= fTraceStartTime
.getScale();
297 // Update the widgets
298 fStartGroup
.setContent(fTraceTimeRange
, fStartGroup
.getCurrentTime());
299 fEndGroup
.setContent(fTraceTimeRange
, fTraceEndTime
);
300 fCurrentGroup
.setContent(fTraceTimeRange
, fCurrentGroup
.getCurrentTime());
302 TmfTimestamp delta
= new TmfTimestamp(fTraceStartTime
.getAdjustment(fTraceEndTime
), fScale
, 0);
303 fTraceSpan
= new TmfTimeRange(new TmfTimestamp(0, fScale
, 0), delta
);
304 fRangeGroup
.setContent(fTraceSpan
, delta
);
311 public void currentTimeUpdated(TmfTimeSynchSignal signal
) {
312 if (signal
.getSource() != this) {
313 fCurrentTime
= signal
.getCurrentTime().synchronize(0, fStartGroup
.getCurrentTime().getScale());
314 if (fStartGroup
.getCurrentTime().compareTo(fCurrentTime
, false) > 0) {
315 fStartGroup
.setContent(new TmfTimeRange(fCurrentTime
, fEndGroup
.getCurrentTime()), fCurrentTime
);
317 if (fEndGroup
.getCurrentTime().compareTo(fCurrentTime
, false) < 0) {
318 fEndGroup
.setContent(new TmfTimeRange(fStartGroup
.getCurrentTime(), fCurrentTime
), fCurrentTime
);
320 fCurrentGroup
.setContent(null, fCurrentTime
);
321 updateSlider(fCurrentGroup
.getTimeRange(), fCurrentTime
);