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