📄 progkeys.java
字号:
/*
* Copyright, 2005, S.E.Morris, C.Speirs
*
* This file is part of SudokuME.
*
* SudokuME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* SudokuME 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with SudokuME; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package sudoku;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
// **********************************************************
// A screen that lets the user assign key-codes to various commands
// This is implemented as a canvas ... contents as follows:
// list with First Option: "Return to main menu" - soft key: Select
// Rest of options (scrollable): list of keys with current KeyCode - soft keys: program / clear
//
// Improvements:
// -) Indicate to User when number keys are free - (?separate for 9x9 and 12x12?) (grey out "Increment" ?)
// X) Check Rules
// -) Copy results back to a key lookup hash
// -) set useNumKeys
// X) save settings in record store
// X) add defaults for known phones.
//
// **********************************************************
class ProgKeys extends Canvas implements CommandListener {
public static final String[] funcStr =
{ "Menu", "Shift", "Left", "Right", "Up", "Down", "Working", "Undo", "Timer", "Lock Cell", "Increment", "Lock Working", "Left Soft Key", "Mid Soft Key", "Right Soft Key" };
static final int RETURN_TO_MENU=-5;
static final int USE_FULL_SCREEN=-4;
static final int AUTO_WORKING=-3;
static final int WORKING_IN_CELL=-2;
static final int BLANK_WORKING=-1; // Blank working for filled cells
static final int MENU=0;
static final int SHIFT=1;
static final int LEFT=2;
static final int RIGHT=3;
static final int UP=4;
static final int DOWN=5;
static final int WORKING=6;
static final int UNDO=7;
static final int TIMER=8;
static final int LOCK_CELL=9;
static final int INCREMENT=10;
static final int LOCK_WORKING=11; // leave this as the last key before the soft keys so that it is always the last found match.
static final int LEFT_SOFT=12;
static final int MID_SOFT=13;
static final int RIGHT_SOFT=14;
static final int REC_STORE_INTRO=3; // number of bytes at start (Version, Mode, FullScreen)
static final int REC_STORE_ENTRY=5; // number of bytes per entry
static final int REC_STORE_SIZE=REC_STORE_INTRO+funcStr.length*REC_STORE_ENTRY;
public int[] funcKeyCode = {0,0,50,51,52,53,54,55,56,57,48,49,50,51,52}; // 0 = not programmed
public boolean[] funcKeyShifted = {false, false, false, false, false, false, false, false, false, false, true, true, true, true, true} ; // if true then shift key needs to be pressed to select this function
private boolean[] bool_funcKeyCommand = {true, false, false, false, false, false, false, false, false, false, false, false, false, false, false} ; // if true then shift key needs to be pressed to select this function
public Command[] funcKeyCommand;
public boolean useFullScreen = false;
public boolean autoWorking = false;
public boolean workingInCell = true;
public boolean blankWorking = true;
private Displayable parent; // Parent screen
private Display display;
private int fh; // Font height
private int item=RETURN_TO_MENU; // currently selected item
private int scroll=RETURN_TO_MENU; // Current number of lines scrolled
private int horizScroll=0;
static final int HORIZ_SCROLL_DIST=4;
private boolean programming=false; // are we programming a key?
private boolean shift=false; // track if shift is selected
private Command programKeyCode; // Program a new key-code
private Command setCommand; // Assign this function to a Command Button
private Command clearKeyCode; // clear the current key-code
private Command exitCommand; // Commands
private Command yesCommand; // used to set / clear full screen
private Command noCommand; // used to set / clear full screen
// Soft keys are just there so we can correctly format text later
// If shift is defined, we can try to detect it for other key-combos
// Rules as follows:
// If Menu is not defined then we will have to use a Command Listener!
// Increment must be defined unless KEY1 to KEY9 are not used anywhere (for 12x12, also need *,0,#)
// No key code can be used for multiple Functions except:
// Soft keys can use same as others (but not each-other)
// Lock Working can be on the same combo as (Lock Cell or Undo or Timer) ... if so, then it
// can only be used when working is selected
ProgKeys() {
funcKeyCommand = new Command[funcStr.length];
/* set intial values of the keys */
setDefaultKeys();
_fillFuncKeyCommandArray();
}
private class _findRecordId implements RecordFilter {
public boolean matches(byte[] candidate) {
return (candidate[0] >= 4 && candidate[1] == SudokuME.KEYCODE_RECORD);
}
}
public void setDefaultKeys() {
int i;
for (i = 0; i < funcStr.length; i++) {
funcKeyCode[i] = 0;
funcKeyShifted[i] = false;
bool_funcKeyCommand[i] = false;
}
// per default, set same codes as in original game
// Note, is not perfect as the game action may be mapped on multiple keys but we lose this
if (System.getProperty("microedition.platform").indexOf("Nokia6230") != -1) {
// This phone has 3 soft keys, a send key and a 4-way arrow available. All functions
// are mapped onto these keys, keeping the whole number pad free for direct-entry.
// Menu, Shift, Left, Right, Up, Down, Working, Undo, Timer, Lock Cell, Increment, Lock Work, LSK, MSK, RSK
int[] defaultKeyCode = { -6, -7, -3, -4, -1, -2, -5, -6, -5, -10, 0, -10, -6, -5, -7};
boolean[] defaultShifted={false, false, false, false, false, false, false, true, true, false, false, false, false, false, false} ;
funcKeyCode = defaultKeyCode;
funcKeyShifted= defaultShifted;
useFullScreen=true;
} else {
funcKeyCode[SHIFT] = getKeyCode(GAME_D);
funcKeyCode[LEFT] = getKeyCode(Canvas.LEFT);
funcKeyCode[RIGHT] = getKeyCode(Canvas.RIGHT);
funcKeyCode[UP] = getKeyCode(Canvas.UP);
funcKeyCode[DOWN] = getKeyCode(Canvas.DOWN);
funcKeyCode[WORKING] = getKeyCode(GAME_B);
funcKeyCode[UNDO] = getKeyCode(GAME_C);
funcKeyCode[TIMER] = getKeyCode(GAME_B);
funcKeyCode[LOCK_WORKING] = getKeyCode(GAME_C);
funcKeyCode[LOCK_CELL] = getKeyCode(GAME_C);
funcKeyCode[INCREMENT] = getKeyCode(Canvas.FIRE);
funcKeyShifted[UNDO] = true;
funcKeyShifted[TIMER] = true;
bool_funcKeyCommand[MENU] = true;
}
}
// Load keys from record store
// keystore is stored as REC_STORE_ENTRY bytes per keyCode -
// first byte stores SHIFT status in bit 0 and Command status in bit 1
// next 4 bytes stores keyCode as int.
public boolean loadKeys() {
RecordStore rs=null;
int recId;
byte recordBuffer[];
try
{ // -----Attempt to find the record holding the KeyCodes
rs = RecordStore.openRecordStore(SudokuME.REC_STORE_NAME,false);
RecordEnumeration re = rs.enumerateRecords(new _findRecordId(),null,false);
if(re.hasNextElement()) {
recId=re.nextRecordId();
int len=rs.getRecordSize(recId);
if (len < REC_STORE_SIZE) {
Alert alert;
alert = new Alert("Error", "Unable to load KeyCodes due to error in record store", null, AlertType.ERROR);
alert.setTimeout(3000);
rs.deleteRecord(recId);
SudokuME.display.setCurrent(alert,SudokuME.display.getCurrent());
return false;
}
recordBuffer = rs.getRecord(recId);
int i;
useFullScreen = ((recordBuffer[2]&(1 << (-USE_FULL_SCREEN)))==0?false:true);
autoWorking = ((recordBuffer[2]&(1 << (-AUTO_WORKING)))==0?false:true);
workingInCell = ((recordBuffer[2]&(1 << (-WORKING_IN_CELL)))==0?false:true);
blankWorking = ((recordBuffer[2]&(1 << (-BLANK_WORKING)))==0?false:true);
for (i = 0; i < funcStr.length; i++) {
funcKeyShifted[i] = ((recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY]&1) == 0?false:true);
bool_funcKeyCommand[i] = ((recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY]&2) == 0?false:true);
funcKeyCode[i] = 0;
funcKeyCode[i] = funcKeyCode[i] | (recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY+1] << 24);
funcKeyCode[i] = funcKeyCode[i] | (recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY+2] << 16);
funcKeyCode[i] = funcKeyCode[i] | (recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY+3] << 8);
funcKeyCode[i] = funcKeyCode[i] | (recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY+4]);
}
if(re.hasNextElement()) {
recId=re.nextRecordId();
rs.deleteRecord(recId);
Alert alert;
alert = new Alert("Warning", "Second Keycode record found, deleted", null, AlertType.WARNING);
alert.setTimeout(3000);
SudokuME.display.setCurrent(alert,SudokuME.display.getCurrent());
}
return true;
}
// no record found;
return false;
}
catch(Exception e)
{
if(!(e instanceof RecordStoreNotFoundException) && SudokuME.debug) e.printStackTrace();
return false;
}
finally
{ try { rs.closeRecordStore(); }catch(Exception e) {}
}
}
// Save keys in record store
public void saveKeys() {
RecordStore rs=null;
int recId = -1;
byte recordBuffer[];
recordBuffer = new byte[REC_STORE_SIZE];
recordBuffer[0] = SudokuME.FORMAT_VERSION;
recordBuffer[1] = SudokuME.KEYCODE_RECORD;
recordBuffer[2] = (byte)(((useFullScreen?1:0) << (-USE_FULL_SCREEN)) |
((autoWorking?1:0) << (-AUTO_WORKING)) |
((workingInCell?1:0) << (-WORKING_IN_CELL)) |
((blankWorking?1:0) << (-BLANK_WORKING)));
int i;
for (i = 0; i < funcStr.length; i++) {
recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY] = (byte)((funcKeyShifted[i]?1:0) | (bool_funcKeyCommand[i]?2:0));
recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY+1] = (byte)((funcKeyCode[i] >> 24) & 0xff);
recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY+2] = (byte)((funcKeyCode[i] >> 16) & 0xff);
recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY+3] = (byte)((funcKeyCode[i] >> 8) & 0xff);
recordBuffer[REC_STORE_INTRO+i*REC_STORE_ENTRY+4] = (byte)((funcKeyCode[i] >> 0) & 0xff);
}
try
{ // -----Attempt to find the record holding the KeyCodes
rs = RecordStore.openRecordStore(SudokuME.REC_STORE_NAME,true);
RecordEnumeration re = rs.enumerateRecords(new _findRecordId(),null,false);
if(re.hasNextElement()) {
recId=re.nextRecordId();
rs.setRecord(recId, recordBuffer, 0, REC_STORE_SIZE);
} else {
rs.addRecord(recordBuffer, 0, REC_STORE_SIZE);
}
}
catch(Exception e)
{
if(!(e instanceof RecordStoreNotFoundException) && SudokuME.debug) e.printStackTrace();
return;
}
finally
{ try { rs.closeRecordStore(); }catch(Exception e) {}
}
}
public void loadCanvas(Display d, Displayable p) {
parent=p;
display = d;
/* Create soft keys */
exitCommand = new Command("Select",Command.EXIT,1);
programKeyCode = new Command("Program",Command.STOP,1);
clearKeyCode = new Command("Clear",Command.OK,2);
setCommand = new Command("Command",Command.OK,1);
yesCommand = new Command("Yes",Command.OK,1);
noCommand = new Command("No",Command.CANCEL,1);
addCommand(exitCommand);
setCommandListener(this);
scroll=RETURN_TO_MENU;
item=RETURN_TO_MENU;
horizScroll=0;
if (SudokuME.hasMIDP2) {
if (useFullScreen) {
setFullScreenMode(true);
} else {
setFullScreenMode(false);
}
}
fh=Font.getDefaultFont().getHeight();
display.setCurrent(this);
}
public void paint(Graphics g) {
int w=getWidth() , h=getHeight(), currentItem, screenpos;
int usableHeight=h;
int maxLineWidth=0;
StringBuffer buffer;
g.setColor(0xff,0xff,0xff); g.fillRect(0,0,w,h);
if (useFullScreen) {
// Reduce the usableHeight so we can add a Menu prompt at the bottom
g.setColor(0x00,0x00,0x00);
usableHeight = h-fh-3;
g.drawString("Menu", w/2, h, Graphics.BOTTOM|Graphics.HCENTER);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -