/* * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package javax.microedition.lcdui; import java.util.Date; import java.util.Calendar; import com.sun.midp.lcdui.*; import com.sun.midp.i18n.Resource; import com.sun.midp.i18n.ResourceConstants; import com.sun.midp.configurator.Constants; import com.sun.midp.chameleon.skins.DateEditorSkin; import com.sun.midp.chameleon.skins.ScreenSkin; import com.sun.midp.chameleon.skins.resources.DateEditorResources; import com.sun.midp.chameleon.layers.PopupLayer; import javax.microedition.lcdui.game.Sprite; import com.sun.midp.log.Logging; import com.sun.midp.log.LogChannels; /** * A utility class for editing date/time components for a DateField. */ class MiniDateEditor extends DateEditor { /** * Create a new DateEditor layer. * * @param lf The DateFieldLFImpl that triggered this date editor */ public MiniDateEditor(DateFieldLFImpl lf) { super(lf); timeComponentsOffset = 0; } void show() { super.show(); switch (mode) { case DateField.DATE: case DateField.DATE_TIME: focusOn = DAY_POPUP; break; } } /** * Hide all sub-popups triggered by this date editor. * Overridden from parent class to close additional * 'day of the month' popup. */ void hideAllPopups() { synchronized (Display.LCDUILock) { ScreenLFImpl sLF = (ScreenLFImpl)lf.df.owner.getLF(); Display d = sLF.lGetCurrentDisplay(); if (d != null) { d.hidePopup(dayPopup); d.hidePopup(monthPopup); d.hidePopup(yearPopup); d.hidePopup(hoursPopup); d.hidePopup(minutesPopup); } } // synchronized } /** * Populate the date components. */ protected void populateDateComponents() { super.populateDateComponents(); // populate DAYS[] int daysInMonth = daysInMonth( editDate.get(Calendar.MONTH), editDate.get(Calendar.YEAR)); DAYS = new String[daysInMonth]; for (int i = 1; i <= daysInMonth; i++) { DAYS[i - 1] = Integer.toString(i); } dayPopup = new DEPopupLayer(this, DAYS, editDate.get(Calendar.DAY_OF_MONTH) - 1, true); } /** * Draw the date components. * * @param g The Graphics object to paint to */ protected void drawDateComponents(Graphics g) { nextX = 4; nextY = 0; int w = 0; int h = 0; g.setFont(DateEditorSkin.FONT_POPUPS); g.setColor(0); g.drawString(Resource.getString(ResourceConstants.LCDUI_DF_DATE_MINI), nextX, nextY, Graphics.LEFT | Graphics.TOP); nextY = DateEditorSkin.FONT_POPUPS.getHeight() + 2; g.translate(nextX, nextY); if (DateEditorSkin.IMAGE_MONTH_BG != null) { g.drawImage(DateEditorSkin.IMAGE_TIME_BG, 0, 0, Graphics.LEFT | Graphics.TOP); w = DateEditorSkin.IMAGE_TIME_BG.getWidth(); h = DateEditorSkin.IMAGE_TIME_BG.getHeight(); if (focusOn == DAY_POPUP) { g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND); g.drawRect(-2, -2, w + 3, h + 3); } dayPopup.setElementSize( w - 4, DateEditorSkin.FONT_POPUPS.getHeight()); dayPopup.setBounds(g.getTranslateX(), g.getTranslateY() + h, w, DateEditorSkin.HEIGHT_POPUPS); } g.setFont(DateEditorSkin.FONT_POPUPS); g.setColor(0); g.drawString(DAYS[editDate.get(Calendar.DAY_OF_MONTH) - 1], 3, 0, Graphics.LEFT | Graphics.TOP); g.translate(w + 2, 0); if (DateEditorSkin.IMAGE_MONTH_BG != null) { g.drawImage(DateEditorSkin.IMAGE_MONTH_BG, 0, 0, Graphics.LEFT | Graphics.TOP); w = DateEditorSkin.IMAGE_MONTH_BG.getWidth(); h = DateEditorSkin.IMAGE_MONTH_BG.getHeight(); if (focusOn == MONTH_POPUP) { g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND); g.drawRect(-2, -2, w + 3, h + 3); } monthPopup.setElementSize( w - 4, DateEditorSkin.FONT_POPUPS.getHeight()); monthPopup.setBounds(g.getTranslateX(), g.getTranslateY() + h, w, DateEditorSkin.HEIGHT_POPUPS); } g.setFont(DateEditorSkin.FONT_POPUPS); g.setColor(0); g.drawString(MONTHS[editDate.get(Calendar.MONTH)], 4, 0, Graphics.LEFT | Graphics.TOP); g.translate(w + 2, 0); if (DateEditorSkin.IMAGE_YEAR_BG != null) { g.drawImage(DateEditorSkin.IMAGE_YEAR_BG, 0, 0, Graphics.LEFT | Graphics.TOP); w = DateEditorSkin.IMAGE_YEAR_BG.getWidth(); h = DateEditorSkin.IMAGE_YEAR_BG.getHeight(); if (focusOn == YEAR_POPUP) { g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND); g.drawRect(-2, -2, w + 3, h + 3); } yearPopup.setElementSize( w - 4, DateEditorSkin.FONT_POPUPS.getHeight()); yearPopup.setBounds(g.getTranslateX(), g.getTranslateY() + h, w, DateEditorSkin.HEIGHT_POPUPS); } g.setFont(DateEditorSkin.FONT_POPUPS); g.setColor(0); g.drawString(Integer.toString(editDate.get(Calendar.YEAR)), 4, 0, Graphics.LEFT | Graphics.TOP); g.translate(-g.getTranslateX() + 4, -nextY); } /** * Draw the time components. * * @param g The Graphics object to paint to */ protected void drawTimeComponents(Graphics g) { nextX = 4; nextY = (mode == DateField.DATE_TIME) ? 33 : 0; g.setFont(DateEditorSkin.FONT_POPUPS); g.setColor(0); g.drawString(Resource.getString(ResourceConstants.LCDUI_DF_TIME_MINI), nextX, nextY, Graphics.LEFT | Graphics.TOP); nextY += DateEditorSkin.FONT_POPUPS.getHeight(); int w = 0; int h = 0; g.translate(nextX, nextY); if (DateEditorSkin.IMAGE_TIME_BG != null) { g.drawImage(DateEditorSkin.IMAGE_TIME_BG, 0, 0, Graphics.LEFT | Graphics.TOP); w = DateEditorSkin.IMAGE_TIME_BG.getWidth(); h = DateEditorSkin.IMAGE_TIME_BG.getHeight(); if (focusOn == HOURS_POPUP) { g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND); g.drawRect(-2, -2, w + 3, h + 3); } hoursPopup.setElementSize( w - 4, DateEditorSkin.FONT_POPUPS.getHeight()); hoursPopup.setBounds(g.getTranslateX(), g.getTranslateY() + h, w, DateEditorSkin.HEIGHT_POPUPS); } g.setFont(DateEditorSkin.FONT_POPUPS); g.setColor(0); g.drawString(Integer.toString(HOURS[hoursPopup.getSelectedIndex()]), 3, 0, Graphics.LEFT | Graphics.TOP); g.translate(w + 2, 0); if (DateEditorSkin.IMAGE_TIME_BG != null) { g.drawImage(DateEditorSkin.IMAGE_TIME_BG, 0, 0, Graphics.LEFT | Graphics.TOP); w = DateEditorSkin.IMAGE_TIME_BG.getWidth(); h = DateEditorSkin.IMAGE_TIME_BG.getHeight(); if (focusOn == MINUTES_POPUP) { g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND); g.drawRect(-2, -2, w + 3, h + 3); } minutesPopup.setElementSize( w - 4, DateEditorSkin.FONT_POPUPS.getHeight()); minutesPopup.setBounds(g.getTranslateX(), g.getTranslateY() + h, w, DateEditorSkin.HEIGHT_POPUPS); } g.setFont(DateEditorSkin.FONT_POPUPS); g.setColor(0); g.drawString(DateFieldLFImpl.twoDigits(editDate.get(Calendar.MINUTE)), 3, 0, Graphics.LEFT | Graphics.TOP); g.translate(w + 2, 0); nextX = (mode == DateField.TIME) ? 15 : 0; nextY = 45; g.translate(-g.getTranslateX(), 20); g.translate(10, 0); paintAmPm(g); } /** * Paint the am/pm indicators. * * @param g The graphics context to paint to */ protected void paintAmPm(Graphics g) { int clockStartX, clockStartY; if (!lf.CLOCK_USES_AM_PM) { clockStartY = 9; } else { // paint AM if (DateEditorSkin.IMAGE_RADIO != null) { g.drawImage((amSelected) ? DateEditorSkin.IMAGE_RADIO[1] : DateEditorSkin.IMAGE_RADIO[0], 0, 0, Graphics.LEFT | Graphics.TOP); if ((focusOn == AM_PM) && (amHilighted)) { g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND); g.drawRect(0, 0, DateEditorSkin.IMAGE_RADIO[0].getWidth(), DateEditorSkin.IMAGE_RADIO[0].getHeight()); g.setColor(0); } if (DateEditorSkin.IMAGE_AMPM != null) { int w = DateEditorSkin.IMAGE_AMPM.getWidth() / 2; g.drawRegion(DateEditorSkin.IMAGE_AMPM, 0, 0, w, DateEditorSkin.IMAGE_AMPM.getHeight(), Sprite.TRANS_NONE, DateEditorSkin.IMAGE_RADIO[0].getWidth(), (DateEditorSkin.IMAGE_RADIO[0].getHeight()/2), Graphics.VCENTER | Graphics.LEFT); } } g.translate(35, 0); // paint PM if (DateEditorSkin.IMAGE_RADIO != null) { g.drawImage((amSelected) ? DateEditorSkin.IMAGE_RADIO[0] : DateEditorSkin.IMAGE_RADIO[1], 0, 0, Graphics.LEFT | Graphics.TOP); if ((focusOn == AM_PM) && (!amHilighted)) { g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND); g.drawRect(0, 0, DateEditorSkin.IMAGE_RADIO[0].getWidth(), DateEditorSkin.IMAGE_RADIO[0].getHeight()); g.setColor(0); } if (DateEditorSkin.IMAGE_AMPM != null) { int w = DateEditorSkin.IMAGE_AMPM.getWidth() / 2; g.drawRegion(DateEditorSkin.IMAGE_AMPM, (DateEditorSkin.IMAGE_AMPM.getWidth() / 2), 0, w, DateEditorSkin.IMAGE_AMPM.getHeight(), Sprite.TRANS_NONE, DateEditorSkin.IMAGE_RADIO[0].getWidth(), (DateEditorSkin.IMAGE_RADIO[0].getHeight()/2), Graphics.VCENTER | Graphics.LEFT); } } g.translate(-35, 0); clockStartY = 22; } } /** * Called when select key is fired, to take further action on it, * based on where the focus is on the date editor. * * @return true if key was handled, false otherwise */ protected boolean selectFired() { boolean done = false; ScreenLFImpl sLF = (ScreenLFImpl)lf.df.owner.getLF(); switch (focusOn) { case DAY_POPUP: if (!dayPopup.open) { sLF.lGetCurrentDisplay().showPopup(dayPopup); dayPopup.open = !dayPopup.open; done = true; } else { dayPopup.open = !dayPopup.open; int day = dayPopup.getSelectedIndex(); editDate.set(Calendar.DAY_OF_MONTH, day + 1); sLF.lGetCurrentDisplay().hidePopup(dayPopup); } break; default: return super.selectFired(); } return done; } /** * Handles internal traversal within the date editor. * * @param code the code of this key event * @return true always, since popup layers swallow all events */ protected boolean traverseEditor(int code) { // handle internal traversal switch (focusOn) { case DAY_POPUP: switch (code) { case Constants.KEYCODE_RIGHT: focusOn = MONTH_POPUP; break; case Constants.KEYCODE_DOWN: if (mode == DateField.DATE_TIME) { focusOn = HOURS_POPUP; } break; default: break; } break; case MONTH_POPUP: switch (code) { case Constants.KEYCODE_RIGHT: focusOn = YEAR_POPUP; break; case Constants.KEYCODE_LEFT: focusOn = DAY_POPUP; break; case Constants.KEYCODE_DOWN: if (mode == DateField.DATE_TIME) { focusOn = MINUTES_POPUP; } default: // no-op break; } break; case YEAR_POPUP: switch (code) { case Constants.KEYCODE_LEFT: focusOn = MONTH_POPUP; break; case Constants.KEYCODE_RIGHT: if (mode == DateField.DATE_TIME) { focusOn = HOURS_POPUP; } break; default: // no-op break; } break; case HOURS_POPUP: switch (code) { case Constants.KEYCODE_UP: if (mode == DateField.DATE_TIME) { focusOn = DAY_POPUP; } break; case Constants.KEYCODE_DOWN: focusOn = AM_PM; break; case Constants.KEYCODE_LEFT: if (mode == DateField.DATE_TIME) { focusOn = YEAR_POPUP; } break; case Constants.KEYCODE_RIGHT: focusOn = MINUTES_POPUP; break; default: // no-op break; } break; case MINUTES_POPUP: switch (code) { case Constants.KEYCODE_UP: if (mode == DateField.DATE_TIME) { focusOn = MONTH_POPUP; } break; case Constants.KEYCODE_DOWN: focusOn = AM_PM; break; case Constants.KEYCODE_LEFT: focusOn = HOURS_POPUP; break; default: // no-op break; } break; case AM_PM: traverseAmPm(code); break; default: Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI, "DateEditor.traverseEditor(), focusOn=" +focusOn); break; } return true; } /** * Handle internal traversal between the am/pm indicators. * * @param code the code of this key event * @return true if internal traversal occurred, false otherwise */ protected boolean traverseAmPm(int code) { boolean traverse = false; switch (code) { case Constants.KEYCODE_UP: focusOn = HOURS_POPUP; traverse = true; break; case Constants.KEYCODE_LEFT: if (amHilighted) { if (mode == DateField.DATE_TIME) { focusOn = YEAR_POPUP; traverse = true; } } else { amHilighted = true; traverse = true; } break; case Constants.KEYCODE_RIGHT: if (amHilighted) { amHilighted = false; traverse = true; } break; default: // no-op break; } return traverse; } /** * Constant indicating the day of the month popup, used in the process * of current focus tracking inside the date editor. */ protected static final int DAY_POPUP = 7; /** * Static array holding the day of the month values. */ protected static String[] DAYS; /** The sub-popup layer used to select day of the month value */ protected DEPopupLayer dayPopup; }