b2d8fefb88070eb99d336c640f3387408e54fc59
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.ui / src / org / eclipse / linuxtools / lttng / ui / views / histogram / TimeTextGroup.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.histogram;
14
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.events.FocusEvent;
17 import org.eclipse.swt.events.FocusListener;
18 import org.eclipse.swt.events.KeyEvent;
19 import org.eclipse.swt.events.KeyListener;
20 import org.eclipse.swt.graphics.Font;
21 import org.eclipse.swt.graphics.FontData;
22 import org.eclipse.swt.layout.GridData;
23 import org.eclipse.swt.layout.GridLayout;
24 import org.eclipse.swt.widgets.Composite;
25 import org.eclipse.swt.widgets.Display;
26 import org.eclipse.swt.widgets.Group;
27 import org.eclipse.swt.widgets.Label;
28 import org.eclipse.swt.widgets.Text;
29
30 /**
31 * <b><u>TimeTextGroup</u></b>
32 * <p>
33 * Special control for HistogramView
34 * <p>
35 * This control will give you a group, a text box and a label at once.
36 */
37 public class TimeTextGroup implements FocusListener, KeyListener {
38
39 /*
40 // 2010-06-10 Yuriy: Has been moved to header into HistogramView.java
41 protected static final String NANOSEC_LABEL = "sec";
42 */
43 private static final String LONGEST_STRING_VALUE = "." + Long.MAX_VALUE;
44 private static final int MAX_CHAR_IN_TEXTBOX = LONGEST_STRING_VALUE.length();
45
46 // The "small font" height used to display time will be "default font" minus this constant
47 private static final int VERY_SMALL_FONT_MODIFIER = 2;
48 private static final int SMALL_FONT_MODIFIER = 1;
49
50 // Indentation size
51 private static final int DEFAULT_INDENT_SIZE = 10;
52
53 private HistogramView parentView = null;
54 private AsyncTimeTextGroupRedrawer asyncRedrawer = null;
55
56 private Group grpName = null;
57 private Text txtNanosec = null;
58 private Label lblNanosec = null;
59
60 private long timeValue = 0L;
61
62 /**
63 * Default Constructor.<p>
64 *
65 * @param newParentView Parent HistogramView
66 * @param parent Parent Composite, used to position the inner controls.
67 * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text)
68 * @param groupStyle Style of the group. Anything that suite a Text
69 */
70 public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle) {
71 this(newParentView, parent, textStyle, groupStyle, "", HistogramConstant.formatNanoSecondsTime(0L), false);
72 }
73
74 /**
75 * Default Constructor with adjustement for small screen.<p>
76 *
77 * @param newParentView Parent HistogramView
78 * @param parent Parent Composite, used to position the inner controls.
79 * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text)
80 * @param groupStyle Style of the group. Anything that suite a Text
81 * @param isSpaceSaverNeeded Value that tell if we try to save some space in the control.
82 */
83 public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle, boolean isSpaceSaverNeeded) {
84 this(newParentView, parent, textStyle, groupStyle, "", HistogramConstant.formatNanoSecondsTime(0L), isSpaceSaverNeeded);
85 }
86
87 /**
88 * Default Constructor, allow you to give the groupname and the textbox value.<p>
89 *
90 * @param newParentView Parent HistogramView
91 * @param parent Parent Composite, used to position the inner controls.
92 * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text)
93 * @param groupStyle Style of the group. Anything that suite a Text
94 * @param groupValue Value (label) of the group.
95 * @param textValue Value of the textbox.
96 */
97 public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle, String groupValue, String textValue) {
98 this(newParentView, parent, textStyle, groupStyle, groupValue, textValue, false);
99 }
100
101 /**
102 * Default Constructor with adjustement for small screen, allow you to give the groupname and the textbox value.<p>
103 *
104 * @param newParentView Parent HistogramView
105 * @param parent Parent Composite, used to position the inner controls.
106 * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text)
107 * @param groupStyle Style of the group. Anything that suite a Text
108 * @param groupValue Value (label) of the group.
109 * @param textValue Value of the textbox.
110 * @param isSpaceSaverNeeded Value that tell if we try to save some space in the control.
111 */
112 public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle, String groupValue, String textValue, boolean isSpaceSaverNeeded) {
113 Font font = parent.getFont();
114 FontData tmpFontData = font.getFontData()[0];
115
116 Font smallFont = null;
117 int textBoxSize = -1;
118 int indentSize = -1;
119
120 // If we were asked to save size, calculate the correct value here
121 if ( isSpaceSaverNeeded == true ) {
122 smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight()-VERY_SMALL_FONT_MODIFIER, tmpFontData.getStyle());
123
124 // No minimum textBoxSize and no indent size
125 textBoxSize = 0;
126 indentSize = 0;
127 }
128 else {
129 // We use only a slightly smaller font
130 smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight()-SMALL_FONT_MODIFIER, tmpFontData.getStyle());
131
132 // ** Creation of the textbox
133 // Calculate the optimal size of the textbox already
134 // This will avoid the control to move around and resize when bigger value are given
135 textBoxSize = HistogramConstant.getTextSizeInControl(parent, LONGEST_STRING_VALUE);
136
137 // Default indent
138 indentSize = DEFAULT_INDENT_SIZE;
139 }
140
141 parentView = newParentView;
142
143 // ** Creation of the group
144 GridLayout gridLayoutgroup = new GridLayout(2, false);
145 gridLayoutgroup.horizontalSpacing = 0;
146 gridLayoutgroup.verticalSpacing = 0;
147 grpName = new Group(parent, groupStyle);
148 grpName.setText(groupValue);
149 grpName.setFont(smallFont);
150 grpName.setLayout(gridLayoutgroup);
151
152 txtNanosec = new Text(grpName, textStyle);
153 txtNanosec.setTextLimit( MAX_CHAR_IN_TEXTBOX );
154 txtNanosec.setText( textValue );
155 txtNanosec.setFont(smallFont);
156 GridData gridDataTextBox = new GridData(SWT.LEFT, SWT.CENTER, true, false);
157 gridDataTextBox.horizontalIndent = indentSize;
158 gridDataTextBox.verticalIndent = 0;
159 gridDataTextBox.minimumWidth = textBoxSize;
160 txtNanosec.setLayoutData(gridDataTextBox);
161
162 // ** Creation of the label
163 /*
164 lblNanosec = new Label(grpName, SWT.LEFT);
165 lblNanosec.setText(NANOSEC_LABEL);
166 lblNanosec.setFont(smallFont);
167 GridData gridDataLabel = new GridData(SWT.LEFT, SWT.CENTER, false, false);
168 gridDataLabel.horizontalIndent = indentSize;
169 gridDataLabel.verticalIndent = 0;
170 lblNanosec.setLayoutData(gridDataLabel);
171 */
172
173 // Add all listener
174 addNeededListeners();
175 }
176
177 /*
178 * Create and add all listeners needed by our control.<p>
179 */
180 protected void addNeededListeners() {
181
182 // AsyncCanvasRedrawer is an internal class
183 // This is used to redraw the canvas without danger from a different thread
184 asyncRedrawer = new AsyncTimeTextGroupRedrawer(this);
185
186 txtNanosec.addFocusListener(this);
187 txtNanosec.addKeyListener(this);
188 }
189
190 /**
191 * Getter for the layout data currently in use.<p>
192 *
193 * @return the layout
194 */
195 public Object getLayoutData() {
196 return grpName.getLayoutData();
197 }
198
199 /**
200 * Set a new layoutData for our control.<p>
201 *
202 * @param layoutData the new layout data
203 */
204 public void setLayoutData(Object layoutData) {
205 grpName.setLayoutData(layoutData);
206 }
207
208 /**
209 * Get the control's parent.<p>
210 *
211 * @return Currently used parent
212 */
213 public Composite getParent() {
214 return grpName.getParent();
215 }
216
217 /**
218 * Set a new parent for the control.<p>
219 *
220 * @return Currently used parent
221 */
222 public void setParent(Composite newParent) {
223 grpName.setParent(newParent);
224 txtNanosec.setParent(newParent);
225 lblNanosec.setParent(newParent);
226 }
227
228 /**
229 * Getter for the time value of the control.<p>
230 *
231 * @return The nanoseconds time value
232 */
233 public long getValue() {
234 return timeValue;
235 }
236
237 /**
238 * Set a new String value to the control.<p>
239 * Note : The String value will be converted in long before being applied;
240 * if any conversion error occur, 0 will be used. <p>
241 *
242 * @param newTimeAsString The value to convert and set.
243 */
244 public void setValue(String newTimeAsString) {
245 long timeAsLong = HistogramConstant.convertStringToNanoseconds(newTimeAsString);
246 setValue( timeAsLong );
247 }
248
249 /**
250 * Set a new value to the control.<p>
251 * Note : The value will be formatted as nanosecond value,
252 * missing zero will be added if needed.<p>
253 *
254 * @param newTime The value to set.
255 */
256 public void setValue(long newTime) {
257 timeValue = newTime;
258 txtNanosec.setText( HistogramConstant.formatNanoSecondsTime(newTime) );
259 }
260
261 /**
262 * Set a new String value, asynchronously.<p>
263 * This will call setValue(String) in async.Exec to avoid Thread Access problem to UI.<p>
264 *
265 * @param newTimeAsString The value to convert and set.
266 */
267 public void setValueAsynchronously(String newTimeAsString) {
268 long timeAsLong = HistogramConstant.convertStringToNanoseconds(newTimeAsString);
269 setValueAsynchronously( timeAsLong );
270 }
271
272 /**
273 * Set a new String value, asynchronously.<p>
274 * This will call setValue(long) in async.Exec to avoid Thread Access problem to UI.<p>
275 *
276 * @param newTimeAsString The value to set.
277 */
278 public void setValueAsynchronously(long newTime) {
279 // Set the correct value ASAP
280 timeValue = newTime;
281
282 // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
283 if ( asyncRedrawer == null ) {
284 asyncRedrawer = new AsyncTimeTextGroupRedrawer(this);
285 }
286
287 asyncRedrawer.asynchronousSetValue(newTime);
288 }
289
290 /**
291 * Set a new group name (label) for this control.<p>
292 *
293 * @param newName The new name to set.
294 */
295 public void setGroupName(String newName) {
296 grpName.setText(newName);
297 }
298
299 /**
300 * Set a new group name (label) for this control, asynchronously.<p>
301 * This will call setValue(long) in async.Exec to avoid Thread Access problem to UI.<p>
302 *
303 * @param newName The new name to set.
304 */
305 public void setGroupNameAsynchronously(String newGroupName) {
306 // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
307 if ( asyncRedrawer == null ) {
308 asyncRedrawer = new AsyncTimeTextGroupRedrawer(this);
309 }
310
311 asyncRedrawer.asynchronousSetGroupName(newGroupName);
312 }
313
314
315 /**
316 * Method to call the "Asynchronous redrawer" for this time text group<p>
317 * This allow safe redraw from different threads.
318 */
319 public void redrawAsynchronously() {
320 // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
321 if ( asyncRedrawer == null ) {
322 asyncRedrawer = new AsyncTimeTextGroupRedrawer(this);
323 }
324
325 asyncRedrawer.asynchronousRedraw();
326 }
327
328 /**
329 * Redraw the control
330 */
331 public void redraw () {
332 grpName.redraw();
333 txtNanosec.redraw();
334 lblNanosec.redraw();
335 }
336
337 /*
338 * This function is called when an user enter a new string in the control by hand.<p>
339 * It will ensure the format of the String is valid.
340 */
341 protected void handleNewStringValue() {
342 String valueInText = txtNanosec.getText();
343 long valueAsLong = HistogramConstant.convertStringToNanoseconds(valueInText);
344
345 if ( getValue() != valueAsLong ) {
346 setValue(valueAsLong);
347 // Notify our parent that the control was updated
348 notifyParentUpdatedTextGroupValue();
349 }
350 }
351
352 /**
353 * This function notify our parent HistogramView that our value changed.
354 */
355 public void notifyParentUpdatedTextGroupValue() {
356 parentView.timeTextGroupChangeNotification();
357 }
358
359 /**
360 * Function that is called when the canvas get focus.<p>
361 *
362 * Doesn't do anything yet...
363 *
364 * @param event The focus event generated.
365 */
366 public void focusGained(FocusEvent event) {
367 // Nothing to do yet
368 }
369
370 /**
371 * Function that is called when the canvas loose focus.<p>
372 * It will validate that the String entered by the user (if any) is valid.<p>
373 *
374 * @param event The focus event generated.
375 */
376 public void focusLost(FocusEvent event) {
377 handleNewStringValue();
378 }
379
380 /**
381 * Function that is called when a key is pressed.<p>
382 * Possible actions :
383 * - Enter (CR) : Validate the entered String.<p>
384 *
385 * @param event The KeyEvent generated when the key was pressed.
386 */
387 public void keyPressed(KeyEvent event) {
388 switch (event.keyCode) {
389 // SWT.CR is "ENTER" Key
390 case SWT.CR:
391 handleNewStringValue();
392 break;
393 default:
394 break;
395 }
396 }
397
398 /**
399 * Function that is called when a key is released.<p>
400 * Possible actions :
401 * Nothing yet
402 *
403 * @param event The KeyEvent generated when the key was pressed.
404 */
405 public void keyReleased(KeyEvent e) {
406
407 }
408 }
409
410 /**
411 * <b><u>AsyncTimeTextGroupRedrawer Inner Class</u></b>
412 * <p>
413 * Asynchronous redrawer for the TimeTextGroup
414 * <p>
415 * This class role is to call method that update the UI on asynchronously.
416 * This should prevent any "invalid thread access" exception when trying to update UI from a different thread.
417 */
418 class AsyncTimeTextGroupRedrawer {
419
420 private TimeTextGroup parentTimeTextGroup = null;
421
422 /**
423 * AsyncTimeTextGroupRedrawer constructor.
424 *
425 * @param newParent Related time text group.
426 */
427 public AsyncTimeTextGroupRedrawer(TimeTextGroup newParent) {
428 parentTimeTextGroup = newParent;
429 }
430
431 /**
432 * Asynchronous SetValue for time text group.
433 *
434 * Basically, it just run "getParent().setValue(time)" in asyncExec.
435 *
436 * @param newTime The new time to set
437 */
438 public void asynchronousSetValue(long newTime) {
439 // Ignore setting of value if widget is disposed
440 if (parentTimeTextGroup.getParent().isDisposed()) return;
441
442 final long tmpTime = newTime;
443
444 Display display = parentTimeTextGroup.getParent().getDisplay();
445 display.asyncExec(new Runnable() {
446 public void run() {
447 if (!parentTimeTextGroup.getParent().isDisposed()) {
448 parentTimeTextGroup.setValue(tmpTime);
449 }
450 }
451 });
452 }
453
454 /**
455 * Asynchronous SetGroupName for time text group.
456 *
457 * Basically, it just run "getParent().setGroupName(name)" in asyncExec.
458 *
459 * @param newGroupName The new group name to set
460 */
461 public void asynchronousSetGroupName(String newGroupName) {
462 // Ignore setting of name if widget is disposed
463 if (parentTimeTextGroup.getParent().isDisposed()) return;
464
465 final String tmpName = newGroupName;
466 Display display = parentTimeTextGroup.getParent().getDisplay();
467 display.asyncExec(new Runnable() {
468 public void run() {
469 if (!parentTimeTextGroup.getParent().isDisposed()) {
470 parentTimeTextGroup.setGroupName(tmpName);
471 }
472 }
473 });
474 }
475
476 /**
477 * Function to redraw the related time text group asynchonously.<p>
478 *
479 * Basically, it just run "getParent().redraw()" in asyncExec.
480 *
481 */
482 public void asynchronousRedraw() {
483 // Ignore redraw if widget is disposed
484 if (parentTimeTextGroup.getParent().isDisposed()) return;
485
486 Display display = parentTimeTextGroup.getParent().getDisplay();
487 display.asyncExec(new Runnable() {
488 public void run() {
489 if (!parentTimeTextGroup.getParent().isDisposed()) {
490 parentTimeTextGroup.getParent().redraw();
491 }
492 }
493 });
494 }
495 }
This page took 0.0417 seconds and 4 git commands to generate.