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