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

📄 statuspanel.java

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

// $Id: StatusPanel.java,v 1.7 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.GlobalOptions;
import ergo.logic.Move;           // for BLACK and WHITE constants
import ergo.logic.GameResultMove;
import ergo.server.SimpleServerConnection;
import ergo.util.Util;
import ergo.util.Debug;
import ergo.util.Position;
import java.awt.*;
import java.awt.event.*;

/**
 * StatusPanel
 * <p>
 * Contains all of the status display to the right of the game board.
 * It contains four subcomponents, arranged vertically from top to bottom
 * as: blackStatus, whiteStatus, currentMove, messages.
 * <pre>
 * ------------------------   ...something like this...
 * | -------------------| |
 * | | X  10:05 (25)    | |
 * | |------------------| |
 * | | Prisoners: 3     | |
 * | | Handicap:        | |
 * | |   X X X X X X    | |
 * | -------------------- |
 * | -------------------- |
 * | | O  11:05 (25)    | |
 * | |------------------| |
 * | | Prisoners: 0     | |
 * | | Komi:      5.5   | |
 * | -------------------| |
 * |                      |
 * | --Current Move-------|
 * | | #9 X C4  (Ko @ c3) |
 * | ---------------------|
 * |                      |
 * | --Messages---------- |
 * | |   Adjourned      | |
 * | |                  | |
 * | -------------------- |
 * ------------------------
 * </pre>
 */
class StatusPanel extends Panel implements Optionizable {
  private static Optionizer opser = ergo.Ergo.opser;
  private Insets insets = new Insets(5, 5, 5, 5);
  private boolean tallConfiguration = true;
  private int spacing = 10;  // space between panels/canvases
  private short margin = 4;  // margin within inner canvases etc
  private short indent = 10; // indent within inner canvases etc

  // Various inner classes use these, relying on the fact that the same font
  // is used throughout the status panel (except in the timers).
  private String statusString = "Status font";
  private Font statusFont;
  private FontMetrics metrics;
  private int lineHeight;

  // The interesting components...
  private PlayerStatusCanvas blackStatus;
  private PlayerStatusCanvas whiteStatus;
  private CurrentMoveCanvas currentMove;
  private MessagesCanvas messages;
  private GameStatusCanvas gstatus;
  private TimerCanvas blackTimer;
  private TimerCanvas whiteTimer;

  private Panel blackPanel = new BorderPanel(); // The whole black status area.
  private Panel whitePanel = new BorderPanel(); // The whole white status area.

  private GameWindow gwin;
  private Position ko = null;  // null = no ko position.
  private MouseListener popupControl;
  private Panel browser;

  private Image blarge;
  private Image wlarge;
  private Image bsmall;
  private Image wsmall;
  private Image btiny;
  private Image wtiny;

  public StatusPanel (GameWindow gw, Panel browser, MouseListener popupControl,
		      boolean tall, SimpleServerConnection conn) {
    gwin = gw;
    this.browser = browser;
    this.popupControl = popupControl;
    tallConfiguration = tall;

    // Fonts etc must be done early since subcomponent creation depends on it.
    try {
      opser.expressOwnership(statusString, Optionizer.TYPE_FONT, this, null);
      statusFont = opser.getFontOption(statusString);
      opser.expressOwnership(GlobalOptions.gwinColorString,
			     Optionizer.TYPE_COLOR, this,
			     new ColorSpec(gw.gwinDefaultBackground));
      setBackground(opser.getColorOption(GlobalOptions.gwinColorString));
    }
    catch (Exception e) {
      Debug.backtrace(e);
    }
    metrics = getFontMetrics(statusFont);
    lineHeight = metrics.getHeight();

    // Create the subcomponents
    blackTimer = new TimerCanvas(conn, gwin.ourColor() == Move.WHITE);
    whiteTimer = new TimerCanvas(conn, gwin.ourColor() == Move.BLACK);
    blackStatus = new PlayerStatusCanvas(Move.BLACK);
    whiteStatus = new PlayerStatusCanvas(Move.WHITE);
    currentMove = new CurrentMoveCanvas();
    messages = new MessagesCanvas();
    gstatus = new GameStatusCanvas();

    // Create a bunch of stone images.  Large and small of both black and white.
    blarge = makeStoneImage(Move.BLACK, blackTimer.getStoneDiameter());
    wlarge = makeStoneImage(Move.WHITE, whiteTimer.getStoneDiameter());
    bsmall = makeStoneImage(Move.BLACK, lineHeight + 2);
    wsmall = makeStoneImage(Move.WHITE, lineHeight + 2);
    btiny = makeStoneImage(Move.BLACK, lineHeight - 2);
    wtiny = makeStoneImage(Move.WHITE, lineHeight - 2);

    // Splatter popup menu MouseListener over any components that should
    // have the standard popup menu.
    blackTimer.addMouseListener(popupControl);
    whiteTimer.addMouseListener(popupControl);
    blackStatus.addMouseListener(popupControl);
    whiteStatus.addMouseListener(popupControl);
    currentMove.addMouseListener(popupControl);
    messages.addMouseListener(popupControl);
    gstatus.addMouseListener(popupControl);

    configure();
  }

