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
.tmf
.event
.TmfTimeRange
;
16 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
17 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalHandler
;
18 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfTimeSynchSignal
;
19 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfExperiment
;
20 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfExperimentSelectedSignal
;
21 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfExperimentUpdatedSignal
;
22 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
23 import org
.eclipse
.swt
.SWT
;
24 import org
.eclipse
.swt
.layout
.GridData
;
25 import org
.eclipse
.swt
.layout
.GridLayout
;
26 import org
.eclipse
.swt
.widgets
.Composite
;
27 import org
.eclipse
.swt
.widgets
.Event
;
28 import org
.eclipse
.swt
.widgets
.Listener
;
29 import org
.eclipse
.swt
.widgets
.Slider
;
32 * <b><u>TimeFrameView</u></b>
34 * The TimeFrameView provides a set of spinners to monitor and set the start
35 * time, end time, the current time interval and current time of the trace
36 * set at the nanosecond level.
38 * It ensures that the following relations are always true:
40 * <li>[ startTime >= start time of the trace ]
41 * <li>[ endTime <= end time of the trace ]
42 * <li>[ startTime <= currentTime <= endTime ]
43 * <li>[ interval == (endTime - startTime) ]
46 * It provides a slider to rapidly set the current time within the time range
47 * (i.e. between startTime and endTime).
49 * Finally, it allows modification of the time range and the current time. This
50 * triggers notifications to the other LTTng views.
52 * FIXME: The slider is very jumpy due to the large number of async updates
53 * FIXME: Revisit the control flow between View, Spinners and Slider
55 public class TimeFrameView
extends TmfView
{
57 public static final String ID
= "org.eclipse.linuxtools.lttng.ui.views.timeframe";
59 // ========================================================================
61 // ========================================================================
63 // The event log timestamp characteristics
64 private TmfTimestamp fTraceStartTime
= new TmfTimestamp();
65 private TmfTimestamp fTraceEndTime
= new TmfTimestamp();
67 private TmfTimestamp fCurrentTime
= new TmfTimestamp();
69 private TmfTimeRange fTraceTimeRange
= new TmfTimeRange(fTraceStartTime
, fTraceEndTime
);
70 private TmfTimeRange fTraceSpan
= new TmfTimeRange(fTraceStartTime
, fTraceEndTime
);
71 private byte fScale
= 0;
74 private static final String START_TIME_LABEL
= "Start Time";
75 private static final String END_TIME_LABEL
= "End Time";
76 private static final String TIME_RANGE_LABEL
= "Interval";
77 private static final String CURRENT_TIME_LABEL
= "Current Time";
79 private static final int SLIDER_RANGE
= 10000;
81 private SpinnerGroup fStartGroup
;
82 private SpinnerGroup fEndGroup
;
83 private SpinnerGroup fRangeGroup
;
84 private SpinnerGroup fCurrentGroup
;
87 private Slider fSlider
;
89 // The current experiment
90 TmfExperiment fExperiment
= null;
95 public TimeFrameView() {
100 * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
103 public void createPartControl(Composite parent
) {
105 // Set the view layout
106 GridLayout layout
= new GridLayout(4, true);
107 parent
.setLayout(layout
);
109 fStartGroup
= new SpinnerGroup(this, parent
, START_TIME_LABEL
, fTraceTimeRange
, fTraceStartTime
);
110 fEndGroup
= new SpinnerGroup(this, parent
, END_TIME_LABEL
, fTraceTimeRange
, fTraceEndTime
);
111 fRangeGroup
= new SpinnerGroup(this, parent
, TIME_RANGE_LABEL
, fTraceTimeRange
, fTraceEndTime
);
112 fCurrentGroup
= new SpinnerGroup(this, parent
, CURRENT_TIME_LABEL
, fTraceTimeRange
, fTraceStartTime
);
115 createSlider(parent
);
119 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
122 public void setFocus() {
123 // TODO Auto-generated method stub
126 // ========================================================================
128 // ========================================================================
131 * One of the spinners has been updated. Synchronize the other widgets.
133 public void synchTimeFrameWidgets(SpinnerGroup trigger
) {
136 TmfTimestamp startTime
= fStartGroup
.getCurrentTime();
137 TmfTimestamp endTime
= fEndGroup
.getCurrentTime();
138 TmfTimestamp timeRange
= fRangeGroup
.getCurrentTime();
139 TmfTimestamp currentTime
= fCurrentGroup
.getCurrentTime();
141 // If startTime was set beyond endTime, adjust endTime and interval
142 if (trigger
== fStartGroup
) {
143 if (startTime
.compareTo(endTime
, false) > 0) {
148 // If endTime was set beyond startTime, adjust startTime and interval
149 if (trigger
== fEndGroup
) {
150 if (endTime
.compareTo(startTime
, false) < 0) {
155 // If timeRange was set, adjust endTime
156 if (trigger
== fRangeGroup
) {
157 long start
= startTime
.getValue();
158 long span
= timeRange
.getValue();
159 TmfTimestamp ts
= new TmfTimestamp(start
+ span
, startTime
.getScale(), 0);
160 if (ts
.compareTo(fTraceEndTime
, false) > 0) {
161 ts
= fTraceEndTime
.synchronize(fTraceEndTime
.getValue(), startTime
.getScale());
166 // Compute the new time range
167 TmfTimeRange subrange
= new TmfTimeRange(startTime
, endTime
);
168 TmfTimestamp interval
= new TmfTimestamp(startTime
.getAdjustment(endTime
), startTime
.getScale(), 0);
170 // Update the spinner groups
171 fStartGroup
.setContent(fTraceTimeRange
, startTime
);
172 fEndGroup
.setContent(fTraceTimeRange
, endTime
);
173 fRangeGroup
.setContent(fTraceSpan
, interval
);
174 fCurrentGroup
.setContent(subrange
, currentTime
);
176 updateSlider(subrange
, currentTime
);
178 // Notify other views
179 if (!fCurrentTime
.equals(currentTime
)) {
180 fCurrentTime
= currentTime
;
181 broadcastSignal(new TmfTimeSynchSignal(this, currentTime
));
185 // ========================================================================
187 // ========================================================================
192 private void createSlider(Composite parent
) {
193 fSlider
= new Slider(parent
, SWT
.SMOOTH
| SWT
.FILL
);
194 fSlider
.setMinimum(0);
195 fSlider
.setMaximum(SLIDER_RANGE
+ fSlider
.getThumb());
196 fSlider
.setIncrement(SLIDER_RANGE
/ 100);
197 fSlider
.setPageIncrement(SLIDER_RANGE
/ 10);
198 fSlider
.setSelection(0);
200 GridData gridData
= new GridData(SWT
.LEFT
, SWT
.TOP
, true, false);
201 gridData
.horizontalAlignment
= SWT
.FILL
;
202 gridData
.horizontalSpan
= 4;
203 fSlider
.setLayoutData(gridData
);
205 fSlider
.addListener(SWT
.Selection
, new Listener() {
206 public void handleEvent(Event event
) {
207 int ratio
= fSlider
.getSelection();
208 TmfTimestamp span
= fCurrentGroup
.getSpan();
209 long value
= span
.getValue() * ratio
/ SLIDER_RANGE
;
210 TmfTimestamp start
= fCurrentGroup
.getStartTime();
211 TmfTimestamp current
= new TmfTimestamp(start
.getValue() + value
, start
.getScale(), 0);
212 fCurrentGroup
.setValue(current
);
222 private void updateSlider(TmfTimeRange range
, TmfTimestamp timestamp
) {
224 // Determine the new relative position
225 long total
= range
.getStartTime().getAdjustment(range
.getEndTime());
226 long relative
= range
.getStartTime().getAdjustment(timestamp
);
228 // Set the slider value
229 final long position
= (total
> 0) ?
(relative
* SLIDER_RANGE
/ total
) : 0;
231 // Update the slider on the UI thread
232 long current
= fSlider
.getSelection();
233 if (position
!= current
) {
234 fSlider
.getDisplay().asyncExec(new Runnable() {
236 fSlider
.setSelection((int) position
);
243 * @see java.lang.Object#toString()
246 public String
toString() {
247 return "[TimeFrameView]";
250 // ========================================================================
251 // TMF Signal Handling
252 // ========================================================================
258 public void experimentSelected(TmfExperimentSelectedSignal signal
) {
260 // Update the trace reference
261 fExperiment
= signal
.getExperiment();
263 // Update the time frame
264 fTraceTimeRange
= fExperiment
.getTimeRange();
265 fTraceStartTime
= fTraceTimeRange
.getStartTime();
266 fTraceEndTime
= fTraceTimeRange
.getEndTime();
267 fScale
= fTraceStartTime
.getScale();
269 // Update the widgets
270 fStartGroup
.setContent(fTraceTimeRange
, fTraceStartTime
);
271 fEndGroup
.setContent(fTraceTimeRange
, fTraceEndTime
);
272 fCurrentGroup
.setContent(fTraceTimeRange
, fTraceStartTime
);
274 fCurrentTime
= fTraceStartTime
;
276 TmfTimestamp delta
= new TmfTimestamp(fTraceStartTime
.getAdjustment(fTraceEndTime
), fScale
, 0);
277 fTraceSpan
= new TmfTimeRange(new TmfTimestamp(0, fScale
, 0), delta
);
278 fRangeGroup
.setContent(fTraceSpan
, delta
);
285 public void experimentUpdated(TmfExperimentUpdatedSignal signal
) {
287 // Update the time frame
288 fTraceTimeRange
= signal
.getTrace().getTimeRange();
289 fTraceStartTime
= fTraceTimeRange
.getStartTime();
290 fTraceEndTime
= fTraceTimeRange
.getEndTime();
291 fScale
= fTraceStartTime
.getScale();
293 // Update the widgets
294 fStartGroup
.setContent(fTraceTimeRange
, fStartGroup
.getCurrentTime());
295 fEndGroup
.setContent(fTraceTimeRange
, fTraceEndTime
);
296 fCurrentGroup
.setContent(fTraceTimeRange
, fCurrentGroup
.getCurrentTime());
298 TmfTimestamp delta
= new TmfTimestamp(fTraceStartTime
.getAdjustment(fTraceEndTime
), fScale
, 0);
299 fTraceSpan
= new TmfTimeRange(new TmfTimestamp(0, fScale
, 0), delta
);
300 fRangeGroup
.setContent(fTraceSpan
, delta
);
307 public void currentTimeUpdated(TmfTimeSynchSignal signal
) {
308 if (signal
.getSource() != this) {
309 fCurrentTime
= signal
.getCurrentTime().synchronize(0, fStartGroup
.getCurrentTime().getScale());
310 if (fStartGroup
.getCurrentTime().compareTo(fCurrentTime
, false) > 0) {
311 fStartGroup
.setContent(new TmfTimeRange(fCurrentTime
, fEndGroup
.getCurrentTime()), fCurrentTime
);
313 if (fEndGroup
.getCurrentTime().compareTo(fCurrentTime
, false) < 0) {
314 fEndGroup
.setContent(new TmfTimeRange(fStartGroup
.getCurrentTime(), fCurrentTime
), fCurrentTime
);
316 fCurrentGroup
.setContent(null, fCurrentTime
);
317 updateSlider(fCurrentGroup
.getTimeRange(), fCurrentTime
);