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

📄 terminalwindow.java

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

// $Id: TerminalWindow.java,v 1.8 1999/08/15 01:40:29 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.Util;
import ergo.util.Debug;
import ergo.util.ErgoException;
import ergo.util.ParsedMessage;
import ergo.util.ParseException;
import ergo.util.Position;
import ergo.util.CommandHistory;
import ergo.server.GoServer;
import ergo.server.ServerConnection;
import ergo.logic.*;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Vector;
import java.util.Enumeration;
import nom.rb.common.*;


/** WindowRegistrar maintains a set of menus.  Each menu is associated
 *  with a given Frame.  Each menu item implements the WindowsMenuCommand
 *  interface.  Menu items are added to a given menu only if they apply
 *  to that menu's associated Frame.
 *
 *  We should really have some higher level notion of command tables
 *  that map to menu items and/or keystrokes.
 *
 *  There is only ever one instance of this class.
 */
class WindowRegistrar {
  // menus and frames must always be kept in synch.
  private Vector menus = new Vector();   // Menu objects only.  no nulls.
  private Vector frames = new Vector();  // Frame objects only.  no nulls.

  // Map from menu to vector of WindowsMenuCommands.
  // The vector of menu commands and the items in the corresponding
  // menu must always be kept in synch.
  private java.util.Hashtable map = new java.util.Hashtable();

  private WindowsMenuCommandSeparator separator = new WindowsMenuCommandSeparator(998, null);

  private Menu menuAt (int i) {
    return (Menu) menus.elementAt(i);
  }

  private Frame frameAt (int i) {
    return (Frame) frames.elementAt(i);
  }

  // Return the index of o in v, or -1 if not found.  Test with ==.
  private int find (Vector v, Object o) {
    for (int i = 0; i < v.size(); i++) {
      if (v.elementAt(i) == o)
	return i;
    }
    return -1;
  }

  // Iterate over all the menus and add this command if it applies
  // to the Frame type associated with that window and if it's not
  // already in them.
  public synchronized void registerWindowsMenuCommand (WindowsMenuCommand cmd) {
    for (int i = 0; i < menus.size(); i++) {
      Menu menu = menuAt(i);
      Frame frame = frameAt(i);
      if (cmd.appliesTo() == null || cmd.appliesTo() == frame.getClass()) {
	registerWindowsMenuCommandInternal(cmd, menu, frame);
      }
    }
  }

  // Add a command to the given menu if it's not already present.
  // Add it at the correct priority.
  private void registerWindowsMenuCommandInternal (WindowsMenuCommand cmd, Menu menu,
						   Frame frame) {
    Vector menuCommands = (Vector) map.get(menu);
    if (find(menuCommands, cmd) != -1)
      return;		// do not duplicate commands
    int index = 0;
    for (int i = 0; i < menuCommands.size(); ++i) {
      WindowsMenuCommand inMenu = (WindowsMenuCommand) menuCommands.elementAt(i);
      if (cmd.menuPriority() < inMenu.menuPriority())
	break;
      else
	++index;
    }
    // all game windows have equal high priority, if we get here, i==size()....
    //    Debug.println("Adding "+cmd.menuString()+" at "+i);
    if (cmd instanceof GameWindow
	&& index > 0
	&& !(menuCommands.elementAt(index - 1) instanceof WindowsMenuCommandSeparator)
	&& !(menuCommands.elementAt(index - 1) instanceof GameWindow)) {
      menu.insertSeparator(index);
      menuCommands.insertElementAt(separator, index);
      ++index;
    }
    menuCommands.insertElementAt(cmd, index);
    if (cmd.menuString() == null)
      menu.insertSeparator(index);
    else {
      java.awt.MenuItem toadd = ((cmd.menuShortcut() == null)
			? new java.awt.MenuItem(cmd.menuString())
			: new java.awt.MenuItem(cmd.menuString(), cmd.menuShortcut()));
      toadd.addActionListener(new WindowsMenuCommandActionListener(cmd, frame));
      menu.insert(toadd, index);
    }
  }    

