Commit | Line | Data |
---|---|---|
6e512b93 | 1 | /******************************************************************************* |
8035003b | 2 | * Copyright (c) 2009 Ericsson |
6e512b93 ASL |
3 | * |
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 | |
8 | * | |
9 | * Contributors: | |
10 | * Francois Chouinard - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.linuxtools.lttng.ui.views.timeframe; | |
14 | ||
6e512b93 ASL |
15 | import org.eclipse.linuxtools.tmf.event.TmfTimeRange; |
16 | import org.eclipse.linuxtools.tmf.event.TmfTimestamp; | |
6e512b93 | 17 | import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; |
8b29a712 | 18 | import org.eclipse.linuxtools.tmf.signal.TmfSignalManager; |
6e512b93 | 19 | import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; |
62d1696a FC |
20 | import org.eclipse.linuxtools.tmf.trace.TmfExperiment; |
21 | import org.eclipse.linuxtools.tmf.trace.TmfExperimentSelectedSignal; | |
146a887c | 22 | import org.eclipse.linuxtools.tmf.trace.TmfExperimentUpdatedSignal; |
6d848cce | 23 | import org.eclipse.linuxtools.tmf.ui.views.TmfView; |
6e512b93 ASL |
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; | |
62d1696a FC |
28 | import org.eclipse.swt.widgets.Event; |
29 | import org.eclipse.swt.widgets.Listener; | |
6e512b93 ASL |
30 | import org.eclipse.swt.widgets.Slider; |
31 | ||
32 | /** | |
33 | * <b><u>TimeFrameView</u></b> | |
34 | * <p> | |
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. | |
38 | * <p> | |
39 | * It ensures that the following relations are always true: | |
40 | * <p> | |
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) ] | |
45 | * </li> | |
46 | * <p> | |
47 | * It provides a slider to rapidly set the current time within the time range | |
48 | * (i.e. between startTime and endTime). | |
49 | * <p> | |
50 | * Finally, it allows modification of the time range and the current time. This | |
51 | * triggers notifications to the other LTTng views. | |
52 | * <p> | |
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 | |
55 | */ | |
6d848cce | 56 | public class TimeFrameView extends TmfView { |
6e512b93 | 57 | |
62d1696a | 58 | public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.timeframe"; |
6e512b93 ASL |
59 | |
60 | // ======================================================================== | |
61 | // TimeFrameView | |
62 | // ======================================================================== | |
63 | ||
64 | // The event log timestamp characteristics | |
8b29a712 FC |
65 | private TmfTimestamp fTraceStartTime = new TmfTimestamp(); |
66 | private TmfTimestamp fTraceEndTime = new TmfTimestamp(); | |
6e512b93 | 67 | |
8b29a712 | 68 | private TmfTimestamp fCurrentTime = new TmfTimestamp(); |
6e512b93 ASL |
69 | |
70 | private TmfTimeRange fTraceTimeRange = new TmfTimeRange(fTraceStartTime, fTraceEndTime); | |
71 | private TmfTimeRange fTraceSpan = new TmfTimeRange(fTraceStartTime, fTraceEndTime); | |
72 | private byte fScale = 0; | |
73 | ||
62d1696a FC |
74 | // Labels |
75 | private static final String START_TIME_LABEL = "Start Time"; | |
76 | private static final String END_TIME_LABEL = "End Time"; | |
77 | private static final String TIME_RANGE_LABEL = "Interval"; | |
78 | private static final String CURRENT_TIME_LABEL = "Current Time"; | |
79 | ||
6e512b93 ASL |
80 | private static final int SLIDER_RANGE = 10000; |
81 | ||
82 | private SpinnerGroup fStartGroup; | |
83 | private SpinnerGroup fEndGroup; | |
84 | private SpinnerGroup fRangeGroup; | |
85 | private SpinnerGroup fCurrentGroup; | |
86 | ||
87 | // The slider | |
88 | private Slider fSlider; | |
89 | ||
62d1696a FC |
90 | // The current experiment |
91 | TmfExperiment fExperiment = null; | |
6e512b93 ASL |
92 | |
93 | /** | |
94 | * Constructor | |
95 | */ | |
96 | public TimeFrameView() { | |
8035003b | 97 | super(); |
6e512b93 ASL |
98 | } |
99 | ||
100 | /* (non-Javadoc) | |
101 | * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) | |
102 | */ | |
6d848cce | 103 | @Override |
6e512b93 ASL |
104 | public void createPartControl(Composite parent) { |
105 | ||
106 | // Set the view layout | |
107 | GridLayout layout = new GridLayout(4, true); | |
108 | parent.setLayout(layout); | |
109 | ||
62d1696a FC |
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); | |
6e512b93 ASL |
114 | |
115 | // Create the slider | |
116 | createSlider(parent); | |
117 | } | |
118 | ||
119 | /* (non-Javadoc) | |
120 | * @see org.eclipse.ui.part.WorkbenchPart#setFocus() | |
121 | */ | |
6d848cce | 122 | @Override |
6e512b93 ASL |
123 | public void setFocus() { |
124 | // TODO Auto-generated method stub | |
125 | } | |
126 | ||
127 | // ======================================================================== | |
128 | // Operators | |
129 | // ======================================================================== | |
130 | ||
131 | /** | |
132 | * One of the spinners has been updated. Synchronize the other widgets. | |
133 | */ | |
134 | public void synchTimeFrameWidgets(SpinnerGroup trigger) { | |
6e512b93 ASL |
135 | |
136 | // Collect the data | |
137 | TmfTimestamp startTime = fStartGroup.getCurrentTime(); | |
138 | TmfTimestamp endTime = fEndGroup.getCurrentTime(); | |
139 | TmfTimestamp timeRange = fRangeGroup.getCurrentTime(); | |
140 | TmfTimestamp currentTime = fCurrentGroup.getCurrentTime(); | |
141 | ||
142 | // If startTime was set beyond endTime, adjust endTime and interval | |
143 | if (trigger == fStartGroup) { | |
144 | if (startTime.compareTo(endTime, false) > 0) { | |
145 | endTime = startTime; | |
6e512b93 ASL |
146 | } |
147 | } | |
148 | ||
149 | // If endTime was set beyond startTime, adjust startTime and interval | |
150 | if (trigger == fEndGroup) { | |
151 | if (endTime.compareTo(startTime, false) < 0) { | |
152 | startTime = endTime; | |
6e512b93 ASL |
153 | } |
154 | } | |
155 | ||
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()); | |
163 | } | |
164 | endTime = ts; | |
6e512b93 ASL |
165 | } |
166 | ||
167 | // Compute the new time range | |
168 | TmfTimeRange subrange = new TmfTimeRange(startTime, endTime); | |
8035003b | 169 | TmfTimestamp interval = new TmfTimestamp(startTime.getAdjustment(endTime), startTime.getScale(), 0); |
6e512b93 ASL |
170 | |
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); | |
176 | ||
177 | updateSlider(subrange, currentTime); | |
6e512b93 | 178 | |
8035003b ASL |
179 | // Notify other views |
180 | if (!fCurrentTime.equals(currentTime)) { | |
181 | fCurrentTime = currentTime; | |
8b29a712 | 182 | TmfSignalManager.dispatchSignal(new TmfTimeSynchSignal(this, currentTime)); |
6e512b93 ASL |
183 | } |
184 | } | |
185 | ||
186 | // ======================================================================== | |
187 | // Slider Handling | |
188 | // ======================================================================== | |
189 | ||
190 | /** | |
191 | * @param parent | |
192 | */ | |
193 | private void createSlider(Composite parent) { | |
194 | fSlider = new Slider(parent, SWT.SMOOTH | SWT.FILL); | |
62d1696a | 195 | fSlider.setMinimum(0); |
6e512b93 | 196 | fSlider.setMaximum(SLIDER_RANGE + fSlider.getThumb()); |
62d1696a FC |
197 | fSlider.setIncrement(SLIDER_RANGE / 100); |
198 | fSlider.setPageIncrement(SLIDER_RANGE / 10); | |
199 | fSlider.setSelection(0); | |
6e512b93 ASL |
200 | |
201 | GridData gridData = new GridData(SWT.LEFT, SWT.TOP, true, false); | |
202 | gridData.horizontalAlignment = SWT.FILL; | |
203 | gridData.horizontalSpan = 4; | |
204 | fSlider.setLayoutData(gridData); | |
205 | ||
62d1696a FC |
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); | |
214 | } | |
215 | }); | |
bf5aa8e4 | 216 | |
6e512b93 ASL |
217 | } |
218 | ||
219 | /** | |
220 | * @param range | |
8b29a712 | 221 | * @param current |
6e512b93 | 222 | */ |
8b29a712 | 223 | private void updateSlider(TmfTimeRange range, TmfTimestamp current) { |
6e512b93 ASL |
224 | |
225 | // Determine the new relative position | |
8035003b | 226 | long total = range.getStartTime().getAdjustment(range.getEndTime()); |
8b29a712 | 227 | long relative = range.getStartTime().getAdjustment(current); |
6e512b93 ASL |
228 | |
229 | // Set the slider value | |
230 | final long position = (total > 0) ? (relative * SLIDER_RANGE / total) : 0; | |
231 | ||
232 | // Update the slider on the UI thread | |
8b29a712 FC |
233 | fSlider.getDisplay().asyncExec(new Runnable() { |
234 | public void run() { | |
235 | fSlider.setSelection((int) position); | |
236 | } | |
237 | }); | |
238 | } | |
239 | ||
6e512b93 ASL |
240 | // ======================================================================== |
241 | // TMF Signal Handling | |
242 | // ======================================================================== | |
243 | ||
8035003b | 244 | /** |
6e512b93 ASL |
245 | * @param signal |
246 | */ | |
6e512b93 | 247 | @TmfSignalHandler |
62d1696a | 248 | public void experimentSelected(TmfExperimentSelectedSignal signal) { |
6e512b93 ASL |
249 | |
250 | // Update the trace reference | |
62d1696a | 251 | fExperiment = signal.getExperiment(); |
6e512b93 ASL |
252 | |
253 | // Update the time frame | |
62d1696a | 254 | fTraceTimeRange = fExperiment.getTimeRange(); |
6e512b93 ASL |
255 | fTraceStartTime = fTraceTimeRange.getStartTime(); |
256 | fTraceEndTime = fTraceTimeRange.getEndTime(); | |
257 | fScale = fTraceStartTime.getScale(); | |
258 | ||
259 | // Update the widgets | |
260 | fStartGroup.setContent(fTraceTimeRange, fTraceStartTime); | |
261 | fEndGroup.setContent(fTraceTimeRange, fTraceEndTime); | |
262 | fCurrentGroup.setContent(fTraceTimeRange, fTraceStartTime); | |
263 | ||
264 | fCurrentTime = fTraceStartTime; | |
265 | ||
8035003b | 266 | TmfTimestamp delta = new TmfTimestamp(fTraceStartTime.getAdjustment(fTraceEndTime), fScale, 0); |
6e512b93 | 267 | fTraceSpan = new TmfTimeRange(new TmfTimestamp(0, fScale, 0), delta); |
8035003b | 268 | fRangeGroup.setContent(fTraceSpan, delta); |
6e512b93 ASL |
269 | } |
270 | ||
271 | /** | |
272 | * @param signal | |
273 | */ | |
274 | @TmfSignalHandler | |
6d848cce | 275 | public void experimentUpdated(TmfExperimentUpdatedSignal signal) { |
6e512b93 ASL |
276 | |
277 | // Update the time frame | |
278 | fTraceTimeRange = signal.getTrace().getTimeRange(); | |
279 | fTraceStartTime = fTraceTimeRange.getStartTime(); | |
280 | fTraceEndTime = fTraceTimeRange.getEndTime(); | |
281 | fScale = fTraceStartTime.getScale(); | |
282 | ||
283 | // Update the widgets | |
284 | fStartGroup.setContent(fTraceTimeRange, fStartGroup.getCurrentTime()); | |
62d1696a | 285 | fEndGroup.setContent(fTraceTimeRange, fTraceEndTime); |
6e512b93 ASL |
286 | fCurrentGroup.setContent(fTraceTimeRange, fCurrentGroup.getCurrentTime()); |
287 | ||
8035003b | 288 | TmfTimestamp delta = new TmfTimestamp(fTraceStartTime.getAdjustment(fTraceEndTime), fScale, 0); |
6e512b93 ASL |
289 | fTraceSpan = new TmfTimeRange(new TmfTimestamp(0, fScale, 0), delta); |
290 | fRangeGroup.setContent(fTraceSpan, delta); | |
291 | } | |
292 | ||
6e512b93 ASL |
293 | /** |
294 | * @param signal | |
295 | */ | |
296 | @TmfSignalHandler | |
297 | public void currentTimeUpdated(TmfTimeSynchSignal signal) { | |
298 | if (signal.getSource() != this) { | |
8b29a712 | 299 | fCurrentTime = signal.getCurrentTime(); |
6e512b93 ASL |
300 | if (fStartGroup.getCurrentTime().compareTo(fCurrentTime, false) > 0) { |
301 | fStartGroup.setContent(new TmfTimeRange(fCurrentTime, fEndGroup.getCurrentTime()), fCurrentTime); | |
302 | } | |
303 | if (fEndGroup.getCurrentTime().compareTo(fCurrentTime, false) < 0) { | |
304 | fEndGroup.setContent(new TmfTimeRange(fStartGroup.getCurrentTime(), fCurrentTime), fCurrentTime); | |
305 | } | |
306 | fCurrentGroup.setContent(null, fCurrentTime); | |
307 | updateSlider(fCurrentGroup.getTimeRange(), fCurrentTime); | |
6e512b93 ASL |
308 | } |
309 | } | |
310 | ||
bf5aa8e4 | 311 | } |