www.pudn.com > Bluegammon蓝牙的应用编程.rar > MenuCanvas.java
// Copyright (c) 2005 Sony Ericsson Mobile Communications AB // // This software is provided "AS IS," without a warranty of any kind. // ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, // INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. // // THIS SOFTWARE IS COMPLEMENTARY OF JAYWAY AB (www.jayway.se) package bluegammon.gui; import java.util.Calendar; import java.util.Date; import java.util.Vector; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import bluegammon.Audio; import bluegammon.Device; import bluegammon.Bluegammon; import bluegammon.Resources; import bluegammon.RmsFacade; import bluegammon.gui.menu.BinaryPageItem; import bluegammon.gui.menu.DefaultMenuPainter; import bluegammon.gui.menu.ItemAction; import bluegammon.gui.menu.Menu; import bluegammon.gui.menu.MenuListener; import bluegammon.gui.menu.MenuPage; import bluegammon.gui.menu.PageItem; import bluegammon.gui.popup.Popup; import bluegammon.logic.GameRecord; import bluegammon.logic.Rules; /** * TheMenuCanvasis the handler of the Bluegammon * menu. There is only one menu per game, thus the singleton pattern. * * @see bluegammon.gui.menu.Menu * @author Peter Andersson */ public class MenuCanvas extends PopupCanvas implements MenuListener, ItemAction, CommandListener { /** Item property key containing help text */ protected static final int ITEM_HELP = 0; /** Action key for starting a local game */ protected static final int ACTION_LOCAL_START = 1; /** Action key for resuming a local game */ protected static final int ACTION_LOCAL_RESUME = 2; /** Action key for quitting midlet */ protected static final int ACTION_QUIT = 3; /** Action key for showing specific score*/ protected static final int ACTION_SCORE = 4; /** Action key for turning audio on/off */ protected static final int ACTION_AUDIO = 100; /** Action key for turning vibra on/off */ protected static final int ACTION_VIBRA = 101; /** Action key for showing about box */ protected static final int ACTION_ABOUT = 200; /** Softbutton back command */ protected static final Command CMD_BACK = new Command(Resources.getString(Resources.TXT_C_BACK), Command.BACK, 1); /** Softbutton help command */ protected static final Command CMD_HELP = new Command(Resources.getString(Resources.TXT_C_HELP), Command.ITEM, 1); /** The menu instance */ protected Menu m_menu; /** Softbuttons of the backgammon menu canvas */ protected SoftButtonControl m_softButtons; /** The background image */ protected Image m_background; /** Special page with scores */ protected MenuPage m_scorePage; /** The local resume page item */ protected PageItem m_resumeGameItem; /** The scores item */ protected PageItem m_scoresItem; /** Rule setting, max five, item */ protected RuleFlagItem m_max5Item; /** Rule setting, even out, item */ protected RuleFlagItem m_evenOutItem; /** Singleton instance */ protected static MenuCanvas m_inst = null; /** * Returns the singleton instance. * @return The singleton instance. */ public static MenuCanvas getInstance() { if (m_inst == null) { m_inst = new MenuCanvas(); } return m_inst; } /** * Creates the menu and initiates the gui controls */ protected MenuCanvas() { m_background = Resources.getImage(Resources.IMG_BACKGROUND); m_softButtons = new SoftButtonControl(); PageItem item; // Create menu MenuPage mainPage = new MenuPage(Resources.getChars(Resources.TXT_T_BLUEGAMMON), null); m_menu = new Menu(mainPage, this, new BackgammonMenuPainter(getWidth())); // Menu titles MenuPage btPage = new MenuPage(Resources.getChars(Resources.TXT_T_BLUETOOTH), null); MenuPage phonePage = new MenuPage(Resources.getChars(Resources.TXT_T_PHONEGAME), null); MenuPage settingsPage = new MenuPage(Resources.getChars(Resources.TXT_T_SETTINGS), null); MenuPage rulesPage = new MenuPage(Resources.getChars(Resources.TXT_T_RULES), null); m_scorePage = new MenuPage(Resources.getChars(Resources.TXT_T_SCORES), null); // Menu main page PageItem btItem = new PageItem(Resources.getChars(Resources.TXT_I_BTGAME), null, null, btPage); btItem.setEnabled(Device.canBluetooth()); btItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_BT_GAME)); PageItem phoneItem = new PageItem(Resources.getChars(Resources.TXT_I_PHONE_GAME), null, null, phonePage); phoneItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_PHONE_GAME)); m_scoresItem = new PageItem(Resources.getChars(Resources.TXT_I_BT_SCORES), null, this, m_scorePage); m_scoresItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_SCORES)); PageItem settingsItem = new PageItem(Resources.getChars(Resources.TXT_I_SETTINGS), null, null, settingsPage); settingsItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_SETTINGS)); mainPage.addItem(btItem); mainPage.addItem(phoneItem); mainPage.addItem(m_scoresItem); mainPage.addItem(settingsItem); mainPage.addItem( new PageItem(Resources.getChars(Resources.TXT_I_ABOUT), null, this, null, ACTION_ABOUT)); mainPage.addItem( new PageItem(Resources.getChars(Resources.TXT_I_EXIT), null, this, null, ACTION_QUIT)); // Menu bluetooth page PageItem btServerItem = new PageItem(Resources.getChars(Resources.TXT_I_BT_SERVER), null, new BluetoothServerWorkflow(), null); btServerItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_BT_SERVER)); BluetoothDevicePage bdp = new BluetoothDevicePage(Resources.getChars(Resources.TXT_T_DEVICES), m_menu, this, m_softButtons); BluetoothClientWorkflow bch = new BluetoothClientWorkflow(bdp); bdp.setClientWorkflow(bch); PageItem btClientItem = new PageItem(Resources.getChars(Resources.TXT_I_BT_CLIENT), null, bch, bdp); btClientItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_BT_CLIENT)); btPage.addItem(btServerItem); btPage.addItem(btClientItem); // Menu local phone page m_resumeGameItem = new PageItem(Resources.getChars(Resources.TXT_I_PG_RESUME), null, this, null, ACTION_LOCAL_RESUME); m_resumeGameItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_PG_RESUME)); PageItem pgNewGameItem = new PageItem(Resources.getChars(Resources.TXT_I_PG_NEW_GAME), null, this, null, ACTION_LOCAL_START); pgNewGameItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_PG_NEW_GAME)); phonePage.addItem(m_resumeGameItem); phonePage.addItem(pgNewGameItem); // Rules page m_max5Item = new RuleFlagItem ( Rules.MAX_FIVE, Resources.getChars(Resources.TXT_I_R_MAXFIVE), Resources.getImage(Resources.IMG_ENABLED), Resources.getImage(Resources.IMG_DISABLED), Integer.MIN_VALUE); m_max5Item.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_R_MAX_FIVE)); m_evenOutItem = new RuleFlagItem ( Rules.EVEN_OUT, Resources.getChars(Resources.TXT_I_R_EVENOUT), Resources.getImage(Resources.IMG_ENABLED), Resources.getImage(Resources.IMG_DISABLED), Integer.MIN_VALUE); m_evenOutItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_R_EVEN_OUT)); rulesPage.addItem(m_max5Item); rulesPage.addItem(m_evenOutItem); // Settings page PersistenceFlagItem perfColItem = new PersistenceFlagItem( Bluegammon.BLACK_PREFERRED, Resources.getChars(Resources.TXT_I_S_COLOR), Resources.getImage(Resources.IMG_BLACK_PIECE), Resources.getImage(Resources.IMG_WHITE_PIECE), Integer.MIN_VALUE); perfColItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_S_COLOR)); PersistenceFlagItem audioItem = new PersistenceFlagItem( Bluegammon.AUDIO_OFF, Resources.getChars(Resources.TXT_I_S_AUDIO), Resources.getImage(Resources.IMG_AUDIO_OFF), Resources.getImage(Resources.IMG_AUDIO_ON), ACTION_AUDIO); audioItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_S_AUDIO)); PersistenceFlagItem vibraItem = new PersistenceFlagItem( Bluegammon.VIBRA_OFF, Resources.getChars(Resources.TXT_I_S_VIBRA), Resources.getImage(Resources.IMG_VIBRA_OFF), Resources.getImage(Resources.IMG_VIBRA_ON), ACTION_VIBRA); vibraItem.setEnabled(Device.canVibrate()); vibraItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_S_VIBRA)); PageItem rulesItem = new PageItem(Resources.getChars(Resources.TXT_I_PG_RULES), null, null, rulesPage); rulesItem.setLayout(PageItem.LAYOUT_ALIGN_RIGHT); rulesItem.setProperty(ITEM_HELP, Resources.getChars(Resources.TXT_H_S_RULES)); settingsPage.addItem(perfColItem); settingsPage.addItem(audioItem); settingsPage.addItem(vibraItem); settingsPage.addItem(rulesItem); setFullScreenMode(true); // Initiate softbuttons m_softButtons.init(this, Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL), CMD_BACK, CMD_HELP); m_softButtons.setCommandListener(this); m_softButtons.enable(CMD_HELP, false); // Setup menu int menuPadding = 16; m_menu.setLocation(0, menuPadding); m_menu.setDimensions(getWidth(), getHeight() - menuPadding * 2); m_menu.setFrameData(10, 20); m_menu.setListener(this); m_menu.start(); } /** * Initializes the states of items and * starts the muzak, called on an already * initialized menu when it is focused again. */ public void initShow() { m_max5Item.setBoolean(Rules.isSet(Rules.MAX_FIVE)); m_evenOutItem.setBoolean(Rules.isSet(Rules.EVEN_OUT)); m_resumeGameItem.setEnabled(Bluegammon.hasSavedLocalGame()); m_scoresItem.setEnabled(GameRecord.countRecords() > 0); m_scorePage.removeAllItems(); Vector recs = GameRecord.getAllRecords(); for (int i = 0; i < recs.size(); i++) { GameRecord rec = (GameRecord)recs.elementAt(i); if (rec.getGameCount() > 0) { m_scorePage.addItem(new GameRecordPageItem(rec)); } } PageItem selItem = m_menu.getSelectedItem(); if (selItem != null) { Object helpTxt = selItem.getProperty(ITEM_HELP); m_softButtons.enable(CMD_HELP, helpTxt != null); } Audio.playSound(Audio.MUSIC); } /** * Paints the menu, the possible popup, and the softbuttons. * @param g The graphics context to draw on. */ protected void paint(Graphics g) { g.setColor(0x888833); g.fillRect(0, 0, getWidth(), getHeight()); g.drawImage(m_background, getWidth() / 2, getHeight() / 2, Graphics.VCENTER | Graphics.HCENTER); m_menu.paint(g); m_softButtons.paint(g); if (getPopup() != null && getPopup().isActive()) { getPopup().paint(g); } } /** * Called when user presses a key. Dispatches the keypress to * possible popup, menu and softbuttons. * @param keyCode The code of the key that is pressed. */ protected void keyPressed(int keyCode) { if (getPopup() != null && getPopup().isActive()) { getPopup().keyPressed(keyCode, getGameAction(keyCode)); repaint(); } else { m_menu.keyPressed(keyCode); m_softButtons.keyPressed(keyCode); } } // Commandlistener implementation // See interface javadoc public void commandAction(Command c, Displayable d) { if (c == CMD_BACK) { m_menu.goBack(); } else if (c == CMD_HELP) { PageItem item = m_menu.getSelectedItem(); if (item != null) { char[] helpTxt = (char[])item.getProperty(ITEM_HELP); if (helpTxt != null) { Bluegammon.showPopup(helpTxt, Popup.ALT_OK, 0, 0, 0, null); } } } } /** * ItemAction implementation, called from items in * this menu. Instead of creating one class per action, * we centralize the action behaviour here. Each action * is identified by its id. * * @param page The page from which the action was called * @param item The item to which the action belongs */ public void itemAction(MenuPage page, PageItem item) { int id = item.getId(); switch(id) { case ACTION_LOCAL_START: Bluegammon.startLocalGame(); break; case ACTION_LOCAL_RESUME: Bluegammon.resumeSavedLocalGame(); break; case ACTION_QUIT: Bluegammon.shutdown(); break; case ACTION_SCORE: GameRecordPageItem grItem = (GameRecordPageItem)item; String str = new String(grItem.getOpponentNameChars()) + "\n\n" + Resources.getString(Resources.TXT_SCORE_PLAYER) + ": " + new String(grItem.getPlayerScoreChars()) + "\n" + Resources.getString(Resources.TXT_SCORE_OPPONENT) + ": " + new String(grItem.getOpponentScoreChars()) + "\n" + Resources.getString(Resources.TXT_SCORE_GAMES) + ": " + new String(grItem.getGamesChars()) + "\n" + Resources.getString(Resources.TXT_SCORE_DATE) + ": " + new String(grItem.getLastDateChars()) + "\n\n"; char[] text = str.toCharArray(); Bluegammon.showPopup(text, Popup.ALT_OK, 0, 0, 0, null); break; case ACTION_AUDIO: if (RmsFacade.getBoolean(Bluegammon.AUDIO_OFF)) { Audio.stopSound(Audio.MUSIC); } else { Audio.playSound(Audio.MUSIC); } break; case ACTION_VIBRA: if (!RmsFacade.getBoolean(Bluegammon.VIBRA_OFF)) { Device.vibrate(100,100,3); } break; case ACTION_ABOUT: Bluegammon.showPopup(Resources.getChars(Resources.TXT_ABOUT), Popup.ALT_OK, 0, 0, 0, null); break; } } // Menulistener implementation // See interface javadoc public void newPage(MenuPage fromPage, MenuPage toPage, boolean back) { m_softButtons.enable(CMD_BACK, toPage != m_menu.getStartPage()); if (fromPage instanceof FocusablePage) { ((FocusablePage)fromPage).onLeave(); } if (toPage instanceof FocusablePage) { ((FocusablePage)toPage).onEnter(); } } // See interface javadoc public void itemSelected(MenuPage page, PageItem oldItem, PageItem newItem) { if (newItem != null) { Object helpTxt = newItem.getProperty(ITEM_HELP); m_softButtons.enable(CMD_HELP, helpTxt != null); } } // See interface javadoc public void actionCalled(MenuPage page, PageItem item, ItemAction action) {} // See interface javadoc public void transitionStarted(MenuPage fromPage, MenuPage toPage, long delay, int frames, boolean back) {} // See interface javadoc public void transitionStopped(MenuPage fromPage, MenuPage toPage) {} /** * Binary page item turning boolean flags in rms on and off. * @author Peter Andersson */ class PersistenceFlagItem extends BinaryPageItem { protected int m_key; public PersistenceFlagItem(int key, char[] label, Image imageTrue, Image imageFalse, int id) { super(label, imageTrue, imageFalse, null, MenuCanvas.this, id); m_key = key; } public boolean getBoolean() { return RmsFacade.getBoolean(m_key); } public void setBoolean(boolean value) { RmsFacade.setBoolean(m_key, value); } } // end of PersistenceFlagItem /** * Binary page item turning boolean rule-flags on and off. * @author Peter Andersson */ class RuleFlagItem extends BinaryPageItem { protected int m_rule; public RuleFlagItem(int rule, char[] label, Image imageTrue, Image imageFalse, int id) { super(label, imageTrue, imageFalse, null, MenuCanvas.this, id); m_rule = rule; } public boolean getBoolean() { return Rules.isSet(m_rule); } public void setBoolean(boolean value) { Rules.set(m_rule, value); RmsFacade.setInt(Bluegammon.RULES_PREFERRED, Rules.getRuleFlags()); } } // end of RuleFlagItem /** * Game record page item showing score status. * @author Peter Andersson */ class GameRecordPageItem extends PageItem { protected GameRecord m_record = null; protected char[] m_opponentNameChars; protected char[] m_playerScoreChars; protected char[] m_opponentScoreChars; protected char[] m_gamesChars; protected char[] m_lastDateChars; public GameRecordPageItem(GameRecord rec) { super(null, null, MenuCanvas.this, null, ACTION_SCORE); m_record = rec; m_opponentNameChars = rec.getOpponentName(); m_playerScoreChars = Integer.toString(rec.getPlayerScore()).toCharArray(); m_opponentScoreChars = Integer.toString(rec.getOpponentScore()).toCharArray(); m_gamesChars = Integer.toString(rec.getGameCount()).toCharArray(); Calendar cal = Calendar.getInstance(); cal.setTime(new Date(rec.getTimestamp())); String lastGameDate = cal.get(Calendar.DAY_OF_MONTH) + " "; int month = cal.get(Calendar.MONTH); switch(month) { case Calendar.JANUARY: lastGameDate += "Jan"; break; case Calendar.FEBRUARY: lastGameDate += "Feb"; break; case Calendar.MARCH: lastGameDate += "Mar"; break; case Calendar.APRIL: lastGameDate += "Apr"; break; case Calendar.MAY: lastGameDate += "May"; break; case Calendar.JUNE: lastGameDate += "Jun"; break; case Calendar.JULY: lastGameDate += "Jul"; break; case Calendar.AUGUST: lastGameDate += "Aug"; break; case Calendar.SEPTEMBER: lastGameDate += "Sep"; break; case Calendar.OCTOBER: lastGameDate += "Oct"; break; case Calendar.NOVEMBER: lastGameDate += "Nov"; break; case Calendar.DECEMBER: lastGameDate += "Dec"; break; } //lastGameDate += " " + cal.get(Calendar.YEAR); int hour = cal.get(Calendar.HOUR_OF_DAY); lastGameDate += (hour < 10 ? " 0" : " ") + hour; int minute = cal.get(Calendar.MINUTE); lastGameDate += (minute < 10 ? ":0" : ":") + minute; m_lastDateChars = lastGameDate.toCharArray(); setLayout(LAYOUT_ALIGN_LEFT); } public char[] getGamesChars() { return m_gamesChars; } public char[] getLastDateChars() { return m_lastDateChars; } public char[] getOpponentNameChars() { return m_opponentNameChars; } public char[] getOpponentScoreChars() { return m_opponentScoreChars; } public char[] getPlayerScoreChars() { return m_playerScoreChars; } public GameRecord getRecord() { return m_record; } } // end of GameRecordPageItem /** * Special painter that also paintsGameRecordPageItems and * adds special effects for selected items. * @author Peter Andersson */ static class BackgammonMenuPainter extends DefaultMenuPainter { protected static final char[] SCORE_TXT = "9999".toCharArray(); protected int m_scoreWidth; protected int[] m_rgbData; protected int m_canvasWidth; public BackgammonMenuPainter(int canvasWidth) { // Create selected item rgb buffer m_canvasWidth = canvasWidth; m_rgbData = new int[m_canvasWidth * 4]; int bgcol = 0x880000; for (int i = 0; i < m_canvasWidth; i++) { double alpha = (double)Math.abs(i - m_canvasWidth / 2) / (double)m_canvasWidth; int col = bgcol | (128 - (int)(255 * alpha) << 24); m_rgbData[i] = col; m_rgbData[i + m_canvasWidth ] = col; m_rgbData[i + m_canvasWidth * 2] = col; m_rgbData[i + m_canvasWidth * 3] = col; } // Calculate maximum score text width m_scoreWidth = super.m_itemFont.charsWidth(SCORE_TXT, 0, SCORE_TXT.length); } // Extend PageItem.paintItem to handle GameRecordPageItems protected void paintItem(Graphics g, PageItem item, boolean selected, int x, int y, int w, int iMaxW, boolean to, boolean from) { if (selected) { int itemH = getItemHeight(item); // draw transparent background on selected item for (int by = y; by < y + itemH; by += 4) { g.drawRGB(m_rgbData, 0, m_canvasWidth, x - m_canvasWidth/2, by, m_canvasWidth, Math.min(4, y + itemH - (by - y)), true); } } if (item instanceof GameRecordPageItem) { g.setFont(super.m_itemFont); GameRecordPageItem grItem = (GameRecordPageItem)item; char[] opName = grItem.getOpponentNameChars(); char[] plScore = grItem.getPlayerScoreChars(); char[] opScore = grItem.getOpponentScoreChars(); if (!selected) { g.setColor(grItem.isEnabled() ? super.m_itemColor : super.m_itemColorDisabled); } else { g.setColor(super.m_selItemColor); } g.drawChars(opName, 0, opName.length, x - iMaxW / 2, y, Graphics.TOP | Graphics.LEFT); g.drawChars(plScore, 0, plScore.length, x - iMaxW / 2 + iMaxW - m_scoreWidth - super.m_imgPadding, y, Graphics.TOP | Graphics.RIGHT); g.drawChars(opScore, 0, opScore.length, x - iMaxW / 2 + iMaxW, y, Graphics.TOP | Graphics.RIGHT); } else { super.paintItem(g, item, selected, x, y, w, iMaxW, to, from); } } // Extend PageItem.getItemWidth to handle GameRecordPageItems protected int getItemWidth(PageItem item) { if (item instanceof GameRecordPageItem) { GameRecordPageItem grItem = (GameRecordPageItem)item; int w = super.m_itemFont.charsWidth(grItem.getOpponentNameChars(), 0, grItem.getOpponentNameChars().length); w += m_scoreWidth * 2; w += super.m_imgPadding * 2; return w; } else { return super.getItemWidth(item); } } } // end of BackgammonMenuPainter }