📄 terminalwindow.java
字号:
((GameWindow) gameWindows.elementAt(i)).adjourn();
}
}
/*
* Find a game window that matches by the names of the players.
* The reason the game number can't be used is that when games
* are adjourned and restarted on the server sometimes they are
* assigned a new number.
*/
public GameWindow getGameWindowByName(String white, String black) {
return getGameWindowByName(white, black, -1);
}
public GameWindow getGameWindowByName(String white, String black,
int number) {
for(Enumeration e = gameWindows.elements(); e.hasMoreElements(); ) {
GameWindow w = (GameWindow) e.nextElement();
if(w.game.whiteName.equals(white)
&& w.game.blackName.equals(black)) {
// Update the game number for this game and invalidate
// any other game with this number, if there is one.
// also, cooperate with SGC to maintain consistency - AMB at 0.7
if (number > 0) {
GameWindow old = getGameWindowByNumber(number);
if (old != null && old != w)
old.gameNumber = 0;
String oldtitle = w.title();
if (w.gameNumber != number) {
w.gameNumber = number;
w.updateTitle();
registrar.updateWindowTitle(w);
}
// inform now performed by ensureActive().
// always inform sgc, even if number is the same.
// conn.control.sgc.inform(w);
}
return w;
}
}
return null;
}
// Find a game window that matches the given game number.
// See getGameWindowByName for explanation.
//
// Fix for case for situation where game finishes,
// the window hangs around, and then the user starts to observe
// new server game with same number. This function preferentially
// returns the window corresponding to the active game, if there is
// a choice. AMB at 0.8
public GameWindow getGameWindowByNumber (int number) {
GameWindow stashedgw = null;
for(Enumeration e = gameWindows.elements(); e.hasMoreElements(); ) {
GameWindow w = (GameWindow) e.nextElement();
if (w.gameNumber == number) {
if (w.isOnServer())
stashedgw = w;
else if (stashedgw == null)
stashedgw = w;
}
}
return stashedgw;
}
public GameWindow getGameBeingPlayed() {
for(Enumeration e = gameWindows.elements(); e.hasMoreElements(); ) {
GameWindow w = (GameWindow) e.nextElement();
if (w.isParticipating())
return w;
}
return null;
}
/*************************************************
* Event handling *
*************************************************/
class menuListener extends urMenuListener {
public void itemSelected (MenuItem source) {
// The user has chosen a menu item.
if (source == loadItem)
load();
else if (source == saveOutputItem)
saveTerminalOutput(mainArea);
else if (source == clearOutputItem) {
mainArea.clearAll();
messageArea.clearAll();
}
else if (source == observeItem) {
if (observeDialog == null)
observeDialog = new ObserveDialog(TerminalWindow.this, conn);
observeDialog.show();
}
else if (source == matchItem)
new MatchDialog(TerminalWindow.this, false).open(conn);
else if (source == localGameItem)
startLocalGame();
else if (source == saveOptionsItem) {
String error = (ergo.inApplet
? "Can't write init file when running as an applet."
: opser.rewriteFile());
if (error != null) {
new InformDialog(TerminalWindow.this, "Error", error).open();
}
}
else if (source == aboutItem)
new AboutDialog(TerminalWindow.this, "About Ergo").open();
else if (source == docItem) {
// docItem is disabled when running as an app, but just in case...
if (ergo.inApplet)
ergo.getAppletContext().showDocument(ergo.getDocumentBase(),
"doc.html");
}
else if (source == newServerItem)
new NewServerDialog().open();
}
}
// This is called when a CheckboxMenuItem is clicked.
class checkboxListener extends urCheckboxListener {
public void itemStateChanged (ItemEvent e) {
Object mi = e.getSource();
if (mi == debugItem) {
boolean state = debugItem.getState();
Debug.setDebug(state);
opser.updateOption(GlobalOptions.debugmodeString, new Boolean(state));
}
else if (mi == rawItem) {
rawMode = !rawMode;
rawItem.setState(rawMode);
}
else if (mi == logicItem) {
Debug.debugGameLogicp = !Debug.debugGameLogicp;
logicItem.setState(Debug.debugGameLogicp);
}
else if (mi == soundItem) {
soundEnabled = !soundEnabled;
opser.updateOption(GlobalOptions.soundString,
new Boolean(soundEnabled));
soundItem.setState(soundEnabled);
}
}
}
/**********************************
* Command-line input processing *
**********************************/
private void send (String text) {
if (conn != null && conn.isConnected())
conn.send(text);
else {
displayString(text);
displayString(">>> Ergo: No server connection. Message not sent.");
}
}
private void processKibitzCommand (String command, ParsedMessage pm,
GameWindow gwin, boolean isLocal) {
String rest = pm.rest();
int gameNum = (gwin == null) ? -1 : gwin.gameNumber;
try {
pm.continueParse("%i ");
gameNum = ((Integer) pm.matchAt(1)).intValue();
rest = pm.rest(); // strip off the game number
}
catch (ParseException pe2) { }
GameWindow w = getGameWindowByNumber(gameNum);
if (w == null) w = gwin; // reasonable default?
if (w == null) {
// If there's a single active game, then use it.
GameWindow it = null;
int count = 0;
for (int i = 0; i < gameWindows.size(); i++) {
GameWindow g = (GameWindow) gameWindows.elementAt(i);
if (g.gameStatus != GameWindow.ADJOURNED
&& g.gameStatus != GameWindow.GAMEOVER) {
it = g;
++count;
}
}
if (count == 1)
w = it;
else
displayString(">>> Ergo: Kibitz not added to local game record since no game# was specified. Try kibitzing from the game window instead.");
}
if (w != null) {
if (!isLocal && w.isNetGame())
conn.send("kibitz " + w.gameNumber + " " + rest, false);
// When playing a teaching game kibitzes are sent to the players
// also. This tries to prevent those kibitzes from being displayed
// twice.
if (isLocal
|| !w.isNetGame()
|| !(w.isTeachingGame() && w.isParticipating())) {
w.addKibitz(getAccountName(), getRank(), rest, isLocal);
}
}
else
send(command); // No game specified. Just send command.
}
// When commands with one arg, the game number, are issued from a
// game window and no game number is specified, add the game number
// of the game window since that's undoubtedly what the user
// intended.
private void processGameArgCommand (String command, ParsedMessage pm,
GameWindow gwin) {
if (gwin == null) // command came from main window
send(command);
else { // add the game number if not already there.
String rest = pm.rest();
boolean hasMore = false;
for (int i = 0; i < rest.length(); i++)
if (!Character.isWhitespace(rest.charAt(i))) {
hasMore = true;
break;
}
if (hasMore)
send(command);
else
send(command + " " + gwin.gameNumber);
}
}
private boolean isWord(String word, String maximal, String minimal) {
if (conn == null || !conn.isConnected() || !conn.server.matchCase()) {
word = word.toLowerCase();
maximal = maximal.toLowerCase();
minimal = minimal.toLowerCase();
}
return (maximal.startsWith(word) && word.startsWith(minimal));
}
private boolean stringEqual (String s1, String s2) {
return ((conn == null || !conn.isConnected() || !conn.server.matchCase())
? s1.equalsIgnoreCase(s2)
: s1.equals(s2));
}
// Process commands entered into the inputField.
public void processCommand (String text, GameWindow gwin) {
CommandHistory hist
= (gwin == null) ? commandHistory : gwin.getCommandHistory();
if (hist != null && text != null && !"".equals(text))
hist.addElement(text);
try {
ParsedMessage pmess = new ParsedMessage(text, " %s ");
String firstWord = (String) pmess.matchAt(0);
if ("'".equals(firstWord)
|| isWord(firstWord, "kibitz ", "kib"))
processKibitzCommand(text, pmess, gwin, false);
else if (stringEqual("say", firstWord)) {
conn.send(text);
GameWindow w = getGameBeingPlayed();
if (w != null && !w.isTeachingGame())
w.addKibitz1("*" + getAccountName() + "*: " + pmess.rest(), false);
}
else if (stringEqual(firstWord, "all"))
processGameArgCommand(text, pmess, gwin);
else if (stringEqual(firstWord, "time"))
processGameArgCommand(text, pmess, gwin);
else if (stringEqual(firstWord, "moves"))
processGameArgCommand(text, pmess, gwin);
else if (stringEqual(firstWord, "score"))
processGameArgCommand(text, pmess, gwin);
else if (isWord(firstWord, "localkibitz ", "loc")
|| stringEqual(firstWord, "lkib")
|| "$".equals(firstWord))
processKibitzCommand(text, pmess, gwin, true);
else // No special processing for the command.
send(text);
}
catch (ParseException pe) {
// If there was a ParseException then there must be no first word.
send(text);
}
}
/****************************
* Miscellaneous code *
****************************/
public boolean getSoundEnabled () {
return soundEnabled;
}
public void setDefaultDirectory (String dir) {
defaultDirectory = dir;
}
public String getDefaultDirectory () {
return defaultDirectory;
}
public boolean saveTerminalOutput (TextArea area) {
// Ask the user for a pathname.
FileDialog saveDialog
= new FileDialog(this, "Save Terminal Output...", FileDialog.SAVE);
if (getDefaultDirectory() != null)
saveDialog.setDirectory(getDefaultDirectory());
saveDialog.setFile("output.txt");
saveDialog.show();
if (saveDialog.getFile() == null)
return true;
else {
String filename = saveDialog.getDirectory() + saveDialog.getFile();
try {
PrintWriter out = new PrintWriter(new FileWriter(filename));
area.save(out);
out.close();
setDefaultDirectory(saveDialog.getDirectory());
return false;
}
catch (IOException e) {
displayString("Error during save: " + e);
}
}
return false;
}
// Load an SGF file.
public void load () {
FileDialog fd = new FileDialog(this, "Load SGF file");
if (defaultDirectory != null)
fd.setDirectory(getDefaultDirectory());
fd.setFilenameFilter(new FilenameFilter() {
public boolean accept (File dir, String filename) {
return filename.toLowerCase().endsWith("sgf");
}
});
fd.show();
String filename = fd.getFile();
if (filename != null) {
setDefaultDirectory(fd.getDirectory());
filename = fd.getDirectory() + filename;
SGF parser = new SGF(this);
try {
Vector games = parser.readSGFFile(filename);
for (int i = 0; i < games.size(); i++) {
Game game = (Game) games.elementAt(i);
try {
GameWindow gwin = new GameWindow(game, this);
game.setWindow(gwin);
addGameWindow(gwin);
gwin.setKibitzState(true, true);
}
catch (ErgoException e) {
Debug.backtrace(e);
}
}
}
catch (Exception e) {
Debug.backtrace(e);
new InformDialog(this, "Error", "Invalid SGF file: \n"
+ e.getMessage()).open();
}
}
}
// +++ This uses package scope rather than private to workaround
// Java bug 4034664. Fixed in Java 1.2.
// I don't know what code the above comment refers to anymore.
private void exit () {
if (conn.isConnected()) {
ActionListener listener = new ActionListener () {
public void actionPerformed (ActionEvent e) {
String cmd = e.getActionCommand();
if ("yes".equalsIgnoreCase(cmd))
actuallyExit();
}
};
new YNCDialog(this, "Really quit?", true,
"You are still connected to " + conn + ". Disconnect and quit?",
listener, false).open();
}
else
actuallyExit();
}
private void actuallyExit() {
if (conn.isConnected())
conn.close();
if (ergo.inApplet)
setVisible(false); // hides game windows also.
else {
if (opser.getBooleanOption(exitString))
opser.rewriteFile();
System.exit(0);
}
}
public void setVisible (boolean visible) {
if (!visible) {
super.setVisible(visible);
for (int i = 0; i < gameWindows.size(); i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -