Java tutorial
/******************************************************************************* * Copyright (c) 2008, 2017 Innoopract Informationssysteme GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation * EclipseSource - ongoing development ******************************************************************************/ package org.eclipse.swt.widgets; import java.text.DateFormat; import java.text.DateFormatSymbols; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.StringTokenizer; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.internal.lifecycle.WidgetLCA; import org.eclipse.rap.rwt.internal.textsize.TextSizeUtil; import org.eclipse.rap.rwt.internal.theme.ThemeAdapter; import org.eclipse.rap.rwt.theme.BoxDimensions; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.internal.widgets.IDateTimeAdapter; import org.eclipse.swt.internal.widgets.datetimekit.DateTimeLCA; import org.eclipse.swt.internal.widgets.datetimekit.DateTimeThemeAdapter; /** * Instances of this class are selectable user interface objects that allow the * user to enter and modify date or time values. * <p> * Note that although this class is a subclass of <code>Composite</code>, it * does not make sense to add children to it, or set a layout on it. * </p> * <dl> * <dt><b>Styles:</b></dt> * <dd>DATE, TIME, CALENDAR, SHORT, MEDIUM, LONG, DROP_DOWN</dd> * <dt><b>Events:</b></dt> * <dd>Selection</dd> * </dl> * <p> * Note: Only one of the styles DATE, TIME, or CALENDAR may be specified, and * only one of the styles SHORT, MEDIUM, or LONG may be specified. * The DROP_DOWN style is a <em>HINT</em>, and it is only valid with the DATE style. * </p> * <p> * IMPORTANT: This class is <em>not</em> intended to be subclassed. * </p> * * @since 1.1.1 */ public class DateTime extends Composite { private final class DateTimeAdapter implements IDateTimeAdapter { @Override public Rectangle getBounds(int widget) { Rectangle result = new Rectangle(0, 0, 0, 0); switch (widget) { case WEEKDAY_TEXTFIELD: result = weekdayTextFieldBounds; break; case DAY_TEXTFIELD: result = dayTextFieldBounds; break; case MONTH_TEXTFIELD: result = monthTextFieldBounds; break; case YEAR_TEXTFIELD: result = yearTextFieldBounds; break; case WEEKDAY_MONTH_SEPARATOR: result = separator0Bounds; break; case MONTH_DAY_SEPARATOR: result = separator1Bounds; break; case DAY_YEAR_SEPARATOR: result = separator2Bounds; break; case SPINNER: result = spinnerBounds; break; case HOURS_TEXTFIELD: result = hoursTextFieldBounds; break; case MINUTES_TEXTFIELD: result = minutesTextFieldBounds; break; case SECONDS_TEXTFIELD: result = secondsTextFieldBounds; break; case HOURS_MINUTES_SEPARATOR: result = separator3Bounds; break; case MINUTES_SECONDS_SEPARATOR: result = separator4Bounds; break; case DROP_DOWN_BUTTON: result = dropDownButtonBounds; break; } return result; } @Override public Point getCellSize() { return new Point(cellSize.x, cellSize.y); } @Override public String[] getMonthNames() { return monthNames; } @Override public String[] getWeekdayNames() { return weekdayNames; } @Override public String[] getWeekdayShortNames() { return weekdayShortNames; } @Override public String getDateSeparator() { return dateSeparator; } @Override public String getDatePattern() { return datePattern; } } private static final int V_PADDING = 1; private static final int H_PADDING = 6; private static final int CALENDAR_HEADER_HEIGHT = 24; private static final int MIN_CELL_WIDTH = 24; private static final int MIN_CELL_HEIGHT = 16; private static final int CELL_PADDING = 2; private final String[] monthNames; private final String[] weekdayNames; private final String[] weekdayShortNames; private final String dateSeparator; private final String datePattern; private final Point cellSize; private transient IDateTimeAdapter dateTimeAdapter; private final Calendar rightNow; private Date minimum; private Date maximum; private boolean ignoreLimits; // Date fields private Rectangle weekdayTextFieldBounds; private Rectangle dayTextFieldBounds; private Rectangle monthTextFieldBounds; private Rectangle yearTextFieldBounds; private Rectangle separator0Bounds; private Rectangle separator1Bounds; private Rectangle separator2Bounds; private Rectangle spinnerBounds; // Time fields private Rectangle hoursTextFieldBounds; private Rectangle minutesTextFieldBounds; private Rectangle secondsTextFieldBounds; private Rectangle separator3Bounds; private Rectangle separator4Bounds; // Date drop down button private Rectangle dropDownButtonBounds; /** * Constructs a new instance of this class given its parent and a style value * describing its behavior and appearance. * <p> * The style value is either one of the style constants defined in class * <code>SWT</code> which is applicable to instances of this class, or must * be built by <em>bitwise OR</em>'ing together (that is, using the * <code>int</code> "|" operator) two or more of those <code>SWT</code> * style constants. The class description lists the style constants that are * applicable to the class. Style bits are also inherited from superclasses. * </p> * * @param parent a composite control which will be the parent of the new * instance (cannot be null) * @param style the style of control to construct * @exception IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> * </ul> * @exception SWTException * <ul> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the parent</li> * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed * subclass</li> * </ul> * @see SWT#DATE * @see SWT#TIME * @see SWT#CALENDAR * @see Widget#checkSubclass * @see Widget#getStyle */ public DateTime(Composite parent, int style) { super(parent, checkStyle(style)); rightNow = Calendar.getInstance(); DateFormatSymbols symbols = new DateFormatSymbols(RWT.getLocale()); monthNames = symbols.getMonths(); weekdayNames = symbols.getWeekdays(); weekdayShortNames = symbols.getShortWeekdays(); dateSeparator = getDateSeparator(); datePattern = getDatePattern(dateSeparator); cellSize = computeCellSize(); computeSubWidgetsBounds(); } @Override void initState() { removeState( /* CANVAS | */THEME_BACKGROUND); } /** * Adds the listener to the collection of listeners who will be notified when * the control is selected by the user, by sending it one of the messages * defined in the <code>SelectionListener</code> interface. * <p> * <code>widgetSelected</code> is called when the user changes the control's * value. <code>widgetDefaultSelected</code> is not called. * </p> * * @param listener the listener which should be notified * @exception IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> * @see SelectionListener * @see #removeSelectionListener * @see SelectionEvent */ public void addSelectionListener(SelectionListener listener) { checkWidget(); if (listener == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.Selection, typedListener); addListener(SWT.DefaultSelection, typedListener); } /** * Removes the listener from the collection of listeners who will be notified * when the control is selected by the user. * * @param listener the listener which should no longer be notified * @exception IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> * @see SelectionListener * @see #addSelectionListener */ public void removeSelectionListener(SelectionListener listener) { checkWidget(); if (listener == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.Selection, listener); removeListener(SWT.DefaultSelection, listener); } /** * Returns the receiver's hours. * <p> * Hours is an integer between 0 and 23. * </p> * * @return an integer between 0 and 23 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public int getHours() { checkWidget(); return rightNow.get(Calendar.HOUR_OF_DAY); } /** * Returns the receiver's minutes. * <p> * Minutes is an integer between 0 and 59. * </p> * * @return an integer between 0 and 59 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public int getMinutes() { checkWidget(); return rightNow.get(Calendar.MINUTE); } /** * Returns the receiver's seconds. * <p> * Seconds is an integer between 0 and 59. * </p> * * @return an integer between 0 and 59 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public int getSeconds() { checkWidget(); return rightNow.get(Calendar.SECOND); } /** * Returns the receiver's date, or day of the month. * <p> * The first day of the month is 1, and the last day depends on the month and * year. * </p> * * @return a positive integer beginning with 1 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public int getDay() { checkWidget(); return rightNow.get(Calendar.DATE); } /** * Returns the receiver's month. * <p> * The first month of the year is 0, and the last month is 11. * </p> * * @return an integer between 0 and 11 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public int getMonth() { checkWidget(); return rightNow.get(Calendar.MONTH); } /** * Returns the receiver's year. * <p> * The first year is 1752 and the last year is 9999. * </p> * * @return an integer between 1752 and 9999 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public int getYear() { checkWidget(); return rightNow.get(Calendar.YEAR); } /** * Returns the minimum value which the receiver will allow or null if no minimum limit is applied. * * @return the minimum value * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the * receiver</li> * </ul> * @since 3.2 */ public Date getMinimum() { checkWidget(); return minimum == null ? null : (Date) minimum.clone(); } /** * Returns the maximum value which the receiver will allow or null if no maximum limit is applied. * * @return the maximum value * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the * receiver</li> * </ul> * @since 3.2 */ public Date getMaximum() { checkWidget(); return maximum == null ? null : (Date) maximum.clone(); } /** * Sets the receiver's hours. * <p> * Hours is an integer between 0 and 23. * </p> * * @param hours an integer between 0 and 23 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setHours(int hours) { checkWidget(); if (checkTime(hours, getMinutes(), getSeconds())) { rightNow.set(Calendar.HOUR_OF_DAY, hours); applyLimits(); } } /** * Sets the receiver's minutes. * <p> * Minutes is an integer between 0 and 59. * </p> * * @param minutes an integer between 0 and 59 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setMinutes(int minutes) { checkWidget(); if (checkTime(getHours(), minutes, getSeconds())) { rightNow.set(Calendar.MINUTE, minutes); applyLimits(); } } /** * Sets the receiver's seconds. * <p> * Seconds is an integer between 0 and 59. * </p> * * @param seconds an integer between 0 and 59 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setSeconds(int seconds) { checkWidget(); if (checkTime(getHours(), getMinutes(), seconds)) { rightNow.set(Calendar.SECOND, seconds); applyLimits(); } } /** * Sets the receiver's date, or day of the month, to the specified day. * <p> * The first day of the month is 1, and the last day depends on the month and * year. * </p> * * @param day a positive integer beginning with 1 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setDay(int day) { checkWidget(); int month = rightNow.get(Calendar.MONTH); int year = rightNow.get(Calendar.YEAR); if (checkDate(year, month, day)) { rightNow.set(Calendar.DATE, day); applyLimits(); } } /** * Sets the receiver's month. * <p> * The first month of the year is 0, and the last month is 11. * </p> * * @param month an integer between 0 and 11 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setMonth(int month) { checkWidget(); int day = rightNow.get(Calendar.DATE); int year = rightNow.get(Calendar.YEAR); if (checkDate(year, month, day)) { rightNow.set(Calendar.MONTH, month); applyLimits(); } } /** * Sets the receiver's year. * <p> * The first year is 1752 and the last year is 9999. * </p> * * @param year an integer between 1752 and 9999 * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setYear(int year) { checkWidget(); int day = rightNow.get(Calendar.DATE); int month = rightNow.get(Calendar.MONTH); if (checkDate(year, month, day)) { rightNow.set(Calendar.YEAR, year); applyLimits(); } } /** * Sets the minimum value. If this value is greater than or equal to the maximum, the value is * ignored. * * @param date the new minimum * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the * receiver</li> * </ul> * @since 3.2 */ public void setMinimum(Date date) { checkWidget(); if (date == null) { minimum = null; applyLimits(); } else if (maximum == null || date.getTime() < maximum.getTime()) { minimum = (Date) date.clone(); applyLimits(); } } /** * Sets the maximum value. If this value is lower than or equal to the minimum, the value is * ignored. * * @param date the new maximum * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the * receiver</li> * </ul> * @since 3.2 */ public void setMaximum(Date date) { checkWidget(); if (date == null) { maximum = null; applyLimits(); } else if (minimum == null || date.getTime() > minimum.getTime()) { maximum = (Date) date.clone(); applyLimits(); } } /** * Sets the receiver's year, month, and day in a single operation. * <p> * This is the recommended way to set the date, because setting the year, * month, and day separately may result in invalid intermediate dates. * </p> * * @param year an integer between 1752 and 9999 * @param month an integer between 0 and 11 * @param day a positive integer beginning with 1 * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver</li> * </ul> * * @since 1.2 */ public void setDate(int year, int month, int day) { checkWidget(); if (checkDate(year, month, day)) { // reset ignoreLimits = true; setYear(9996); setMonth(0); setDay(1); // set setYear(year); setMonth(month); setDay(day); ignoreLimits = false; applyLimits(); } } /** * Sets the receiver's hours, minutes, and seconds in a single operation. * * @param hours an integer between 0 and 23 * @param minutes an integer between 0 and 59 * @param seconds an integer between 0 and 59 * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver</li> * </ul> * * @since 1.2 */ public void setTime(int hours, int minutes, int seconds) { checkWidget(); if (checkTime(hours, minutes, seconds)) { setHours(hours); setMinutes(minutes); setSeconds(seconds); } } @Override public void setFont(Font font) { if (font != getFont()) { super.setFont(font); } computeSubWidgetsBounds(); } @Override @SuppressWarnings("unchecked") public <T> T getAdapter(Class<T> adapter) { if (adapter == IDateTimeAdapter.class) { if (dateTimeAdapter == null) { dateTimeAdapter = new DateTimeAdapter(); } return (T) dateTimeAdapter; } if (adapter == WidgetLCA.class) { return (T) DateTimeLCA.INSTANCE; } return super.getAdapter(adapter); } @Override public Point computeSize(int wHint, int hHint, boolean changed) { checkWidget(); int width = 0, height = 0; if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) { Point size = computeSubWidgetsBounds(); width = size.x; height = size.y; } if (width == 0) { width = DEFAULT_WIDTH; } if (height == 0) { height = DEFAULT_HEIGHT; } if (wHint != SWT.DEFAULT) { width = wHint; } if (hHint != SWT.DEFAULT) { height = hHint; } return new Point(width, height); } @Override public void setBounds(Rectangle bounds) { super.setBounds(bounds); // [if] Recalculate the sub widgets bounds important for using it in FillLayout where the // DateTime#computeSize() is not call. computeSubWidgetsBounds(); } private Point computeCellSize() { int width = MIN_CELL_WIDTH; int height = MIN_CELL_HEIGHT; for (int i = 0; i < weekdayShortNames.length; i++) { Point nameSize = TextSizeUtil.stringExtent(getFont(), weekdayShortNames[i]); width = Math.max(width, nameSize.x + CELL_PADDING); height = Math.max(height, nameSize.y + CELL_PADDING); } return new Point(width, height); } private Point computeSubWidgetsBounds() { Font font = getFont(); int width = 0, height = 0; BoxDimensions padding = getFieldPadding(); BoxDimensions border = getBorder(); if ((style & SWT.CALENDAR) != 0) { width = cellSize.x * 8 + border.left + border.right; height = cellSize.y * 7 + CALENDAR_HEADER_HEIGHT + border.top + border.bottom; } else if ((style & SWT.DATE) != 0) { Point prefSize = new Point(0, 0); if (datePattern.equals("MDY")) { prefSize = computeMDYBounds(); } else if (datePattern.equals("DMY")) { prefSize = computeDMYBounds(); } else { if ((style & SWT.MEDIUM) != 0) { prefSize = computeYMDBounds(); } else { prefSize = computeMDYBounds(); } } // Overall default widget size width = prefSize.x + border.left + border.right; height = prefSize.y + border.top + border.bottom; } else if ((style & SWT.TIME) != 0) { // Hours text field hoursTextFieldBounds = new Rectangle(padding.left, padding.top, 0, 0); hoursTextFieldBounds.width = TextSizeUtil.stringExtent(font, "88").x + H_PADDING; hoursTextFieldBounds.height = TextSizeUtil.stringExtent(font, "88").y + V_PADDING; // Hours minutes separator separator3Bounds = new Rectangle(0, padding.top, 0, 0); separator3Bounds.x = hoursTextFieldBounds.x + hoursTextFieldBounds.width; separator3Bounds.width = TextSizeUtil.stringExtent(font, ":").x; separator3Bounds.height = hoursTextFieldBounds.height; // Minutes text field minutesTextFieldBounds = new Rectangle(0, padding.top, 0, 0); minutesTextFieldBounds.x = separator3Bounds.x + separator3Bounds.width; minutesTextFieldBounds.width = hoursTextFieldBounds.width; minutesTextFieldBounds.height = hoursTextFieldBounds.height; // Minutes seconds separator separator4Bounds = new Rectangle(0, padding.top, 0, 0); separator4Bounds.x = minutesTextFieldBounds.x + minutesTextFieldBounds.width; separator4Bounds.width = separator3Bounds.width; separator4Bounds.height = hoursTextFieldBounds.height; // Seconds text field secondsTextFieldBounds = new Rectangle(0, padding.top, 0, 0); secondsTextFieldBounds.x = separator4Bounds.x + separator4Bounds.width; secondsTextFieldBounds.width = hoursTextFieldBounds.width; secondsTextFieldBounds.height = hoursTextFieldBounds.height; // The spinner bounds spinnerBounds = new Rectangle(0, 0, 0, 0); spinnerBounds.x = minutesTextFieldBounds.x + minutesTextFieldBounds.width + padding.left; if ((style & SWT.MEDIUM) != 0 || (style & SWT.LONG) != 0) { spinnerBounds.x = secondsTextFieldBounds.x + secondsTextFieldBounds.width + padding.left; } spinnerBounds.width = getSpinnerButtonWidth(); spinnerBounds.height = hoursTextFieldBounds.height + padding.top + padding.bottom; // Overall default widget size width = spinnerBounds.x + spinnerBounds.width + border.left + border.right; height = spinnerBounds.height + border.top + border.bottom; } adjustButtonsBounds(); return new Point(width, height); } private Point computeMDYBounds() { Font font = getFont(); BoxDimensions padding = getFieldPadding(); // The weekday text field bounds weekdayTextFieldBounds = new Rectangle(padding.left, padding.top, 0, 0); if ((style & SWT.LONG) != 0) { weekdayTextFieldBounds.width = getMaxWidth(weekdayNames) + H_PADDING + 2; } weekdayTextFieldBounds.height = TextSizeUtil.stringExtent(font, weekdayNames[1]).y + V_PADDING; // The weekday month separator bounds separator0Bounds = new Rectangle(0, padding.top, 0, 0); separator0Bounds.x = weekdayTextFieldBounds.x + weekdayTextFieldBounds.width; if ((style & SWT.LONG) != 0) { separator0Bounds.width = TextSizeUtil.stringExtent(font, ",").x; } separator0Bounds.height = weekdayTextFieldBounds.height; // The month text field bounds monthTextFieldBounds = new Rectangle(0, padding.top, 0, 0); monthTextFieldBounds.x = separator0Bounds.x + separator0Bounds.width; if ((style & SWT.MEDIUM) != 0) { monthTextFieldBounds.width = TextSizeUtil.stringExtent(font, "88").x + H_PADDING; } else { monthTextFieldBounds.width = getMaxWidth(monthNames) + H_PADDING + 2; } monthTextFieldBounds.height = weekdayTextFieldBounds.height; // The month date separator bounds separator1Bounds = new Rectangle(0, padding.top, 0, 0); separator1Bounds.x = monthTextFieldBounds.x + monthTextFieldBounds.width; if ((style & SWT.MEDIUM) != 0) { separator1Bounds.width = TextSizeUtil.stringExtent(font, dateSeparator).x; } separator1Bounds.height = weekdayTextFieldBounds.height; // The date text field bounds dayTextFieldBounds = new Rectangle(0, padding.top, 0, 0); dayTextFieldBounds.x = separator1Bounds.x + separator1Bounds.width; if ((style & SWT.SHORT) == 0) { dayTextFieldBounds.width = TextSizeUtil.stringExtent(font, "88").x + H_PADDING; } dayTextFieldBounds.height = weekdayTextFieldBounds.height; // The date year separator bounds separator2Bounds = new Rectangle(0, padding.top, 0, 0); separator2Bounds.x = dayTextFieldBounds.x + dayTextFieldBounds.width; if ((style & SWT.MEDIUM) != 0) { separator2Bounds.width = TextSizeUtil.stringExtent(font, dateSeparator).x; } else { separator2Bounds.width = TextSizeUtil.stringExtent(font, ",").x; } separator2Bounds.height = weekdayTextFieldBounds.height; // The year text field bounds yearTextFieldBounds = new Rectangle(0, padding.top, 0, 0); yearTextFieldBounds.x = separator2Bounds.x + separator2Bounds.width; yearTextFieldBounds.width = TextSizeUtil.stringExtent(font, "8888").x + H_PADDING; yearTextFieldBounds.height = weekdayTextFieldBounds.height; // The spinner bounds spinnerBounds = new Rectangle(0, 0, 0, 0); spinnerBounds.x = yearTextFieldBounds.x + yearTextFieldBounds.width + padding.left; spinnerBounds.width = getSpinnerButtonWidth(); spinnerBounds.height = weekdayTextFieldBounds.height + padding.top + padding.bottom; // The drop-down button bounds dropDownButtonBounds = new Rectangle(spinnerBounds.x, spinnerBounds.y, getDropDownButtonWidth(), spinnerBounds.height); // Overall default widget size int width = spinnerBounds.x; int height = spinnerBounds.height; if ((style & SWT.DROP_DOWN) == 0) { width += spinnerBounds.width; } else { width += dropDownButtonBounds.width; } return new Point(width, height); } private Point computeDMYBounds() { Font font = getFont(); BoxDimensions padding = getFieldPadding(); // The weekday text field bounds weekdayTextFieldBounds = new Rectangle(padding.left, padding.top, 0, 0); if ((style & SWT.LONG) != 0) { weekdayTextFieldBounds.width = getMaxWidth(weekdayNames) + H_PADDING + 2; } weekdayTextFieldBounds.height = TextSizeUtil.stringExtent(font, weekdayNames[1]).y + V_PADDING; // The weekday day separator bounds separator0Bounds = new Rectangle(0, padding.top, 0, 0); separator0Bounds.x = weekdayTextFieldBounds.x + weekdayTextFieldBounds.width; if ((style & SWT.LONG) != 0) { separator0Bounds.width = TextSizeUtil.stringExtent(font, ",").x; } separator0Bounds.height = weekdayTextFieldBounds.height; // The day text field bounds dayTextFieldBounds = new Rectangle(0, padding.top, 0, 0); dayTextFieldBounds.x = separator0Bounds.x + separator0Bounds.width; if ((style & SWT.SHORT) == 0) { dayTextFieldBounds.width = TextSizeUtil.stringExtent(font, "88").x + H_PADDING; } dayTextFieldBounds.height = weekdayTextFieldBounds.height; // The day month separator bounds separator1Bounds = new Rectangle(0, padding.top, 0, 0); separator1Bounds.x = dayTextFieldBounds.x + dayTextFieldBounds.width; if ((style & SWT.MEDIUM) != 0) { separator1Bounds.width = TextSizeUtil.stringExtent(font, dateSeparator).x; } separator1Bounds.height = weekdayTextFieldBounds.height; // The month text field bounds monthTextFieldBounds = new Rectangle(0, padding.top, 0, 0); monthTextFieldBounds.x = separator1Bounds.x + separator1Bounds.width; if ((style & SWT.MEDIUM) != 0) { monthTextFieldBounds.width = TextSizeUtil.stringExtent(font, "88").x + H_PADDING; } else { monthTextFieldBounds.width = getMaxWidth(monthNames) + H_PADDING + 2; } monthTextFieldBounds.height = weekdayTextFieldBounds.height; // The month year separator bounds separator2Bounds = new Rectangle(0, padding.top, 0, 0); separator2Bounds.x = monthTextFieldBounds.x + monthTextFieldBounds.width; if ((style & SWT.MEDIUM) != 0) { separator2Bounds.width = TextSizeUtil.stringExtent(font, dateSeparator).x; } else { separator2Bounds.width = TextSizeUtil.stringExtent(font, ",").x; } separator2Bounds.height = weekdayTextFieldBounds.height; // The year text field bounds yearTextFieldBounds = new Rectangle(0, padding.top, 0, 0); yearTextFieldBounds.x = separator2Bounds.x + separator2Bounds.width; yearTextFieldBounds.width = TextSizeUtil.stringExtent(font, "8888").x + H_PADDING; yearTextFieldBounds.height = weekdayTextFieldBounds.height; // The spinner bounds spinnerBounds = new Rectangle(0, 0, 0, 0); spinnerBounds.x = yearTextFieldBounds.x + yearTextFieldBounds.width + padding.left; spinnerBounds.width = getSpinnerButtonWidth(); spinnerBounds.height = weekdayTextFieldBounds.height + padding.top + padding.bottom; // The drop-down button bounds dropDownButtonBounds = new Rectangle(spinnerBounds.x, spinnerBounds.y, getDropDownButtonWidth(), spinnerBounds.height); // Overall default widget size int width = spinnerBounds.x; int height = spinnerBounds.height; if ((style & SWT.DROP_DOWN) == 0) { width += spinnerBounds.width; } else { width += dropDownButtonBounds.width; } return new Point(width, height); } private Point computeYMDBounds() { Font font = getFont(); BoxDimensions padding = getFieldPadding(); // The weekday text field bounds weekdayTextFieldBounds = new Rectangle(padding.left, padding.top, 0, 0); if ((style & SWT.LONG) != 0) { weekdayTextFieldBounds.width = getMaxWidth(weekdayNames) + H_PADDING + 2; } weekdayTextFieldBounds.height = TextSizeUtil.stringExtent(font, weekdayNames[1]).y + V_PADDING; // The weekday day separator bounds separator0Bounds = new Rectangle(0, padding.top, 0, 0); separator0Bounds.x = weekdayTextFieldBounds.x + weekdayTextFieldBounds.width; if ((style & SWT.LONG) != 0) { separator0Bounds.width = TextSizeUtil.stringExtent(font, ",").x; } separator0Bounds.height = weekdayTextFieldBounds.height; // The year text field bounds yearTextFieldBounds = new Rectangle(0, padding.top, 0, 0); yearTextFieldBounds.x = separator0Bounds.x + separator0Bounds.width; yearTextFieldBounds.width = TextSizeUtil.stringExtent(font, "8888").x + H_PADDING; yearTextFieldBounds.height = weekdayTextFieldBounds.height; // The year month separator bounds separator1Bounds = new Rectangle(0, padding.top, 0, 0); separator1Bounds.x = yearTextFieldBounds.x + yearTextFieldBounds.width; if ((style & SWT.MEDIUM) != 0) { separator1Bounds.width = TextSizeUtil.stringExtent(font, dateSeparator).x; } // The month text field bounds monthTextFieldBounds = new Rectangle(0, padding.top, 0, 0); monthTextFieldBounds.x = separator1Bounds.x + separator1Bounds.width; if ((style & SWT.MEDIUM) != 0) { monthTextFieldBounds.width = TextSizeUtil.stringExtent(font, "88").x + H_PADDING; } else { monthTextFieldBounds.width = getMaxWidth(monthNames) + H_PADDING + 2; } monthTextFieldBounds.height = weekdayTextFieldBounds.height; // The month day separator bounds separator2Bounds = new Rectangle(0, padding.top, 0, 0); separator2Bounds.x = monthTextFieldBounds.x + monthTextFieldBounds.width; if ((style & SWT.MEDIUM) != 0) { separator2Bounds.width = TextSizeUtil.stringExtent(font, dateSeparator).x; } else { separator2Bounds.width = TextSizeUtil.stringExtent(font, ",").x; } separator2Bounds.height = weekdayTextFieldBounds.height; // The day text field bounds dayTextFieldBounds = new Rectangle(0, padding.top, 0, 0); dayTextFieldBounds.x = separator2Bounds.x + separator2Bounds.width; if ((style & SWT.SHORT) == 0) { dayTextFieldBounds.width = TextSizeUtil.stringExtent(font, "88").x + H_PADDING; } dayTextFieldBounds.height = weekdayTextFieldBounds.height; separator1Bounds.height = weekdayTextFieldBounds.height; // The spinner bounds spinnerBounds = new Rectangle(0, 0, 0, 0); spinnerBounds.x = dayTextFieldBounds.x + dayTextFieldBounds.width + padding.left; spinnerBounds.width = getSpinnerButtonWidth(); spinnerBounds.height = weekdayTextFieldBounds.height + padding.top + padding.bottom; // The drop-down button bounds dropDownButtonBounds = new Rectangle(spinnerBounds.x, spinnerBounds.y, getDropDownButtonWidth(), spinnerBounds.height); // Overall default widget size int width = spinnerBounds.x; int height = spinnerBounds.height; if ((style & SWT.DROP_DOWN) == 0) { width += spinnerBounds.width; } else { width += dropDownButtonBounds.width; } return new Point(width, height); } private void adjustButtonsBounds() { Point size = getSize(); BoxDimensions border = getBorder(); if ((style & SWT.DROP_DOWN) != 0) { dropDownButtonBounds.x = size.x - (border.left + border.right) - dropDownButtonBounds.width; dropDownButtonBounds.height = size.y - (border.top + border.bottom); } else if ((style & SWT.DATE) != 0 || (style & SWT.TIME) != 0) { spinnerBounds.x = size.x - (border.left + border.right) - spinnerBounds.width; spinnerBounds.height = size.y - (border.top + border.bottom); } } private int getSpinnerButtonWidth() { return getDateTimeThemeAdapter().getSpinnerButtonWidth(this); } private DateTimeThemeAdapter getDateTimeThemeAdapter() { return (DateTimeThemeAdapter) getAdapter(ThemeAdapter.class); } private int getDropDownButtonWidth() { return getDateTimeThemeAdapter().getDropDownButtonWidth(this); } private BoxDimensions getFieldPadding() { return getDateTimeThemeAdapter().getFieldPadding(this); } @Override String getNameText() { return "DateTime"; } private static int getDaysInMonth(int month, int year) { GregorianCalendar cal = new GregorianCalendar(year, month, 1); return cal.getActualMaximum(Calendar.DAY_OF_MONTH); } private int getMaxWidth(String[] strings) { Font font = getFont(); int result = 0; for (int i = 0; i < strings.length; i++) { int width = TextSizeUtil.stringExtent(font, strings[i]).x; result = Math.max(result, width); } return result; } private static String getDateSeparator() { DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, RWT.getLocale()); String datePattern = ((SimpleDateFormat) dateFormat).toPattern(); String result = ""; int index = 0; while (Character.isLetter(datePattern.charAt(index))) { index++; } result = Character.toString(datePattern.charAt(index)); return result; } private static String getDatePattern(String dateSeparator) { DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, RWT.getLocale()); String datePattern = ((SimpleDateFormat) format).toPattern(); String result = ""; StringTokenizer tokenizer = new StringTokenizer(datePattern, dateSeparator); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); result += Character.toString(token.charAt(0)); } return result.toUpperCase(); } private static boolean checkDate(int year, int month, int day) { int daysInMonth = getDaysInMonth(month, year); boolean validYear = (year >= 1752 && year <= 9999 && day <= daysInMonth); boolean validMonth = (month >= 0 && month <= 11 && day <= daysInMonth); boolean validDay = (day >= 1 && day <= daysInMonth); return validYear && validMonth && validDay; } private static boolean checkTime(int hours, int minutes, int seconds) { boolean validHours = (hours >= 0 && hours <= 23); boolean validMinutes = (minutes >= 0 && minutes <= 59); boolean validSeconds = (seconds >= 0 && seconds <= 59); return validHours && validMinutes && validSeconds; } static int checkStyle(int value) { /* * Even though it is legal to create this widget with scroll bars, they * serve no useful purpose because they do not automatically scroll the * widget's client area. The fix is to clear the SWT style. */ int style = value; style &= ~(SWT.H_SCROLL | SWT.V_SCROLL); style = checkBits(style, SWT.DATE, SWT.TIME, SWT.CALENDAR, 0, 0, 0); style = checkBits(style, SWT.MEDIUM, SWT.SHORT, SWT.LONG, 0, 0, 0); if ((style & SWT.DATE) == 0) { style &= ~SWT.DROP_DOWN; } return style; } private void applyLimits() { if (!ignoreLimits) { if (maximum != null && rightNow.getTimeInMillis() > maximum.getTime()) { rightNow.setTime(maximum); } if (minimum != null && rightNow.getTimeInMillis() < minimum.getTime()) { rightNow.setTime(minimum); } } } }