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
.core
.event
.ITmfTimestamp
;
16 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
17 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
18 import org
.eclipse
.swt
.SWT
;
19 import org
.eclipse
.swt
.events
.ModifyEvent
;
20 import org
.eclipse
.swt
.events
.ModifyListener
;
21 import org
.eclipse
.swt
.layout
.GridData
;
22 import org
.eclipse
.swt
.widgets
.Composite
;
23 import org
.eclipse
.swt
.widgets
.Group
;
24 import org
.eclipse
.swt
.widgets
.Label
;
25 import org
.eclipse
.swt
.widgets
.Spinner
;
27 // ========================================================================
29 // ========================================================================
32 * <b><u>SpinnerGroup</u></b>
34 * A SpinnerGroup holds two coordinated spinners (for seconds and
35 * nanoseconds) representing the current time within the trace.
37 * The current time can take any value anything within the time range (start
40 public class SpinnerGroup
{
42 // The nanosecond scale (10^9)
43 private static final int NS_PER_SECOND
= 1000 * 1000 * 1000;
44 private static final byte NS_SCALING_FACTOR
= -9;
47 private static final String SECONDS_LABEL
= "sec"; //$NON-NLS-1$
48 private static final String NANOSEC_LABEL
= "ns"; //$NON-NLS-1$
52 private Spinner seconds
;
53 private Spinner nanosec
;
55 // The valid time range - start time
56 private ITmfTimestamp startTime
;
57 private int startSeconds
;
58 private int startNanosec
;
60 // The valid time range - end time
61 private ITmfTimestamp endTime
;
62 private int endSeconds
;
63 private int endNanosec
;
65 // The current time value
66 private ITmfTimestamp currentTime
;
67 private int currentSeconds
;
68 private int currentNanosec
;
70 @SuppressWarnings("unused")
71 private TimeFrameView fOwner
;
74 * <b><u>Constructor</u></b>
76 * <li>Creates the display group and formats it for the grid cell
77 * <li>Sets the initial values for Start/End/Current time
80 * @param parent - the parent Composite
81 * @param groupName - the group name
82 * @param range - the valid time range (start/end time)
83 * @param current - the current time
85 public SpinnerGroup(TimeFrameView owner
, Composite parent
, String groupName
, TmfTimeRange range
, ITmfTimestamp current
) {
90 group
= new Group(parent
, SWT
.BORDER
);
91 group
.setText(groupName
);
93 // Make it use the whole grid cell
94 GridData gridData
= new GridData(SWT
.LEFT
, SWT
.TOP
, true, false);
95 gridData
.horizontalAlignment
= SWT
.FILL
;
96 group
.setLayoutData(gridData
);
98 // Create and position the widgets
99 seconds
= new Spinner(group
, SWT
.BORDER
);
100 seconds
.addModifyListener(new ModifyListener() {
102 public void modifyText(ModifyEvent e
) {
103 currentSeconds
= seconds
.getSelection();
104 refreshCurrentTime();
107 seconds
.setBounds(5, 25, 110, 25);
109 Label label
= new Label(group
, SWT
.LEFT
);
110 label
.setText(SECONDS_LABEL
);
111 label
.setBounds(120, 28, 25, 22);
113 nanosec
= new Spinner(group
, SWT
.BORDER
);
114 nanosec
.addModifyListener(new ModifyListener() {
116 public void modifyText(ModifyEvent e
) {
117 currentNanosec
= nanosec
.getSelection();
118 // Correct for nanosec underflow
119 if (currentNanosec
< 0) {
121 currentNanosec
= NS_PER_SECOND
- 1;
123 // Correct for nanosec overflow
124 if (currentNanosec
>= NS_PER_SECOND
) {
128 refreshCurrentTime();
131 nanosec
.setBounds(150, 25, 110, 25);
133 label
= new Label(group
, SWT
.LEFT
);
134 label
.setText(NANOSEC_LABEL
);
135 label
.setBounds(265, 28, 25, 22);
137 setContent(range
, current
);
140 private void refreshCurrentTime() {
141 long newCurrentTime
= ((long) currentSeconds
) * NS_PER_SECOND
+ currentNanosec
;
142 TmfTimestamp ts
= new TmfTimestamp(newCurrentTime
, NS_SCALING_FACTOR
, 0);
144 // fOwner.synchTimeFrameWidgets(this);
147 // ====================================================================
149 // ====================================================================
151 public ITmfTimestamp
getStartTime() {
155 public ITmfTimestamp
getEndTime() {
159 public ITmfTimestamp
getCurrentTime() {
163 public TmfTimestamp
getSpan() {
164 TmfTimestamp span
= (TmfTimestamp
) startTime
.getDelta(endTime
);
168 public TmfTimeRange
getTimeRange() {
169 TmfTimeRange range
= new TmfTimeRange(startTime
, endTime
);
173 public void setStartTime(ITmfTimestamp ts
) {
175 startTime
= (TmfTimestamp
) ts
.getDelta(new TmfTimestamp(0, NS_SCALING_FACTOR
));
176 startSeconds
= (int) (startTime
.getValue() / NS_PER_SECOND
);
177 startNanosec
= (int) (startTime
.getValue() % NS_PER_SECOND
);
179 catch (ArithmeticException e
) {
183 public void setEndTime(ITmfTimestamp ts
) {
185 endTime
= (TmfTimestamp
) ts
.getDelta(new TmfTimestamp(0, NS_SCALING_FACTOR
));
186 endSeconds
= (int) (endTime
.getValue() / NS_PER_SECOND
);
187 endNanosec
= (int) (endTime
.getValue() % NS_PER_SECOND
);
189 catch (ArithmeticException e
) {
193 public void setCurrentTime(ITmfTimestamp ts
) {
195 currentTime
= (TmfTimestamp
) ts
.getDelta(new TmfTimestamp(0, NS_SCALING_FACTOR
));
196 currentSeconds
= (int) (currentTime
.getValue() / NS_PER_SECOND
);
197 currentNanosec
= (int) (currentTime
.getValue() % NS_PER_SECOND
);
199 catch (ArithmeticException e
) {
203 // ====================================================================
205 // ====================================================================
208 * <b><u>setContent</u></b>
210 * <li>validates that [startTime <= currentTime <= endTime] is respected
211 * <li>sets the start/current/end time and update the spinners
218 public void setContent(TmfTimeRange range
, ITmfTimestamp current
) {
221 // Extract the time range
222 ITmfTimestamp start
= range
.getStartTime();
223 ITmfTimestamp end
= range
.getEndTime();
225 // Assume start time is OK
228 // Make sure end time >= start time
229 if (end
.compareTo(start
, false) < 0) {
234 // Make sure [start time <= current time <= end time]
235 // If not: current = min(max(start, current), end);
236 if (current
.compareTo(start
, false) < 0) {
239 if (current
.compareTo(end
, false) > 0) {
243 setCurrentTime(current
);
245 // And configure the spinners
250 * <b><u>setValue</u></b>
252 * <li>validates that [startTime <= currentTime <= endTime] is respected
253 * <li>sets the current time and the spinners
260 public void setValue(ITmfTimestamp current
) {
262 // Make sure [start time <= current time <= end time]
263 // If not: current = min(max(start, current), end);
264 if (current
.compareTo(startTime
, false) < 0) {
267 if (current
.compareTo(endTime
, false) > 0) {
270 setCurrentTime(current
);
272 // And configure the spinners
277 * Update the spinners with the new current time value
278 * Perform the update on the UI thread
280 public void updateSpinners() {
281 // Ignore update if disposed
282 if (seconds
.isDisposed()) return;
284 seconds
.getDisplay().asyncExec(new Runnable() {
287 if (!seconds
.isDisposed() && !nanosec
.isDisposed()) {
288 // If we are on the start second, ensure that [currentNS >= startNS]
289 // If the currentSeconds > startSeconds, set startns to -1 so we can
292 if (currentSeconds
<= startSeconds
) {
293 currentSeconds
= startSeconds
;
294 startns
= startNanosec
;
295 if (currentNanosec
< startns
) {
296 currentNanosec
= startns
;
300 // If we are on the end second, ensure that [currentNS <= endNS]
301 // If the currentSeconds < endSeconds, set endns to MAX so we can
303 int endns
= NS_PER_SECOND
;
304 if (currentSeconds
>= endSeconds
) {
305 currentSeconds
= endSeconds
;
307 if (currentNanosec
> endns
) {
308 currentNanosec
= endns
;
312 // Refresh the spinners (value, range, increments, ...)
313 // To ensure that the spinners are properly set, the range has to be > 0
314 // seconds.setValues(currentSeconds, startSeconds - 1, endSeconds + 1, 0, 1, 10);
315 // nanosec.setValues(currentNanosec, startns - 1, endns + 1, 0, 1, 1000000);
316 seconds
.setValues(currentSeconds
, startSeconds
, endSeconds
, 0, 1, 10);
317 nanosec
.setValues(currentNanosec
, startns
, endns
, 0, 100000, 10000000);
319 // If start == end (i.e. no range), disable the spinner
320 // (if start == end, the spinner widget range is set to [0..100] by default)
321 seconds
.setEnabled(startSeconds
!= endSeconds
);
322 nanosec
.setEnabled(startns
!= endns
);