0001: /*
0002: *
0003: *
0004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License version
0009: * 2 only, as published by the Free Software Foundation.
0010: *
0011: * This program is distributed in the hope that it will be useful, but
0012: * WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * General Public License version 2 for more details (a copy is
0015: * included at /legal/license.txt).
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * version 2 along with this work; if not, write to the Free Software
0019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA
0021: *
0022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023: * Clara, CA 95054 or visit www.sun.com if you need additional
0024: * information or have any questions.
0025: */
0026:
0027: package javax.microedition.lcdui;
0028:
0029: import java.util.Date;
0030: import java.util.Calendar;
0031:
0032: import com.sun.midp.lcdui.*;
0033: import com.sun.midp.i18n.Resource;
0034: import com.sun.midp.i18n.ResourceConstants;
0035: import com.sun.midp.configurator.Constants;
0036: import com.sun.midp.chameleon.skins.DateEditorSkin;
0037: import com.sun.midp.chameleon.skins.ScreenSkin;
0038: import com.sun.midp.chameleon.layers.PopupLayer;
0039:
0040: import javax.microedition.lcdui.game.Sprite;
0041:
0042: import com.sun.midp.log.Logging;
0043: import com.sun.midp.log.LogChannels;
0044:
0045: /**
0046: * A utility class for editing date/time components for a DateField.
0047: */
0048: class DateEditor extends PopupLayer implements CommandListener {
0049:
0050: /**
0051: * Create a new DateEditor layer.
0052: *
0053: * @param lf The DateFieldLFImpl that triggered this date editor
0054: */
0055: public DateEditor(DateFieldLFImpl lf) {
0056: super (DateEditorSkin.IMAGE_BG, DateEditorSkin.COLOR_BG);
0057: this .lf = lf;
0058: }
0059:
0060: /**
0061: * Initialize Date editor
0062: */
0063: public void init() {
0064: mode = lf.df.mode;
0065: initialized = lf.df.initialized;
0066: editDate = Calendar.getInstance();
0067: Date date = lf.df.getDate();
0068: if (date != null) {
0069: editDate.setTime(date);
0070: }
0071:
0072: selectedDate = hilightedDate = editDate.get(Calendar.DATE);
0073:
0074: if (editDate.get(Calendar.AM_PM) == Calendar.AM) {
0075: amSelected = true;
0076: amHilighted = true;
0077: }
0078:
0079: switch (mode) {
0080: case DateField.DATE:
0081: focusOn = MONTH_POPUP;
0082: populateDateComponents();
0083: break;
0084: case DateField.TIME:
0085: focusOn = HOURS_POPUP;
0086: timeComponentsOffset = 0;
0087: populateTimeComponents();
0088: break;
0089: case DateField.DATE_TIME:
0090: focusOn = MONTH_POPUP;
0091: timeComponentsOffset = 98;
0092: populateDateComponents();
0093: populateTimeComponents();
0094: break;
0095: default:
0096: Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
0097: "DateEditor constructor, mode=" + mode);
0098: break;
0099: }
0100:
0101: // initialize the bounds(used for pointer input) with invariant
0102: // relative coordinate of the uppper left corner and with invalid
0103: // width, height values dependent on skin images
0104: month_bounds = new int[] { (mode == DateField.DATE) ? 10 : 4,
0105: 5, 0, 0 };
0106: year_bounds = new int[] { month_bounds[X] + 45,
0107: month_bounds[Y], 0, 0 };
0108: hours_bounds = new int[] {
0109: timeComponentsOffset
0110: + ((mode == DateField.TIME) ? 17 : 0),
0111: ((mode == DateField.TIME) ? 10 : 5), 0, 0 };
0112: minutes_bounds = new int[] { hours_bounds[X] + 34,
0113: hours_bounds[Y], 0, 0 };
0114: calendar_bounds = new int[] {
0115: (mode == DateField.DATE) ? 10 : 4, 29, 0, 0 };
0116: ampm_bounds = new int[] {
0117: timeComponentsOffset
0118: + ((mode == DateField.TIME) ? 15 : 0), 29, 0, 0 };
0119:
0120: setCommands(commands);
0121: setCommandListener(this );
0122: sizeChanged = true;
0123: isIitialized = true;
0124: }
0125:
0126: /**
0127: * Sets the location of the popup layer.
0128: *
0129: * @param x the x-coordinate of the popup layer location
0130: * @param y the y-coordinate of the popup layer location
0131: */
0132: public void setLocation(int x, int y) {
0133: if (!isIitialized) {
0134: init();
0135: }
0136: bounds[X] = x;
0137: bounds[Y] = y;
0138: bounds[H] = DateEditorSkin.HEIGHT;
0139:
0140: switch (mode) {
0141: case DateField.DATE:
0142: bounds[W] = DateEditorSkin.WIDTH_DATE;
0143: break;
0144: case DateField.TIME:
0145: bounds[W] = DateEditorSkin.WIDTH_TIME;
0146: break;
0147: case DateField.DATE_TIME:
0148: bounds[W] = DateEditorSkin.WIDTH_DATETIME;
0149: break;
0150: default:
0151: Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
0152: "DateEditor.setLocation(), mode=" + mode);
0153: break;
0154: }
0155:
0156: if (bounds[X] + bounds[W] > ScreenSkin.WIDTH) {
0157: bounds[X] = ScreenSkin.WIDTH - bounds[W];
0158: } else if (bounds[X] < 0) {
0159: bounds[X] = 0;
0160: }
0161:
0162: if (sizeChanged) {
0163: callSizeChanged();
0164: }
0165: sizeChanged = false;
0166: }
0167:
0168: /**
0169: * Paints the background of the date editor layer.
0170: *
0171: * @param g The graphics context to paint to
0172: */
0173:
0174: public void paintBackground(Graphics g) {
0175: super .paintBackground(g);
0176: if (DateEditorSkin.IMAGE_BG == null) {
0177: g.setColor(DateEditorSkin.COLOR_BORDER);
0178: g.drawRect(0, 0, bounds[W] - 1, bounds[H] - 1);
0179: g.setColor(0);
0180: }
0181: }
0182:
0183: /**
0184: * Paints the body (open state) of the date editor layer.
0185: *
0186: * @param g The graphics context to paint to
0187: */
0188: public void paintBody(Graphics g) {
0189: setDayOffset();
0190: lastDay = daysInMonth(editDate.get(Calendar.MONTH), editDate
0191: .get(Calendar.YEAR));
0192:
0193: nextX = 0;
0194: nextY = 0;
0195:
0196: switch (mode) {
0197: case DateField.DATE:
0198: drawDateComponents(g);
0199: break;
0200: case DateField.TIME:
0201: drawTimeComponents(g);
0202: break;
0203: case DateField.DATE_TIME:
0204: drawDateComponents(g);
0205: drawTimeComponents(g);
0206: break;
0207: default:
0208: Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
0209: "DateEditor.paintBody(), mode=" + mode);
0210: break;
0211: }
0212: }
0213:
0214: /**
0215: * Handles key input to the popup layer.
0216: *
0217: * @param type the type of this key event (pressed, released)
0218: * @param code the code of this key event
0219: * @return true always, since popupLayers swallow all key events
0220: */
0221: public boolean keyInput(int type, int code) {
0222: if (type == EventConstants.PRESSED && lf != null) {
0223: if (code == Constants.KEYCODE_SELECT) {
0224: selectFired();
0225: requestRepaint();
0226: } else {
0227: traverseEditor(code);
0228: requestRepaint();
0229: }
0230: }
0231: // PopupLayers always swallow all key events
0232: return (code != EventConstants.SOFT_BUTTON1 && code != EventConstants.SOFT_BUTTON2);
0233: }
0234:
0235: /**
0236: * Handles pointer input to the popup layer.
0237: *
0238: * @param type the type of this key event (pressed, released)
0239: * @param x x coordinate of pointer
0240: * @param y y coordinate of pointer
0241: * @return true always, since popupLayers swallow all pointer events
0242: */
0243: public boolean pointerInput(int type, int x, int y) {
0244: boolean consume = true;
0245: switch (type) {
0246: case EventConstants.PRESSED:
0247: itemIndexWhenPressed = itemIndexAtPointerPosition(x, y);
0248: switch (itemIndexWhenPressed) {
0249: case AM_PM:
0250: amHilighted = (x - ampm_bounds[X] < 35);
0251: break;
0252: case CALENDAR:
0253: pressedDate = getDateAtPointerPosition(x, y);
0254: if (pressedDate > 0) {
0255: hilightedDate = pressedDate;
0256: }
0257: break;
0258: case PRESS_OUT_OF_BOUNDS:
0259: commandAction(cancel, lf.df.owner);
0260: consume = false;
0261: break;
0262: }
0263: if (itemIndexWhenPressed > 0
0264: && focusOn != itemIndexWhenPressed) {
0265: DEPopupLayer popup = null;
0266: switch (focusOn) {
0267: case MONTH_POPUP:
0268: popup = monthPopup;
0269: break;
0270: case YEAR_POPUP:
0271: popup = yearPopup;
0272: break;
0273: case HOURS_POPUP:
0274: popup = hoursPopup;
0275: break;
0276: case MINUTES_POPUP:
0277: popup = minutesPopup;
0278: break;
0279: default:
0280: break;
0281: }
0282: if (popup != null && popup.open) {
0283: popup.hide();
0284: }
0285:
0286: focusOn = itemIndexWhenPressed;
0287: requestRepaint();
0288: }
0289: break;
0290: case EventConstants.RELEASED:
0291: int itemIndexWhenReleased = itemIndexAtPointerPosition(x, y);
0292: if (itemIndexWhenPressed == itemIndexWhenReleased) {
0293: if (itemIndexWhenPressed > 0) {
0294: if ((itemIndexWhenPressed == AM_PM && amHilighted == (x
0295: - ampm_bounds[X] < 35))
0296: || (itemIndexWhenPressed == CALENDAR
0297: && pressedDate == getDateAtPointerPosition(
0298: x, y) && pressedDate > 0)
0299: || (itemIndexWhenPressed != AM_PM && itemIndexWhenPressed != CALENDAR)) {
0300: selectFired();
0301: if (itemIndexWhenPressed > 0) {
0302: focusOn = itemIndexWhenPressed;
0303: requestRepaint();
0304: }
0305: }
0306: }
0307: }
0308: if (itemIndexWhenReleased == PRESS_OUT_OF_BOUNDS) {
0309: consume = false;
0310: }
0311:
0312: itemIndexWhenPressed = PRESS_OUT_OF_BOUNDS; // remember to reset the variables
0313: pressedDate = 0;
0314: break;
0315: }
0316: return consume;
0317: }
0318:
0319: /**
0320: * Helper function to determine the date index at the x,y position
0321: *
0322: * @param x pointer x coordinate
0323: * @param y pointer y coordinate
0324: *
0325: * @return 0 (invalid value) or 1 - lastDay(valid value)
0326: * depends on the pointer position.
0327: */
0328: private int getDateAtPointerPosition(int x, int y) {
0329: int dateAt = 0;
0330: int transX = x - calendar_bounds[X];
0331: int transY = y - calendar_bounds[Y];
0332: int o = DateEditorSkin.IMAGE_CAL_BG.getWidth() / 7;
0333: int rowH = 11;
0334: //variable o, rowH, h is same as in paintCalendar()
0335: int h = DateEditorSkin.IMAGE_DATES.getHeight() / 31;
0336:
0337: if (transX >= 0 && transX <= calendar_bounds[W] && transY >= 0
0338: && transY <= calendar_bounds[H] && transY >= h + 3) {
0339: int row = (transY - h - 3) / rowH;
0340: int col = (transX - 1) / o;
0341: int row_Day1 = 0;
0342: int col_Day1 = dayOffset - 1; //index from 0
0343:
0344: if (row != row_Day1 || col >= col_Day1) {
0345: //index from 1
0346: int dateAtPointer = (row - row_Day1) * 7
0347: + (col - col_Day1) + 1;
0348: if (dateAtPointer <= lastDay) {
0349: dateAt = dateAtPointer;
0350: }
0351: }
0352: }
0353: return dateAt;
0354: }
0355:
0356: /**
0357: * Helper function to determine the focusable area Index at the x,y position
0358: *
0359: * @param x x pointer coordinate
0360: * @param y y pointer coordinate
0361: * @return focusable area index, can be PRESS_OUT_OF_BOUNDS,
0362: * 0, MONTH_POPUP, YEAR_POPUP, HOURS_POPUP, MINUTES_POPUP,
0363: * CALENDAR, or AM_PM, depends on the pointer position.
0364: */
0365: private int itemIndexAtPointerPosition(int x, int y) {
0366: int area = PRESS_OUT_OF_BOUNDS;
0367: if (containsPoint(x + this .bounds[X], y + this .bounds[Y])) {
0368: if (x >= month_bounds[X]
0369: && x < month_bounds[X] + month_bounds[W]
0370: && y >= month_bounds[Y]
0371: && y < month_bounds[Y] + month_bounds[H]) {
0372: area = MONTH_POPUP;
0373: } else if (x >= year_bounds[X]
0374: && x < year_bounds[X] + year_bounds[W]
0375: && y >= year_bounds[Y]
0376: && y < year_bounds[Y] + year_bounds[H]) {
0377: area = YEAR_POPUP;
0378: } else if (x >= hours_bounds[X]
0379: && x < hours_bounds[X] + hours_bounds[W]
0380: && y >= hours_bounds[Y]
0381: && y < hours_bounds[Y] + hours_bounds[H]) {
0382: area = HOURS_POPUP;
0383: } else if (x > minutes_bounds[X]
0384: && x < minutes_bounds[X] + minutes_bounds[W]
0385: && y >= minutes_bounds[Y]
0386: && y < minutes_bounds[Y] + minutes_bounds[H]) {
0387: area = MINUTES_POPUP;
0388: } else if (x >= calendar_bounds[X]
0389: && x < calendar_bounds[X] + calendar_bounds[W]
0390: && y >= calendar_bounds[Y]
0391: && y < calendar_bounds[Y] + calendar_bounds[H]) {
0392: area = CALENDAR;
0393: } else if (x >= ampm_bounds[X]
0394: && x < ampm_bounds[X] + ampm_bounds[W]
0395: && y >= ampm_bounds[Y]
0396: && y < ampm_bounds[Y] + ampm_bounds[H]) {
0397: area = AM_PM;
0398: } else {
0399: area = 0;
0400: }
0401: }
0402: return area; // Value 0: invaliad but inside one focusable area
0403: }
0404:
0405: /**
0406: * Handle a command action.
0407: *
0408: * @param cmd The Command to handle
0409: * @param s The Displayable with the Command
0410: */
0411: public void commandAction(Command cmd, Displayable s) {
0412:
0413: lf.uCallKeyPressed(Constants.KEYCODE_SELECT);
0414:
0415: if (cmd == set) {
0416: if (mode == DateField.TIME) {
0417: lf.saveDate(new Date(editDate.getTime().getTime()
0418: % (24 * 60 * 60 * 1000)));
0419: } else {
0420: lf.saveDate(editDate.getTime());
0421: }
0422: }
0423:
0424: // SYNC NOTE: Move the call to the application's
0425: // ItemStateListener outside LCDUILock
0426: Form form = null;
0427: synchronized (Display.LCDUILock) {
0428: if (lf.df.owner instanceof Form) {
0429: form = (Form) lf.df.owner;
0430: }
0431: }
0432:
0433: if (form != null) {
0434: form.uCallItemStateChanged(lf.df);
0435: }
0436: }
0437:
0438: // ********** package private *********** //
0439: /**
0440: * Show the date editor popup.
0441: */
0442: void show() {
0443:
0444: // refresh the edit date to value stored in DateField each time
0445: editDate = Calendar.getInstance();
0446: Date date = lf.df.getDate();
0447: if (date != null) {
0448: editDate.setTime(date);
0449: }
0450:
0451: selectedDate = hilightedDate = editDate.get(Calendar.DATE);
0452:
0453: amSelected = amHilighted = false;
0454: if (editDate.get(Calendar.AM_PM) == Calendar.AM) {
0455: amSelected = true;
0456: amHilighted = true;
0457: }
0458:
0459: switch (mode) {
0460: case DateField.DATE:
0461: case DateField.DATE_TIME:
0462: focusOn = MONTH_POPUP;
0463: break;
0464: case DateField.TIME:
0465: focusOn = HOURS_POPUP;
0466: break;
0467: default:
0468: Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
0469: "DateEditor.show(), mode=" + mode);
0470: break;
0471: }
0472:
0473: popUpOpen = true;
0474:
0475: ScreenLFImpl sLF = (ScreenLFImpl) lf.df.owner.getLF();
0476: sLF.lGetCurrentDisplay().showPopup(this );
0477: }
0478:
0479: /**
0480: * Hide all sub-popups triggered by this date editor.
0481: */
0482: void hideAllPopups() {
0483: if (monthPopup != null)
0484: monthPopup.hide();
0485: if (yearPopup != null)
0486: yearPopup.hide();
0487: if (hoursPopup != null)
0488: hoursPopup.hide();
0489: if (minutesPopup != null)
0490: minutesPopup.hide();
0491: popUpOpen = false;
0492: }
0493:
0494: // *********** private ************ //
0495: /**
0496: * Populate the date components.
0497: */
0498: protected void populateDateComponents() {
0499: // populate MONTHS[]
0500: MONTHS = new String[DateFieldLFImpl.MONTH_NAMES.length];
0501: for (int i = 0; i < DateFieldLFImpl.MONTH_NAMES.length; i++) {
0502: MONTHS[i] = DateFieldLFImpl.MONTH_NAMES[i].substring(0, 3);
0503: }
0504: monthPopup = new DEPopupLayer(this , MONTHS, editDate
0505: .get(Calendar.MONTH), true);
0506:
0507: // populate YEARS[]
0508: int selectedIndex = createYearStrings(editDate
0509: .get(Calendar.YEAR) - 10);
0510: yearPopup = new DEPopupLayer(this , YEARS, selectedIndex, false);
0511: }
0512:
0513: /**
0514: * Recreates years string given a start year.
0515: * @param startYear the first year to be added to the YEARS array
0516: * @return selected year in the newly created array
0517: */
0518: protected int createYearStrings(int startYear) {
0519: int selectedIndex = 0;
0520: int year = startYear;
0521: YEARS = new String[22];
0522: YEARS[0] = Resource
0523: .getString(ResourceConstants.LCDUI_DF_YEAR_BEFORE);
0524: YEARS[21] = Resource
0525: .getString(ResourceConstants.LCDUI_DF_YEAR_AFTER);
0526: for (int i = 1; i < 21; i++) {
0527: if (year == editDate.get(Calendar.YEAR)) {
0528: selectedIndex = i;
0529: }
0530: YEARS[i] = Integer.toString(year++);
0531: }
0532: return selectedIndex;
0533: }
0534:
0535: /**
0536: * Populate the time components.
0537: */
0538: protected void populateTimeComponents() {
0539: int selectedIndex = 0;
0540:
0541: // populate HOURS[]
0542: String[] hours;
0543: if (lf.CLOCK_USES_AM_PM) {
0544: HOURS = new int[12];
0545: hours = new String[12];
0546:
0547: selectedIndex = editDate.get(Calendar.HOUR) - 1;
0548: if (selectedIndex < 0) {
0549: selectedIndex = 11;
0550: }
0551:
0552: for (int i = 0; i < 12; i++) {
0553: HOURS[i] = i + 1;
0554: hours[i] = Integer.toString(i + 1);
0555: }
0556: } else {
0557: HOURS = new int[24];
0558: hours = new String[24];
0559: selectedIndex = editDate.get(Calendar.HOUR_OF_DAY);
0560: for (int i = 0; i < 24; i++) {
0561: HOURS[i] = i;
0562: hours[i] = Integer.toString(i);
0563: }
0564: }
0565: hoursPopup = new DEPopupLayer(this , hours, selectedIndex, true);
0566:
0567: // populate MINUTES[]
0568: selectedIndex = 0;
0569: MINUTES = new int[60];
0570: String[] minutes = new String[60];
0571: int minute = editDate.get(Calendar.MINUTE);
0572: for (int i = 0; i < 60; i++) {
0573: if (i == minute) {
0574: selectedIndex = i;
0575: }
0576: MINUTES[i] = i;
0577: minutes[i] = Integer.toString(i);
0578: }
0579: minutesPopup = new DEPopupLayer(this , minutes, selectedIndex,
0580: true);
0581: }
0582:
0583: /**
0584: * Set popup location and bounds
0585: *
0586: * @param popup popup to relocate
0587: * @param image background image of popup
0588: * @param bounds relative bounds of the popup layer
0589: */
0590: protected void setPopupLocation(DEPopupLayer popup, Image image,
0591: int[] bounds) {
0592:
0593: int x = this .bounds[X] + bounds[X];
0594: int y = this .bounds[Y] + bounds[Y];
0595: int w = image.getWidth();
0596: int h = image.getHeight();
0597: popup.setElementSize(w - 4, DateEditorSkin.FONT_POPUPS
0598: .getHeight());
0599: popup.setBounds(x, y + h, w, DateEditorSkin.HEIGHT_POPUPS);
0600: popup.updateScrollIndicator();
0601: bounds[W] = w;
0602: bounds[H] = h;
0603: }
0604:
0605: /**
0606: * Set month popup location using upper left corner coordinate of the
0607: * DateEditor layer and relative coordinates of the popup anchor.
0608: */
0609: protected void setMonthPopupLocation() {
0610: setPopupLocation(monthPopup, DateEditorSkin.IMAGE_MONTH_BG,
0611: month_bounds);
0612: }
0613:
0614: /**
0615: * Set year popup location using upper left corner coordinate of the
0616: * DateEditor layer and relative coordinates of the popup anchor.
0617: */
0618: protected void setYearPopupLocation() {
0619: setPopupLocation(yearPopup, DateEditorSkin.IMAGE_YEAR_BG,
0620: year_bounds);
0621: }
0622:
0623: /**
0624: * Set hours popup location using upper left corner coordinate of the
0625: * DateEditor layer and relative coordinates of the popup anchor.
0626: */
0627: protected void setHoursPopupLocation() {
0628: setPopupLocation(hoursPopup, DateEditorSkin.IMAGE_TIME_BG,
0629: hours_bounds);
0630: }
0631:
0632: /**
0633: * Set minutes popup location using upper left corner coordinate of the
0634: * DateEditor layer and relative coordinates of the popup anchor.
0635: */
0636: protected void setMinutesPopupLocation() {
0637: setPopupLocation(minutesPopup, DateEditorSkin.IMAGE_TIME_BG,
0638: minutes_bounds);
0639: }
0640:
0641: /**
0642: * Draws month popup content.
0643: * @param g The Graphics object to paint to
0644: */
0645: protected void drawMonthComponent(Graphics g) {
0646: if (DateEditorSkin.IMAGE_MONTH_BG != null) {
0647: g.drawImage(DateEditorSkin.IMAGE_MONTH_BG, 0, 0,
0648: Graphics.LEFT | Graphics.TOP);
0649: int w = DateEditorSkin.IMAGE_MONTH_BG.getWidth();
0650: int h = DateEditorSkin.IMAGE_MONTH_BG.getHeight();
0651: if (focusOn == MONTH_POPUP) {
0652: g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND);
0653: g.drawRect(-2, -2, w + 3, h + 3);
0654: }
0655: }
0656: g.setFont(DateEditorSkin.FONT_POPUPS);
0657: g.setColor(0);
0658: g.drawString(MONTHS[editDate.get(Calendar.MONTH)], 4, 0,
0659: Graphics.LEFT | Graphics.TOP);
0660: }
0661:
0662: /**
0663: * Draws year popup content.
0664: * @param g The Graphics object to paint to
0665: */
0666: protected void drawYearComonent(Graphics g) {
0667: if (DateEditorSkin.IMAGE_YEAR_BG != null) {
0668: g.drawImage(DateEditorSkin.IMAGE_YEAR_BG, 0, 0,
0669: Graphics.LEFT | Graphics.TOP);
0670: int w = DateEditorSkin.IMAGE_YEAR_BG.getWidth();
0671: int h = DateEditorSkin.IMAGE_YEAR_BG.getHeight();
0672: if (focusOn == YEAR_POPUP) {
0673: g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND);
0674: g.drawRect(-2, -2, w + 3, h + 3);
0675: }
0676: }
0677:
0678: g.setFont(DateEditorSkin.FONT_POPUPS);
0679: g.setColor(0);
0680: g.drawString(Integer.toString(editDate.get(Calendar.YEAR)), 4,
0681: 0, Graphics.LEFT | Graphics.TOP);
0682: }
0683:
0684: /**
0685: * Draws hours popup content.
0686: * @param g The Graphics object to paint to
0687: */
0688: protected void drawHoursComponent(Graphics g) {
0689: if (DateEditorSkin.IMAGE_TIME_BG != null) {
0690: g.drawImage(DateEditorSkin.IMAGE_TIME_BG, 0, 0,
0691: Graphics.LEFT | Graphics.TOP);
0692: int w = DateEditorSkin.IMAGE_TIME_BG.getWidth();
0693: int h = DateEditorSkin.IMAGE_TIME_BG.getHeight();
0694: if (focusOn == HOURS_POPUP) {
0695: g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND);
0696: g.drawRect(-2, -2, w + 3, h + 3);
0697: }
0698: }
0699:
0700: g.setFont(DateEditorSkin.FONT_POPUPS);
0701: g.setColor(0);
0702:
0703: int hour;
0704: if (lf.CLOCK_USES_AM_PM) {
0705: hour = editDate.get(Calendar.HOUR) == 0 ? 12 : editDate
0706: .get(Calendar.HOUR) % 12;
0707: } else {
0708: hour = editDate.get(Calendar.HOUR_OF_DAY);
0709: }
0710:
0711: g.drawString(DateFieldLFImpl.twoDigits(hour), 3, 0,
0712: Graphics.LEFT | Graphics.TOP);
0713: }
0714:
0715: /**
0716: * Draws minutes popup content.
0717: * @param g The Graphics object to paint to
0718: */
0719: protected void drawMinutesComponent(Graphics g) {
0720: if (DateEditorSkin.IMAGE_TIME_BG != null) {
0721: g.drawImage(DateEditorSkin.IMAGE_TIME_BG, 0, 0,
0722: Graphics.LEFT | Graphics.TOP);
0723: int w = DateEditorSkin.IMAGE_TIME_BG.getWidth();
0724: int h = DateEditorSkin.IMAGE_TIME_BG.getHeight();
0725: if (focusOn == MINUTES_POPUP) {
0726: g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND);
0727: g.drawRect(-2, -2, w + 3, h + 3);
0728: }
0729: }
0730:
0731: g.setFont(DateEditorSkin.FONT_POPUPS);
0732: g.setColor(0);
0733: g.drawString(DateFieldLFImpl.twoDigits(editDate
0734: .get(Calendar.MINUTE)), 3, 0, Graphics.LEFT
0735: | Graphics.TOP);
0736: }
0737:
0738: /**
0739: * Draw the date components.
0740: * @param g The Graphics object to paint to
0741: */
0742: protected void drawDateComponents(Graphics g) {
0743: g.translate(month_bounds[X], month_bounds[Y]);
0744: drawMonthComponent(g);
0745: g.translate(-month_bounds[X], -month_bounds[Y]);
0746:
0747: g.translate(year_bounds[X], year_bounds[Y]);
0748: drawYearComonent(g);
0749: g.translate(-year_bounds[X], -year_bounds[Y]);
0750:
0751: g.translate(calendar_bounds[X], calendar_bounds[Y]);
0752: paintCalendar(g);
0753: g.translate(-calendar_bounds[X], -calendar_bounds[Y]);
0754: }
0755:
0756: /**
0757: * Draw the time components.
0758: * @param g The Graphics object to paint to
0759: */
0760: protected void drawTimeComponents(Graphics g) {
0761: g.translate(hours_bounds[X], hours_bounds[Y]);
0762: drawHoursComponent(g);
0763: g.translate(-hours_bounds[X], -hours_bounds[Y]);
0764:
0765: g.translate(minutes_bounds[X], minutes_bounds[Y]);
0766: drawMinutesComponent(g);
0767: g.translate(-minutes_bounds[X], -minutes_bounds[Y]);
0768:
0769: g.translate(ampm_bounds[X], ampm_bounds[Y]);
0770: paintAmPm(g);
0771: g.translate(-ampm_bounds[X], -ampm_bounds[Y]);
0772: }
0773:
0774: /**
0775: * Paint the Calendar.
0776: * @param g The Graphics context to paint to
0777: */
0778: protected void paintCalendar(Graphics g) {
0779: if (DateEditorSkin.IMAGE_CAL_BG == null
0780: || DateEditorSkin.IMAGE_DATES == null) {
0781: return;
0782: }
0783:
0784: g.drawImage(DateEditorSkin.IMAGE_CAL_BG, 0, 0, Graphics.LEFT
0785: | Graphics.TOP);
0786:
0787: if (DateEditorSkin.IMAGE_DATES == null) {
0788: return;
0789: }
0790: g.translate(2, 0);
0791:
0792: int o = DateEditorSkin.IMAGE_CAL_BG.getWidth() / 7;
0793: int rowH = 11;
0794: int h = DateEditorSkin.IMAGE_DATES.getHeight() / 31;
0795: int w = DateEditorSkin.IMAGE_DATES.getWidth();
0796:
0797: // draw calendar
0798: int x = 5 + ((dayOffset - 1) * o);
0799: int y = h + 4;
0800:
0801: if (hilightedDate > lastDay) {
0802: hilightedDate = lastDay;
0803: }
0804:
0805: calendarTopLimit = y;
0806: int lastCol = 7 * o;
0807: for (int i = 1; i <= lastDay; ++i) {
0808: // draw focus highlight
0809: if (i == hilightedDate) {
0810: dateHilightX = x;
0811: dateHilightY = y;
0812: g
0813: .setColor((focusOn == CALENDAR) ? DateEditorSkin.COLOR_TRAVERSE_IND
0814: : 0);
0815: g.drawRect(x - 6, y - 1, w, h + 1);
0816: }
0817:
0818: g.drawRegion(DateEditorSkin.IMAGE_DATES, 0, ((i - 1) * h),
0819: w, h, Sprite.TRANS_NONE, x, y, Graphics.TOP
0820: | Graphics.HCENTER);
0821:
0822: x += o;
0823: if (x > lastCol) {
0824: calendarRightLimit = x - o;
0825: x = 5;
0826: y += rowH;
0827: }
0828: }
0829: calendarBottomLimit = y;
0830: g.translate(-2, 0);
0831:
0832: calendar_bounds[W] = DateEditorSkin.IMAGE_CAL_BG.getWidth();
0833: //add rowH as the date may be written under the calendar bg.
0834: calendar_bounds[H] = DateEditorSkin.IMAGE_CAL_BG.getHeight()
0835: + rowH;
0836: }
0837:
0838: /**
0839: * Paint the am/pm indicators.
0840: *
0841: * @param g The graphics context to paint to
0842: */
0843: protected void paintAmPm(Graphics g) {
0844: int clockStartX, clockStartY;
0845:
0846: if (!lf.CLOCK_USES_AM_PM) {
0847: clockStartY = 9;
0848: } else {
0849: // paint AM
0850: if (DateEditorSkin.IMAGE_RADIO != null) {
0851: g.drawImage(
0852: (amSelected) ? DateEditorSkin.IMAGE_RADIO[1]
0853: : DateEditorSkin.IMAGE_RADIO[0], 0, 0,
0854: Graphics.LEFT | Graphics.TOP);
0855:
0856: if ((focusOn == AM_PM) && (amHilighted)) {
0857: g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND);
0858: g.drawRect(0, 0, DateEditorSkin.IMAGE_RADIO[0]
0859: .getWidth(), DateEditorSkin.IMAGE_RADIO[0]
0860: .getHeight());
0861: g.setColor(0);
0862: }
0863:
0864: if (DateEditorSkin.IMAGE_AMPM != null) {
0865: int w = DateEditorSkin.IMAGE_AMPM.getWidth() / 2;
0866: g
0867: .drawRegion(DateEditorSkin.IMAGE_AMPM, 0,
0868: 0, w, DateEditorSkin.IMAGE_AMPM
0869: .getHeight(),
0870: Sprite.TRANS_NONE,
0871: DateEditorSkin.IMAGE_RADIO[0]
0872: .getWidth(),
0873: (DateEditorSkin.IMAGE_RADIO[0]
0874: .getHeight() / 2),
0875: Graphics.VCENTER | Graphics.LEFT);
0876: }
0877: ampm_bounds[W] = 35 * 2;
0878: ampm_bounds[H] = DateEditorSkin.IMAGE_RADIO[0]
0879: .getHeight();
0880: }
0881:
0882: g.translate(35, 0);
0883: // paint PM
0884: if (DateEditorSkin.IMAGE_RADIO != null) {
0885: g.drawImage(
0886: (amSelected) ? DateEditorSkin.IMAGE_RADIO[0]
0887: : DateEditorSkin.IMAGE_RADIO[1], 0, 0,
0888: Graphics.LEFT | Graphics.TOP);
0889:
0890: if ((focusOn == AM_PM) && (!amHilighted)) {
0891: g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND);
0892: g.drawRect(0, 0, DateEditorSkin.IMAGE_RADIO[0]
0893: .getWidth(), DateEditorSkin.IMAGE_RADIO[0]
0894: .getHeight());
0895: g.setColor(0);
0896: }
0897:
0898: if (DateEditorSkin.IMAGE_AMPM != null) {
0899: int w = DateEditorSkin.IMAGE_AMPM.getWidth() / 2;
0900: g
0901: .drawRegion(DateEditorSkin.IMAGE_AMPM,
0902: (DateEditorSkin.IMAGE_AMPM
0903: .getWidth() / 2), 0, w,
0904: DateEditorSkin.IMAGE_AMPM
0905: .getHeight(),
0906: Sprite.TRANS_NONE,
0907: DateEditorSkin.IMAGE_RADIO[0]
0908: .getWidth(),
0909: (DateEditorSkin.IMAGE_RADIO[0]
0910: .getHeight() / 2),
0911: Graphics.VCENTER | Graphics.LEFT);
0912: }
0913: }
0914: g.translate(-35, 0);
0915: clockStartY = 22;
0916: }
0917:
0918: clockStartX = (mode == DateField.TIME) ? 10 : 6;
0919: g.translate(clockStartX, clockStartY);
0920: if (DateEditorSkin.IMAGE_CLOCK_BG != null) {
0921: g.drawImage(DateEditorSkin.IMAGE_CLOCK_BG, 0, 0,
0922: Graphics.LEFT | Graphics.TOP);
0923: paintTime(g);
0924: }
0925: g.translate(-clockStartX, -clockStartY);
0926: }
0927:
0928: /**
0929: * Paint the clock.
0930: *
0931: * @param g The Graphics to paint to
0932: */
0933: protected void paintTime(Graphics g) {
0934: int hour = editDate.get(Calendar.HOUR) % 12;
0935: int minute = editDate.get(Calendar.MINUTE);
0936:
0937: int minuteAngle = 90 - (minute * 6);
0938: int hourAngle = 90 - (hour * 30 + (minute / 2));
0939:
0940: int anchorX = DateEditorSkin.IMAGE_CLOCK_BG.getWidth() / 2;
0941: int anchorY = DateEditorSkin.IMAGE_CLOCK_BG.getHeight() / 2;
0942: g.translate(anchorX, anchorY);
0943:
0944: g.setColor(DateEditorSkin.COLOR_CLOCKHAND_DK);
0945: int x = (cos(hourAngle) * anchorX / 2) >> 16;
0946: int y = -(sin(hourAngle) * anchorX / 2) >> 16;
0947: g.drawLine(0, 0, x, y);
0948: g.drawLine(0, 1, x, y + 1);
0949: g.setColor(DateEditorSkin.COLOR_CLOCKHAND_LT);
0950: g.drawLine(0, 2, x, y + 2);
0951:
0952: g.setColor(DateEditorSkin.COLOR_CLOCKHAND_DK);
0953: x = (cos(minuteAngle) * (anchorX - 10)) >> 16;
0954: y = -(sin(minuteAngle) * (anchorX - 10)) >> 16;
0955: g.drawLine(0, 0, x, y);
0956: g.drawLine(0, 1, x, y + 1);
0957: g.setColor(DateEditorSkin.COLOR_CLOCKHAND_LT);
0958: g.drawLine(0, 2, x, y + 2);
0959:
0960: g.translate(-anchorX, -anchorY);
0961: }
0962:
0963: /**
0964: * Called when select key is fired, to take further action on it,
0965: * based on where the focus is on the date editor.
0966: *
0967: * @return true if key was handled, false otherwise
0968: */
0969: protected boolean selectFired() {
0970: boolean done = false;
0971: ScreenLFImpl sLF = (ScreenLFImpl) lf.df.owner.getLF();
0972: switch (focusOn) {
0973:
0974: case MONTH_POPUP:
0975: if (!monthPopup.open) {
0976: setMonthPopupLocation();
0977: monthPopup.show(sLF);
0978: done = true;
0979: } else {
0980: int month = monthPopup.getSelectedIndex();
0981: lastDay = daysInMonth(month, editDate
0982: .get(Calendar.YEAR));
0983: if (selectedDate > lastDay) {
0984: selectedDate = lastDay;
0985: editDate.set(Calendar.DATE, selectedDate);
0986: }
0987: monthPopup.setSelectedIndex(month);
0988: editDate.set(Calendar.MONTH, month);
0989: monthPopup.hide();
0990: }
0991: break;
0992: case YEAR_POPUP:
0993: if (!yearPopup.open) {
0994: setYearPopupLocation();
0995: yearPopup.show(sLF);
0996: done = true;
0997: } else {
0998: int selectedIndex = yearPopup.getSelectedIndex();
0999: if (selectedIndex == 0) {
1000: createYearStrings(Integer.parseInt(YEARS[1]) - 19);
1001: yearPopup.setContent(YEARS, 20);
1002: yearPopup.requestRepaint();
1003:
1004: } else if (selectedIndex == 21) {
1005: createYearStrings(Integer.parseInt(YEARS[20]));
1006: yearPopup.setContent(YEARS, 1);
1007: yearPopup.requestRepaint();
1008:
1009: } else {
1010: int year = Integer.parseInt(YEARS[selectedIndex]);
1011: lastDay = daysInMonth(editDate.get(Calendar.MONTH),
1012: year);
1013: if (selectedDate > lastDay) {
1014: selectedDate = lastDay;
1015: editDate.set(Calendar.DATE, selectedDate);
1016: }
1017:
1018: yearPopup.setSelectedIndex(selectedIndex);
1019: editDate.set(Calendar.YEAR, year);
1020: yearPopup.hide();
1021: }
1022: }
1023: break;
1024: case HOURS_POPUP:
1025: if (!hoursPopup.open) {
1026: setHoursPopupLocation();
1027: hoursPopup.show(sLF);
1028: done = true;
1029: } else {
1030: int selId = hoursPopup.getSelectedIndex();
1031: hoursPopup.setSelectedIndex(selId);
1032: int hour = HOURS[selId];
1033: if ((lf.CLOCK_USES_AM_PM) && (!amSelected)) {
1034: hour += 12;
1035: }
1036: editDate.set(Calendar.HOUR_OF_DAY, hour);
1037: hoursPopup.hide();
1038: }
1039: break;
1040: case MINUTES_POPUP:
1041: if (!minutesPopup.open) {
1042: setMinutesPopupLocation();
1043: minutesPopup.show(sLF);
1044: done = true;
1045: } else {
1046: int selId = minutesPopup.getSelectedIndex();
1047: editDate.set(Calendar.MINUTE, MINUTES[selId]);
1048: minutesPopup.setSelectedIndex(selId);
1049: minutesPopup.hide();
1050: }
1051: break;
1052: case CALENDAR:
1053: selectedDate = hilightedDate;
1054: editDate.set(Calendar.DATE, selectedDate);
1055: focusOn = MONTH_POPUP;
1056: done = true;
1057: break;
1058: case AM_PM:
1059: amSelected = amHilighted;
1060: int hour = hoursPopup.getSelectedIndex() + 1;
1061: if (hour == 12) {
1062: if (amSelected) {
1063: hour = 0;
1064: }
1065: } else if (!amSelected) {
1066: hour += 12;
1067: }
1068:
1069: editDate.set(Calendar.HOUR_OF_DAY, hour);
1070: done = true;
1071: break;
1072: default:
1073: lf.uCallKeyPressed(Constants.KEYCODE_SELECT);
1074: done = true;
1075: break;
1076: }
1077: return done;
1078: }
1079:
1080: /**
1081: * Handles internal traversal within the date editor.
1082: *
1083: * @param code the code of this key event
1084: * @return true always, since popup layers swallow all events
1085: */
1086: protected boolean traverseEditor(int code) {
1087: // handle internal traversal
1088: switch (focusOn) {
1089: case MONTH_POPUP:
1090: switch (code) {
1091: case Constants.KEYCODE_DOWN:
1092: focusOn = CALENDAR;
1093: break;
1094: case Constants.KEYCODE_RIGHT:
1095: focusOn = YEAR_POPUP;
1096: break;
1097: default:
1098: // no-op
1099: break;
1100: }
1101: break;
1102: case YEAR_POPUP:
1103: switch (code) {
1104: case Constants.KEYCODE_DOWN:
1105: focusOn = CALENDAR;
1106: break;
1107: case Constants.KEYCODE_LEFT:
1108: focusOn = MONTH_POPUP;
1109: break;
1110: case Constants.KEYCODE_RIGHT:
1111: if (mode == DateField.DATE_TIME) {
1112: focusOn = HOURS_POPUP;
1113: }
1114: break;
1115: default:
1116: // no-op
1117: break;
1118: }
1119: break;
1120: case HOURS_POPUP:
1121: switch (code) {
1122: case Constants.KEYCODE_DOWN:
1123: focusOn = AM_PM;
1124: break;
1125: case Constants.KEYCODE_LEFT:
1126: if (mode == DateField.DATE_TIME) {
1127: focusOn = YEAR_POPUP;
1128: }
1129: break;
1130: case Constants.KEYCODE_RIGHT:
1131: focusOn = MINUTES_POPUP;
1132: break;
1133: default:
1134: // no-op
1135: break;
1136: }
1137: break;
1138: case MINUTES_POPUP:
1139: switch (code) {
1140: case Constants.KEYCODE_DOWN:
1141: focusOn = AM_PM;
1142: break;
1143: case Constants.KEYCODE_LEFT:
1144: focusOn = HOURS_POPUP;
1145: break;
1146: default:
1147: // no-op
1148: break;
1149: }
1150: break;
1151: case CALENDAR:
1152: if (!traverseCalendar(code)) {
1153: switch (code) {
1154: case Constants.KEYCODE_RIGHT:
1155: if (mode == DateField.DATE_TIME) {
1156: focusOn = AM_PM;
1157: }
1158: break;
1159: case Constants.KEYCODE_UP:
1160: focusOn = MONTH_POPUP;
1161: break;
1162: default:
1163: // no-op
1164: break;
1165: }
1166: }
1167: break;
1168: case AM_PM:
1169: traverseAmPm(code);
1170: break;
1171: default:
1172: Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
1173: "DateEditor.traverseEditor(), focusOn=" + focusOn);
1174: break;
1175: }
1176: return true;
1177: }
1178:
1179: /**
1180: * Handle internal traversal between the am/pm indicators.
1181: *
1182: * @param code the code of this key event
1183: * @return true if internal traversal occurred, false otherwise
1184: */
1185: protected boolean traverseAmPm(int code) {
1186: boolean traverse = false;
1187: switch (code) {
1188: case Constants.KEYCODE_UP:
1189: focusOn = HOURS_POPUP;
1190: traverse = true;
1191: break;
1192: case Constants.KEYCODE_LEFT:
1193: if (amHilighted) {
1194: focusOn = CALENDAR;
1195: traverse = true;
1196: } else {
1197: amHilighted = true;
1198: traverse = true;
1199: }
1200: break;
1201: case Constants.KEYCODE_RIGHT:
1202: if (amHilighted) {
1203: amHilighted = false;
1204: traverse = true;
1205: }
1206: break;
1207: default:
1208: // no-op
1209: break;
1210: }
1211: return traverse;
1212: }
1213:
1214: /**
1215: * Handle internal traversal within the calendar.
1216: *
1217: * @param code the code of this key event
1218: * @return true if internal traversal occurred, false otherwise
1219: */
1220: protected boolean traverseCalendar(int code) {
1221: boolean traverse = false;
1222:
1223: switch (code) {
1224: case Constants.KEYCODE_LEFT:
1225: if (hilightedDate > 1) {
1226: hilightedDate--;
1227: }
1228: traverse = true;
1229: break;
1230: case Constants.KEYCODE_RIGHT:
1231: if ((hilightedDate < lastDay)
1232: && (dateHilightX < calendarRightLimit)) {
1233: hilightedDate++;
1234: traverse = true;
1235: }
1236: break;
1237: case Constants.KEYCODE_UP:
1238: if (hilightedDate == 1) {
1239: break;
1240: }
1241: if (hilightedDate > 7) {
1242: hilightedDate -= 7;
1243: traverse = true;
1244: } else if (dateHilightY > calendarTopLimit) {
1245: hilightedDate = 1;
1246: traverse = true;
1247: }
1248: break;
1249: case Constants.KEYCODE_DOWN:
1250: if (hilightedDate == lastDay) {
1251: break;
1252: }
1253: if (hilightedDate <= (lastDay - 7)) {
1254: hilightedDate += 7;
1255: traverse = true;
1256: } else if (dateHilightY < calendarBottomLimit) {
1257: hilightedDate = lastDay;
1258: traverse = true;
1259: }
1260: break;
1261: default:
1262: // no-op
1263: break;
1264: }
1265: return traverse;
1266: } // traverseCalendar()
1267:
1268: // *************** utility methods *********** //
1269:
1270: /**
1271: * Utility method to return the cosine of an angle.
1272: *
1273: * @param angle The angle to compute the cosine of
1274: * @return int The cosine of the angle
1275: */
1276: protected static int cos(int angle) {
1277: angle += 360000;
1278: angle %= 360;
1279:
1280: if (angle >= 270) {
1281: return TRIG_TABLE[360 - angle];
1282: } else if (angle >= 180) {
1283: return -TRIG_TABLE[angle - 180];
1284: } else if (angle >= 90) {
1285: return -TRIG_TABLE[180 - angle];
1286: } else {
1287: return TRIG_TABLE[angle];
1288: }
1289: }
1290:
1291: /**
1292: * Utility method to return the sin of an angle.
1293: *
1294: * @param angle The angle to compute the sin of
1295: * @return int The sin of the angle
1296: */
1297: protected static int sin(int angle) {
1298: return cos(90 - angle);
1299: }
1300:
1301: /**
1302: * Utility method to calculate the number of days
1303: * in a month.
1304: *
1305: * @param month The month to use
1306: * @param year The year the month occurs in
1307: * @return int The number of days in the month
1308: */
1309: protected int daysInMonth(int month, int year) {
1310: switch (month) {
1311: case Calendar.JANUARY:
1312: case Calendar.MARCH:
1313: case Calendar.MAY:
1314: case Calendar.JULY:
1315: case Calendar.AUGUST:
1316: case Calendar.OCTOBER:
1317: case Calendar.DECEMBER:
1318: return 31;
1319: case Calendar.FEBRUARY:
1320: if (((year % 400) == 0)
1321: || (((year & 3) == 0) && ((year % 100) != 0))) {
1322: return 29;
1323: }
1324: return 28;
1325: case Calendar.APRIL:
1326: case Calendar.JUNE:
1327: case Calendar.SEPTEMBER:
1328: case Calendar.NOVEMBER:
1329: default:
1330: return 30;
1331: }
1332: }
1333:
1334: /**
1335: * Set the day offset.
1336: */
1337: protected void setDayOffset() {
1338: Date save = editDate.getTime();
1339: editDate.set(Calendar.DATE, 1);
1340: dayOffset = editDate.get(Calendar.DAY_OF_WEEK);
1341:
1342: if (Resource.getFirstDayOfWeek() != Calendar.SUNDAY) {
1343: dayOffset = (dayOffset == 1) ? 7 : (dayOffset - 1);
1344: }
1345: editDate.setTime(save);
1346: }
1347:
1348: /**
1349: * Return sizeChanged flag
1350: *
1351: * @return true if size change iccurs
1352: */
1353: public boolean isSizeChanged() {
1354: return sizeChanged;
1355: }
1356:
1357: /** Set sizeChanged flag to true */
1358: public void setSizeChanged() {
1359: this .sizeChanged = true;
1360: }
1361:
1362: /**
1363: * Return Popup layer flag
1364: *
1365: * @return true if popup Layer is shown
1366: */
1367: public boolean isPopupOpen() {
1368: return popUpOpen;
1369: }
1370:
1371: /**
1372: * Set popup Layer flag
1373: *
1374: * @param popUpOpen true if popup Layer is shown
1375: */
1376: public void setPopupOpen(boolean popUpOpen) {
1377: this .popUpOpen = popUpOpen;
1378: }
1379:
1380: public void callSizeChanged() {
1381: if (monthPopup != null) {
1382: setMonthPopupLocation();
1383: }
1384: if (yearPopup != null) {
1385: setYearPopupLocation();
1386: }
1387: if (hoursPopup != null) {
1388: setHoursPopupLocation();
1389: }
1390: if (minutesPopup != null) {
1391: setMinutesPopupLocation();
1392: }
1393: }
1394:
1395: // *********** attributes ************* //
1396:
1397: /**
1398: * Table of trigonometric functions, in 16.16 fixed point.
1399: */
1400: protected static final int TRIG_TABLE[] = { 65535, // cos 0
1401: 65525, // cos 1
1402: 65495, // cos 2
1403: 65445, // cos 3
1404: 65375, // cos 4
1405: 65285, // cos 5
1406: 65175, // cos 6
1407: 65046, // cos 7
1408: 64897, // cos 8
1409: 64728, // cos 9
1410: 64539, // cos 10
1411: 64330, // cos 11
1412: 64102, // cos 12
1413: 63855, // cos 13
1414: 63588, // cos 14
1415: 63301, // cos 15
1416: 62996, // cos 16
1417: 62671, // cos 17
1418: 62327, // cos 18
1419: 61964, // cos 19
1420: 61582, // cos 20
1421: 61182, // cos 21
1422: 60762, // cos 22
1423: 60325, // cos 23
1424: 59869, // cos 24
1425: 59394, // cos 25
1426: 58902, // cos 26
1427: 58392, // cos 27
1428: 57863, // cos 28
1429: 57318, // cos 29
1430: 56754, // cos 30
1431: 56174, // cos 31
1432: 55576, // cos 32
1433: 54962, // cos 33
1434: 54330, // cos 34
1435: 53683, // cos 35
1436: 53018, // cos 36
1437: 52338, // cos 37
1438: 51642, // cos 38
1439: 50930, // cos 39
1440: 50202, // cos 40
1441: 49459, // cos 41
1442: 48701, // cos 42
1443: 47929, // cos 43
1444: 47141, // cos 44
1445: 46340, // cos 45
1446: 45524, // cos 46
1447: 44694, // cos 47
1448: 43851, // cos 48
1449: 42994, // cos 49
1450: 42125, // cos 50
1451: 41242, // cos 51
1452: 40347, // cos 52
1453: 39439, // cos 53
1454: 38520, // cos 54
1455: 37589, // cos 55
1456: 36646, // cos 56
1457: 35692, // cos 57
1458: 34728, // cos 58
1459: 33753, // cos 59
1460: 32767, // cos 60
1461: 31771, // cos 61
1462: 30766, // cos 62
1463: 29752, // cos 63
1464: 28728, // cos 64
1465: 27696, // cos 65
1466: 26655, // cos 66
1467: 25606, // cos 67
1468: 24549, // cos 68
1469: 23485, // cos 69
1470: 22414, // cos 70
1471: 21336, // cos 71
1472: 20251, // cos 72
1473: 19160, // cos 73
1474: 18063, // cos 74
1475: 16961, // cos 75
1476: 15854, // cos 76
1477: 14742, // cos 77
1478: 13625, // cos 78
1479: 12504, // cos 79
1480: 11380, // cos 80
1481: 10251, // cos 81
1482: 9120, // cos 82
1483: 7986, // cos 83
1484: 6850, // cos 84
1485: 5711, // cos 85
1486: 4571, // cos 86
1487: 3429, // cos 87
1488: 2287, // cos 88
1489: 1143, // cos 89
1490: 0 // cos 90
1491: };
1492:
1493: /**
1494: * Constant indicating the month popup, used in the process of current
1495: * focus tracking inside the date editor.
1496: */
1497: protected static final int MONTH_POPUP = 1;
1498:
1499: /**
1500: * Constant indicating the year popup, used in the process of current
1501: * focus tracking inside the date editor.
1502: */
1503: protected static final int YEAR_POPUP = 2;
1504:
1505: /**
1506: * Constant indicating the hour popup, used in the process of current
1507: * focus tracking inside the date editor.
1508: */
1509: protected static final int HOURS_POPUP = 3;
1510:
1511: /**
1512: * Constant indicating the minutes popup, used in the process of current
1513: * focus tracking inside the date editor.
1514: */
1515: protected static final int MINUTES_POPUP = 4;
1516:
1517: /**
1518: * Constant indicating the calendar, used in the process of current
1519: * focus tracking inside the date editor.
1520: */
1521: protected static final int CALENDAR = 5;
1522:
1523: /**
1524: * Constant indicating the am/pm indicators, used in the process of
1525: * current focus tracking inside the date editor.
1526: */
1527: protected static final int AM_PM = 6;
1528:
1529: /**
1530: * Static array holding the localized equivalent of month names.
1531: */
1532: protected static String[] MONTHS;
1533:
1534: /**
1535: * Static array holding the year values.
1536: */
1537: protected static String[] YEARS;
1538:
1539: /**
1540: * Static array holding the hour values.
1541: */
1542: protected static int[] HOURS;
1543:
1544: /**
1545: * Static array holding the minute values.
1546: */
1547: protected static int[] MINUTES;
1548:
1549: /**
1550: * The DateFieldLFImpl that triggered this date editor.
1551: */
1552: protected DateFieldLFImpl lf;
1553:
1554: /**
1555: * The date currently being edited.
1556: */
1557: protected Calendar editDate;
1558:
1559: /**
1560: * The mode of the date field, that triggered this date editor.
1561: */
1562: protected int mode;
1563:
1564: /**
1565: * Whether date field that triggered this date editor was initialized
1566: * or not.
1567: */
1568: protected boolean initialized = false;
1569:
1570: /**
1571: * Special command to cancel any changes and close the date editor
1572: * without any impact on the datefield that triggered this editor.
1573: */
1574: protected Command cancel = new Command(Resource
1575: .getString(ResourceConstants.CANCEL), Command.CANCEL, 0);
1576:
1577: /**
1578: * Special command to set/save the changes done in the editor into the
1579: * datefield that triggered this editor and close the editor.
1580: */
1581: protected Command set = new Command(Resource
1582: .getString(ResourceConstants.SET), Command.OK, 1);
1583:
1584: /**
1585: * The command array that holds both the commands associated with
1586: * the date editor.
1587: */
1588: protected Command[] commands = { set, cancel };
1589:
1590: /**
1591: * The location x-coordinate, used to calculate where to draw
1592: * the next component.
1593: */
1594: protected int nextX = 0;
1595:
1596: /**
1597: * The location y-coordinate, used to calculate where to draw
1598: * the next component.
1599: */
1600: protected int nextY = 0;
1601:
1602: /** The last day of the month. */
1603: protected int lastDay;
1604:
1605: /** The day offset. */
1606: protected int dayOffset;
1607:
1608: /** The sub-popup layer used to select month value. */
1609: protected DEPopupLayer monthPopup;
1610:
1611: /** The sub-popup layer used to select year value. */
1612: protected DEPopupLayer yearPopup;
1613:
1614: /** The sub-popup layer used to select hour value. */
1615: protected DEPopupLayer hoursPopup;
1616:
1617: /** The sub-popup layer used to select minutes value. */
1618: protected DEPopupLayer minutesPopup;
1619:
1620: /** Keeps track of the currently focused item inside the date editor. */
1621: protected int focusOn;
1622:
1623: /**
1624: * Indicates whether am or pm is currently selected. True indicates "am"
1625: * is selected and false indicates "pm" is selected.
1626: */
1627: protected boolean amSelected = false;
1628:
1629: /**
1630: * Indicates whether am or pm is currently highlighted.
1631: * True indicates "am" is highlighted and false indicates "pm" is
1632: * highlighted.
1633: */
1634: protected boolean amHilighted = false;
1635:
1636: /** Currently highlighted date in the calendar. */
1637: protected int hilightedDate = 1;
1638:
1639: /** Currently selected date in the calendar. */
1640: protected int selectedDate = 1;
1641:
1642: /** Width of a sub-popup in its closed state. */
1643: protected int popupWidth;
1644:
1645: /** Height of a sub-popup in its closed state. */
1646: protected int popupHeight;
1647:
1648: /** Width of the element within the popup in its closed state. */
1649: protected int elementWidth;
1650:
1651: /** Height of the element within the popup in its closed state. */
1652: protected int elementHeight;
1653:
1654: /**
1655: * The location offset to draw time components used for DateField.TIME
1656: * and DateField.DATE_TIME modes.
1657: */
1658: protected int timeComponentsOffset;
1659:
1660: /** Indicates calendar's top limit, used in traversal calculations. */
1661: protected int calendarTopLimit;
1662:
1663: /** Indicates calendar's bottom limit, used in traversal calculations. */
1664: protected int calendarBottomLimit;
1665:
1666: /** Indicates calendar's right limit, used in traversal calculations. */
1667: protected int calendarRightLimit;
1668:
1669: /**
1670: * Indicates x co-ordinate of previously highlighted date, used in
1671: * traversal calculations.
1672: */
1673: protected int dateHilightX;
1674:
1675: /**
1676: * Indicates y co-ordinate of previously highlighted date, used in
1677: * traversal calculations.
1678: */
1679: protected int dateHilightY;
1680:
1681: /*pointer pressed outside of the Layer's bounds*/
1682: final int PRESS_OUT_OF_BOUNDS = -1;
1683:
1684: /*variable used in pointerInput handling,indicating focused area at pressed */
1685: private int itemIndexWhenPressed = PRESS_OUT_OF_BOUNDS;
1686:
1687: /* bounds (in this popupLayer's coordinate space) for each focusable area*/
1688: private int month_bounds[];
1689: private int year_bounds[];
1690: private int hours_bounds[];
1691: private int minutes_bounds[];
1692: private int calendar_bounds[];
1693: private int ampm_bounds[];
1694:
1695: /*date index at pressed, may be valid value or invalid value 0*/
1696: private int pressedDate;
1697:
1698: /**
1699: * The state of the date editor popup (Default: false = closed).
1700: */
1701: private boolean popUpOpen;
1702:
1703: // True if size of screen was changed
1704: private boolean sizeChanged;
1705:
1706: // True if Date Edidor is initialized
1707: private boolean isIitialized;
1708: }
|