⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gamewindow.java

📁 ErGo是一个很早的Java通用围棋服务器(IGS/NNGS)客户端程序。有全部源码和文档
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
package ergo.ui;

///  $Id: GameWindow.java,v 1.9 1999/08/29 02:42:24 sigue Exp $

/*
 *  Copyright (C) 1999  Carl L. Gay and Antranig M. Basman.
 *  See the file copyright.txt, distributed with this software,
 *  for further information.
 */

import ergo.Ergo;
import ergo.GlobalOptions;
import ergo.util.*;
import ergo.logic.*;
import ergo.server.ServerConnection;

import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.util.Vector;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import nom.rb.common.*;

/**
 * A GameWindow is responsible for coordinating a single game (playing
 * or observing).  It handles all user input for that game, i.e., menus
 * and mousing.  The two important objects it deals with are the Game
 * object which handles the game logic, and the BoardCanvas, which does
 * all drawing on the board.
 * <p>
 * Structural note - the thread for this Frame is created in
 * TerminalWindow.addGameWindow().... AMB at 0.7
 */
public class GameWindow extends Frame
  implements Runnable, WindowsMenuCommand, Optionizable, OutputFocus, PopupContributor {

  public static final int PLAYING = 0, ADJOURNED = 1, GAMEOVER = 2, SCORING = 3;

  private PopupController popupControl;
  private PopupHandler popupHandler;

  // Default background is "cream" colored.
  // The string is parsed as a ColorSpec.
  public static final String gwinDefaultBackground = "255 255 230";

  // Question: Is the SCORING state in use? AMB 0.8
  // isOnServer() below assumes that PLAYING is enough.
  // I think it is used.  -sigue

  public ServerConnection conn = null;
  int gameNumber;		// 0 if game invalid, -1 if local game
  int gameStatus;		// PLAYING, ADJOURNED, GAMEOVER, etc.
  private boolean isParticipating; // Whether the user is a player in this game.
  private int ourColor;
  public Game game;		// The game record.  Should be private.
  TerminalWindow window;
  Optionizer opser = Ergo.opser;

  private boolean browsing = false;	// Set with setBrowsing().
  private boolean savedBrowsing;	// used by scoring mode.
  private int jumpSize = 20;            // Number of moves to jump forward or back.
  private String filename = null; // Filename associated with this game.
  private boolean needsSaving = false;

  private CommandHistory commandHistory = new CommandHistory();
  boolean showKibitzes = true;
  private boolean showKibitzesForThisMoveOnly = false;

  private boolean tallConfiguration = true;

  // Components of the game window
  private Panel topPanel = new GWPanel();    // top, containing goban and status
  private Panel bottomPanel = new GWPanel(); // bottom, containing kibitz, etc

  private CoordinateCanvas northCanvas;
  private CoordinateCanvas southCanvas;
  private CoordinateCanvas eastCanvas;
  private CoordinateCanvas westCanvas;
  private StatusPanel statusPanel;
  private BoardCanvas boardCanvas;
  private Panel boardPanel = new GWPanel();
  private TextArea kibitzArea = new TextArea(6, 40, null, true);
  private TextField inputField = new TextField();

  private mouseListener mouseListen = new mouseListener();

  private ImageButton makeImageButton (String filename) {
    Image button_image = Ergo.loadImage("/" + Ergo.mmdir + filename);
    ImageButton ib = new ImageButton(button_image);
    ib.addMouseListener(mouseListen);
    return ib;
  }

/***
 *
 * The browseButton was partially implemented and then removed.  Search
 * for browseButton.
  private Button browseButton = null;  // Label changes: "Browse" <-> "Stop Browsing"
 ***/

  private ImageButton stepBackButton;
  private ImageButton stepForwardButton;
  //private ImageButton jumpBackButton;
  //private ImageButton jumpForwardButton;
  private ImageButton toBeginningButton;
  private ImageButton toEndButton;
  private ImageButton fwdKibButton;
  private ImageButton backKibButton;
  private ImageButton fwdBranchButton;
  private ImageButton backBranchButton;

  PositionVector starPoints;

  // Menus, menu items, and the menubar.
  // The reason that these are all named variables is so that they can be
  // compared with == instead of using string-equal.  This way, if they are
  // to be changed it is only necessary to update the string in one place 
  // in the code.

  private urMenuBar menuBar = new urMenuBar(this);
  private menuListener mListen = new menuListener();
  private checkboxListener cListen = new checkboxListener();
  private exclusiveCheckboxListener xListen = new exclusiveCheckboxListener();
  // File menu
  private Menu fileMenu = menuBar.generate("File");
  private MenuItem saveItem = mListen.generate(fileMenu, "Save", new MenuShortcut('s'));
  private MenuItem saveAsItem
    = mListen.generate(fileMenu, "Save As...", new MenuShortcut('s', true));
  private MenuItem saveOutputItem = mListen.generate(fileMenu, "Save Terminal Output...");
  private MenuItem loadItem
    = mListen.generate(fileMenu, "Open Game...", new MenuShortcut('o', true));
  private MenuItem closeItem
    = mListen.generateWithSep(fileMenu, "Close", true, new MenuShortcut('w'));

  // View menu
  private Menu viewMenu = menuBar.generate("View");
  private Menu refreshMenu = mListen.generateMenuWithSep(viewMenu, "Refresh");
  // Refresh submenu
  private MenuItem refreshLocalItem = mListen.generate(refreshMenu, "Local",
						       new MenuShortcut('r'));
  private MenuItem refreshHostItem = mListen.generate(refreshMenu, "Server",
						      new MenuShortcut('r', true));

  private CheckboxMenuItem focusHereItem
    = cListen.generate(viewMenu, "Show Terminal Output");
  private CheckboxMenuItem showCoordinatesItem
    = cListen.generate(viewMenu, "Show Coordinates");
  boolean showCoordinates = true;
  private CheckboxMenuItem showVariationsItem
    = cListen.generate(viewMenu, "Show Variations");
  boolean showVariations;
    // Show Status submenu
  private Menu showStatusMenu = mListen.generateMenu(viewMenu, "Show Status");
  private CBMIGroup statusGroup = new CBMIGroup(xListen, showStatusMenu);
  private CheckboxMenuItem showStatusNoneItem = statusGroup.generate("None");
  private CheckboxMenuItem showStatusRightItem = statusGroup.generate("Right");
  private CheckboxMenuItem showStatusBottomItem = statusGroup.generate("Bottom");
  boolean showStatus;

    // Kibitz submenu
  private Menu kibitzMenu = mListen.generateMenu(viewMenu, "Show Kibitzes");
  private CBMIGroup kibitzGroup = new CBMIGroup(xListen, kibitzMenu);
  private CheckboxMenuItem kibitzAllItem = kibitzGroup.generate("All");
  private CheckboxMenuItem kibitzCurrentItem = kibitzGroup.generate("Current move");
  private CheckboxMenuItem kibitzNoneItem = kibitzGroup.generate("None");
    // Stones submenu
  private Menu stonesMenu = mListen.generateMenu(viewMenu, "Stones style");
  private CBMIGroup stonesGroup = new CBMIGroup(xListen, stonesMenu);
  // MUST AGREE with Styles Interface:
  private CheckboxMenuItem stonesItems[] = new CheckboxMenuItem[] {
    stonesGroup.generate("Basic"),
    stonesGroup.generate("Anti-aliased"),
    stonesGroup.generate("3d")
  };
  // Board submenu
  private Menu boardMenu = mListen.generateMenu(viewMenu, "Board style");
  private CBMIGroup boardGroup = new CBMIGroup(xListen, boardMenu);
  // MUST AGREE with Styles Interface:
  private CheckboxMenuItem boardItems[] = new CheckboxMenuItem[] {
    boardGroup.generate("Basic"), boardGroup.generate("Wooden")
  };

  // Options menu
  private Menu optionsMenu = menuBar.generate("Options");
  private CheckboxMenuItem browsingItem
    = cListen.generate(optionsMenu, "Browse");
  private CheckboxMenuItem soundItem = cListen.generate(optionsMenu, "Sound");
  private boolean sound = opser.getBooleanOption(GlobalOptions.soundString);
  private boolean focusHere;
  // This should really go in an Edit menu, but this'll do for now.
  private String copyAsSGFString = "Copy (as SGF)";
  private MenuItem copyAsSGFItem
    = mListen.generateWithSep(optionsMenu, copyAsSGFString, true, new MenuShortcut('c'));


  // Windows menu
  // (Note that items added to the windows menu are
  // handled specially because the items are duplicated for each window.)
  private Menu windowsMenu = menuBar.generate("Window");
  private static WindowsMenuCommand duplicateItem
    = new WindowsMenuCommand () {
      public String menuString () { return "Duplicate Window"; }
      public MenuShortcut menuShortcut () {
	return new MenuShortcut('d');
      }
      public int menuPriority () { return 10; }
      public void menuSelect (Frame f) {
	if (f instanceof GameWindow)
	  ((GameWindow) f).duplicate();
      }
      public Class appliesTo () {
	try {
	  return Class.forName("ergo.ui.GameWindow");
	} catch (ClassNotFoundException myDogHasFleas) { return null; }
      }
    };

  // A special separator that only applies to GameWindows in the
  // Window menu.
  // This is initialized further in the constructor.
  private static WindowsMenuCommandSeparator separatorItem
    = new WindowsMenuCommandSeparator(11, null);

  // Game menu
  private Menu gameMenu = menuBar.generate("Game");
  private Menu handicapMenu = mListen.generateMenu(gameMenu, "Place Handicap");
  private MenuItem passItem = mListen.generate(gameMenu, "Pass");
  private MenuItem undoItem = mListen.generateWithSep(gameMenu, "Undo");
  private MenuItem doneItem = mListen.generate(gameMenu, "Done");
  private MenuItem adjournItem = mListen.generate(gameMenu, "Adjourn");
  private MenuItem resignItem = mListen.generate(gameMenu, "Resign");
  private CheckboxMenuItem localScoringItem
    = cListen.generateWithSep(gameMenu, "Calculate Score", true);
  
  // Variations menu
  private Menu variationsMenu = menuBar.generate("Variations");

  // Debug menu
  private Menu debugMenu = menuBar.generate("Debug");
  private MenuItem dumpBoardItem = mListen.generate(debugMenu, "Dump Board");
  private MenuItem dumpGroupsItem = mListen.generate(debugMenu, "Dump Groups");

  // Option Strings

  private String gwinTermOutString = "Game Window Show Terminal Output";
  private String savePromptString = "Game Window prompt for save";
  private String NcoordString = "North Board Coordinates";
  private String WcoordString = "West Board Coodinates";
  private String EcoordString = "East Board Coordinates";
  private String ScoordString = "South Board Coordinates";

  private String statusString = "Game Window Show Game Status";
  private String kibitzString = "Game Window Show Kibitz Area";
  // ---*** Is the following redundant with GlobalOptions.variationString???
  private String variationString = "Game Window Show Variation Letters";
  private String bsizeString = "Game Window Size";
  private String sizeString; // initialised in init().
  String getSizeString() {return sizeString;}
  
  private static Boolean T = new Boolean(true);
  private static Boolean F = new Boolean(false);
  // init() below expresses ownership.

  /** A class of panel that sets its background to the game window's
   *  background and listens to various events. */
  class GWPanel extends Panel implements Optionizable {
    GWPanel () {
      super();
      try {
	opser.expressOwnership(GlobalOptions.gwinColorString, 
			       Optionizer.TYPE_COLOR, this,
			       new ColorSpec(gwinDefaultBackground));
	setBackground(opser.getColorOption(GlobalOptions.gwinColorString));
      }
      catch (Exception e) {
	Debug.backtrace(e);
      }
    }
    public void optionEvent (String key, Object value) {
      if (opser.isSameKey(key, GlobalOptions.gwinColorString)) {
	setBackground(opser.getColorOption(GlobalOptions.gwinColorString));
	repaint();
      }
    }
  }  // end inner class GWPanel


  /****************************
   * Initialization           *
   ****************************/

  // Make a server game
  public GameWindow (int size, String white, String wrank, String black,
		     String brank, double komi, TerminalWindow term,
		     ServerConnection sc, int gnum, int matchi, int byotime,
		     boolean freeGame) throws ErgoException {
    window = term;
    conn = sc;
    game = new Game(this, size, white, wrank, black, brank, komi, byotime, 
		    freeGame, (conn == null ? null : conn.server));
    gameNumber = gnum;
    browsing = false;
    isParticipating = matchi != -1;
    // +++ should probably use Move.NONE here instead of -1
    ourColor = matchi;		// Move.WHITE, Move.BLACK, Move.BOTH, or -1
    init();
  }

  // Make a local game
  public GameWindow (int size, String white, String wrank,
		     String black, String brank, double komi,
		     TerminalWindow term) throws ErgoException {
    this(size, white, wrank, black, brank, komi, term, null, -1, -1, -1, true);
  }

  // Make a game window from an already constructed game.  Used by SGF reader.
  public GameWindow (Game g, TerminalWindow term) throws ErgoException {
    window = term;
    game = g;
    gameNumber = -1;
    browsing = false;
    isParticipating = false;
    init();
  }


  // For the Optionizable Interface
  public void optionEvent (String keyword, Object value) {
    if (opser.isSameKey(keyword, statusString))
      statusPanel = configureStatus( (String)value);
    else if (opser.isSameKey(keyword, kibitzString))
      setKibitzVisible( ((Boolean)value).booleanValue()); 
    else if (TextColorManager.isColorString(keyword))
      kibitzArea.setColorVec(TextColorManager.getColorVec());
    else if (opser.isSameKey(keyword, GlobalOptions.textfontString))
      kibitzArea.setFont(opser.getFontOption(GlobalOptions.textfontString));
    else if (opser.isSameKey(keyword, GlobalOptions.gwinColorString)) {
      setBackground(opser.getColorOption(GlobalOptions.gwinColorString));
      repaint();
    }
  }


  class SizeListener extends ComponentAdapter {
    public void componentResized(ComponentEvent e) {
      Dimension s = getSize();
      opser.updateOption(getSizeString(), s);
    }
  }

  // Initialize everything.
  private void init () {
    popupControl = new PopupController(this, "Options");
    popupHandler = new PopupHandler();

    separatorItem.appliesTo = this.getClass();

    setBrowsing(false);
/***
    if (!isLocalGame()) {
      browseButton = new Button("    Browse    ");  // Should be ImageButton eventually
      browseButton.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
	  toggleBrowsingMode();
	}
      });
    }
 ***/
    stepBackButton    = makeImageButton("back.gif");
    stepForwardButton = makeImageButton("fwd.gif");
    //jumpBackButton    = makeImageButton("backfast.gif");
    //jumpForwardButton = makeImageButton("fwdfast.gif");
    toBeginningButton = makeImageButton("backstart.gif");
    toEndButton       = makeImageButton("fwdend.gif");
    fwdKibButton      = makeImageButton("fwdkib.gif");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -