(no commit message)
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.ui / src / org / eclipse / linuxtools / lttng / ui / views / timeframe / SpinnerGroup.java
1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
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
15 import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
16 import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.events.ModifyEvent;
19 import org.eclipse.swt.events.ModifyListener;
20 import org.eclipse.swt.layout.GridData;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Group;
23 import org.eclipse.swt.widgets.Label;
24 import org.eclipse.swt.widgets.Spinner;
25
26 // ========================================================================
27 // SpinnerGroup
28 // ========================================================================
29
30 /**
31 * <b><u>SpinnerGroup</u></b>
32 * <p>
33 * A SpinnerGroup holds two coordinated spinners (for seconds and
34 * nanoseconds) representing the current time within the trace.
35 * <p>
36 * The current time can take any value anything within the time range (start
37 * and end time).
38 */
39 public class SpinnerGroup {
40
41 // The nanosecond scale (10^9)
42 private static final int NS_PER_SECOND = 1000 * 1000 * 1000;
43 private static final byte NS_SCALING_FACTOR = -9;
44
45 // Labels
46 private static final String SECONDS_LABEL = "sec";
47 private static final String NANOSEC_LABEL = "ns";
48
49 // Widgets
50 private Group group;
51 private Spinner seconds;
52 private Spinner nanosec;
53
54 // The valid time range - start time
55 private TmfTimestamp startTime;
56 private int startSeconds;
57 private int startNanosec;
58
59 // The valid time range - end time
60 private TmfTimestamp endTime;
61 private int endSeconds;
62 private int endNanosec;
63
64 // The current time value
65 private TmfTimestamp currentTime;
66 private int currentSeconds;
67 private int currentNanosec;
68
69 @SuppressWarnings("unused")
70 private TimeFrameView fOwner;
71
72 /**
73 * <b><u>Constructor</u></b>
74 * <p>
75 * <li>Creates the display group and formats it for the grid cell
76 * <li>Sets the initial values for Start/End/Current time
77 * </li>
78 * <p>
79 * @param parent - the parent Composite
80 * @param groupName - the group name
81 * @param range - the valid time range (start/end time)
82 * @param current - the current time
83 */
84 public SpinnerGroup(TimeFrameView owner, Composite parent, String groupName, TmfTimeRange range, TmfTimestamp current) {
85
86 fOwner = owner;
87
88 // Create the group
89 group = new Group(parent, SWT.BORDER);
90 group.setText(groupName);
91
92 // Make it use the whole grid cell
93 GridData gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
94 gridData.horizontalAlignment = SWT.FILL;
95 group.setLayoutData(gridData);
96
97 // Create and position the widgets
98 seconds = new Spinner(group, SWT.BORDER);
99 seconds.addModifyListener(new ModifyListener() {
100 public void modifyText(ModifyEvent e) {
101 currentSeconds = seconds.getSelection();
102 refreshCurrentTime();
103 }
104 });
105 seconds.setBounds(5, 25, 110, 25);
106
107 Label label = new Label(group, SWT.LEFT);
108 label.setText(SECONDS_LABEL);
109 label.setBounds(120, 28, 25, 22);
110
111 nanosec = new Spinner(group, SWT.BORDER);
112 nanosec.addModifyListener(new ModifyListener() {
113 public void modifyText(ModifyEvent e) {
114 currentNanosec = nanosec.getSelection();
115 // Correct for nanosec underflow
116 if (currentNanosec < 0) {
117 currentSeconds--;
118 currentNanosec = NS_PER_SECOND - 1;
119 }
120 // Correct for nanosec overflow
121 if (currentNanosec >= NS_PER_SECOND) {
122 currentSeconds++;
123 currentNanosec = 0;
124 }
125 refreshCurrentTime();
126 }
127 });
128 nanosec.setBounds(150, 25, 110, 25);
129
130 label = new Label(group, SWT.LEFT);
131 label.setText(NANOSEC_LABEL);
132 label.setBounds(265, 28, 25, 22);
133
134 setContent(range, current);
135 }
136
137 private void refreshCurrentTime() {
138 long newCurrentTime = ((long) currentSeconds) * NS_PER_SECOND + currentNanosec;
139 TmfTimestamp ts = new TmfTimestamp(newCurrentTime, NS_SCALING_FACTOR, 0);
140 currentTime = ts;
141 // fOwner.synchTimeFrameWidgets(this);
142 }
143
144 // ====================================================================
145 // Get/Set
146 // ====================================================================
147
148 public TmfTimestamp getStartTime() {
149 return startTime;
150 }
151
152 public TmfTimestamp getEndTime() {
153 return endTime;
154 }
155
156 public TmfTimestamp getCurrentTime() {
157 return currentTime;
158 }
159
160 public TmfTimestamp getSpan() {
161 TmfTimestamp span = new TmfTimestamp(startTime.getAdjustment(endTime, NS_SCALING_FACTOR), NS_SCALING_FACTOR, 0);
162 return span;
163 }
164
165 public TmfTimeRange getTimeRange() {
166 TmfTimeRange range = new TmfTimeRange(startTime, endTime);
167 return range;
168 }
169
170 public void setStartTime(TmfTimestamp ts) {
171 try {
172 startTime = ts.synchronize(0, NS_SCALING_FACTOR);
173 startSeconds = (int) (startTime.getValue() / NS_PER_SECOND);
174 startNanosec = (int) (startTime.getValue() % NS_PER_SECOND);
175 }
176 catch (ArithmeticException e) {
177 }
178 }
179
180 public void setEndTime(TmfTimestamp ts) {
181 try {
182 endTime = ts.synchronize(0, NS_SCALING_FACTOR);
183 endSeconds = (int) (endTime.getValue() / NS_PER_SECOND);
184 endNanosec = (int) (endTime.getValue() % NS_PER_SECOND);
185 }
186 catch (ArithmeticException e) {
187 }
188 }
189
190 public void setCurrentTime(TmfTimestamp ts) {
191 try {
192 currentTime = ts.synchronize(0, NS_SCALING_FACTOR);
193 currentSeconds = (int) (currentTime.getValue() / NS_PER_SECOND);
194 currentNanosec = (int) (currentTime.getValue() % NS_PER_SECOND);
195 }
196 catch (ArithmeticException e) {
197 }
198 }
199
200 // ====================================================================
201 // Operators
202 // ====================================================================
203
204 /**
205 * <b><u>setContent</u></b>
206 * <p>
207 * <li>validates that [startTime <= currentTime <= endTime] is respected
208 * <li>sets the start/current/end time and update the spinners
209 * </li>
210 * <p>
211 *
212 * @param range
213 * @param current
214 */
215 public void setContent(TmfTimeRange range, TmfTimestamp current) {
216
217 if (range != null) {
218 // Extract the time range
219 TmfTimestamp start = range.getStartTime();
220 TmfTimestamp end = range.getEndTime();
221
222 // Assume start time is OK
223 setStartTime(start);
224
225 // Make sure end time >= start time
226 if (end.compareTo(start, false) < 0) {
227 end = start;
228 }
229 setEndTime(end);
230
231 // Make sure [start time <= current time <= end time]
232 // If not: current = min(max(start, current), end);
233 if (current.compareTo(start, false) < 0) {
234 current = start;
235 }
236 if (current.compareTo(end, false) > 0) {
237 current = end;
238 }
239 }
240 setCurrentTime(current);
241
242 // And configure the spinners
243 updateSpinners();
244 }
245
246 /**
247 * <b><u>setValue</u></b>
248 * <p>
249 * <li>validates that [startTime <= currentTime <= endTime] is respected
250 * <li>sets the current time and the spinners
251 * </li>
252 * <p>
253 *
254 * @param range
255 * @param current
256 */
257 public void setValue(TmfTimestamp current) {
258
259 // Make sure [start time <= current time <= end time]
260 // If not: current = min(max(start, current), end);
261 if (current.compareTo(startTime, false) < 0) {
262 current = startTime;
263 }
264 if (current.compareTo(endTime, false) > 0) {
265 current = endTime;
266 }
267 setCurrentTime(current);
268
269 // And configure the spinners
270 updateSpinners();
271 }
272
273 /**
274 * Update the spinners with the new current time value
275 * Perform the update on the UI thread
276 */
277 public void updateSpinners() {
278
279 seconds.getDisplay().asyncExec(new Runnable() {
280 public void run() {
281 if (!seconds.isDisposed() && !nanosec.isDisposed()) {
282 // If we are on the start second, ensure that [currentNS >= startNS]
283 // If the currentSeconds > startSeconds, set startns to -1 so we can
284 // "underflow"
285 int startns = -1;
286 if (currentSeconds <= startSeconds) {
287 currentSeconds = startSeconds;
288 startns = startNanosec;
289 if (currentNanosec < startns) {
290 currentNanosec = startns;
291 }
292 }
293
294 // If we are on the end second, ensure that [currentNS <= endNS]
295 // If the currentSeconds < endSeconds, set endns to MAX so we can
296 // "overflow"
297 int endns = NS_PER_SECOND;
298 if (currentSeconds >= endSeconds) {
299 currentSeconds = endSeconds;
300 endns = endNanosec;
301 if (currentNanosec > endns) {
302 currentNanosec = endns;
303 }
304 }
305
306 // Refresh the spinners (value, range, increments, ...)
307 // To ensure that the spinners are properly set, the range has to be > 0
308 // seconds.setValues(currentSeconds, startSeconds - 1, endSeconds + 1, 0, 1, 10);
309 // nanosec.setValues(currentNanosec, startns - 1, endns + 1, 0, 1, 1000000);
310 seconds.setValues(currentSeconds, startSeconds, endSeconds, 0, 1, 10);
311 nanosec.setValues(currentNanosec, startns, endns, 0, 100000, 10000000);
312
313 // If start == end (i.e. no range), disable the spinner
314 // (if start == end, the spinner widget range is set to [0..100] by default)
315 seconds.setEnabled(startSeconds != endSeconds);
316 nanosec.setEnabled(startns != endns);
317 }
318 }
319 });
320 }
321 }
This page took 0.040367 seconds and 5 git commands to generate.