  // Remove the command from each menu that contains it,
  // and from the associated vector of commands.
  public void deregisterWindowsMenuCommand (WindowsMenuCommand cmd) {
    for (int i = 0; i < menus.size(); i++) {
      Menu menu = menuAt(i);
      Vector commands = (Vector) map.get(menu);
      int index = find(commands, cmd);
      if (index != -1) {
	commands.removeElementAt(index);
	menu.remove(index);	// corresponding element in menu
	// Remove a separator above this command, if any.
	if (index > 0
	    && commands.elementAt(index - 1) instanceof WindowsMenuCommandSeparator
	    && cmd instanceof GameWindow
	    // ...and the following item isn't a GameWindow.
	    // Note that index now points to the following item.
	    && (index >= commands.size()
		|| !(commands.elementAt(index) instanceof GameWindow))) {
	  commands.removeElementAt(index - 1);
	  menu.remove(index - 1);
	}
      }
    }
  }

  public void updateWindowTitle (WindowsMenuCommand cmd) {
    for (int i = 0; i < menus.size(); i++) {
      Menu menu = menuAt(i);
      Vector v = (Vector) map.get(menuAt(i));
      if (v != null) {
	int index = find(v, cmd);
	if (index != -1) {
	  MenuItem item = menu.getItem(index);
	  if (item != null)
	    item.setLabel(cmd.menuString());
	}
      }
    }
  }

  // Compiler goes into infinite loop if this is anonymous at 1.1.1.
  // It looked very cool, tho.
  class WindowsMenuCommandActionListener implements ActionListener {
    WindowsMenuCommand cmd;
    Frame frame;
    WindowsMenuCommandActionListener (WindowsMenuCommand r1, Frame f) {
      cmd = r1;
      frame = f;
    }
    public void actionPerformed (ActionEvent e) {
      cmd.menuSelect(frame);
    }
  }
  
  // Add all the same items to a menu as are in another menu that belongs
  // to the same type of frame.
  private void menuManufac (Menu menu, Frame frame) {
    // Try to find another menu that corresponds to the same kind of frame.
    if (menus.size() > 0) {  // otherwise nothing to copy
      Menu m = null;
      for (int i = 0; i < menus.size(); ++i) {
	Frame f = frameAt(i);
	// Note we don't want to use the menu we're trying to populate.
	if (menuAt(i) != menu && f.getClass() == frame.getClass()) {
	  m = menuAt(i);
	  break;
	}
      }
      if (m == null)
	m = menuAt(0);  // Just use the first one.  Should work for now.
      Vector v = (Vector) map.get(m);
      if (v != null) {
	for (int j = 0; j < v.size(); j++) {
	  WindowsMenuCommand cmd = (WindowsMenuCommand) v.elementAt(j);
	  // This actually goes through all the hoops of registering this
	  // command with all the menus, but it should only add it to the
	  // new menu since the others already contain this command.
	  if (cmd != null)
	    registerWindowsMenuCommand(cmd);
	}
      }
    }
  }

  public Menu registerMenu (Menu menu, Frame parent) {
    menus.addElement(menu);
    frames.addElement(parent);
    map.put(menu, new Vector());
    menuManufac(menu, parent);
    return menu;
  }

  public void releaseMenu (Menu togo) {
    for (int i = 0; i < menus.size(); i++) {
      if (menuAt(i) == togo) {
	menus.removeElementAt(i);
	frames.removeElementAt(i);
      }
    }
  }
}  // end class WindowRegistrar


/**
 * TerminalWindow is the top-level window for user input, chatting,
 * and miscellaneous output.  A major function of the TerminalWindow
 * is to implement the GoClient interface.
 */
