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; 
 
 
/** 
 * The MenuCanvas is 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 paints GameRecordPageItems 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 
}