diff options
author | Carolyn MacLeod <carolyn> | 2006-10-30 19:45:12 +0000 |
---|---|---|
committer | Carolyn MacLeod <carolyn> | 2006-10-30 19:45:12 +0000 |
commit | beca6310b5a08f08f4d4efeb88b832d208de8eb6 (patch) | |
tree | 6022f54dae594d7537b8497d87374b642e010943 /bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DateTime.java | |
parent | d99830b9dc889f9a89bda98cdd4a92b116044815 (diff) | |
download | eclipse.platform.swt-beca6310b5a08f08f4d4efeb88b832d208de8eb6.tar.gz eclipse.platform.swt-beca6310b5a08f08f4d4efeb88b832d208de8eb6.tar.xz eclipse.platform.swt-beca6310b5a08f08f4d4efeb88b832d208de8eb6.zip |
add emulated date and time
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DateTime.java')
-rw-r--r-- | bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DateTime.java | 510 |
1 files changed, 475 insertions, 35 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DateTime.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DateTime.java index 9f1a4c45ad..6c23c65bb4 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DateTime.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DateTime.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.swt.widgets; +import java.text.DateFormatSymbols; import java.util.Calendar; import org.eclipse.swt.*; @@ -23,8 +24,68 @@ import org.eclipse.swt.internal.gtk.OS; static final int MIN_YEAR = 1752; // Gregorian switchover in North America: September 19, 1752 static final int MAX_YEAR = 9999; + // Emulated DATE and TIME variables + Calendar calendar; + DateFormatSymbols formatSymbols; + Button down, up; + Text text; + String format; + Point[] fieldIndices; + int[] fieldNames; + int fieldCount, currentField = 0, characterCount = 0; + boolean ignoreVerify = false; + static String defaultDateFormat = "MM/DD/YYYY"; + static String defaultTimeFormat = "HH:MM:SS AM"; + public DateTime (Composite parent, int style) { super (parent, checkStyle (style)); + if ((this.style & SWT.CALENDAR) == 0) { + /* SWT.DATE and SWT.TIME */ + calendar = Calendar.getInstance(); + formatSymbols = new DateFormatSymbols(); + text = new Text(this, SWT.SINGLE); + setFormat((this.style == SWT.DATE ? defaultDateFormat : defaultTimeFormat)); + text.setText(getFormattedString(this.style)); + Listener listener = new Listener() { + public void handleEvent(Event event) { + switch(event.type) { + case SWT.KeyDown: onKeyDown(event); break; + case SWT.FocusIn: onFocusIn(event); break; + case SWT.FocusOut: onFocusOut(event); break; + case SWT.MouseDown: onMouseClick(event); break; + case SWT.MouseUp: onMouseClick(event); break; + case SWT.Verify: onVerify(event); break; + } + } + }; + text.addListener(SWT.KeyDown, listener); + text.addListener(SWT.FocusIn, listener); + text.addListener(SWT.FocusOut, listener); + text.addListener(SWT.MouseDown, listener); + text.addListener(SWT.MouseUp, listener); + text.addListener(SWT.Verify, listener); + up = new Button(this, SWT.ARROW | SWT.UP); + //up.setToolTipText(SWT.getMessage ("SWT_Up")); //$NON-NLS-1$ + down = new Button(this, SWT.ARROW | SWT.DOWN); + //down.setToolTipText(SWT.getMessage ("SWT_Down")); //$NON-NLS-1$ + up.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + incrementField(+1); + text.setFocus(); + } + }); + down.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + incrementField(-1); + text.setFocus(); + } + }); + addListener(SWT.Resize, new Listener() { + public void handleEvent(Event event) { + onResize(event); + } + }); + } } static int checkStyle (int style) { @@ -55,13 +116,20 @@ public Point computeSize (int wHint, int hHint, boolean changed) { checkWidget (); int width = 0, height = 0; if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) { -// if ((style & SWT.CALENDAR) != 0) { + if ((style & SWT.CALENDAR) != 0) { // TODO: CALENDAR computeSize width = 300; height = 200; -// } else { - // TODO: TIME and DATE -// } + } else { + /* SWT.DATE and SWT.TIME */ + GC gc = new GC(text); + Point textSize = gc.stringExtent(getComputeSizeString(style)); + gc.dispose(); + Rectangle trim = text.computeTrim(0, 0, textSize.x, textSize.y); + Point buttonSize = up.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed); + width = trim.width + buttonSize.x; + height = Math.max(trim.height, buttonSize.y); + } } if (width == 0) width = DEFAULT_WIDTH; if (height == 0) height = DEFAULT_HEIGHT; @@ -73,7 +141,7 @@ public Point computeSize (int wHint, int hHint, boolean changed) { } void createHandle (int index) { -// if ((style & SWT.CALENDAR) != 0) { + if ((style & SWT.CALENDAR) != 0) { state |= HANDLE; fixedHandle = OS.g_object_new (display.gtk_fixed_get_type (), 0); if (fixedHandle == 0) error (SWT.ERROR_NO_HANDLES); @@ -86,16 +154,70 @@ void createHandle (int index) { } else { OS.gtk_calendar_display_options(handle, OS.GTK_CALENDAR_SHOW_HEADING | OS.GTK_CALENDAR_SHOW_DAY_NAMES); } -// } else { /* SWT.DATE and SWT.TIME */ - // TODO: emulated date & time -// } + } else { + super.createHandle(index); + } } void createWidget (int index) { super.createWidget (index); -// if ((style & SWT.CALENDAR) != 0) { + if ((style & SWT.CALENDAR) != 0) { getDate(); -// } + } +} + +void commitCurrentField() { + if (characterCount > 0) { + characterCount = 0; + int fieldName = fieldNames[currentField]; + int newValue = unformattedIntValue(fieldName, text.getSelectionText(), characterCount == 0, calendar.getActualMaximum(fieldName)); + if (newValue != -1) setTextField(fieldName, newValue, true, true); + } +} + +String formattedStringValue(int fieldName, int value, boolean adjust) { + if (fieldName == Calendar.AM_PM) { + String[] ampm = formatSymbols.getAmPmStrings(); + return ampm[value]; + } + if (adjust) { + if (fieldName == Calendar.HOUR && value == 0) { + return String.valueOf(12); + } + if (fieldName == Calendar.MONTH) { + return String.valueOf(value + 1); + } + } + return String.valueOf(value); +} + +String getComputeSizeString(int style) { + return (style & SWT.TIME) != 0 ? defaultTimeFormat : defaultDateFormat; +} + +int getFieldIndex(int fieldName) { + for (int i = 0; i < fieldCount; i++) { + if (fieldNames[i] == fieldName) { + return i; + } + } + return -1; +} + +String getFormattedString(int style) { + if ((style & SWT.TIME) != 0) { + String[] ampm = formatSymbols.getAmPmStrings(); + int h = calendar.get(Calendar.HOUR); if (h == 0) h = 12; + int m = calendar.get(Calendar.MINUTE); + int s = calendar.get(Calendar.SECOND); + int a = calendar.get(Calendar.AM_PM); + return "" + (h < 10 ? " " : "") + h + ":" + (m < 10 ? " " : "") + m + ":" + (s < 10 ? " " : "") + s + " " + ampm[a]; + } + /* SWT.DATE */ + int y = calendar.get(Calendar.YEAR); + int m = calendar.get(Calendar.MONTH) + 1; + int d = calendar.get(Calendar.DAY_OF_MONTH); + return "" + (m < 10 ? " " : "") + m + "/" + (d < 10 ? " " : "") + d + "/" + y; } void getDate() { @@ -110,35 +232,59 @@ void getDate() { public int getDay () { checkWidget (); - getDate(); - return day; + if ((style & SWT.CALENDAR) != 0) { + getDate(); + return day; + } else { + return calendar.get(Calendar.DAY_OF_MONTH); + } } public int getHour () { checkWidget (); - return hour; + if ((style & SWT.CALENDAR) != 0) { + return hour; + } else { + return calendar.get(Calendar.HOUR_OF_DAY); + } } public int getMinute () { checkWidget (); - return minute; + if ((style & SWT.CALENDAR) != 0) { + return minute; + } else { + return calendar.get(Calendar.MINUTE); + } } public int getMonth () { checkWidget (); - getDate(); - return month + 1; + if ((style & SWT.CALENDAR) != 0) { + getDate(); + return month + 1; + } else { + return calendar.get(Calendar.MONTH) + 1; + } } public int getSecond () { checkWidget (); - return second; + if ((style & SWT.CALENDAR) != 0) { + return second; + } else { + return calendar.get(Calendar.SECOND); + } } public int getYear () { checkWidget (); - getDate(); - return year; + if ((style & SWT.CALENDAR) != 0) { + getDate(); + return year; + } else { + return calendar.get(Calendar.YEAR); + } } int /*long*/ gtk_day_selected (int /*long*/ widget) { @@ -153,21 +299,169 @@ int /*long*/ gtk_month_changed (int /*long*/ widget) { void hookEvents () { super.hookEvents(); -// if ((style & SWT.CALENDAR) != 0) { + if ((style & SWT.CALENDAR) != 0) { OS.g_signal_connect_closure (handle, OS.day_selected, display.closures [DAY_SELECTED], false); OS.g_signal_connect_closure (handle, OS.month_changed, display.closures [MONTH_CHANGED], false); -// } + } } boolean isValid(int fieldName, int value) { - Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.YEAR, year); - calendar.set(Calendar.MONTH, month); - int min = calendar.getActualMinimum(fieldName); - int max = calendar.getActualMaximum(fieldName); + Calendar validCalendar; + if ((style & SWT.CALENDAR) != 0) { + validCalendar = Calendar.getInstance(); + validCalendar.set(Calendar.YEAR, year); + validCalendar.set(Calendar.MONTH, month); + } else { + validCalendar = calendar; + } + int min = validCalendar.getActualMinimum(fieldName); + int max = validCalendar.getActualMaximum(fieldName); return value >= min && value <= max; } +void incrementField(int amount) { + int fieldName = fieldNames[currentField]; + int value = calendar.get(fieldName); + if (fieldName == Calendar.HOUR) { + int max = calendar.getMaximum(Calendar.HOUR); + int min = calendar.getMinimum(Calendar.HOUR); + if ((value == max && amount == 1) || (value == min && amount == -1)) { + int temp = currentField; + currentField = getFieldIndex(Calendar.AM_PM); + setTextField(Calendar.AM_PM, (calendar.get(Calendar.AM_PM) + 1) % 2, true, true); + currentField = temp; + } + } + setTextField(fieldName, value + amount, true, true); +} + +void onKeyDown(Event event) { + int fieldName; + switch (event.keyCode) { + case SWT.ARROW_RIGHT: + case SWT.KEYPAD_DIVIDE: + // a right arrow or a valid separator navigates to the field on the right, with wraping + selectField((currentField + 1) % fieldCount); + break; + case SWT.ARROW_LEFT: + // navigate to the field on the left, with wrapping + int index = currentField - 1; + selectField(index < 0 ? fieldCount - 1 : index); + break; + case SWT.ARROW_UP: + case SWT.KEYPAD_ADD: + // set the value of the current field to value + 1, with wrapping + commitCurrentField(); + incrementField(+1); + break; + case SWT.ARROW_DOWN: + case SWT.KEYPAD_SUBTRACT: + // set the value of the current field to value - 1, with wrapping + commitCurrentField(); + incrementField(-1); + break; + case SWT.HOME: + // set the value of the current field to its minimum + fieldName = fieldNames[currentField]; + setTextField(fieldName, calendar.getActualMinimum(fieldName), true, true); + break; + case SWT.END: + // set the value of the current field to its maximum + fieldName = fieldNames[currentField]; + setTextField(fieldName, calendar.getActualMaximum(fieldName), true, true); + break; + default: + switch (event.character) { + case '/': + case ':': + case '-': + case '.': + // a valid separator navigates to the field on the right, with wraping + selectField((currentField + 1) % fieldCount); + break; + } + } +} + +void onFocusIn(Event event) { + selectField(currentField); +} + +void onFocusOut(Event event) { + commitCurrentField(); +} + +void onMouseClick(Event event) { + if (event.button != 1) return; + Point sel = text.getSelection(); + for (int i = 0; i < fieldCount; i++) { + if (sel.x >= fieldIndices[i].x && sel.x <= fieldIndices[i].y) { + currentField = i; + break; + } + } + selectField(currentField); +} + +void onResize(Event event) { + Rectangle rect = getClientArea (); + int width = rect.width; + int height = rect.height; + Point buttonSize = up.computeSize(SWT.DEFAULT, height); + int buttonHeight = buttonSize.y / 2; + text.setBounds(0, 0, width - buttonSize.x, height); + up.setBounds(width - buttonSize.x, 0, buttonSize.x, buttonHeight); + down.setBounds(width - buttonSize.x, buttonHeight, buttonSize.x, buttonHeight); +} + +void onVerify(Event event) { + if (ignoreVerify) return; + event.doit = false; + int fieldName = fieldNames[currentField]; + int start = fieldIndices[currentField].x; + int end = fieldIndices[currentField].y; + int length = end - start; + String newText = event.text; + if (fieldName == Calendar.AM_PM) { + String[] ampm = formatSymbols.getAmPmStrings(); + if (newText.equalsIgnoreCase(ampm[Calendar.AM].substring(0, 1)) || newText.equalsIgnoreCase(ampm[Calendar.AM])) { + setTextField(fieldName, Calendar.AM, true, false); + } else if (newText.equalsIgnoreCase(ampm[Calendar.PM].substring(0, 1)) || newText.equalsIgnoreCase(ampm[Calendar.PM])) { + setTextField(fieldName, Calendar.PM, true, false); + } + return; + } + if (characterCount > 0) { + newText = "" + text.getSelectionText() + newText; + } + int newTextLength = newText.length(); + boolean first = characterCount == 0; + characterCount = (newTextLength < length) ? newTextLength : 0; + int max = calendar.getActualMaximum(fieldName); + int min = calendar.getActualMinimum(fieldName); + int newValue = unformattedIntValue(fieldName, newText, characterCount == 0, max); + if (newValue == -1) { + characterCount = 0; + return; + } + if (first && newValue == 0 && length > 1) { + setTextField(fieldName, newValue, false, false); + } else if (min <= newValue && newValue <= max) { + setTextField(fieldName, newValue, characterCount == 0, characterCount == 0); + } else { + if (newTextLength >= length) { + newText = newText.substring(newTextLength - length + 1); + newValue = unformattedIntValue(fieldName, newText, characterCount == 0, max); + if (newValue != -1) { + characterCount = length - 1; + if (min <= newValue && newValue <= max) { + setTextField(fieldName, newValue, characterCount == 0, true); + } + } + } + } +} + void releaseWidget () { super.releaseWidget(); //TODO: need to do anything here? @@ -181,6 +475,28 @@ public void removeSelectionListener (SelectionListener listener) { eventTable.unhook (SWT.DefaultSelection, listener); } +void selectField(int index) { + if (index != currentField) { + commitCurrentField(); + } + final int start = fieldIndices[index].x; + final int end = fieldIndices[index].y; + Point pt = text.getSelection(); + if (index == currentField && start == pt.x && end == pt.y) return; + currentField = index; + display.asyncExec(new Runnable() { + public void run() { + if (!text.isDisposed()) { + String value = text.getText(start, end - 1); + int s = value.lastIndexOf(' '); + if (s == -1) s = start; + else s = start + s + 1; + text.setSelection(s, end); + } + } + }); +} + void sendSelectionEvent () { int [] y = new int [1]; int [] m = new int [1]; @@ -197,45 +513,169 @@ void sendSelectionEvent () { } } +/*public*/ void setFormat(String string) { + checkWidget(); + fieldCount = (style & SWT.DATE) != 0 ? 3 : 4; + fieldIndices = new Point[fieldCount]; + fieldNames = new int[fieldCount]; + if ((style & SWT.DATE) != 0) { + fieldNames[0] = Calendar.MONTH; + fieldIndices[0] = new Point(0, 2); + fieldNames[1] = Calendar.DAY_OF_MONTH; + fieldIndices[1] = new Point(3, 5); + fieldNames[2] = Calendar.YEAR; + fieldIndices[2] = new Point(6, 10); + } else { /* SWT.TIME */ + fieldNames[0] = Calendar.HOUR; + fieldIndices[0] = new Point(0, 2); + fieldNames[1] = Calendar.MINUTE; + fieldIndices[1] = new Point(3, 5); + fieldNames[2] = Calendar.SECOND; + fieldIndices[2] = new Point(6, 8); + fieldNames[3] = Calendar.AM_PM; + fieldIndices[3] = new Point(9, 11); + } + format = string; +} + +void setField(int fieldName, int value) { + if (calendar.get(fieldName) == value) return; + if (fieldName == Calendar.AM_PM) { + calendar.roll(Calendar.HOUR_OF_DAY, 12); // TODO: needs more work for setFormat and locale + } + calendar.set(fieldName, value); + notifyListeners(SWT.Selection, new Event()); +} + +void setTextField(int fieldName, int value, boolean commit, boolean adjust) { + if (commit) { + int max = calendar.getActualMaximum(fieldName); + int min = calendar.getActualMinimum(fieldName); + if (fieldName == Calendar.YEAR) { + max = MAX_YEAR; + min = MIN_YEAR; + /* Special case: convert 1 or 2-digit years into reasonable 4-digit years. */ + int currentYear = Calendar.getInstance().get(Calendar.YEAR); + int currentCentury = (currentYear / 100) * 100; + if (value < (currentYear + 30) % 100) value += currentCentury; + else if (value < 100) value += currentCentury - 100; + } + if (value > max) value = min; // wrap + if (value < min) value = max; // wrap + } + int start = fieldIndices[currentField].x; + int end = fieldIndices[currentField].y; + text.setSelection(start, end); + String newValue = formattedStringValue(fieldName, value, adjust); + StringBuffer buffer = new StringBuffer(newValue); + /* Convert leading 0's into spaces. */ + int prependCount = end - start - buffer.length(); + for (int i = 0; i < prependCount; i++) { + buffer.insert(0, ' '); + } + newValue = buffer.toString(); + ignoreVerify = true; + text.insert(newValue); + ignoreVerify = false; + selectField(currentField); + if (commit) setField(fieldName, value); +} + public void setDay (int day) { checkWidget (); if (!isValid(Calendar.DAY_OF_MONTH, day)) return; - this.day = day; - OS.gtk_calendar_select_day(handle, day); + if ((style & SWT.CALENDAR) != 0) { + this.day = day; + OS.gtk_calendar_select_day(handle, day); + } else { + calendar.set(Calendar.DAY_OF_MONTH, day); + updateControl(); + } } public void setHour (int hour) { checkWidget (); if (!isValid(Calendar.HOUR_OF_DAY, hour)) return; - this.hour = hour; + if ((style & SWT.CALENDAR) != 0) { + this.hour = hour; + } else { + calendar.set(Calendar.HOUR_OF_DAY, hour); + updateControl(); + } } public void setMinute (int minute) { checkWidget (); if (!isValid(Calendar.MINUTE, minute)) return; - this.minute = minute; + if ((style & SWT.CALENDAR) != 0) { + this.minute = minute; + } else { + calendar.set(Calendar.MINUTE, minute); + updateControl(); + } } public void setMonth (int month) { checkWidget (); month--; if (!isValid(Calendar.MONTH, month)) return; - this.month = month; - OS.gtk_calendar_select_month(handle, month, year); + if ((style & SWT.CALENDAR) != 0) { + this.month = month; + OS.gtk_calendar_select_month(handle, month, year); + } else { + calendar.set(Calendar.MONTH, month); + updateControl(); + } } public void setSecond (int second) { checkWidget (); if (!isValid(Calendar.SECOND, second)) return; - this.second = second; + if ((style & SWT.CALENDAR) != 0) { + this.second = second; + } else { + calendar.set(Calendar.SECOND, second); + updateControl(); + } } public void setYear (int year) { checkWidget (); //if (!isValid(Calendar.YEAR, year)) return; if (year < MIN_YEAR || year > MAX_YEAR) return; - this.year = year; - OS.gtk_calendar_select_month(handle, month, year); + if ((style & SWT.CALENDAR) != 0) { + this.year = year; + OS.gtk_calendar_select_month(handle, month, year); + } else { + calendar.set(Calendar.YEAR, year); + updateControl(); + } } +int unformattedIntValue(int fieldName, String newText, boolean adjust, int max) { + int newValue; + try { + newValue = Integer.parseInt(newText); + } catch (NumberFormatException ex) { + return -1; + } + if (fieldName == Calendar.MONTH && adjust) { + newValue--; + if (newValue == -1) newValue = max; + } + if (fieldName == Calendar.HOUR && adjust) { + if (newValue == 12) newValue = 0; // TODO: needs more work for setFormat and locale + } + return newValue; +} + +public void updateControl() { + if (text != null) { + String string = getFormattedString(style); + ignoreVerify = true; + text.setText(string); + ignoreVerify = false; + } + redraw(); +} } |