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