public class TerminalWindow extends Frame
  implements Runnable, Focusable, WindowsMenuCommand, Optionizable,
	     GoClient, PopupContributor {

  // +++ These need to be optionized.
  public static Color defaultColor = Color.black;
  public static Color tellColor = Color.magenta;
  public static Color yellColor = Color.blue;
  public static Color shoutColor = Color.black;
  // kibitzColor is also used for "say" output.
  public static Color kibitzColor = new Color(0, 100, 0); // dark green.
  public static Color warningColor = Color.black;
  public static Color commandColor = Color.red;

  private PopupController popupControl;
  private PopupHandler popupHandler;
  private CommandHistory commandHistory = new CommandHistory();
  public static WindowRegistrar registrar = new WindowRegistrar();
  
  private Vector focusOrder = null;    // For the Focusable interface...
  private int focusIndex = 0;
  
  private String accountName = null;
  private String rank = null;
  public Ergo ergo = null;
  public ServerConnection conn; // required for title of info windows
  private Vector gameWindows = new Vector();
  private Vector otherWindows = new Vector();
  private ObserveDialog observeDialog;

  private String defaultDirectory = null; // where to load/save SGF files.
  
  // This is part of TerminalWindow because it should retain defaults
  // throughout the life of the Ergo app, but it's public since
  // the Controller is the one that uses it most.
  private LoginDialog loginDialog = null;
  
  // 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.
  // ---*** The above comment is still somewhat true, but the menu items are
  //        being replaced by Command objects so the strings will only be in
  //        the Command anyway.  -sigue July 23, 1999
  private urMenuBar menuBar;
  
  // File menu
  private Menu goConnectSubmenu;
  private MenuItem newServerItem;
  private MenuItem disconnectItem;
  private MenuItem saveOutputItem;
  private MenuItem clearOutputItem;
  private MenuItem loadItem;
  
  // Go menu
  private MenuItem observeItem;
  private MenuItem matchItem;
  private MenuItem automatchItem;
  private MenuItem localGameItem;
  
  // Options menu
  private CheckboxMenuItem soundItem;
  private MenuItem saveOptionsItem;

  // Debug menu
  private Menu debugMenu;
  private CheckboxMenuItem debugItem;
  private CheckboxMenuItem logicItem;
  private CheckboxMenuItem rawItem;
  private boolean rawMode;
  
  // Windows menu
  private Menu windowsMenu;
  
  // Help menu
  private Menu helpMenu;
  private MenuItem aboutItem;
  private MenuItem docItem;
  
  public TextField inputField;
  public TextArea mainArea;
  public TextArea messageArea;

  // ini Keys for server.
  private String serverString = "Server";
  private String widthString = "Main window width"; // default: 80
  private String heightString = "Main area height"; // default: 24
  private String mheightString = "Message area height"; // default: 7
  private String exitString = "Save Options on Exit"; // default: true
  private String mainposString = "Main Window Position"; // default: 0, 0

  private boolean soundEnabled;
  private Optionizer opser = Ergo.opser; // bit silly.

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

  // Note that by the time this window is created the init file has been loaded.
  public TerminalWindow (Ergo ergo, GoServer server, boolean connect) {
    init_options();
    init_menus();
    conn = new ServerConnection(this);
    if (connect && server != null)
      conn.open(server);
    this.ergo = ergo;
    Debug.setDebug(opser.getBooleanOption(GlobalOptions.debugmodeString));

    popupControl = new PopupController(this, "Options");
    popupHandler = new PopupHandler();
    populateServers();
    if (server != null)
      goConnectSubmenu.add(new GoServerMenuItem(server));

    int width = opser.getIntegerOption(widthString);
    inputField = new TextField(width);
    mainArea = new TextArea(opser.getIntegerOption(heightString), width, null, true);
    messageArea = new TextArea(opser.getIntegerOption(mheightString), width);

    inputField.addActionListener(new ActionListener () {
      public void actionPerformed (ActionEvent e) {
	// The user has pressed Return in the inputField...
	String text = inputField.getText();
	inputField.setText("");
	processCommand(text.trim(), null);
      }
    });

    addWindowListener(new WindowAdapter () {
      public void windowClosing (WindowEvent e) {
	exit();
      }
    });
  
    // Set the focus to inputField when the window is initially shown.
    addComponentListener(new ComponentAdapter () {
      public void componentShown (ComponentEvent e) {
	// Putting a little delay here seems to make this work more often than not.
	// I wonder if there's a better way...  200ms shouldn't be too noticable...
	try {
	  Thread.sleep(200);
	} catch (InterruptedException ie) {}
	inputField.requestFocus();
      }
    });

    // Make arrow keys get Next/Previous input history item.
    inputField.addKeyListener(new KeyAdapter() {
      public void keyPressed (KeyEvent e) {
	switch (e.getKeyCode()) {
	case KeyEvent.VK_UP:
	  String prev = commandHistory.getPreviousElement();
	  if (prev != null) {
	    inputField.setText(prev);
	    inputField.setCaretPosition(prev.length());
	  }
	  break;
	case KeyEvent.VK_DOWN:
	  String next = commandHistory.getNextElement();
	  if (next != null) {
	    inputField.setText(next);
	    inputField.setCaretPosition(next.length());
	  }
	  break;
	}
      }
    });

    // We begin in a disconnected state.
    if (conn == null || !conn.isConnected())
      noteDisconnected();
    

⌨️ 快捷键说明

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