  //
  // Setup the component hierarchy (do by-hand layout crapola).
  // Dylan is so incredibly elegant by comparison...
  //
  private void configure () {
    Panel blacktop = new Panel();
    Panel whitetop = new Panel();
    ImageLabel blacklabel = new ImageLabel(blarge);
    ImageLabel whitelabel = new ImageLabel(wlarge);

    blacktop.addMouseListener(popupControl);
    whitetop.addMouseListener(popupControl);
    blacklabel.addMouseListener(popupControl);
    whitelabel.addMouseListener(popupControl);

    blacktop.add(blacklabel);
    blacktop.add(blackTimer);
    blackPanel.setLayout(new BorderLayout());
    blackPanel.add("North", blacktop);
    blackPanel.add("South", blackStatus);
    whitetop.add(whitelabel);
    whitetop.add(whiteTimer);
    whitePanel.setLayout(new BorderLayout());
    whitePanel.add("North", whitetop);
    whitePanel.add("South", whiteStatus);

    if (tallConfiguration) {
      ColumnLayout cl = new ColumnLayout(ColumnLayout.LEFT, 5, 2, true);
      this.setLayout(cl);
      add(blackPanel);
      add(whitePanel);
      add(gstatus);
      add(currentMove);
      add(messages);
      add(browser, cl.makeConstraint(ColumnLayout.CENTER, 0, true));
    }
    else {
      RowLayout rl = new RowLayout(RowLayout.TOP, 5, 2, true);
      this.setLayout(rl);

      Panel p1 = new Panel();
      p1.setLayout(new BorderLayout());
      p1.add("North", blackPanel);
      p1.add("South", whitePanel);

      Panel p2 = new BorderPanel();
      ColumnLayout cl = new ColumnLayout(ColumnLayout.LEFT, 0, 2, true);
      p2.setLayout(cl);
      p2.add(gstatus);
      p2.add(currentMove);
      p2.add(messages);

      add(p1);
      add(p2);
      add(browser);
    }
  }

  public void setConfiguration (boolean tall) {
    if (tall != tallConfiguration) {
      tallConfiguration = tall;
      configure();
    }
  }

  public void commitSuicide () {
    blackTimer.commitSuicide();
    whiteTimer.commitSuicide();
  }

  public Insets getInsets () {
    return insets;
  }

  public Dimension getPreferredSize () {
    Dimension bspref = blackPanel.getPreferredSize();
    Dimension wspref = whitePanel.getPreferredSize();
    Dimension cpref = currentMove.getPreferredSize();
    Dimension mpref = messages.getPreferredSize();
    Dimension gpref = gstatus.getPreferredSize();
    if (tallConfiguration)
      return new Dimension(insets.left
			   + Math.max(Math.max(bspref.width, wspref.width),
				      Math.max(cpref.width, mpref.width))
			   + insets.right,
			   insets.top + bspref.height
			   + spacing + wspref.height
			   + spacing + cpref.height
			   + spacing + mpref.height
			   + spacing + gpref.height
			   + insets.bottom);
    else
      return new Dimension(insets.left + Math.max(bspref.width, wspref.width)
			   + spacing + Math.max(cpref.width, mpref.width)
			   + insets.right,
			   insets.top +
			   Math.max(Math.max(bspref.height + wspref.height,
					     cpref.height + mpref.height + gpref.height),
				    browser.getPreferredSize().height)
			   + insets.bottom);
  }

  public Dimension getMinimumSize () {
    return getPreferredSize();
  }

  // Implement the Optionizable interface.
  public void optionEvent (String keyword, Object value) {
    if (opser.isSameKey(keyword, statusString)) {
      statusFont = (Font)value;
      setFont(statusFont);
      // +++ Is this correct, or is refresh() required also?
      // gwin.validate();
    }
    else if (opser.isSameKey(keyword, GlobalOptions.gwinColorString)) {
      setBackground(opser.getColorOption(GlobalOptions.gwinColorString));
      repaint();
    }

  }

