📄 statuspanel.java
字号:
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 + -