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