  public void refresh () {
    blackStatus.repaint();
    whiteStatus.repaint();
    gstatus.repaint();
    currentMove.repaint();
    messages.repaint();
  }

  public void setKoPosition (Position p) {
    ko = p;
    whiteStatus.repaint();
  }

  private TimerCanvas playerTimer (int player) {
    switch (player) {
    case Move.BLACK:
      return blackTimer;
    case Move.WHITE:
      return whiteTimer;
    default:
      return null;
    }
  }

  public void setTime (int player, int seconds, int stones) {
    TimerCanvas tcan = playerTimer(player);
    if (tcan != null)
      tcan.setTime(seconds, stones);  // repaint() is called in TimerCanvas.
  }

  public void stopTicking (int player) {
    TimerCanvas tcan = playerTimer(player);
    if (tcan != null)
      tcan.stopTicking();
  }

  public void startTicking (int player) {
    TimerCanvas tcan = playerTimer(player);
    if (tcan != null)
      tcan.startTicking();
  }

  public void stopTicking () {
    stopTicking(Move.BLACK);
    stopTicking(Move.WHITE);
  }

  private Image makeStoneImage (int player, int diameter) {
    int boardStyle = opser.getIntegerOption(GlobalOptions.boardStyleString);
    int backcol = ((boardStyle == Styles.BOARD_WOOD)
		   ? OodInnaBox.getAverageColor()
		   : opser.getColorOption(GlobalOptions.boardColorString).getRGB());
    int stoneStyle = opser.getIntegerOption(GlobalOptions.stoneString);
    RawImage stone = StoneMaker.makeStoneImage(player, false, diameter,
					     stoneStyle, backcol, 0.0);
    return createImage(stone.mis());
  }

  ///
  /// BorderPanel
  ///
  class BorderPanel extends Panel implements Optionizable {
    BorderPanel () {
      super();
      try {
	opser.expressOwnership(GlobalOptions.gwinColorString,
			       Optionizer.TYPE_COLOR, this,
			       new ColorSpec(gwin.gwinDefaultBackground));
	setBackground(opser.getColorOption(GlobalOptions.gwinColorString));
      }
      catch (Exception e) {
	Debug.backtrace(e);
      }
    }

    public Insets getInsets () {
      return new Insets(3, 3, 3, 3);  // 1-pixel border + 2 pixels spacing
    }

    public void optionEvent (String key, Object value) {
      if (opser.isSameKey(key, GlobalOptions.gwinColorString)) {
	setBackground(opser.getColorOption(GlobalOptions.gwinColorString));
	repaint();
      }
    }

    public void paint (Graphics g) {
      update(g);
    }

    public void update (Graphics g) {
      int width = getSize().width;
      int height = getSize().height;
      g.setColor(getBackground());
      g.fillRect(0, 0, width - 1, height - 1);
      g.setColor(getForeground());
      g.drawRect(1, 1, width - 2, height - 2);
    }

  }  // end inner class BorderPanel


  ///
  /// PlayerStatusCanvas - Displays a clock and prisoners
  ///

  class PlayerStatusCanvas extends ErgoCanvas {
    private int player;   // Move.BLACK or Move.WHITE
    private String widthString = "Prisoners: 999";

    PlayerStatusCanvas (int player) {
      this.player = player;
      setFont(statusFont);
    }

    public void paint (Graphics g) {
      needsRedisplay = true;
      update(g);
    }

    public void update (Graphics g) {
      if (getSize().height != height || getSize().width != width) {
	width = getSize().width;
	height = getSize().height;
      }
      g.setColor(getBackground());
      g.fillRect(0, 0, width, height);
      g.setColor(getForeground());

      int y = margin + metrics.getAscent();
      int x = margin;
      int captured = 0;
      boolean isblack = (player == Move.BLACK);
      if (isblack)
	captured = gwin.game.capturedWhite();
      else
	captured = gwin.game.capturedBlack();
      g.drawString("Prisoners: " + captured, x, y);
    }

    public Dimension getPreferredSize () {
      Dimension d = new Dimension();
      d.width = metrics.stringWidth(widthString) + indent;
      // +++ adjust upwards when drawing hcap stones.
      d.height = metrics.getHeight();
      d.height += margin * 2;
      return d;

⌨️ 快捷键说明

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