Mercurial > projects > dwt2
annotate org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/widgets/DateTime.d @ 120:536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
===D2===
* added [Try]Immutable/Const/Shared templates to work with differenses in D1/D2 instead of version statements
used these templates to work with strict type storage rules of dmd-2.053
* com.ibm.icu now also compilable with D2, but not tested yet
* small fixes
Snippet288 - shared data is in TLS
===Phobos===
* fixed critical bugs in Phobos implemention
completely incorrect segfault prone fromStringz (Linux's port ruthless killer)
terrible, incorrect StringBuffer realization (StyledText killer)
* fixed small bugs as well
Snippet72 - misprint in the snippet
* implemented missed functionality for Phobos
ByteArrayOutputStream implemented (image loading available)
formatting correctly works for all DWT's cases
As a result, folowing snippets now works with Phobos (Snippet### - what is fixed):
Snippet24, 42, 111, 115, 130, 235, 276 - bad string formatting
Snippet48, 282 - crash on image loading
Snippet163, 189, 211, 213, 217, 218, 222 - crash on copy/cut in StyledText
Snippet244 - hang-up
===Tango===
* few changes for the latest Tango trunc-r5661
* few small performance improvments
===General===
* implMissing-s for only one version changed to implMissingInTango/InPhobos
* incorrect calls to Format in toString-s fixed
* fixed loading \uXXXX characters in ResourceBundle
* added good UTF-8 support for StyledText, TextLayout (Win32) and friends
UTF functions revised and tested. It is now in java.nonstandard.*Utf modules
StyledText and TextLayout (Win32) modules revised for UTF-8 support
* removed small diferences in most identical files in *.swt.* folders
*.swt.internal.image, *.swt.events and *.swt.custom are identical in Win32/Linux32
now 179 of 576 (~31%) files in *.swt.* folders are fully identical
* Win32: snippets now have right subsystem, pretty icons and native system style controls
* small fixes in snippets
Snippet44 - it's not Snippet44
Snippet212 - functions work with different images and offsets arrays
Win32: Snippet282 - crash on close if the button has an image
Snippet293 - setGrayed is commented
and others
Win32: As a result, folowing snippets now works
Snippet68 - color doesn't change
Snippet163, 189, 211, 213, 217, 218, 222 - UTF-8 issues (see above)
Snippet193 - no tabel headers
author | Denis Shelomovskij <verylonglogin.reg@gmail.com> |
---|---|
date | Sat, 09 Jul 2011 15:50:20 +0300 |
parents | c01d033c633a |
children |
rev | line source |
---|---|
25 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2008 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module org.eclipse.swt.widgets.DateTime; | |
14 | |
15 import org.eclipse.swt.SWT; | |
16 import org.eclipse.swt.SWTException; | |
17 import org.eclipse.swt.events.SelectionEvent; | |
18 import org.eclipse.swt.events.SelectionListener; | |
19 import org.eclipse.swt.graphics.Color; | |
20 import org.eclipse.swt.graphics.Font; | |
21 import org.eclipse.swt.graphics.GC; | |
22 import org.eclipse.swt.graphics.Point; | |
23 import org.eclipse.swt.graphics.Rectangle; | |
24 import org.eclipse.swt.internal.gtk.OS; | |
25 import org.eclipse.swt.internal.Compatibility; | |
26 | |
27 import org.eclipse.swt.widgets.Composite; | |
28 import org.eclipse.swt.widgets.Listener; | |
29 import org.eclipse.swt.widgets.Button; | |
30 import org.eclipse.swt.widgets.Event; | |
31 import org.eclipse.swt.widgets.Text; | |
32 import org.eclipse.swt.widgets.TypedListener; | |
33 | |
49
7a2dd761a8b2
more work until dmd 2.026 linux segfaults.
Frank Benoit <benoit@tionex.de>
parents:
48
diff
changeset
|
34 import java.lang.all; |
7a2dd761a8b2
more work until dmd 2.026 linux segfaults.
Frank Benoit <benoit@tionex.de>
parents:
48
diff
changeset
|
35 |
48 | 36 version(Tango){ |
51 | 37 import tango.util.Convert; |
25 | 38 |
51 | 39 static import tango.text.Util; |
40 //static import tango.text.locale.Core; | |
41 static import tango.time.Time; | |
42 static import tango.time.WallClock; | |
43 static import tango.time.chrono.Gregorian; | |
44 static import tango.time.chrono.Calendar; | |
48 | 45 } else { // Phobos |
51 | 46 import std.conv; |
120
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
47 static import std.datetime; |
48 | 48 } |
25 | 49 |
50 | |
51 private class Calendar{ | |
52 enum { | |
53 AM, | |
54 PM | |
55 } | |
56 enum { | |
57 AM_PM, | |
58 HOUR, | |
59 MINUTE, | |
60 SECOND, | |
61 MONTH, | |
62 YEAR, | |
63 DAY_OF_MONTH, | |
64 DAY_SELECTED, | |
65 MONTH_CHANGED, | |
66 HOUR_OF_DAY, | |
67 } | |
68 private static const int[] MONTH_DAYS = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; | |
69 static private Calendar instance; | |
70 | |
71 private int second; | |
72 private int minute; | |
73 private int hour; | |
74 private int dayofmonth; | |
75 private int month; | |
76 private int year; | |
77 | |
78 static Calendar getInstance(){ | |
79 if( instance is null ){ | |
80 synchronized { | |
81 if( instance is null ){ | |
82 instance = new Calendar; | |
83 } | |
84 } | |
85 } | |
86 return instance; | |
87 } | |
88 | |
89 public this(){ | |
51 | 90 version(Tango){ |
91 tango.time.Time.Time time = tango.time.WallClock.WallClock.now(); | |
92 tango.time.Time.TimeSpan span = time.time.span; | |
93 this.second = span.seconds % 60; | |
94 this.minute = span.minutes % 60; | |
95 this.hour = span.hours; | |
96 auto greg = tango.time.chrono.Gregorian.Gregorian.generic; | |
97 this.dayofmonth = greg.getDayOfMonth( time ); | |
98 this.month = greg.getMonth( time ); | |
99 this.year = greg.getYear( time ); | |
100 } else { // Phobos | |
120
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
101 auto time = std.datetime.Clock.currTime(); |
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
102 this.second = time.second; |
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
103 this.minute = time.minute; |
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
104 this.hour = time.hour; |
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
105 this.dayofmonth = time.day; |
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
106 this.month = time.month; |
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
107 this.year = time.year; |
51 | 108 } |
25 | 109 } |
110 int getActualMaximum(int field){ | |
111 switch( field ){ | |
112 case YEAR: | |
113 return 2100; | |
114 case MONTH: | |
115 return MONTH_DAYS.length -1; | |
116 case DAY_OF_MONTH: | |
117 return MONTH_DAYS[month]; | |
118 case HOUR: | |
119 return 11; | |
120 case HOUR_OF_DAY: | |
121 return 23; | |
122 case MINUTE: | |
123 return 59; | |
124 case SECOND: | |
125 return 59; | |
126 case AM_PM: | |
127 return PM; | |
128 default: assert( false, Format( "no matching switch case for field {}.", field )); | |
129 } | |
130 } | |
131 | |
132 int getActualMinimum(int field){ | |
133 switch( field ){ | |
134 case YEAR: | |
135 return 1900; | |
136 case MONTH: | |
137 return 0; | |
138 case DAY_OF_MONTH: | |
139 return 1; | |
140 case HOUR: | |
141 case HOUR_OF_DAY: | |
142 return 0; | |
143 case MINUTE: | |
144 return 0; | |
145 case SECOND: | |
146 return 0; | |
147 case AM_PM: | |
148 return AM; | |
149 default: assert( false, Format( "no matching switch case for field {}.", field )); | |
150 } | |
151 } | |
152 | |
153 int getMaximum(int field){ | |
154 switch( field ){ | |
155 case YEAR: | |
156 return 2100; | |
157 case MONTH: | |
158 return 11; | |
159 case DAY_OF_MONTH: | |
160 return 31; | |
161 case HOUR: | |
162 return 11; | |
163 case HOUR_OF_DAY: | |
164 return 23; | |
165 case MINUTE: | |
166 return 59; | |
167 case SECOND: | |
168 return 59; | |
169 case AM_PM: | |
170 return PM; | |
171 default: assert( false, Format( "no matching switch case for field {}.", field )); | |
172 } | |
173 } | |
174 | |
175 int getMinimum(int field){ | |
176 switch( field ){ | |
177 case YEAR: | |
178 return 1900; | |
179 case MONTH: | |
180 return 0; | |
181 case DAY_OF_MONTH: | |
182 return 1; | |
183 case HOUR: | |
184 case HOUR_OF_DAY: | |
185 return 0; | |
186 case MINUTE: | |
187 return 0; | |
188 case SECOND: | |
189 return 0; | |
190 case AM_PM: | |
191 return AM; | |
192 default: assert( false, Format( "no matching switch case for field {}.", field )); | |
193 } | |
194 } | |
195 int get(int field){ | |
196 switch( field ){ | |
197 case YEAR: | |
198 return year; | |
199 case MONTH: | |
200 return month; | |
201 case DAY_OF_MONTH: | |
202 return dayofmonth; | |
203 case HOUR: | |
204 return hour; | |
205 case HOUR_OF_DAY: | |
206 return hour % 12; | |
207 case MINUTE: | |
208 return minute; | |
209 case SECOND: | |
210 return second; | |
211 case AM_PM: | |
212 return ( hour < 12 ) ? AM : PM; | |
213 default: assert( false, Format( "no matching switch case for field {}.", field )); | |
214 } | |
215 } | |
216 void set( int year, int month, int day ){ | |
217 this.year = year; | |
218 this.month = month; | |
219 this.dayofmonth = day; | |
220 } | |
221 void set(int field, int value){ | |
222 switch( field ){ | |
223 case YEAR: | |
224 year = value; | |
225 break; | |
226 case MONTH: | |
227 assert( value >= 0 && value < 12 ); | |
228 month = value; | |
229 break; | |
230 case DAY_OF_MONTH: | |
231 assert( value > 0 && value <= getActualMaximum( DAY_OF_MONTH ) ); | |
232 dayofmonth = value; | |
233 break; | |
234 case HOUR: | |
235 assert( value >= 0 && value < 12 ); | |
236 hour = value; | |
237 break; | |
238 case HOUR_OF_DAY: | |
239 assert( value >= 0 && value < 24 ); | |
240 hour = value; | |
241 break; | |
242 case MINUTE: | |
243 assert( value >= 0 && value < 60 ); | |
244 minute = value; | |
245 break; | |
246 case SECOND: | |
247 assert( value >= 0 && value < 60 ); | |
248 second = value; | |
249 break; | |
250 case AM_PM: | |
251 if( get(field) is AM ){ | |
252 if( value is AM ){ | |
253 return; | |
254 } | |
255 else{ | |
256 hour += 12; | |
257 } | |
258 } | |
259 else{ // PM | |
260 if( value is AM ){ | |
261 hour -= 12; | |
262 } | |
263 else{ | |
264 return; | |
265 } | |
266 } | |
267 break; | |
268 default: assert( false, Format( "no matching switch case for field {}.", field )); | |
269 } | |
270 } | |
271 | |
272 void roll(int field, int value){ | |
273 switch( field ){ | |
274 case YEAR: | |
275 year = value; | |
276 break; | |
277 case MONTH: | |
278 month += value; | |
279 month %= 12; | |
280 break; | |
281 case DAY_OF_MONTH: | |
282 dayofmonth += value; | |
283 dayofmonth %= getActualMaximum( DAY_OF_MONTH ); | |
284 break; | |
285 case HOUR: | |
286 case HOUR_OF_DAY: | |
287 hour += value; | |
288 hour %= 24; | |
289 break; | |
290 case MINUTE: | |
291 minute += value; | |
292 minute %= 60; | |
293 break; | |
294 case SECOND: | |
295 second += value; | |
296 second %= 60; | |
297 break; | |
298 case AM_PM: | |
299 set( AM_PM, get( AM_PM ) is AM ? PM : AM ); | |
300 break; | |
301 default: assert( false, Format( "no matching switch case for field {}.", field )); | |
302 } | |
303 } | |
304 } | |
305 | |
306 | |
307 private class DateFormatSymbols { | |
308 private const String[] ampm = [ "AM"[], "PM" ]; | |
120
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
309 TryConst!(String[]) getAmPmStrings(){ |
25 | 310 return ampm; |
311 } | |
312 } | |
313 | |
314 | |
315 /** | |
316 * Instances of this class are selectable user interface | |
317 * objects that allow the user to enter and modify date | |
318 * or time values. | |
319 * <p> | |
320 * Note that although this class is a subclass of <code>Composite</code>, | |
321 * it does not make sense to add children to it, or set a layout on it. | |
322 * </p> | |
323 * <dl> | |
324 * <dt><b>Styles:</b></dt> | |
325 * <dd>DATE, TIME, CALENDAR, SHORT, MEDIUM, LONG</dd> | |
326 * <dt><b>Events:</b></dt> | |
327 * <dd>Selection</dd> | |
328 * </dl> | |
329 * <p> | |
330 * Note: Only one of the styles DATE, TIME, or CALENDAR may be specified, | |
331 * and only one of the styles SHORT, MEDIUM, or LONG may be specified. | |
332 * </p><p> | |
333 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | |
334 * </p> | |
335 * | |
336 * @see <a href="http://www.eclipse.org/swt/snippets/#datetime">DateTime snippets</a> | |
337 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a> | |
338 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
339 * | |
340 * @since 3.3 | |
341 */ | |
342 public class DateTime : Composite { | |
343 int day, month, year, hours, minutes, seconds; | |
344 | |
345 static const int MIN_YEAR = 1752; // Gregorian switchover in North America: September 19, 1752 | |
346 static const int MAX_YEAR = 9999; | |
347 | |
348 /* Emulated DATE and TIME variables */ | |
349 Calendar calendar; | |
350 DateFormatSymbols formatSymbols; | |
351 Button down, up; | |
352 Text text; | |
353 String format; | |
354 Point[] fieldIndices; | |
355 int[] fieldNames; | |
356 int fieldCount, currentField = 0, characterCount = 0; | |
357 bool ignoreVerify = false; | |
358 static const String DEFAULT_SHORT_DATE_FORMAT = "MM/YYYY"; | |
359 static const String DEFAULT_MEDIUM_DATE_FORMAT = "MM/DD/YYYY"; | |
360 static const String DEFAULT_LONG_DATE_FORMAT = "MM/DD/YYYY"; | |
361 static const String DEFAULT_SHORT_TIME_FORMAT = "HH:MM AM"; | |
362 static const String DEFAULT_MEDIUM_TIME_FORMAT = "HH:MM:SS AM"; | |
363 static const String DEFAULT_LONG_TIME_FORMAT = "HH:MM:SS AM"; | |
364 | |
365 | |
366 | |
367 /** | |
368 * Constructs a new instance of this class given its parent | |
369 * and a style value describing its behavior and appearance. | |
370 * <p> | |
371 * The style value is either one of the style constants defined in | |
372 * class <code>SWT</code> which is applicable to instances of this | |
373 * class, or must be built by <em>bitwise OR</em>'ing together | |
374 * (that is, using the <code>int</code> "|" operator) two or more | |
375 * of those <code>SWT</code> style constants. The class description | |
376 * lists the style constants that are applicable to the class. | |
377 * Style bits are also inherited from superclasses. | |
378 * </p> | |
379 * | |
380 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
381 * @param style the style of control to construct | |
382 * | |
383 * @exception IllegalArgumentException <ul> | |
384 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
385 * </ul> | |
386 * @exception SWTException <ul> | |
387 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
388 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
389 * </ul> | |
390 * | |
391 * @see SWT#DATE | |
392 * @see SWT#TIME | |
393 * @see SWT#CALENDAR | |
394 * @see Widget#checkSubclass | |
395 * @see Widget#getStyle | |
396 */ | |
397 public this (Composite parent, int style) { | |
398 super (parent, checkStyle (style)); | |
399 if ((this.style & SWT.CALENDAR) is 0) { | |
400 /* SWT.DATE and SWT.TIME */ | |
401 calendar = Calendar.getInstance(); | |
402 formatSymbols = new DateFormatSymbols(); | |
403 | |
404 text = new Text(this, SWT.SINGLE); | |
405 /* disable the native drag and drop for the date/time text field */ | |
406 OS.gtk_drag_dest_unset(text.handle); | |
407 if ((this.style & SWT.DATE) !is 0) { | |
408 setFormat((this.style & SWT.SHORT) !is 0 ? DEFAULT_SHORT_DATE_FORMAT : (this.style & SWT.LONG) !is 0 ? DEFAULT_LONG_DATE_FORMAT : DEFAULT_MEDIUM_DATE_FORMAT); | |
409 } else { // SWT.TIME | |
410 setFormat((this.style & SWT.SHORT) !is 0 ? DEFAULT_SHORT_TIME_FORMAT : (this.style & SWT.LONG) !is 0 ? DEFAULT_LONG_TIME_FORMAT : DEFAULT_MEDIUM_TIME_FORMAT); | |
411 } | |
412 text.setText(getFormattedString(this.style)); | |
413 Listener listener = new class () Listener { | |
414 public void handleEvent(Event event) { | |
415 switch(event.type) { | |
416 case SWT.KeyDown: onKeyDown(event); break; | |
417 case SWT.FocusIn: onFocusIn(event); break; | |
418 case SWT.FocusOut: onFocusOut(event); break; | |
419 case SWT.MouseDown: onMouseClick(event); break; | |
420 case SWT.MouseUp: onMouseClick(event); break; | |
421 case SWT.Verify: onVerify(event); break; | |
422 default: | |
423 } | |
424 } | |
425 }; | |
426 text.addListener(SWT.KeyDown, listener); | |
427 text.addListener(SWT.FocusIn, listener); | |
428 text.addListener(SWT.FocusOut, listener); | |
429 text.addListener(SWT.MouseDown, listener); | |
430 text.addListener(SWT.MouseUp, listener); | |
431 text.addListener(SWT.Verify, listener); | |
432 up = new Button(this, SWT.ARROW | SWT.UP); | |
433 //up.setToolTipText(SWT.getMessage ("SWT_Up")); //$NON-NLS-1$ | |
434 down = new Button(this, SWT.ARROW | SWT.DOWN); | |
435 //down.setToolTipText(SWT.getMessage ("SWT_Down")); //$NON-NLS-1$ | |
436 up.addListener(SWT.Selection, new class() Listener { | |
437 public void handleEvent(Event event) { | |
438 incrementField(+1); | |
439 text.setFocus(); | |
440 } | |
441 }); | |
442 down.addListener(SWT.Selection, new class() Listener { | |
443 public void handleEvent(Event event) { | |
444 incrementField(-1); | |
445 text.setFocus(); | |
446 } | |
447 }); | |
448 addListener(SWT.Resize, new class() Listener { | |
449 public void handleEvent(Event event) { | |
450 onResize(event); | |
451 } | |
452 }); | |
453 } | |
454 } | |
455 | |
456 static int checkStyle (int style) { | |
457 /* | |
458 * Even though it is legal to create this widget | |
459 * with scroll bars, they serve no useful purpose | |
460 * because they do not automatically scroll the | |
461 * widget's client area. The fix is to clear | |
462 * the SWT style. | |
463 */ | |
464 style &= ~(SWT.H_SCROLL | SWT.V_SCROLL); | |
465 style = checkBits (style, SWT.DATE, SWT.TIME, SWT.CALENDAR, 0, 0, 0); | |
466 return checkBits (style, SWT.MEDIUM, SWT.SHORT, SWT.LONG, 0, 0, 0); | |
467 } | |
468 | |
469 /** | |
470 * Adds the listener to the collection of listeners who will | |
471 * be notified when the control is selected by the user, by sending | |
472 * it one of the messages defined in the <code>SelectionListener</code> | |
473 * interface. | |
474 * <p> | |
475 * <code>widgetSelected</code> is called when the user changes the control's value. | |
476 * <code>widgetDefaultSelected</code> is not called. | |
477 * </p> | |
478 * | |
479 * @param listener the listener which should be notified | |
480 * | |
481 * @exception IllegalArgumentException <ul> | |
482 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
483 * </ul> | |
484 * @exception SWTException <ul> | |
485 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
486 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
487 * </ul> | |
488 * | |
489 * @see SelectionListener | |
490 * @see #removeSelectionListener | |
491 * @see SelectionEvent | |
492 */ | |
493 public void addSelectionListener (SelectionListener listener) { | |
494 checkWidget (); | |
495 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
496 TypedListener typedListener = new TypedListener (listener); | |
497 addListener (SWT.Selection, typedListener); | |
498 addListener (SWT.DefaultSelection, typedListener); | |
499 } | |
500 | |
501 protected void checkSubclass () { | |
502 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); | |
503 } | |
504 | |
505 public Point computeSize (int wHint, int hHint, bool changed) { | |
506 checkWidget (); | |
507 int width = 0, height = 0; | |
508 if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) { | |
509 if ((style & SWT.CALENDAR) !is 0) { | |
510 // TODO: CALENDAR computeSize | |
511 width = 300; | |
512 height = 200; | |
513 } else { | |
514 /* SWT.DATE and SWT.TIME */ | |
515 GC gc = new GC(text); | |
516 Point textSize = gc.stringExtent(getComputeSizeString(style)); | |
517 gc.dispose(); | |
518 Rectangle trim = text.computeTrim(0, 0, textSize.x, textSize.y); | |
519 Point buttonSize = up.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed); | |
520 width = trim.width + buttonSize.x; | |
521 height = Math.max(trim.height, buttonSize.y); | |
522 } | |
523 } | |
524 if (width is 0) width = DEFAULT_WIDTH; | |
525 if (height is 0) height = DEFAULT_HEIGHT; | |
526 if (wHint !is SWT.DEFAULT) width = wHint; | |
527 if (hHint !is SWT.DEFAULT) height = hHint; | |
528 int border = getBorderWidth (); | |
529 width += border * 2; height += border * 2; | |
530 return new Point (width, height); | |
531 } | |
532 | |
533 void createHandle (int index) { | |
534 if ((style & SWT.CALENDAR) !is 0) { | |
535 state |= HANDLE; | |
536 fixedHandle = cast(GtkWidget*)OS.g_object_new (display.gtk_fixed_get_type (), null); | |
537 if (fixedHandle is null) error (SWT.ERROR_NO_HANDLES); | |
538 OS.gtk_fixed_set_has_window (fixedHandle, true); | |
539 handle = cast(GtkWidget*)OS.gtk_calendar_new (); | |
540 if (handle is null) error (SWT.ERROR_NO_HANDLES); | |
541 OS.gtk_container_add (fixedHandle, handle); | |
542 if (OS.GTK_VERSION >= OS.buildVERSION(2, 4, 0)) { | |
543 OS.gtk_calendar_set_display_options(handle, OS.GTK_CALENDAR_SHOW_HEADING | OS.GTK_CALENDAR_SHOW_DAY_NAMES); | |
544 } else { | |
545 OS.gtk_calendar_display_options(handle, OS.GTK_CALENDAR_SHOW_HEADING | OS.GTK_CALENDAR_SHOW_DAY_NAMES); | |
546 } | |
547 } else { | |
548 super.createHandle(index); | |
549 } | |
550 } | |
551 | |
552 void createWidget (int index) { | |
553 super.createWidget (index); | |
554 if ((style & SWT.CALENDAR) !is 0) { | |
555 getDate(); | |
556 } | |
557 } | |
558 | |
559 void commitCurrentField() { | |
560 if (characterCount > 0) { | |
561 characterCount = 0; | |
562 int fieldName = fieldNames[currentField]; | |
563 int start = fieldIndices[currentField].x; | |
564 int end = fieldIndices[currentField].y; | |
565 String value = text.getText(start, end - 1); | |
566 int s = value.lastIndexOf(' '); | |
567 if (s !is -1) value = value.substring(s + 1); | |
568 int newValue = unformattedIntValue(fieldName, value, characterCount is 0, calendar.getActualMaximum(fieldName)); | |
569 if (newValue !is -1) setTextField(fieldName, newValue, true, true); | |
570 } | |
571 } | |
572 | |
573 String formattedStringValue(int fieldName, int value, bool adjust) { | |
574 if (fieldName is Calendar.AM_PM) { | |
120
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
575 return formatSymbols.getAmPmStrings()[value]; |
25 | 576 } |
577 if (adjust) { | |
578 if (fieldName is Calendar.HOUR && value is 0) { | |
579 return to!(String)(12); | |
580 } | |
581 if (fieldName is Calendar.MONTH) { | |
582 return to!(String)(value + 1); | |
583 } | |
584 } | |
585 return to!(String)(value); | |
586 } | |
587 | |
588 String getComputeSizeString(int style) { | |
589 if ((style & SWT.DATE) !is 0) { | |
590 return (style & SWT.SHORT) !is 0 ? DEFAULT_SHORT_DATE_FORMAT : (style & SWT.LONG) !is 0 ? DEFAULT_LONG_DATE_FORMAT : DEFAULT_MEDIUM_DATE_FORMAT; | |
591 } | |
592 // SWT.TIME | |
593 return (style & SWT.SHORT) !is 0 ? DEFAULT_SHORT_TIME_FORMAT : (style & SWT.LONG) !is 0 ? DEFAULT_LONG_TIME_FORMAT : DEFAULT_MEDIUM_TIME_FORMAT; | |
594 } | |
595 | |
596 int getFieldIndex(int fieldName) { | |
597 for (int i = 0; i < fieldCount; i++) { | |
598 if (fieldNames[i] is fieldName) { | |
599 return i; | |
600 } | |
601 } | |
602 return -1; | |
603 } | |
604 | |
605 String getFormattedString(int style) { | |
606 if ((style & SWT.TIME) !is 0) { | |
120
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
607 auto ampm = formatSymbols.getAmPmStrings(); |
25 | 608 int h = calendar.get(Calendar.HOUR); if (h is 0) h = 12; |
609 int m = calendar.get(Calendar.MINUTE); | |
610 int s = calendar.get(Calendar.SECOND); | |
611 int a = calendar.get(Calendar.AM_PM); | |
612 if ((style & SWT.SHORT) !is 0) return "" ~ (h < 10 ? " " : "") ~ to!(String)(h) ~ ":" ~ (m < 10 ? "0" : "") ~ to!(String)(m) ~ " " ~ ampm[a]; | |
613 return "" ~ (h < 10 ? " " : "") ~ to!(String)(h) ~ ":" ~ (m < 10 ? "0" : "") ~ to!(String)(m) ~ ":" ~ (s < 10 ? "0" : "") ~ to!(String)(s) ~ " " ~ ampm[a]; | |
614 } | |
615 /* SWT.DATE */ | |
616 int y = calendar.get(Calendar.YEAR); | |
617 int m = calendar.get(Calendar.MONTH) + 1; | |
618 int d = calendar.get(Calendar.DAY_OF_MONTH); | |
619 if ((style & SWT.SHORT) !is 0) return "" ~ (m < 10 ? " " : "") ~ to!(String)(m) ~ "/" ~ to!(String)(y); | |
620 return "" ~ (m < 10 ? " " : "") ~ to!(String)(m) ~ "/" ~ (d < 10 ? " " : "") ~ to!(String)(d) ~ "/" ~ to!(String)(y); | |
621 } | |
622 | |
623 void getDate() { | |
624 uint y; | |
625 uint m; | |
626 uint d; | |
627 OS.gtk_calendar_get_date(handle, &y, &m, &d); | |
628 year = y; | |
629 month = m; | |
630 day = d; | |
631 } | |
632 | |
633 /** | |
634 * Returns the receiver's date, or day of the month. | |
635 * <p> | |
636 * The first day of the month is 1, and the last day depends on the month and year. | |
637 * </p> | |
638 * | |
639 * @return a positive integer beginning with 1 | |
640 * | |
641 * @exception SWTException <ul> | |
642 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
643 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
644 * </ul> | |
645 */ | |
646 public int getDay () { | |
647 checkWidget (); | |
648 if ((style & SWT.CALENDAR) !is 0) { | |
649 getDate(); | |
650 return day; | |
651 } else { | |
652 return calendar.get(Calendar.DAY_OF_MONTH); | |
653 } | |
654 } | |
655 | |
656 /** | |
657 * Returns the receiver's hours. | |
658 * <p> | |
659 * Hours is an integer between 0 and 23. | |
660 * </p> | |
661 * | |
662 * @return an integer between 0 and 23 | |
663 * | |
664 * @exception SWTException <ul> | |
665 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
666 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
667 * </ul> | |
668 */ | |
669 public int getHours () { | |
670 checkWidget (); | |
671 if ((style & SWT.CALENDAR) !is 0) { | |
672 return hours; | |
673 } else { | |
674 return calendar.get(Calendar.HOUR_OF_DAY); | |
675 } | |
676 } | |
677 | |
678 /** | |
679 * Returns the receiver's minutes. | |
680 * <p> | |
681 * Minutes is an integer between 0 and 59. | |
682 * </p> | |
683 * | |
684 * @return an integer between 0 and 59 | |
685 * | |
686 * @exception SWTException <ul> | |
687 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
688 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
689 * </ul> | |
690 */ | |
691 public int getMinutes () { | |
692 checkWidget (); | |
693 if ((style & SWT.CALENDAR) !is 0) { | |
694 return minutes; | |
695 } else { | |
696 return calendar.get(Calendar.MINUTE); | |
697 } | |
698 } | |
699 | |
700 /** | |
701 * Returns the receiver's month. | |
702 * <p> | |
703 * The first month of the year is 0, and the last month is 11. | |
704 * </p> | |
705 * | |
706 * @return an integer between 0 and 11 | |
707 * | |
708 * @exception SWTException <ul> | |
709 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
710 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
711 * </ul> | |
712 */ | |
713 public int getMonth () { | |
714 checkWidget (); | |
715 if ((style & SWT.CALENDAR) !is 0) { | |
716 getDate(); | |
717 return month; | |
718 } else { | |
719 return calendar.get(Calendar.MONTH); | |
720 } | |
721 } | |
722 | |
723 String getNameText() { | |
724 if((style & SWT.TIME) !is 0){ | |
725 return Format( "{}:{}:{}", getHours(), getMinutes(), getSeconds() ); | |
726 } | |
727 else{ | |
728 return Format( "{}/{}/{}", (getMonth() + 1), getDay(), getYear() ); | |
729 } | |
730 } | |
731 | |
732 /** | |
733 * Returns the receiver's seconds. | |
734 * <p> | |
735 * Seconds is an integer between 0 and 59. | |
736 * </p> | |
737 * | |
738 * @return an integer between 0 and 59 | |
739 * | |
740 * @exception SWTException <ul> | |
741 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
742 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
743 * </ul> | |
744 */ | |
745 public int getSeconds () { | |
746 checkWidget (); | |
747 if ((style & SWT.CALENDAR) !is 0) { | |
748 return seconds; | |
749 } else { | |
750 return calendar.get(Calendar.SECOND); | |
751 } | |
752 } | |
753 | |
754 /** | |
755 * Returns the receiver's year. | |
756 * <p> | |
757 * The first year is 1752 and the last year is 9999. | |
758 * </p> | |
759 * | |
760 * @return an integer between 1752 and 9999 | |
761 * | |
762 * @exception SWTException <ul> | |
763 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
764 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
765 * </ul> | |
766 */ | |
767 public int getYear () { | |
768 checkWidget (); | |
769 if ((style & SWT.CALENDAR) !is 0) { | |
770 getDate(); | |
771 return year; | |
772 } else { | |
773 return calendar.get(Calendar.YEAR); | |
774 } | |
775 } | |
776 | |
777 override int gtk_day_selected (GtkWidget* widget) { | |
778 sendSelectionEvent (); | |
779 return 0; | |
780 } | |
781 | |
782 override int gtk_month_changed (GtkWidget* widget) { | |
783 sendSelectionEvent (); | |
784 return 0; | |
785 } | |
786 | |
787 void hookEvents () { | |
788 super.hookEvents(); | |
789 if ((style & SWT.CALENDAR) !is 0) { | |
790 OS.g_signal_connect_closure (handle, OS.day_selected.ptr, display.closures [DAY_SELECTED], false); | |
791 OS.g_signal_connect_closure (handle, OS.month_changed.ptr, display.closures [MONTH_CHANGED], false); | |
792 } | |
793 } | |
794 | |
795 bool isValid(int fieldName, int value) { | |
796 Calendar validCalendar; | |
797 if ((style & SWT.CALENDAR) !is 0) { | |
798 validCalendar = Calendar.getInstance(); | |
799 validCalendar.set(Calendar.YEAR, year); | |
800 validCalendar.set(Calendar.MONTH, month); | |
801 } else { | |
802 validCalendar = calendar; | |
803 } | |
804 int min = validCalendar.getActualMinimum(fieldName); | |
805 int max = validCalendar.getActualMaximum(fieldName); | |
806 return value >= min && value <= max; | |
807 } | |
808 | |
809 bool isValid(int year, int month, int day) { | |
810 Calendar valid = Calendar.getInstance(); | |
811 valid.set(year, month, day); | |
812 return valid.get(Calendar.YEAR) is year && valid.get(Calendar.MONTH) is month && valid.get(Calendar.DAY_OF_MONTH) is day; | |
813 } | |
814 | |
815 void incrementField(int amount) { | |
816 int fieldName = fieldNames[currentField]; | |
817 int value = calendar.get(fieldName); | |
818 if (fieldName is Calendar.HOUR) { | |
819 int max = calendar.getMaximum(Calendar.HOUR); | |
820 int min = calendar.getMinimum(Calendar.HOUR); | |
821 if ((value is max && amount is 1) || (value is min && amount is -1)) { | |
822 int temp = currentField; | |
823 currentField = getFieldIndex(Calendar.AM_PM); | |
824 setTextField(Calendar.AM_PM, (calendar.get(Calendar.AM_PM) + 1) % 2, true, true); | |
825 currentField = temp; | |
826 } | |
827 } | |
828 setTextField(fieldName, value + amount, true, true); | |
829 } | |
830 | |
831 void onKeyDown(Event event) { | |
832 int fieldName; | |
833 switch (event.keyCode) { | |
834 case SWT.ARROW_RIGHT: | |
835 case SWT.KEYPAD_DIVIDE: | |
836 // a right arrow or a valid separator navigates to the field on the right, with wraping | |
837 selectField((currentField + 1) % fieldCount); | |
838 break; | |
839 case SWT.ARROW_LEFT: | |
840 // navigate to the field on the left, with wrapping | |
841 int index = currentField - 1; | |
842 selectField(index < 0 ? fieldCount - 1 : index); | |
843 break; | |
844 case SWT.ARROW_UP: | |
845 case SWT.KEYPAD_ADD: | |
846 // set the value of the current field to value + 1, with wrapping | |
847 commitCurrentField(); | |
848 incrementField(+1); | |
849 break; | |
850 case SWT.ARROW_DOWN: | |
851 case SWT.KEYPAD_SUBTRACT: | |
852 // set the value of the current field to value - 1, with wrapping | |
853 commitCurrentField(); | |
854 incrementField(-1); | |
855 break; | |
856 case SWT.HOME: | |
857 // set the value of the current field to its minimum | |
858 fieldName = fieldNames[currentField]; | |
859 setTextField(fieldName, calendar.getActualMinimum(fieldName), true, true); | |
860 break; | |
861 case SWT.END: | |
862 // set the value of the current field to its maximum | |
863 fieldName = fieldNames[currentField]; | |
864 setTextField(fieldName, calendar.getActualMaximum(fieldName), true, true); | |
865 break; | |
866 default: | |
867 switch (event.character) { | |
868 case '/': | |
869 case ':': | |
870 case '-': | |
871 case '.': | |
872 // a valid separator navigates to the field on the right, with wraping | |
873 selectField((currentField + 1) % fieldCount); | |
874 break; | |
875 default: | |
876 } | |
877 } | |
878 } | |
879 | |
880 void onFocusIn(Event event) { | |
881 selectField(currentField); | |
882 } | |
883 | |
884 void onFocusOut(Event event) { | |
885 commitCurrentField(); | |
886 } | |
887 | |
888 void onMouseClick(Event event) { | |
889 if (event.button !is 1) return; | |
890 Point sel = text.getSelection(); | |
891 for (int i = 0; i < fieldCount; i++) { | |
892 if (sel.x >= fieldIndices[i].x && sel.x <= fieldIndices[i].y) { | |
893 currentField = i; | |
894 break; | |
895 } | |
896 } | |
897 selectField(currentField); | |
898 } | |
899 | |
900 void onResize(Event event) { | |
901 Rectangle rect = getClientArea (); | |
902 int width = rect.width; | |
903 int height = rect.height; | |
904 Point buttonSize = up.computeSize(SWT.DEFAULT, height); | |
905 int buttonHeight = buttonSize.y / 2; | |
906 text.setBounds(0, 0, width - buttonSize.x, height); | |
907 up.setBounds(width - buttonSize.x, 0, buttonSize.x, buttonHeight); | |
908 down.setBounds(width - buttonSize.x, buttonHeight, buttonSize.x, buttonHeight); | |
909 } | |
910 | |
911 void onVerify(Event event) { | |
912 if (ignoreVerify) return; | |
913 event.doit = false; | |
914 int fieldName = fieldNames[currentField]; | |
915 int start = fieldIndices[currentField].x; | |
916 int end = fieldIndices[currentField].y; | |
917 int length_ = end - start; | |
918 String newText = event.text; | |
919 if (fieldName is Calendar.AM_PM) { | |
120
536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
Denis Shelomovskij <verylonglogin.reg@gmail.com>
parents:
51
diff
changeset
|
920 auto ampm = formatSymbols.getAmPmStrings(); |
25 | 921 if (newText.equalsIgnoreCase(ampm[Calendar.AM].substring(0, 1)) || newText.equalsIgnoreCase(ampm[Calendar.AM])) { |
922 setTextField(fieldName, Calendar.AM, true, false); | |
923 } else if (newText.equalsIgnoreCase(ampm[Calendar.PM].substring(0, 1)) || newText.equalsIgnoreCase(ampm[Calendar.PM])) { | |
924 setTextField(fieldName, Calendar.PM, true, false); | |
925 } | |
926 return; | |
927 } | |
928 if (characterCount > 0) { | |
929 try { | |
51 | 930 Integer.parseInt(newText); |
931 } catch (NumberFormatException ex) { | |
25 | 932 return; |
933 } | |
934 String value = text.getText(start, end - 1); | |
935 int s = value.lastIndexOf(' '); | |
936 if (s !is -1) value = value.substring(s + 1); | |
937 newText = value ~ newText; | |
938 } | |
939 int newTextLength = newText.length; | |
940 bool first = characterCount is 0; | |
941 characterCount = (newTextLength < length_) ? newTextLength : 0; | |
942 int max = calendar.getActualMaximum(fieldName); | |
943 int min = calendar.getActualMinimum(fieldName); | |
944 int newValue = unformattedIntValue(fieldName, newText, characterCount is 0, max); | |
945 if (newValue is -1) { | |
946 characterCount = 0; | |
947 return; | |
948 } | |
949 if (first && newValue is 0 && length_ > 1) { | |
950 setTextField(fieldName, newValue, false, false); | |
951 } else if (min <= newValue && newValue <= max) { | |
952 setTextField(fieldName, newValue, characterCount is 0, characterCount is 0); | |
953 } else { | |
954 if (newTextLength >= length_) { | |
955 newText = newText.substring(newTextLength - length_ + 1); | |
956 newValue = unformattedIntValue(fieldName, newText, characterCount is 0, max); | |
957 if (newValue !is -1) { | |
958 characterCount = length_ - 1; | |
959 if (min <= newValue && newValue <= max) { | |
960 setTextField(fieldName, newValue, characterCount is 0, true); | |
961 } | |
962 } | |
963 } | |
964 } | |
965 } | |
966 | |
967 void releaseWidget () { | |
968 super.releaseWidget(); | |
969 //TODO: need to do anything here? | |
970 } | |
971 | |
972 /** | |
973 * Removes the listener from the collection of listeners who will | |
974 * be notified when the control is selected by the user. | |
975 * | |
976 * @param listener the listener which should no longer be notified | |
977 * | |
978 * @exception IllegalArgumentException <ul> | |
979 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
980 * </ul> | |
981 * @exception SWTException <ul> | |
982 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
983 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
984 * </ul> | |
985 * | |
986 * @see SelectionListener | |
987 * @see #addSelectionListener | |
988 */ | |
989 public void removeSelectionListener (SelectionListener listener) { | |
990 checkWidget (); | |
991 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
992 if (eventTable is null) return; | |
993 eventTable.unhook (SWT.Selection, listener); | |
994 eventTable.unhook (SWT.DefaultSelection, listener); | |
995 } | |
996 | |
997 void selectField(int index) { | |
998 if (index !is currentField) { | |
999 commitCurrentField(); | |
1000 } | |
49
7a2dd761a8b2
more work until dmd 2.026 linux segfaults.
Frank Benoit <benoit@tionex.de>
parents:
48
diff
changeset
|
1001 int start = fieldIndices[index].x; |
7a2dd761a8b2
more work until dmd 2.026 linux segfaults.
Frank Benoit <benoit@tionex.de>
parents:
48
diff
changeset
|
1002 int end = fieldIndices[index].y; |
25 | 1003 Point pt = text.getSelection(); |
1004 if (index is currentField && start is pt.x && end is pt.y) return; | |
1005 currentField = index; | |
1006 display.asyncExec(new class( start, end ) Runnable { | |
1007 int start, end; | |
1008 this( int start, int end ){ | |
1009 this.start = start; this.end = end; | |
1010 } | |
1011 public void run() { | |
1012 if (!text.isDisposed()) { | |
1013 String value = text.getText(start, end - 1); | |
1014 int s = value.lastIndexOf(' '); | |
1015 if (s is -1 ) s = start; | |
1016 else s = start + s + 1; | |
1017 text.setSelection(s, end); | |
1018 } | |
1019 } | |
1020 }); | |
1021 } | |
1022 | |
1023 void sendSelectionEvent () { | |
1024 uint y; | |
1025 uint m; | |
1026 uint d; | |
1027 OS.gtk_calendar_get_date(handle, &y, &m, &d); | |
1028 //TODO: hours, minutes, seconds? | |
1029 if (d !is day || | |
1030 m !is month || | |
1031 y !is year) { | |
1032 year = y; | |
1033 month = m; | |
1034 day = d; | |
1035 postEvent (SWT.Selection); | |
1036 } | |
1037 } | |
1038 | |
1039 public void setBackground(Color color) { | |
1040 checkWidget(); | |
1041 super.setBackground(color); | |
1042 if (text !is null) text.setBackground(color); | |
1043 } | |
1044 | |
1045 public void setFont(Font font) { | |
1046 checkWidget(); | |
1047 super.setFont(font); | |
1048 if (text !is null) text.setFont(font); | |
1049 redraw(); | |
1050 } | |
1051 | |
1052 public void setForeground(Color color) { | |
1053 checkWidget(); | |
1054 super.setForeground(color); | |
1055 if (text !is null) text.setForeground(color); | |
1056 } | |
1057 | |
1058 /*public*/ void setFormat(String string) { | |
1059 checkWidget(); | |
1060 // TODO: this needs to be locale sensitive | |
1061 fieldCount = (style & SWT.DATE) !is 0 ? ((style & SWT.SHORT) !is 0 ? 2 : 3) : ((style & SWT.SHORT) !is 0 ? 3 : 4); | |
1062 fieldIndices = new Point[fieldCount]; | |
1063 fieldNames = new int[fieldCount]; | |
1064 if ((style & SWT.DATE) !is 0) { | |
1065 fieldNames[0] = Calendar.MONTH; | |
1066 fieldIndices[0] = new Point(0, 2); | |
1067 if ((style & SWT.SHORT) !is 0) { | |
1068 fieldNames[1] = Calendar.YEAR; | |
1069 fieldIndices[1] = new Point(3, 7); | |
1070 } else { | |
1071 fieldNames[1] = Calendar.DAY_OF_MONTH; | |
1072 fieldIndices[1] = new Point(3, 5); | |
1073 fieldNames[2] = Calendar.YEAR; | |
1074 fieldIndices[2] = new Point(6, 10); | |
1075 } | |
1076 } else { /* SWT.TIME */ | |
1077 fieldNames[0] = Calendar.HOUR; | |
1078 fieldIndices[0] = new Point(0, 2); | |
1079 fieldNames[1] = Calendar.MINUTE; | |
1080 fieldIndices[1] = new Point(3, 5); | |
1081 if ((style & SWT.SHORT) !is 0) { | |
1082 fieldNames[2] = Calendar.AM_PM; | |
1083 fieldIndices[2] = new Point(6, 8); | |
1084 } else { | |
1085 fieldNames[2] = Calendar.SECOND; | |
1086 fieldIndices[2] = new Point(6, 8); | |
1087 fieldNames[3] = Calendar.AM_PM; | |
1088 fieldIndices[3] = new Point(9, 11); | |
1089 } | |
1090 } | |
1091 } | |
1092 | |
1093 void setField(int fieldName, int value) { | |
1094 if (calendar.get(fieldName) is value) return; | |
1095 if (fieldName is Calendar.AM_PM) { | |
1096 calendar.roll(Calendar.HOUR_OF_DAY, 12); // TODO: needs more work for setFormat and locale | |
1097 } | |
1098 calendar.set(fieldName, value); | |
1099 postEvent(SWT.Selection); | |
1100 } | |
1101 | |
1102 void setTextField(int fieldName, int value, bool commit, bool adjust) { | |
1103 if (commit) { | |
1104 int max = calendar.getActualMaximum(fieldName); | |
1105 int min = calendar.getActualMinimum(fieldName); | |
1106 if (fieldName is Calendar.YEAR) { | |
1107 max = MAX_YEAR; | |
1108 min = MIN_YEAR; | |
1109 /* Special case: convert 1 or 2-digit years into reasonable 4-digit years. */ | |
1110 int currentYear = Calendar.getInstance().get(Calendar.YEAR); | |
1111 int currentCentury = (currentYear / 100) * 100; | |
1112 if (value < (currentYear + 30) % 100) value += currentCentury; | |
1113 else if (value < 100) value += currentCentury - 100; | |
1114 } | |
1115 if (value > max) value = min; // wrap | |
1116 if (value < min) value = max; // wrap | |
1117 } | |
1118 int start = fieldIndices[currentField].x; | |
1119 int end = fieldIndices[currentField].y; | |
1120 text.setSelection(start, end); | |
1121 String newValue = formattedStringValue(fieldName, value, adjust); | |
1122 StringBuffer buffer = new StringBuffer(newValue); | |
1123 /* Convert leading 0's into spaces. */ | |
1124 int prependCount = end - start - buffer.length(); | |
1125 for (int i = 0; i < prependCount; i++) { | |
1126 switch (fieldName) { | |
1127 case Calendar.MINUTE: | |
1128 case Calendar.SECOND: | |
1129 buffer.insert(0, 0); | |
1130 break; | |
1131 default: | |
1132 buffer.insert(0, ' '); | |
1133 break; | |
1134 } | |
1135 } | |
1136 newValue = buffer.toString(); | |
1137 ignoreVerify = true; | |
1138 text.insert(newValue); | |
1139 ignoreVerify = false; | |
1140 selectField(currentField); | |
1141 if (commit) setField(fieldName, value); | |
1142 } | |
1143 | |
1144 /** | |
1145 * Sets the receiver's year, month, and day in a single operation. | |
1146 * <p> | |
1147 * This is the recommended way to set the date, because setting the year, | |
1148 * month, and day separately may result in invalid intermediate dates. | |
1149 * </p> | |
1150 * | |
1151 * @param year an integer between 1752 and 9999 | |
1152 * @param month an integer between 0 and 11 | |
1153 * @param day a positive integer beginning with 1 | |
1154 * | |
1155 * @exception SWTException <ul> | |
1156 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1157 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1158 * </ul> | |
1159 * | |
1160 * @since 3.4 | |
1161 */ | |
1162 public void setDate (int year, int month, int day) { | |
1163 checkWidget (); | |
1164 if (!isValid(year, month, day)) return; | |
1165 if ((style & SWT.CALENDAR) !is 0) { | |
1166 this.year = year; | |
1167 this.month = month; | |
1168 this.day = day; | |
1169 OS.gtk_calendar_select_month(handle, month, year); | |
1170 OS.gtk_calendar_select_day(handle, day); | |
1171 } else { | |
1172 calendar.set(Calendar.YEAR, year); | |
1173 calendar.set(Calendar.MONTH, month); | |
1174 calendar.set(Calendar.DAY_OF_MONTH, day); | |
1175 updateControl(); | |
1176 } | |
1177 } | |
1178 | |
1179 /** | |
1180 * Sets the receiver's date, or day of the month, to the specified day. | |
1181 * <p> | |
1182 * The first day of the month is 1, and the last day depends on the month and year. | |
1183 * </p> | |
1184 * | |
1185 * @param day a positive integer beginning with 1 | |
1186 * | |
1187 * @exception SWTException <ul> | |
1188 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1189 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1190 * </ul> | |
1191 */ | |
1192 public void setDay (int day) { | |
1193 checkWidget (); | |
1194 if (!isValid(Calendar.DAY_OF_MONTH, day)) return; | |
1195 if ((style & SWT.CALENDAR) !is 0) { | |
1196 this.day = day; | |
1197 OS.gtk_calendar_select_day(handle, day); | |
1198 } else { | |
1199 calendar.set(Calendar.DAY_OF_MONTH, day); | |
1200 updateControl(); | |
1201 } | |
1202 } | |
1203 | |
1204 /** | |
1205 * Sets the receiver's hours. | |
1206 * <p> | |
1207 * Hours is an integer between 0 and 23. | |
1208 * </p> | |
1209 * | |
1210 * @param hours an integer between 0 and 23 | |
1211 * | |
1212 * @exception SWTException <ul> | |
1213 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1214 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1215 * </ul> | |
1216 */ | |
1217 public void setHours (int hours) { | |
1218 checkWidget (); | |
1219 if (!isValid(Calendar.HOUR_OF_DAY, hours)) return; | |
1220 if ((style & SWT.CALENDAR) !is 0) { | |
1221 this.hours = hours; | |
1222 } else { | |
1223 calendar.set(Calendar.HOUR_OF_DAY, hours); | |
1224 updateControl(); | |
1225 } | |
1226 } | |
1227 | |
1228 /** | |
1229 * Sets the receiver's minutes. | |
1230 * <p> | |
1231 * Minutes is an integer between 0 and 59. | |
1232 * </p> | |
1233 * | |
1234 * @param minutes an integer between 0 and 59 | |
1235 * | |
1236 * @exception SWTException <ul> | |
1237 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1238 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1239 * </ul> | |
1240 */ | |
1241 public void setMinutes (int minutes) { | |
1242 checkWidget (); | |
1243 if (!isValid(Calendar.MINUTE, minutes)) return; | |
1244 if ((style & SWT.CALENDAR) !is 0) { | |
1245 this.minutes = minutes; | |
1246 } else { | |
1247 calendar.set(Calendar.MINUTE, minutes); | |
1248 updateControl(); | |
1249 } | |
1250 } | |
1251 | |
1252 /** | |
1253 * Sets the receiver's month. | |
1254 * <p> | |
1255 * The first month of the year is 0, and the last month is 11. | |
1256 * </p> | |
1257 * | |
1258 * @param month an integer between 0 and 11 | |
1259 * | |
1260 * @exception SWTException <ul> | |
1261 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1262 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1263 * </ul> | |
1264 */ | |
1265 public void setMonth (int month) { | |
1266 checkWidget (); | |
1267 if (!isValid(Calendar.MONTH, month)) return; | |
1268 if ((style & SWT.CALENDAR) !is 0) { | |
1269 this.month = month; | |
1270 OS.gtk_calendar_select_month(handle, month, year); | |
1271 } else { | |
1272 calendar.set(Calendar.MONTH, month); | |
1273 updateControl(); | |
1274 } | |
1275 } | |
1276 | |
1277 /** | |
1278 * Sets the receiver's seconds. | |
1279 * <p> | |
1280 * Seconds is an integer between 0 and 59. | |
1281 * </p> | |
1282 * | |
1283 * @param seconds an integer between 0 and 59 | |
1284 * | |
1285 * @exception SWTException <ul> | |
1286 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1287 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1288 * </ul> | |
1289 */ | |
1290 public void setSeconds (int seconds) { | |
1291 checkWidget (); | |
1292 if (!isValid(Calendar.SECOND, seconds)) return; | |
1293 if ((style & SWT.CALENDAR) !is 0) { | |
1294 this.seconds = seconds; | |
1295 } else { | |
1296 calendar.set(Calendar.SECOND, seconds); | |
1297 updateControl(); | |
1298 } | |
1299 } | |
1300 | |
1301 /** | |
1302 * Sets the receiver's hours, minutes, and seconds in a single operation. | |
1303 * | |
1304 * @param hours an integer between 0 and 23 | |
1305 * @param minutes an integer between 0 and 59 | |
1306 * @param seconds an integer between 0 and 59 | |
1307 * | |
1308 * @exception SWTException <ul> | |
1309 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1310 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1311 * </ul> | |
1312 * | |
1313 * @since 3.4 | |
1314 */ | |
1315 public void setTime (int hours, int minutes, int seconds) { | |
1316 checkWidget (); | |
1317 if (!isValid(Calendar.HOUR_OF_DAY, hours)) return; | |
1318 if (!isValid(Calendar.MINUTE, minutes)) return; | |
1319 if (!isValid(Calendar.SECOND, seconds)) return; | |
1320 if ((style & SWT.CALENDAR) !is 0) { | |
1321 this.hours = hours; | |
1322 this.minutes = minutes; | |
1323 this.seconds = seconds; | |
1324 } else { | |
1325 calendar.set(Calendar.HOUR_OF_DAY, hours); | |
1326 calendar.set(Calendar.MINUTE, minutes); | |
1327 calendar.set(Calendar.SECOND, seconds); | |
1328 updateControl(); | |
1329 } | |
1330 } | |
1331 | |
1332 /** | |
1333 * Sets the receiver's year. | |
1334 * <p> | |
1335 * The first year is 1752 and the last year is 9999. | |
1336 * </p> | |
1337 * | |
1338 * @param year an integer between 1752 and 9999 | |
1339 * | |
1340 * @exception SWTException <ul> | |
1341 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1342 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1343 * </ul> | |
1344 */ | |
1345 public void setYear (int year) { | |
1346 checkWidget (); | |
1347 //if (!isValid(Calendar.YEAR, year)) return; | |
1348 if (year < MIN_YEAR || year > MAX_YEAR) return; | |
1349 if ((style & SWT.CALENDAR) !is 0) { | |
1350 this.year = year; | |
1351 OS.gtk_calendar_select_month(handle, month, year); | |
1352 } else { | |
1353 calendar.set(Calendar.YEAR, year); | |
1354 updateControl(); | |
1355 } | |
1356 } | |
1357 | |
1358 int unformattedIntValue(int fieldName, String newText, bool adjust, int max) { | |
1359 int newValue; | |
1360 try { | |
51 | 1361 newValue = Integer.parseInt(newText); |
1362 } catch (NumberFormatException ex) { | |
25 | 1363 return -1; |
1364 } | |
1365 if (fieldName is Calendar.MONTH && adjust) { | |
1366 newValue--; | |
1367 if (newValue is -1) newValue = max; | |
1368 } | |
1369 if (fieldName is Calendar.HOUR && adjust) { | |
1370 if (newValue is 12) newValue = 0; // TODO: needs more work for setFormat and locale | |
1371 } | |
1372 return newValue; | |
1373 } | |
1374 | |
1375 public void updateControl() { | |
1376 if (text !is null) { | |
1377 String string = getFormattedString(style); | |
1378 ignoreVerify = true; | |
1379 text.setText(string); | |
1380 ignoreVerify = false; | |
1381 } | |
1382 redraw(); | |
1383 } | |
1384 } |