m_commands;
- private final MessageDialogs m_messageDialogs;
+ private final MessageDialogs m_messageDialogs;
- private final Listener m_listener;
+ private final Listener m_listener;
- private String m_lastUpdateOptionsCommand;
+ private String m_lastUpdateOptionsCommand;
- private void clearCommand()
- {
- m_listener.actionClearAnalyzeCommand();
- m_autoRun.setSelected(false);
- }
+ private void clearCommand() {
+ m_listener.actionClearAnalyzeCommand();
+ m_autoRun.setSelected(false);
+ }
- private void comboBoxChanged()
- {
- Object item = m_comboBoxHistory.getSelectedItem();
- if (item == null)
- {
- m_list.clearSelection();
- return;
- }
- String label = item.toString();
- updateOptions(label);
- String selectedValue = (String)m_list.getSelectedValue();
- if (selectedValue != null && ! selectedValue.equals(label))
- m_list.clearSelection();
+ private void comboBoxChanged() {
+ Object item = m_comboBoxHistory.getSelectedItem();
+ if (item == null) {
+ m_list.clearSelection();
+ return;
}
-
- private JPanel createButtons()
- {
- JPanel innerPanel = new JPanel(new GridLayout(1, 0, 5, 0));
- m_runButton = new JButton("Run");
- m_runButton.setToolTipText("Run Command");
- m_runButton.setActionCommand("run");
- m_runButton.addActionListener(this);
- m_runButton.setMnemonic(KeyEvent.VK_R);
- m_runButton.setEnabled(false);
- GuiUtil.setMacBevelButton(m_runButton);
- innerPanel.add(m_runButton);
- m_clearButton = new JButton("Clear");
- m_clearButton.setToolTipText(("Clear command"));
- m_clearButton.setActionCommand("clear");
- m_clearButton.addActionListener(this);
- m_clearButton.setMnemonic(KeyEvent.VK_C);
- GuiUtil.setMacBevelButton(m_clearButton);
- innerPanel.add(m_clearButton);
- JPanel outerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
- outerPanel.add(innerPanel);
- return outerPanel;
+ String label = item.toString();
+ updateOptions(label);
+ String selectedValue = (String) m_list.getSelectedValue();
+ if (selectedValue != null && !selectedValue.equals(label)) m_list.clearSelection();
+ }
+
+ private JPanel createButtons() {
+ JPanel innerPanel = new JPanel(new GridLayout(1, 0, 5, 0));
+ m_runButton = new JButton("Run");
+ m_runButton.setToolTipText("Run Command");
+ m_runButton.setActionCommand("run");
+ m_runButton.addActionListener(this);
+ m_runButton.setMnemonic(KeyEvent.VK_R);
+ m_runButton.setEnabled(false);
+ GuiUtil.setMacBevelButton(m_runButton);
+ innerPanel.add(m_runButton);
+ m_clearButton = new JButton("Clear");
+ m_clearButton.setToolTipText(("Clear command"));
+ m_clearButton.setActionCommand("clear");
+ m_clearButton.addActionListener(this);
+ m_clearButton.setMnemonic(KeyEvent.VK_C);
+ GuiUtil.setMacBevelButton(m_clearButton);
+ innerPanel.add(m_clearButton);
+ JPanel outerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ outerPanel.add(innerPanel);
+ return outerPanel;
+ }
+
+ private JComponent createColorPanel() {
+ m_colorBox = Box.createVerticalBox();
+ ButtonGroup group = new ButtonGroup();
+ m_black = new JRadioButton("Black");
+ m_black.setToolTipText("Black");
+ m_black.setEnabled(false);
+ group.add(m_black);
+ m_colorBox.add(m_black);
+ m_white = new JRadioButton("White");
+ m_white.setToolTipText("White");
+ m_white.setEnabled(false);
+ group.add(m_white);
+ m_colorBox.add(m_white);
+ return m_colorBox;
+ }
+
+ private JPanel createCommandPanel() {
+ JPanel panel = new JPanel(new BorderLayout());
+ m_list = new JList();
+ m_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ m_list.setVisibleRowCount(25);
+ m_list.addMouseListener(
+ new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ int modifiers = e.getModifiers();
+ int mask = ActionEvent.ALT_MASK;
+ if (e.getClickCount() == 2 || ((modifiers & mask) != 0)) {
+ // int index =
+ // m_list.locationToIndex(event.getPoint());
+ runCommand();
+ }
+ }
+ });
+ m_list.addFocusListener(
+ new FocusAdapter() {
+ public void focusGained(FocusEvent e) {
+ int index = getSelectedCommand();
+ if (index >= 0) m_list.setSelectedIndex(index);
+ }
+ });
+ m_list.addListSelectionListener(this);
+ JScrollPane scrollPane = new JScrollPane(m_list);
+ if (Platform.isMac())
+ // Default Apple L&F uses no border, but Quaqua 3.7.4 does
+ scrollPane.setBorder(null);
+ panel.add(scrollPane, BorderLayout.CENTER);
+ panel.add(createLowerPanel(), BorderLayout.SOUTH);
+ String[] labels = new String[m_commands.size()];
+ for (int i = 0; i < m_commands.size(); ++i) labels[i] = m_commands.get(i).getLabel();
+ m_list.setListData(labels);
+ comboBoxChanged();
+ loadRecent();
+ return panel;
+ }
+
+ private JComponent createLowerPanel() {
+ Box panel = Box.createVerticalBox();
+ panel.add(GuiUtil.createFiller());
+ m_comboBoxHistory = new JComboBox();
+ panel.add(m_comboBoxHistory);
+ Box lowerPanel = Box.createVerticalBox();
+ lowerPanel.setBorder(GuiUtil.createEmptyBorder());
+ panel.add(lowerPanel);
+ Box optionsPanel = Box.createHorizontalBox();
+ lowerPanel.add(optionsPanel);
+ JPanel leftPanel = new JPanel();
+ optionsPanel.add(leftPanel);
+ Box leftBox = Box.createVerticalBox();
+ leftPanel.add(leftBox);
+ m_autoRun = new JCheckBox("Autorun");
+ m_autoRun.addItemListener(
+ new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ if (!m_autoRun.isSelected()) m_listener.actionClearAnalyzeCommand();
+ }
+ });
+ m_autoRun.setToolTipText("Autorun");
+ m_autoRun.setEnabled(false);
+ leftBox.add(m_autoRun);
+ m_clearBoard = new JCheckBox("Clearboard");
+ m_clearBoard.setToolTipText("Clearboard");
+ m_clearBoard.setEnabled(false);
+ leftBox.add(m_clearBoard);
+ m_clearBoard.setSelected(true);
+ m_reuseWindow = new JCheckBox("Reuse Text");
+ m_reuseWindow.setToolTipText("Reuse text window");
+ leftBox.add(m_reuseWindow);
+ JPanel rightPanel = new JPanel();
+ rightPanel.add(createColorPanel());
+ optionsPanel.add(rightPanel);
+
+ // TODO: The following horizontal glue does not really work as expected
+ // (tested on Linux/Sun Java 1.6.0_14) and the left two components in
+ // the box are not aligned to the left.
+ optionsPanel.add(Box.createHorizontalGlue());
+
+ // TODO: If GTK Looks L&F is used on Linux/Sun Java 1.6.0_14 or OpenJDK
+ // 6b14-1.4.1-0ubuntu11, then the text of the checkbox items can be
+ // truncated a bit on the left (wrong minimum size calculation?). The
+ // two fillers are a workaround for this.
+ optionsPanel.add(GuiUtil.createFiller());
+ optionsPanel.add(GuiUtil.createFiller());
+
+ lowerPanel.add(createButtons());
+ m_comboBoxHistory.addActionListener(this);
+ return panel;
+ }
+
+ private String getComboBoxItem(int i) {
+ return m_comboBoxHistory.getItemAt(i).toString();
+ }
+
+ private int getComboBoxItemCount() {
+ return m_comboBoxHistory.getItemCount();
+ }
+
+ private int getCommandIndex(String label) {
+ for (int i = 0; i < m_commands.size(); ++i)
+ if (m_commands.get(i).getLabel().equals(label)) return i;
+ return -1;
+ }
+
+ private int getSelectedCommand() {
+ Object item = m_comboBoxHistory.getSelectedItem();
+ if (item == null) return -1;
+ return getCommandIndex(item.toString());
+ }
+
+ private void insertComboBoxItem(String label, int index) {
+ m_comboBoxHistory.insertItemAt(GuiUtil.createComboBoxItem(label), index);
+ }
+
+ private void loadRecent() {
+ m_comboBoxHistory.removeAllItems();
+ m_fullRecentList = PrefUtil.getList("net/sf/hexgui/gui/analyzedialog/recentcommands");
+ for (int i = 0; i < m_fullRecentList.size(); ++i) {
+ String name = m_fullRecentList.get(i);
+ if (getCommandIndex(name) >= 0) m_comboBoxHistory.addItem(GuiUtil.createComboBoxItem(name));
+ if (m_comboBoxHistory.getItemCount() > 20) break;
}
-
- private JComponent createColorPanel()
- {
- m_colorBox = Box.createVerticalBox();
- ButtonGroup group = new ButtonGroup();
- m_black = new JRadioButton("Black");
- m_black.setToolTipText("Black");
- m_black.setEnabled(false);
- group.add(m_black);
- m_colorBox.add(m_black);
- m_white = new JRadioButton("White");
- m_white.setToolTipText("White");
- m_white.setEnabled(false);
- group.add(m_white);
- m_colorBox.add(m_white);
- return m_colorBox;
+ int index = getSelectedCommand();
+ if (index >= 0) selectCommand(index);
+ m_firstIsTemp = false;
+ }
+
+ private void runCommand() {
+ // if (m_gtp.isCommandInProgress())
+ // {
+ // showError("MSG_ANALYZE_CANNOT_EXECUTE",
+ // "MSG_ANALYZE_CANNOT_EXECUTE_2",
+ // false);
+ // return;
+ // }
+ int index = getSelectedCommand();
+ if (index < 0) {
+ // String name = m_gtp.getName();
+ // if (name == null)
+ // showError("MSG_ANALYZE_NOT_SUPPORTED",
+ // "MSG_ANALYZE_NOT_SUPPORTED_2", false);
+ // else
+ // showError("MSG_ANALYZE_NOT_SUPPORTED",
+ // "MSG_ANALYZE_NOT_SUPPORTED_3", false, name);
+ return;
}
-
- private JPanel createCommandPanel()
- {
- JPanel panel = new JPanel(new BorderLayout());
- m_list = new JList();
- m_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- m_list.setVisibleRowCount(25);
- m_list.addMouseListener(new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
- int modifiers = e.getModifiers();
- int mask = ActionEvent.ALT_MASK;
- if (e.getClickCount() == 2
- || ((modifiers & mask) != 0))
- {
- //int index =
- // m_list.locationToIndex(event.getPoint());
- runCommand();
- }
- }
- });
- m_list.addFocusListener(new FocusAdapter() {
- public void focusGained(FocusEvent e) {
- int index = getSelectedCommand();
- if (index >= 0)
- m_list.setSelectedIndex(index);
- }
- });
- m_list.addListSelectionListener(this);
- JScrollPane scrollPane = new JScrollPane(m_list);
- if (Platform.isMac())
- // Default Apple L&F uses no border, but Quaqua 3.7.4 does
- scrollPane.setBorder(null);
- panel.add(scrollPane, BorderLayout.CENTER);
- panel.add(createLowerPanel(), BorderLayout.SOUTH);
- String[] labels = new String[m_commands.size()];
- for (int i = 0; i < m_commands.size(); ++i)
- labels[i] = m_commands.get(i).getLabel();
- m_list.setListData(labels);
- comboBoxChanged();
- loadRecent();
- return panel;
+ updateRecent(index);
+ AnalyzeCommand command = new AnalyzeCommand(m_commands.get(index));
+ if (command.needsColorArg()) command.setColorArg(getSelectedColor());
+ String label = command.getResultTitle();
+ if (command.needsStringArg()) {
+ String stringArg =
+ JOptionPane.showInputDialog(this, label, "TIT_INPUT", JOptionPane.PLAIN_MESSAGE);
+ if (stringArg == null) return;
+ command.setStringArg(stringArg);
}
-
- private JComponent createLowerPanel()
- {
- Box panel = Box.createVerticalBox();
- panel.add(GuiUtil.createFiller());
- m_comboBoxHistory = new JComboBox();
- panel.add(m_comboBoxHistory);
- Box lowerPanel = Box.createVerticalBox();
- lowerPanel.setBorder(GuiUtil.createEmptyBorder());
- panel.add(lowerPanel);
- Box optionsPanel = Box.createHorizontalBox();
- lowerPanel.add(optionsPanel);
- JPanel leftPanel = new JPanel();
- optionsPanel.add(leftPanel);
- Box leftBox = Box.createVerticalBox();
- leftPanel.add(leftBox);
- m_autoRun = new JCheckBox("Autorun");
- m_autoRun.addItemListener(new ItemListener() {
- public void itemStateChanged(ItemEvent e) {
- if (! m_autoRun.isSelected())
- m_listener.actionClearAnalyzeCommand();
- }
- });
- m_autoRun.setToolTipText("Autorun");
- m_autoRun.setEnabled(false);
- leftBox.add(m_autoRun);
- m_clearBoard = new JCheckBox("Clearboard");
- m_clearBoard.setToolTipText("Clearboard");
- m_clearBoard.setEnabled(false);
- leftBox.add(m_clearBoard);
- m_clearBoard.setSelected(true);
- m_reuseWindow = new JCheckBox("Reuse Text");
- m_reuseWindow.setToolTipText("Reuse text window");
- leftBox.add(m_reuseWindow);
- JPanel rightPanel = new JPanel();
- rightPanel.add(createColorPanel());
- optionsPanel.add(rightPanel);
-
- // TODO: The following horizontal glue does not really work as expected
- // (tested on Linux/Sun Java 1.6.0_14) and the left two components in
- // the box are not aligned to the left.
- optionsPanel.add(Box.createHorizontalGlue());
-
- // TODO: If GTK Looks L&F is used on Linux/Sun Java 1.6.0_14 or OpenJDK
- // 6b14-1.4.1-0ubuntu11, then the text of the checkbox items can be
- // truncated a bit on the left (wrong minimum size calculation?). The
- // two fillers are a workaround for this.
- optionsPanel.add(GuiUtil.createFiller());
- optionsPanel.add(GuiUtil.createFiller());
-
- lowerPanel.add(createButtons());
- m_comboBoxHistory.addActionListener(this);
- return panel;
- }
-
- private String getComboBoxItem(int i)
- {
- return m_comboBoxHistory.getItemAt(i).toString();
- }
-
- private int getComboBoxItemCount()
- {
- return m_comboBoxHistory.getItemCount();
+ if (command.needsOptStringArg()) {}
+ if (command.getType() == AnalyzeType.EPLIST) {}
+ if (command.needsFileArg()) {
+ File fileArg = FileDialogs.showSelectFile(this, label);
+ if (fileArg == null) return;
+ command.setFileArg(fileArg);
}
-
- private int getCommandIndex(String label)
- {
- for (int i = 0; i < m_commands.size(); ++i)
- if (m_commands.get(i).getLabel().equals(label))
- return i;
- return -1;
+ if (command.needsFileOpenArg()) {
+ File fileArg = FileDialogs.showOpen(this, label);
+ if (fileArg == null) return;
+ command.setFileOpenArg(fileArg);
}
-
- private int getSelectedCommand()
- {
- Object item = m_comboBoxHistory.getSelectedItem();
- if (item == null)
- return -1;
- return getCommandIndex(item.toString());
+ if (command.needsFileSaveArg()) {
+ File fileArg = FileDialogs.showSave(this, label, m_messageDialogs);
+ if (fileArg == null) return;
+ command.setFileSaveArg(fileArg);
}
-
- private void insertComboBoxItem(String label, int index)
- {
- m_comboBoxHistory.insertItemAt(GuiUtil.createComboBoxItem(label),
- index);
- }
-
- private void loadRecent()
- {
- m_comboBoxHistory.removeAllItems();
- m_fullRecentList =
- PrefUtil.getList("net/sf/hexgui/gui/analyzedialog/recentcommands");
- for (int i = 0; i < m_fullRecentList.size(); ++i)
- {
- String name = m_fullRecentList.get(i);
- if (getCommandIndex(name) >= 0)
- m_comboBoxHistory.addItem(GuiUtil.createComboBoxItem(name));
- if (m_comboBoxHistory.getItemCount() > 20)
- break;
- }
- int index = getSelectedCommand();
- if (index >= 0)
- selectCommand(index);
- m_firstIsTemp = false;
- }
-
- private void runCommand()
- {
- // if (m_gtp.isCommandInProgress())
- // {
- // showError("MSG_ANALYZE_CANNOT_EXECUTE",
- // "MSG_ANALYZE_CANNOT_EXECUTE_2",
- // false);
- // return;
- // }
- int index = getSelectedCommand();
- if (index < 0)
- {
- // String name = m_gtp.getName();
- // if (name == null)
- // showError("MSG_ANALYZE_NOT_SUPPORTED",
- // "MSG_ANALYZE_NOT_SUPPORTED_2", false);
- // else
- // showError("MSG_ANALYZE_NOT_SUPPORTED",
- // "MSG_ANALYZE_NOT_SUPPORTED_3", false, name);
- return;
- }
- updateRecent(index);
- AnalyzeCommand command = new AnalyzeCommand(m_commands.get(index));
- if (command.needsColorArg())
- command.setColorArg(getSelectedColor());
- String label = command.getResultTitle();
- if (command.needsStringArg())
- {
- String stringArg =
- JOptionPane.showInputDialog(this, label,
- "TIT_INPUT",
- JOptionPane.PLAIN_MESSAGE);
- if (stringArg == null)
- return;
- command.setStringArg(stringArg);
- }
- if (command.needsOptStringArg())
- {
- }
- if (command.getType() == AnalyzeType.EPLIST)
- {
- }
- if (command.needsFileArg())
- {
- File fileArg = FileDialogs.showSelectFile(this, label);
- if (fileArg == null)
- return;
- command.setFileArg(fileArg);
- }
- if (command.needsFileOpenArg())
- {
- File fileArg = FileDialogs.showOpen(this, label);
- if (fileArg == null)
- return;
- command.setFileOpenArg(fileArg);
- }
- if (command.needsFileSaveArg())
- {
- File fileArg = FileDialogs.showSave(this, label, m_messageDialogs);
- if (fileArg == null)
- return;
- command.setFileSaveArg(fileArg);
- }
- if (command.needsColorArg())
- command.setColorArg(getSelectedColor());
- boolean autoRun = m_autoRun.isEnabled() && m_autoRun.isSelected();
- boolean clearBoard =
- ! m_clearBoard.isEnabled() || m_clearBoard.isSelected();
- boolean reuseWindow =
- m_reuseWindow.isEnabled() && m_reuseWindow.isSelected();
- m_listener.actionSetAnalyzeCommand(command, autoRun, clearBoard,
- false, reuseWindow);
- }
-
- private void selectCommand(int index)
- {
- String label = m_commands.get(index).getLabel();
- updateOptions(label);
- m_comboBoxHistory.removeActionListener(this);
- if (m_firstIsTemp && getComboBoxItemCount() > 0)
- m_comboBoxHistory.removeItemAt(0);
- if (getComboBoxItemCount() == 0 || ! getComboBoxItem(0).equals(label))
- {
- insertComboBoxItem(label, 0);
- m_firstIsTemp = true;
- m_comboBoxHistory.setSelectedIndex(0);
- }
- m_comboBoxHistory.addActionListener(this);
- }
-
- private void selectColor()
- {
- if (m_selectedColor == BLACK)
- m_black.setSelected(true);
- else if (m_selectedColor == WHITE)
- m_white.setSelected(true);
- }
-
- private void showError(String mainMessage, String optionalMessage,
- boolean isCritical)
- {
- ShowError.msg(this, mainMessage);
- }
-
- private void showError(String mainMessage, String optionalMessage,
- boolean isCritical, Object... args)
- {
- ShowError.msg(this, mainMessage);
- }
-
- private void updateOptions(String label)
- {
- if (label.equals(m_lastUpdateOptionsCommand))
- return;
- m_lastUpdateOptionsCommand = label;
- int index = getCommandIndex(label);
- if (index < 0)
- return;
- AnalyzeCommand command =
- new AnalyzeCommand(m_commands.get(index));
- boolean needsColorArg = command.needsColorArg();
- m_black.setEnabled(needsColorArg);
- m_white.setEnabled(needsColorArg);
- m_autoRun.setEnabled(command.getType() != AnalyzeType.PARAM);
- m_autoRun.setSelected(false);
- m_clearBoard.setEnabled(command.getType() != AnalyzeType.PARAM);
- m_runButton.setEnabled(true);
- }
-
- private void updateRecent(int index)
- {
- String label = m_commands.get(index).getLabel();
- insertComboBoxItem(label, 0);
- m_comboBoxHistory.setSelectedIndex(0);
- for (int i = 1; i < getComboBoxItemCount(); ++i)
- if (getComboBoxItem(i).equals(label))
- m_comboBoxHistory.removeItemAt(i);
- m_firstIsTemp = false;
+ if (command.needsColorArg()) command.setColorArg(getSelectedColor());
+ boolean autoRun = m_autoRun.isEnabled() && m_autoRun.isSelected();
+ boolean clearBoard = !m_clearBoard.isEnabled() || m_clearBoard.isSelected();
+ boolean reuseWindow = m_reuseWindow.isEnabled() && m_reuseWindow.isSelected();
+ m_listener.actionSetAnalyzeCommand(command, autoRun, clearBoard, false, reuseWindow);
+ }
+
+ private void selectCommand(int index) {
+ String label = m_commands.get(index).getLabel();
+ updateOptions(label);
+ m_comboBoxHistory.removeActionListener(this);
+ if (m_firstIsTemp && getComboBoxItemCount() > 0) m_comboBoxHistory.removeItemAt(0);
+ if (getComboBoxItemCount() == 0 || !getComboBoxItem(0).equals(label)) {
+ insertComboBoxItem(label, 0);
+ m_firstIsTemp = true;
+ m_comboBoxHistory.setSelectedIndex(0);
}
+ m_comboBoxHistory.addActionListener(this);
+ }
+
+ private void selectColor() {
+ if (m_selectedColor == BLACK) m_black.setSelected(true);
+ else if (m_selectedColor == WHITE) m_white.setSelected(true);
+ }
+
+ private void showError(String mainMessage, String optionalMessage, boolean isCritical) {
+ ShowError.msg(this, mainMessage);
+ }
+
+ private void showError(
+ String mainMessage, String optionalMessage, boolean isCritical, Object... args) {
+ ShowError.msg(this, mainMessage);
+ }
+
+ private void updateOptions(String label) {
+ if (label.equals(m_lastUpdateOptionsCommand)) return;
+ m_lastUpdateOptionsCommand = label;
+ int index = getCommandIndex(label);
+ if (index < 0) return;
+ AnalyzeCommand command = new AnalyzeCommand(m_commands.get(index));
+ boolean needsColorArg = command.needsColorArg();
+ m_black.setEnabled(needsColorArg);
+ m_white.setEnabled(needsColorArg);
+ m_autoRun.setEnabled(command.getType() != AnalyzeType.PARAM);
+ m_autoRun.setSelected(false);
+ m_clearBoard.setEnabled(command.getType() != AnalyzeType.PARAM);
+ m_runButton.setEnabled(true);
+ }
+
+ private void updateRecent(int index) {
+ String label = m_commands.get(index).getLabel();
+ insertComboBoxItem(label, 0);
+ m_comboBoxHistory.setSelectedIndex(0);
+ for (int i = 1; i < getComboBoxItemCount(); ++i)
+ if (getComboBoxItem(i).equals(label)) m_comboBoxHistory.removeItemAt(i);
+ m_firstIsTemp = false;
+ }
}
diff --git a/src/main/java/hexgui/gui/BoardDrawerBase.java b/src/main/java/hexgui/gui/BoardDrawerBase.java
index f40f823..f1027ea 100644
--- a/src/main/java/hexgui/gui/BoardDrawerBase.java
+++ b/src/main/java/hexgui/gui/BoardDrawerBase.java
@@ -1,376 +1,352 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
-import hexgui.util.Pair;
-import hexgui.util.RadialGradientPaint;
import hexgui.hex.HexColor;
import hexgui.hex.HexPoint;
-
-import java.util.Vector;
-import javax.swing.*;
-
-import java.awt.Point;
-import java.awt.Polygon;
+import hexgui.util.Pair;
+import java.awt.AlphaComposite;
import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
import java.awt.Graphics2D;
-import java.awt.AlphaComposite;
import java.awt.Image;
-import java.awt.FontMetrics;
-import java.awt.Font;
+import java.awt.Point;
+import java.awt.Polygon;
import java.awt.RenderingHints;
-import java.awt.Graphics;
-
import java.awt.event.*;
import java.net.URL;
+import java.util.Vector;
+import javax.swing.*;
-//----------------------------------------------------------------------------
-
-/** Base class for board drawing.
-
- Board drawers are responsible for drawing the background,
- labels, field outlines, and stone shadows. In addition, they
- are also responsible for determining the actual position of each
- field in the window. Field contents (i.e. stones, markers,
- numerical values, etc) are not drawn, they are drawn with the
- GuiField class.
-
-
Board sizes supported are m x n where
- m and n range from 1 to 26. By
- default, black connects top and bottom and should be labeled with
- letters. White connects left and right and should be labeled with
- numbers.
-*/
-public abstract class BoardDrawerBase
-{
- public BoardDrawerBase()
- {
- m_background = null;
- m_aspect_ratio = 1.0;
+// ----------------------------------------------------------------------------
+
+/**
+ * Base class for board drawing.
+ *
+ *
Board drawers are responsible for drawing the background, labels, field outlines, and stone
+ * shadows. In addition, they are also responsible for determining the actual position of each field
+ * in the window. Field contents (i.e. stones, markers, numerical values, etc) are not drawn, they
+ * are drawn with the GuiField class.
+ *
+ *
Board sizes supported are m x n where m and n range
+ * from 1 to 26. By default, black connects top and bottom and should be labeled with letters. White
+ * connects left and right and should be labeled with numbers.
+ */
+public abstract class BoardDrawerBase {
+ public BoardDrawerBase() {
+ m_background = null;
+ m_aspect_ratio = 1.0;
+ }
+
+ /**
+ * Loads the image in filename and sets it as the background. If filename
+ * does not exist no background image is displayed. Image will be scaled to fit the
+ * window.
+ *
+ * @param filename filename of the image to use as a background.
+ */
+ public void loadBackground(String filename) {
+ ClassLoader classLoader = getClass().getClassLoader();
+ URL url = classLoader.getResource(filename);
+ if (url == null) {
+ System.out.println("loadBackground: could not load '" + filename + "'!");
+ m_background = null;
+ } else {
+ m_background = new ImageIcon(url).getImage();
}
-
- /** Loads the image in filename and sets it as the
- background. If filename does not exist no
- background image is displayed. Image will be scaled to fit
- the window.
- @param filename filename of the image to use as a background.
- */
- public void loadBackground(String filename)
- {
- ClassLoader classLoader = getClass().getClassLoader();
- URL url = classLoader.getResource(filename);
- if (url == null) {
- System.out.println("loadBackground: could not load '" +
- filename + "'!");
- m_background = null;
- } else {
- m_background = new ImageIcon(url).getImage();
- }
+ }
+
+ /**
+ * Gets the field containing the specified point. NOTE: uses the position of fields from the last
+ * call to draw(). Also assumes the set of fields given are the same as those in the last call to
+ * draw().
+ *
+ * @param p the point
+ * @param field the set of fields to search through.
+ * @return the field in the set that p is in or null if p is not in any field.
+ */
+ public GuiField getFieldContaining(Point p, GuiField field[]) {
+ if (m_outline == null) return null;
+ for (int x = 0; x < field.length; x++) {
+ if (m_outline[x].contains(p)) return field[x];
}
-
- /** Gets the field containing the specified point.
- NOTE: uses the position of fields from the last call to draw().
- Also assumes the set of fields given are the same as those in the
- last call to draw().
- @param p the point
- @param field the set of fields to search through.
- @return the field in the set that p is in or null if
- p is not in any field.
- */
- public GuiField getFieldContaining(Point p, GuiField field[])
- {
- if (m_outline == null)
- return null;
- for (int x=0; x> arrows) {
+ m_width = w;
+ m_height = h;
+
+ m_bwidth = bw;
+ m_bheight = bh;
+
+ m_alphaontop = alphaontop;
+
+ computeFieldPlacement();
+ m_outline = calcCellOutlines(field);
+
+ setAntiAliasing(g);
+ drawBackground(g);
+ drawCells(g, field);
+ drawLabels(g, alphaontop);
+ drawShadows(g, field);
+ drawFields(g, field);
+ drawAlpha(g, field);
+
+ drawArrows(g, arrows);
+ }
+
+ // ------------------------------------------------------------
+
+ protected abstract Point getLocation(HexPoint p);
+
+ /**
+ * Calculates the width of a field given the dimensions of the window and board.
+ *
+ * @param w width of window
+ * @param h height of window
+ * @param bw width of board
+ * @param bh height of board
+ */
+ protected abstract int calcFieldWidth(int w, int h, int bw, int bh);
+
+ /**
+ * Calculates the height of a field given the dimensions of the window and board.
+ *
+ * @see calcFieldWidth
+ */
+ protected abstract int calcFieldHeight(int w, int h, int bw, int bh);
+
+ protected abstract int calcStepSize();
+
+ /**
+ * Calculates the width of the board in pixels.
+ *
+ * @requires calcFieldWidth and calcFieldHeight to have been called.
+ */
+ protected abstract int calcBoardWidth();
+
+ /**
+ * Calculates the height of the board in pixels.
+ *
+ * @requires calcFieldWidth and calcFieldHeight to have been called.
+ */
+ protected abstract int calcBoardHeight();
+
+ /**
+ * Performs any necessary initializations for drawing the outlines of the fields.
+ *
+ * @param the fields it will need to draw
+ */
+ protected abstract Polygon[] calcCellOutlines(GuiField field[]);
+
+ /**
+ * Draws the outlines of the given fields.
+ *
+ * @param g graphics context to draw to.
+ * @param field the list of fields to draw.
+ */
+ protected void drawCells(Graphics g, GuiField field[]) {
+ g.setColor(Color.black);
+ for (int i = 0; i < m_outline.length; i++) {
+ if ((field[i].getAttributes() & GuiField.DRAW_CELL_OUTLINE) != 0) {
+ g.drawPolygon(m_outline[i]);
+ }
}
- /** Draws the board.
- The size of the region to draw to, the size of the board, and the
- field to draw must be given. The position of each field is
- then calculated and the board drawn.
- @param g graphics context to draw to
- @param w the width of the region to draw in
- @param h the height of the region to draw in
- @param bw the width of the board (in fields)
- @param bh the height of the board (in fields)
- @param alphaontop true if letters are on top, otherwise numbers
- @param field the fields to draw
- @param arrows the list of arrows to draw
- */
- public void draw(Graphics g,
- int w, int h, int bw, int bh,
- boolean alphaontop,
- GuiField field[],
- Vector> arrows)
- {
- m_width = w;
- m_height = h;
-
- m_bwidth = bw;
- m_bheight = bh;
-
- m_alphaontop = alphaontop;
-
- computeFieldPlacement();
- m_outline = calcCellOutlines(field);
-
- setAntiAliasing(g);
- drawBackground(g);
- drawCells(g, field);
- drawLabels(g, alphaontop);
- drawShadows(g, field);
- drawFields(g, field);
- drawAlpha(g, field);
-
- drawArrows(g, arrows);
+ g.setColor(Color.yellow);
+ for (int i = 0; i < m_outline.length; i++) {
+ if ((field[i].getAttributes() & GuiField.SELECTED) != 0) {
+ g.drawPolygon(m_outline[i]);
+ }
}
+ }
- //------------------------------------------------------------
-
- protected abstract Point getLocation(HexPoint p);
-
- /** Calculates the width of a field given the dimensions of the
- window and board.
- @param w width of window
- @param h height of window
- @param bw width of board
- @param bh height of board
- */
- protected abstract int calcFieldWidth(int w, int h, int bw, int bh);
-
- /** Calculates the height of a field given the dimensions of the
- window and board.
- @see calcFieldWidth
- */
- protected abstract int calcFieldHeight(int w, int h, int bw, int bh);
-
-
- protected abstract int calcStepSize();
-
- /** Calculates the width of the board in pixels.
- @requires calcFieldWidth and calcFieldHeight to have been called.
- */
- protected abstract int calcBoardWidth();
-
- /** Calculates the height of the board in pixels.
- @requires calcFieldWidth and calcFieldHeight to have been called.
- */
- protected abstract int calcBoardHeight();
-
- /** Performs any necessary initializations for drawing the
- outlines of the fields.
- @param the fields it will need to draw
- */
- protected abstract Polygon[] calcCellOutlines(GuiField field[]);
-
- /** Draws the outlines of the given fields.
- @param g graphics context to draw to.
- @param field the list of fields to draw.
- */
- protected void drawCells(Graphics g, GuiField field[])
- {
- g.setColor(Color.black);
- for (int i=0; i= (int)(m_fieldWidth/m_aspect_ratio)) {
- m_fieldHeight = (int)(m_fieldWidth/m_aspect_ratio);
- } else {
- m_fieldWidth = (int)(m_fieldHeight*m_aspect_ratio);
- }
-
- // If field dimensions are not even then the inner cell lines
- // on the board can be doubled up.
- // FIXME: lines still get doubled up...why?
- if ((m_fieldWidth & 1) != 0) m_fieldWidth--;
- if ((m_fieldHeight & 1) != 0) m_fieldHeight--;
-
- m_fieldRadius = (m_fieldWidth < m_fieldHeight) ?
- m_fieldWidth : m_fieldHeight;
-
- m_step = calcStepSize();
+ protected void computeFieldPlacement() {
+ m_fieldWidth = calcFieldWidth(m_width, m_height, m_bwidth, m_bheight);
+ m_fieldHeight = calcFieldHeight(m_width, m_height, m_bwidth, m_bheight);
- int bw = calcBoardWidth();
- int bh = calcBoardHeight();
-
- // add a half cell's worth of empty space
- int extra = (m_width - (bw + 3*m_fieldWidth));
- m_marginX = extra/2 + 3*m_fieldWidth/2;
-
- m_marginY = (m_height - bh)/2 + m_fieldHeight/2;
+ if (m_fieldHeight >= (int) (m_fieldWidth / m_aspect_ratio)) {
+ m_fieldHeight = (int) (m_fieldWidth / m_aspect_ratio);
+ } else {
+ m_fieldWidth = (int) (m_fieldHeight * m_aspect_ratio);
}
- //------------------------------------------------------------
-
- protected int getShadowOffset()
- {
- return (m_fieldRadius - 2*GuiField.getStoneMargin(m_fieldRadius)) / 12;
+ // If field dimensions are not even then the inner cell lines
+ // on the board can be doubled up.
+ // FIXME: lines still get doubled up...why?
+ if ((m_fieldWidth & 1) != 0) m_fieldWidth--;
+ if ((m_fieldHeight & 1) != 0) m_fieldHeight--;
+
+ m_fieldRadius = (m_fieldWidth < m_fieldHeight) ? m_fieldWidth : m_fieldHeight;
+
+ m_step = calcStepSize();
+
+ int bw = calcBoardWidth();
+ int bh = calcBoardHeight();
+
+ // add a half cell's worth of empty space
+ int extra = (m_width - (bw + 3 * m_fieldWidth));
+ m_marginX = extra / 2 + 3 * m_fieldWidth / 2;
+
+ m_marginY = (m_height - bh) / 2 + m_fieldHeight / 2;
+ }
+
+ // ------------------------------------------------------------
+
+ protected int getShadowOffset() {
+ return (m_fieldRadius - 2 * GuiField.getStoneMargin(m_fieldRadius)) / 12;
+ }
+
+ protected void drawBackground(Graphics g) {
+ if (m_background != null) g.drawImage(m_background, 0, 0, m_width, m_height, null);
+ }
+
+ protected void drawLabel(Graphics g, Point p, String string, int xoff) {
+ double size = Math.min(m_fieldWidth, m_fieldHeight) * 0.4;
+ Font f = g.getFont();
+ Font f2 = f.deriveFont((float) size);
+
+ FontMetrics fm = g.getFontMetrics(f2);
+ int width = fm.stringWidth(string);
+ int height = fm.getAscent();
+
+ g.setFont(f2);
+ int x = width / 2;
+ int y = height / 2;
+ g.drawString(string, p.x + xoff - x, p.y + y);
+ g.setFont(f);
+ }
+
+ protected abstract void drawLabels(Graphics g, boolean alphatop);
+
+ protected void drawShadows(Graphics graphics, GuiField[] field) {
+ if (m_fieldRadius <= 5) return;
+ Graphics2D graphics2D = graphics instanceof Graphics2D ? (Graphics2D) graphics : null;
+ if (graphics2D == null) return;
+ graphics2D.setComposite(COMPOSITE_3);
+ int size = m_fieldRadius - 2 * GuiField.getStoneMargin(m_fieldRadius);
+ int offset = getShadowOffset();
+ for (int pos = 0; pos < field.length; pos++) {
+ if (field[pos].getColor() == HexColor.EMPTY) continue;
+ Point location = getLocation(field[pos].getPoint());
+ graphics.setColor(Color.black);
+ graphics.fillOval(location.x - size / 2 + offset, location.y - size / 2 + offset, size, size);
}
+ graphics.setPaintMode();
+ }
- protected void drawBackground(Graphics g)
- {
- if (m_background != null)
- g.drawImage(m_background, 0, 0, m_width, m_height, null);
+ protected void drawFields(Graphics g, GuiField field[]) {
+ for (int x = 0; x < field.length; x++) {
+ Point p = getLocation(field[x].getPoint());
+ field[x].draw(g, p.x, p.y, m_fieldWidth, m_fieldHeight);
}
+ }
- protected void drawLabel(Graphics g, Point p, String string, int xoff)
- {
- double size = Math.min(m_fieldWidth, m_fieldHeight) * 0.4;
- Font f = g.getFont();
- Font f2 = f.deriveFont((float)size);
-
- FontMetrics fm = g.getFontMetrics(f2);
- int width = fm.stringWidth(string);
- int height = fm.getAscent();
-
- g.setFont(f2);
- int x = width/2;
- int y = height/2;
- g.drawString(string, p.x + xoff - x, p.y + y);
- g.setFont(f);
- }
+ protected void drawAlpha(Graphics g, GuiField field[]) {
+ if (g instanceof Graphics2D) {
+ Graphics2D g2d = (Graphics2D) g;
- protected abstract void drawLabels(Graphics g, boolean alphatop);
-
- protected void drawShadows(Graphics graphics, GuiField[] field)
- {
- if (m_fieldRadius <= 5)
- return;
- Graphics2D graphics2D =
- graphics instanceof Graphics2D ? (Graphics2D)graphics : null;
- if (graphics2D == null)
- return;
- graphics2D.setComposite(COMPOSITE_3);
- int size = m_fieldRadius - 2 * GuiField.getStoneMargin(m_fieldRadius);
- int offset = getShadowOffset();
- for (int pos = 0; pos < field.length; pos++) {
- if (field[pos].getColor() == HexColor.EMPTY)
- continue;
- Point location = getLocation(field[pos].getPoint());
- graphics.setColor(Color.black);
- graphics.fillOval(location.x - size / 2 + offset,
- location.y - size / 2 + offset,
- size, size);
- }
- graphics.setPaintMode();
- }
+ for (int i = 0; i < m_outline.length; i++) {
+ if ((field[i].getAttributes() & GuiField.DRAW_ALPHA) == 0) continue;
- protected void drawFields(Graphics g, GuiField field[])
- {
- for (int x=0; x> arrows)
- {
- if (g instanceof Graphics2D) {
- Graphics2D g2d = (Graphics2D)g;
- g2d.setColor(Color.BLUE);
- for (int i=0; i> arrows) {
+ if (g instanceof Graphics2D) {
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.setColor(Color.BLUE);
+ for (int i = 0; i < arrows.size(); i++) {
+ Point fm = getLocation(arrows.get(i).first);
+ Point to = getLocation(arrows.get(i).second);
+ drawArrow(g2d, fm.x, fm.y, to.x, to.y, 1.5);
+ }
}
+ }
- public static void drawArrow(Graphics g2d, int x1, int y1,
- int x2, int y2, double stroke)
- {
- double aDir=Math.atan2(x1-x2,y1-y2);
- g2d.drawLine(x2,y2,x1,y1);
- // make the arrow head solid even if dash pattern has been specified
- //g2d.setStroke(new BasicStroke(1f));
-
- Polygon tmpPoly=new Polygon();
- int i1=12+(int)(stroke*2);
- // make the arrow head the same size regardless of the length length
- int i2=6+(int)stroke;
- tmpPoly.addPoint(x2,y2); // arrow tip
- tmpPoly.addPoint(x2+xCor(i1,aDir+.5),y2+yCor(i1,aDir+.5));
- tmpPoly.addPoint(x2+xCor(i2,aDir),y2+yCor(i2,aDir));
- tmpPoly.addPoint(x2+xCor(i1,aDir-.5),y2+yCor(i1,aDir-.5));
- tmpPoly.addPoint(x2,y2); // arrow tip
- g2d.drawPolygon(tmpPoly);
- g2d.fillPolygon(tmpPoly);
+ protected void setAntiAliasing(Graphics g) {
+ if (g instanceof Graphics2D) {
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
-
- private static int yCor(int len, double dir) {return (int)(len * Math.cos(dir));}
- private static int xCor(int len, double dir) {return (int)(len * Math.sin(dir));}
-
-
- protected boolean m_alphaontop;
-
- protected double m_aspect_ratio;
-
- protected Image m_background;
-
- protected int m_width, m_height;
- protected int m_bwidth, m_bheight;
- protected int m_marginX, m_marginY;
- protected int m_fieldWidth, m_fieldHeight, m_fieldRadius, m_step;
- protected Polygon m_outline[];
-
- protected static final AlphaComposite COMPOSITE_3
- = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
-
+ }
+
+ public static void drawArrow(Graphics g2d, int x1, int y1, int x2, int y2, double stroke) {
+ double aDir = Math.atan2(x1 - x2, y1 - y2);
+ g2d.drawLine(x2, y2, x1, y1);
+ // make the arrow head solid even if dash pattern has been specified
+ // g2d.setStroke(new BasicStroke(1f));
+
+ Polygon tmpPoly = new Polygon();
+ int i1 = 12 + (int) (stroke * 2);
+ // make the arrow head the same size regardless of the length length
+ int i2 = 6 + (int) stroke;
+ tmpPoly.addPoint(x2, y2); // arrow tip
+ tmpPoly.addPoint(x2 + xCor(i1, aDir + .5), y2 + yCor(i1, aDir + .5));
+ tmpPoly.addPoint(x2 + xCor(i2, aDir), y2 + yCor(i2, aDir));
+ tmpPoly.addPoint(x2 + xCor(i1, aDir - .5), y2 + yCor(i1, aDir - .5));
+ tmpPoly.addPoint(x2, y2); // arrow tip
+ g2d.drawPolygon(tmpPoly);
+ g2d.fillPolygon(tmpPoly);
+ }
+
+ private static int yCor(int len, double dir) {
+ return (int) (len * Math.cos(dir));
+ }
+
+ private static int xCor(int len, double dir) {
+ return (int) (len * Math.sin(dir));
+ }
+
+ protected boolean m_alphaontop;
+
+ protected double m_aspect_ratio;
+
+ protected Image m_background;
+
+ protected int m_width, m_height;
+ protected int m_bwidth, m_bheight;
+ protected int m_marginX, m_marginY;
+ protected int m_fieldWidth, m_fieldHeight, m_fieldRadius, m_step;
+ protected Polygon m_outline[];
+
+ protected static final AlphaComposite COMPOSITE_3 =
+ AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/BoardDrawerDiamond.java b/src/main/java/hexgui/gui/BoardDrawerDiamond.java
index 651a44a..1c120fd 100644
--- a/src/main/java/hexgui/gui/BoardDrawerDiamond.java
+++ b/src/main/java/hexgui/gui/BoardDrawerDiamond.java
@@ -1,143 +1,123 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
-import hexgui.util.Hexagon;
-import hexgui.hex.HexColor;
import hexgui.hex.HexPoint;
-
-import javax.swing.*;
+import hexgui.util.Hexagon;
import java.awt.*;
import java.awt.event.*;
-import java.net.URL;
-
-//----------------------------------------------------------------------------
-
-public class BoardDrawerDiamond extends BoardDrawerBase
-{
-
- protected static final double ASPECT_RATIO = 1.1547;
-
- public BoardDrawerDiamond()
- {
- super();
- loadBackground("hexgui/images/wood.png");
- m_aspect_ratio = ASPECT_RATIO;
+import javax.swing.*;
+
+// ----------------------------------------------------------------------------
+
+public class BoardDrawerDiamond extends BoardDrawerBase {
+
+ protected static final double ASPECT_RATIO = 1.1547;
+
+ public BoardDrawerDiamond() {
+ super();
+ loadBackground("hexgui/images/wood.png");
+ m_aspect_ratio = ASPECT_RATIO;
+ }
+
+ /**
+ * Returns the location in the window of the field with coordinates (x,y).
+ * Coordinates increase to the right and down, with the top left of the board having coordinates
+ * (0,0). Negative values are acceptable.
+ *
+ * @param x the x coordinate of the field.
+ * @param y the y coordinate of the field.
+ * @return the center of the field at (x,y).
+ */
+ protected Point getLocation(int x, int y) {
+ // yoffset will be positive when bwidth > bheight (to push the
+ // board down) and negative when bwidth < bheight (to lift it
+ // up) because the a1 square (0,0) will not be
+ // in the center of the vertical space occupied by the board.
+ int yoffset = (m_bwidth - m_bheight) * m_fieldHeight / 2;
+
+ Point ret = new Point();
+ ret.x = m_marginX + (y + x) * m_step;
+ ret.y = m_marginY + yoffset + (m_bheight / 2) * m_fieldHeight + (y - x) * m_fieldHeight / 2;
+ return ret;
+ }
+
+ /** Returns the location of the field with HexPoint pos. */
+ protected Point getLocation(HexPoint pos) {
+ if (pos == HexPoint.EAST) {
+ return getLocation(m_bwidth + 1, m_bheight / 2 - 1);
+ } else if (pos == HexPoint.WEST) {
+ return getLocation(-2, m_bheight / 2 + 1);
+ } else if (pos == HexPoint.SOUTH) {
+ return getLocation(m_bwidth / 2 - 1, m_bheight + 1);
+ } else if (pos == HexPoint.NORTH) {
+ return getLocation(m_bwidth / 2 + 1, -2);
}
-
- /** Returns the location in the window of the field with
- coordinates (x,y). Coordinates increase to the
- right and down, with the top left of the board having
- coordinates (0,0). Negative values are acceptable.
- @param x the x coordinate of the field.
- @param y the y coordinate of the field.
- @return the center of the field at (x,y).
- */
- protected Point getLocation(int x, int y)
- {
- // yoffset will be positive when bwidth > bheight (to push the
- // board down) and negative when bwidth < bheight (to lift it
- // up) because the a1 square (0,0) will not be
- // in the center of the vertical space occupied by the board.
- int yoffset = (m_bwidth - m_bheight)*m_fieldHeight/2;
-
- Point ret = new Point();
- ret.x = m_marginX + (y + x)*m_step;
- ret.y = m_marginY + yoffset + (m_bheight/2)*m_fieldHeight
- + (y - x)*m_fieldHeight/2;
- return ret;
+ return getLocation(pos.x, pos.y);
+ }
+
+ protected int calcFieldWidth(int w, int h, int bw, int bh) {
+ return w / (bw + (bh - 1) / 2 + 2);
+ }
+
+ protected int calcFieldHeight(int w, int h, int bw, int bh) {
+ return h / (bh + 2);
+ }
+
+ protected int calcStepSize() {
+ return m_fieldWidth / 4 + m_fieldWidth / 2;
+ }
+
+ protected int calcBoardWidth() {
+ return (m_bwidth + m_bheight - 1) * m_step;
+ }
+
+ protected int calcBoardHeight() {
+ return m_bheight * m_fieldHeight + (m_bwidth - m_bheight) * m_fieldHeight / 2;
+ }
+
+ protected Polygon[] calcCellOutlines(GuiField field[]) {
+ Polygon outline[] = new Polygon[field.length];
+ for (int x = 0; x < outline.length; x++) {
+ Point p = getLocation(field[x].getPoint());
+ outline[x] = Hexagon.createHorizontalHexagon(p, m_fieldWidth, m_fieldHeight);
+ // System.out.println("-----");
+ // System.out.println(field[x].getPoint().toString());
+ // Polygon poly = outline[x];
+ // for (int j=0; j<6; j++) {
+ // System.out.print("(" + poly.xpoints[j] +
+ // "," + poly.ypoints[j] +
+ // ") ");
+ // }
+ // System.out.println("");
}
-
- /** Returns the location of the field with HexPoint pos. */
- protected Point getLocation(HexPoint pos)
- {
- if (pos == HexPoint.EAST) {
- return getLocation(m_bwidth+1, m_bheight/2-1);
- } else if (pos == HexPoint.WEST) {
- return getLocation(-2, m_bheight/2+1);
- } else if (pos == HexPoint.SOUTH) {
- return getLocation(m_bwidth/2-1, m_bheight+1);
- } else if (pos == HexPoint.NORTH) {
- return getLocation(m_bwidth/2+1, -2);
- }
- return getLocation(pos.x, pos.y);
- }
-
- protected int calcFieldWidth(int w, int h, int bw, int bh)
- {
- return w / (bw + (bh-1)/2 + 2);
+ return outline;
+ }
+
+ protected void drawLabels(Graphics g, boolean alphatop) {
+ int xoffset;
+ String string;
+ g.setColor(Color.black);
+
+ xoffset = 0;
+ for (int x = 0; x < m_bwidth; x++) {
+ if (alphatop) string = Character.toString((char) ((int) 'A' + x));
+ else string = Integer.toString(x + 1);
+ drawLabel(g, getLocation(x, -1), string, xoffset);
+ drawLabel(g, getLocation(x, m_bheight), string, xoffset);
}
-
- protected int calcFieldHeight(int w, int h, int bw, int bh)
- {
- return h / (bh + 2);
- }
-
- protected int calcStepSize()
- {
- return m_fieldWidth/4 + m_fieldWidth/2;
- }
- protected int calcBoardWidth()
- {
- return (m_bwidth+m_bheight-1)*m_step;
- }
-
- protected int calcBoardHeight()
- {
- return m_bheight*m_fieldHeight
- + (m_bwidth - m_bheight)*m_fieldHeight/2;
- }
-
- protected Polygon[] calcCellOutlines(GuiField field[])
- {
- Polygon outline[] = new Polygon[field.length];
- for (int x = 0; x < outline.length; x++) {
- Point p = getLocation(field[x].getPoint());
- outline[x] = Hexagon.createHorizontalHexagon(p,
- m_fieldWidth,
- m_fieldHeight);
-// System.out.println("-----");
-// System.out.println(field[x].getPoint().toString());
-// Polygon poly = outline[x];
-// for (int j=0; j<6; j++) {
-// System.out.print("(" + poly.xpoints[j] +
-// "," + poly.ypoints[j] +
-// ") ");
-// }
-// System.out.println("");
- }
- return outline;
- }
-
- protected void drawLabels(Graphics g, boolean alphatop)
- {
- int xoffset;
- String string;
- g.setColor(Color.black);
-
- xoffset = 0;
- for (int x=0; x(x,y).
+ * Coordinates increase to the right and down, with the top left of the board having coordinates
+ * (0,0). Negative values are acceptable.
+ *
+ * @param x the x coordinate of the field.
+ * @param y the y coordinate of the field.
+ * @return the center of the field at (x,y).
+ */
+ protected Point getLocation(int x, int y) {
+ Point ret = new Point();
+ ret.x = m_marginX + y * m_fieldWidth / 2 + x * m_fieldWidth;
+ ret.y = m_marginY + y * m_step;
+ return ret;
+ }
+
+ /** Returns the location of the field with HexPoint pos. */
+ protected Point getLocation(HexPoint pos) {
+ if (pos == HexPoint.EAST) {
+ return getLocation(m_bwidth + 1, m_bheight / 2 - 1);
+ } else if (pos == HexPoint.WEST) {
+ return getLocation(-2, m_bheight / 2 + 1);
+ } else if (pos == HexPoint.SOUTH) {
+ return getLocation(m_bwidth / 2 - 1, m_bheight + 1);
+ } else if (pos == HexPoint.NORTH) {
+ return getLocation(m_bwidth / 2 + 1, -2);
}
-
- /** Returns the location in the window of the field with
- coordinates (x,y). Coordinates increase to the
- right and down, with the top left of the board having
- coordinates (0,0). Negative values are acceptable.
- @param x the x coordinate of the field.
- @param y the y coordinate of the field.
- @return the center of the field at (x,y).
- */
- protected Point getLocation(int x, int y)
- {
- Point ret = new Point();
- ret.x = m_marginX + y*m_fieldWidth/2 + x*m_fieldWidth;
- ret.y = m_marginY + y*m_step;
- return ret;
+ return getLocation(pos.x, pos.y);
+ }
+
+ protected int calcFieldWidth(int w, int h, int bw, int bh) {
+ return w / (bw + (bh - 1) / 2 + 2);
+ }
+
+ protected int calcFieldHeight(int w, int h, int bw, int bh) {
+ return h / ((bh + 1) / 2 + (bh / 4) + 4);
+ }
+
+ protected int calcStepSize() {
+ return m_fieldHeight / 4 + m_fieldHeight / 2;
+ }
+
+ protected int calcBoardWidth() {
+ return m_bwidth * m_fieldWidth + (m_bheight - 1) * m_fieldWidth / 2;
+ }
+
+ protected int calcBoardHeight() {
+ return m_fieldHeight * (m_bheight + 1) / 2 + m_fieldHeight * m_bheight / 4;
+ }
+
+ protected Polygon[] calcCellOutlines(GuiField field[]) {
+ Polygon outline[] = new Polygon[field.length];
+ for (int x = 0; x < outline.length; x++) {
+ Point p = getLocation(field[x].getPoint());
+ outline[x] = Hexagon.createVerticalHexagon(p, m_fieldWidth, m_fieldHeight);
}
-
- /** Returns the location of the field with HexPoint pos. */
- protected Point getLocation(HexPoint pos)
- {
- if (pos == HexPoint.EAST) {
- return getLocation(m_bwidth+1, m_bheight/2-1);
- } else if (pos == HexPoint.WEST) {
- return getLocation(-2, m_bheight/2+1);
- } else if (pos == HexPoint.SOUTH) {
- return getLocation(m_bwidth/2-1, m_bheight+1);
- } else if (pos == HexPoint.NORTH) {
- return getLocation(m_bwidth/2+1, -2);
- }
- return getLocation(pos.x, pos.y);
- }
-
- protected int calcFieldWidth(int w, int h, int bw, int bh)
- {
- return w / (bw + (bh-1)/2 + 2);
+ return outline;
+ }
+
+ protected void drawLabels(Graphics g, boolean alphatop) {
+ String string;
+ int xoffset, yoffset;
+ g.setColor(Color.black);
+
+ xoffset = m_fieldWidth / 2;
+ yoffset = 1;
+ for (int x = 0; x < m_bwidth; x++) {
+ if (alphatop) string = Character.toString((char) ((int) 'A' + x));
+ else string = Integer.toString(x + 1);
+ drawLabel(g, getLocation(x, -1), string, xoffset);
+ drawLabel(g, getLocation(x - yoffset, m_bheight), string, xoffset);
}
-
- protected int calcFieldHeight(int w, int h, int bw, int bh)
- {
- return h / ((bh+1)/2 + (bh/4) + 4);
- }
-
- protected int calcStepSize()
- {
- return m_fieldHeight/4 + m_fieldHeight/2;
-
- }
- protected int calcBoardWidth()
- {
- return m_bwidth*m_fieldWidth + (m_bheight-1)*m_fieldWidth/2;
- }
-
- protected int calcBoardHeight()
- {
- return m_fieldHeight*(m_bheight+1)/2
- + m_fieldHeight*m_bheight/4;
- }
-
- protected Polygon[] calcCellOutlines(GuiField field[])
- {
- Polygon outline[] = new Polygon[field.length];
- for (int x = 0; x < outline.length; x++) {
- Point p = getLocation(field[x].getPoint());
- outline[x] = Hexagon.createVerticalHexagon(p,
- m_fieldWidth,
- m_fieldHeight);
- }
- return outline;
- }
-
- protected void drawLabels(Graphics g, boolean alphatop)
- {
- String string;
- int xoffset,yoffset;
- g.setColor(Color.black);
-
- xoffset = m_fieldWidth/2;
- yoffset = 1;
- for (int x=0; x(x,y).
+ * Coordinates increase to the right and down, with the top left of the board having coordinates
+ * (0,0). Negative values are acceptable.
+ *
+ * @param x the x coordinate of the field.
+ * @param y the y coordinate of the field.
+ * @return the center of the field at (x,y).
+ */
+ protected Point getLocation(int x, int y) {
+ Point ret = new Point();
+ ret.x = m_marginX + y * m_fieldWidth / 2 + x * m_fieldWidth;
+ ret.y = m_marginY + (m_bheight - 1 - y) * m_step;
+ return ret;
+ }
+
+ /** Returns the location of the field with HexPoint pos. */
+ protected Point getLocation(HexPoint pos) {
+ if (pos == HexPoint.EAST) {
+ return getLocation(m_bwidth + 1, m_bheight / 2 - 1);
+ } else if (pos == HexPoint.WEST) {
+ return getLocation(-2, m_bheight / 2 + 1);
+ } else if (pos == HexPoint.SOUTH) {
+ return getLocation(m_bwidth / 2 - 1, m_bheight + 1);
+ } else if (pos == HexPoint.NORTH) {
+ return getLocation(m_bwidth / 2 + 1, -2);
}
-
- /** Returns the location in the window of the field with
- coordinates (x,y). Coordinates increase to the
- right and down, with the top left of the board having
- coordinates (0,0). Negative values are acceptable.
- @param x the x coordinate of the field.
- @param y the y coordinate of the field.
- @return the center of the field at (x,y).
- */
- protected Point getLocation(int x, int y)
- {
- Point ret = new Point();
- ret.x = m_marginX + y*m_fieldWidth/2 + x*m_fieldWidth;
- ret.y = m_marginY + (m_bheight-1-y)*m_step;
- return ret;
+ return getLocation(pos.x, pos.y);
+ }
+
+ protected int calcFieldWidth(int w, int h, int bw, int bh) {
+ return w / (bw + (bh - 1) / 2 + 2);
+ }
+
+ protected int calcFieldHeight(int w, int h, int bw, int bh) {
+ return h / ((bh + 1) / 2 + (bh / 4) + 4);
+ }
+
+ protected int calcStepSize() {
+ return m_fieldHeight / 4 + m_fieldHeight / 2;
+ }
+
+ protected int calcBoardWidth() {
+ return m_bwidth * m_fieldWidth + (m_bheight - 1) * m_fieldWidth / 2;
+ }
+
+ protected int calcBoardHeight() {
+ return m_fieldHeight * (m_bheight + 1) / 2 + m_fieldHeight * m_bheight / 4;
+ }
+
+ protected Polygon[] calcCellOutlines(GuiField field[]) {
+ Polygon outline[] = new Polygon[field.length];
+ for (int x = 0; x < outline.length; x++) {
+ Point p = getLocation(field[x].getPoint());
+ outline[x] = Hexagon.createVerticalHexagon(p, m_fieldWidth, m_fieldHeight);
}
-
- /** Returns the location of the field with HexPoint pos. */
- protected Point getLocation(HexPoint pos)
- {
- if (pos == HexPoint.EAST) {
- return getLocation(m_bwidth+1, m_bheight/2-1);
- } else if (pos == HexPoint.WEST) {
- return getLocation(-2, m_bheight/2+1);
- } else if (pos == HexPoint.SOUTH) {
- return getLocation(m_bwidth/2-1, m_bheight+1);
- } else if (pos == HexPoint.NORTH) {
- return getLocation(m_bwidth/2+1, -2);
- }
- return getLocation(pos.x, pos.y);
- }
-
- protected int calcFieldWidth(int w, int h, int bw, int bh)
- {
- return w / (bw + (bh-1)/2 + 2);
+ return outline;
+ }
+
+ protected void drawLabels(Graphics g, boolean alphatop) {
+ String string;
+ int xoffset, yoffset;
+ g.setColor(Color.black);
+
+ xoffset = m_fieldWidth / 2;
+ yoffset = 1;
+ for (int x = 0; x < m_bwidth; x++) {
+ if (alphatop) string = Character.toString((char) ((int) 'A' + x));
+ else string = Integer.toString(x + 1);
+ drawLabel(g, getLocation(x, -1), string, xoffset);
+ drawLabel(g, getLocation(x - yoffset, m_bheight), string, xoffset);
}
-
- protected int calcFieldHeight(int w, int h, int bw, int bh)
- {
- return h / ((bh+1)/2 + (bh/4) + 4);
- }
-
- protected int calcStepSize()
- {
- return m_fieldHeight/4 + m_fieldHeight/2;
-
- }
- protected int calcBoardWidth()
- {
- return m_bwidth*m_fieldWidth + (m_bheight-1)*m_fieldWidth/2;
- }
-
- protected int calcBoardHeight()
- {
- return m_fieldHeight*(m_bheight+1)/2
- + m_fieldHeight*m_bheight/4;
- }
-
- protected Polygon[] calcCellOutlines(GuiField field[])
- {
- Polygon outline[] = new Polygon[field.length];
- for (int x = 0; x < outline.length; x++) {
- Point p = getLocation(field[x].getPoint());
- outline[x] = Hexagon.createVerticalHexagon(p,
- m_fieldWidth,
- m_fieldHeight);
- }
- return outline;
- }
-
- protected void drawLabels(Graphics g, boolean alphatop)
- {
- String string;
- int xoffset,yoffset;
- g.setColor(Color.black);
-
- xoffset = m_fieldWidth/2;
- yoffset = 1;
- for (int x=0; x(x,y). Coordinates increase to the
- right and down, with the top left of the board having
- coordinates (0,0). Negative values are acceptable.
- @param x the x coordinate of the field.
- @param y the y coordinate of the field.
- @return the center of the field at (x,y).
- */
- protected Point getLocation(int x, int y)
- {
- Point ret = new Point();
- int center = m_marginX + m_bwidth*m_fieldWidth / 2;
- ret.x = center - y*m_fieldWidth/2 + x*m_fieldWidth;
- ret.y = m_marginY + y*m_step;
- return ret;
- }
-
- /** Returns the location of the field with HexPoint pos. */
- protected Point getLocation(HexPoint pos)
- {
- if (pos == HexPoint.EAST) {
- return getLocation(m_bheight/2+2, m_bheight/2);
- } else if (pos == HexPoint.WEST) {
- return getLocation(-2, m_bheight/2);
- } else if (pos == HexPoint.SOUTH) {
- return getLocation(m_bwidth/2+1, m_bheight+1);
- }
- return getLocation(pos.x, pos.y);
+import javax.swing.*;
+
+// ----------------------------------------------------------------------------
+
+public class BoardDrawerY extends BoardDrawerBase {
+ protected static final double ASPECT_RATIO = 1.0 / 1.1547;
+
+ public BoardDrawerY() {
+ super();
+ loadBackground("hexgui/images/wood.png");
+ m_aspect_ratio = ASPECT_RATIO;
+ }
+
+ /**
+ * Returns the location in the window of the field with coordinates (x,y).
+ * Coordinates increase to the right and down, with the top left of the board having coordinates
+ * (0,0). Negative values are acceptable.
+ *
+ * @param x the x coordinate of the field.
+ * @param y the y coordinate of the field.
+ * @return the center of the field at (x,y).
+ */
+ protected Point getLocation(int x, int y) {
+ Point ret = new Point();
+ int center = m_marginX + m_bwidth * m_fieldWidth / 2;
+ ret.x = center - y * m_fieldWidth / 2 + x * m_fieldWidth;
+ ret.y = m_marginY + y * m_step;
+ return ret;
+ }
+
+ /** Returns the location of the field with HexPoint pos. */
+ protected Point getLocation(HexPoint pos) {
+ if (pos == HexPoint.EAST) {
+ return getLocation(m_bheight / 2 + 2, m_bheight / 2);
+ } else if (pos == HexPoint.WEST) {
+ return getLocation(-2, m_bheight / 2);
+ } else if (pos == HexPoint.SOUTH) {
+ return getLocation(m_bwidth / 2 + 1, m_bheight + 1);
}
-
- protected int calcFieldWidth(int w, int h, int bw, int bh)
- {
- return w / (bw + 3); // width + 2 cells for labels + 1 for spacing
- }
-
- protected int calcFieldHeight(int w, int h, int bw, int bh)
- {
- // each row takes 3/4 of the height of hex
- // need 2 extra rows for labels + 1 row of spacing
- return h / ( 3*bh/4 + 3);
- }
-
- protected int calcStepSize()
- {
- return m_fieldHeight/4 + m_fieldHeight/2;
-
+ return getLocation(pos.x, pos.y);
+ }
+
+ protected int calcFieldWidth(int w, int h, int bw, int bh) {
+ return w / (bw + 3); // width + 2 cells for labels + 1 for spacing
+ }
+
+ protected int calcFieldHeight(int w, int h, int bw, int bh) {
+ // each row takes 3/4 of the height of hex
+ // need 2 extra rows for labels + 1 row of spacing
+ return h / (3 * bh / 4 + 3);
+ }
+
+ protected int calcStepSize() {
+ return m_fieldHeight / 4 + m_fieldHeight / 2;
+ }
+
+ protected int calcBoardWidth() {
+ return m_bwidth * m_fieldWidth;
+ }
+
+ protected int calcBoardHeight() {
+ // return m_fieldHeight*(m_bheight+1)/2
+ // + m_fieldHeight*m_bheight/4;
+ return 3 * m_fieldHeight / 4 * (m_bheight + 2);
+ }
+
+ protected Polygon[] calcCellOutlines(GuiField field[]) {
+ Polygon outline[] = new Polygon[field.length];
+ for (int x = 0; x < outline.length; x++) {
+ Point p = getLocation(field[x].getPoint());
+ outline[x] = Hexagon.createVerticalHexagon(p, m_fieldWidth, m_fieldHeight);
}
- protected int calcBoardWidth()
- {
- return m_bwidth*m_fieldWidth;
+ return outline;
+ }
+
+ protected void drawLabels(Graphics g, boolean alphatop) {
+ String string;
+ int xoffset, yoffset;
+ g.setColor(Color.black);
+
+ xoffset = m_fieldWidth / 2;
+ yoffset = 1;
+ for (int x = 0; x < m_bwidth; x++) {
+ string = Character.toString((char) ((int) 'A' + x));
+ // drawLabel(g, getLocation(x, -1), string, xoffset);
+ drawLabel(g, getLocation(x, m_bheight), string, xoffset);
}
-
- protected int calcBoardHeight()
- {
- // return m_fieldHeight*(m_bheight+1)/2
- // + m_fieldHeight*m_bheight/4;
- return 3*m_fieldHeight/4*(m_bheight+2);
- }
-
- protected Polygon[] calcCellOutlines(GuiField field[])
- {
- Polygon outline[] = new Polygon[field.length];
- for (int x = 0; x < outline.length; x++) {
- Point p = getLocation(field[x].getPoint());
- outline[x] = Hexagon.createVerticalHexagon(p,
- m_fieldWidth,
- m_fieldHeight);
- }
- return outline;
- }
-
- protected void drawLabels(Graphics g, boolean alphatop)
- {
- String string;
- int xoffset,yoffset;
- g.setColor(Color.black);
-
- xoffset = m_fieldWidth/2;
- yoffset = 1;
- for (int x=0; x programs)
- {
- super(owner, true);
- setTitle(title);
-
- m_programs = programs;
-
- // create gui
- JEditorPane info = new JEditorPane();
- info.setEditable(false);
- info.setEditorKit(new HTMLEditorKit());
- info.setText("Select program from list below.");
- add(info, BorderLayout.NORTH);
- add(createProgramPanel(), BorderLayout.CENTER);
- add(createButtonPanel(), BorderLayout.SOUTH);
-
- pack();
-
- setResizable(false);
- }
-
- public void actionPerformed(ActionEvent e)
- {
- String cmd = e.getActionCommand();
- if (cmd.equals("OK")) {
-
- m_program = m_programs.get(m_list.getSelectedIndex());
-
- // set the program
- setVisible(false);
-
- } else if (cmd.equals("Cancel")) {
- setVisible(false);
- }
- }
-
- public Program getProgram()
- {
- return m_program;
- }
-
- private JPanel createProgramPanel()
- {
- JPanel panel = new JPanel();
-
- m_list = new JList(m_programs);
- m_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- m_list.setVisibleRowCount(10);
- m_list.setSelectedIndex(0);
- m_list.setPreferredSize(new Dimension(200, 250));
-
- JScrollPane sc = new JScrollPane(m_list);
- sc.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
-
- panel.add(sc);
-
- return panel;
- }
-
- private JPanel createButtonPanel()
- {
- JPanel panel = new JPanel();
-
- JButton button = new JButton(" OK ");
- button.addActionListener(this);
- button.setActionCommand("OK");
- panel.add(button);
-
- button = new JButton("Cancel");
- button.addActionListener(this);
- button.setActionCommand("Cancel");
- panel.add(button);
-
- return panel;
+class ChooseProgramDialog extends JDialog implements ActionListener {
+ public ChooseProgramDialog(Frame owner, String title, Vector programs) {
+ super(owner, true);
+ setTitle(title);
+
+ m_programs = programs;
+
+ // create gui
+ JEditorPane info = new JEditorPane();
+ info.setEditable(false);
+ info.setEditorKit(new HTMLEditorKit());
+ info.setText("Select program from list below.");
+ add(info, BorderLayout.NORTH);
+ add(createProgramPanel(), BorderLayout.CENTER);
+ add(createButtonPanel(), BorderLayout.SOUTH);
+
+ pack();
+
+ setResizable(false);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+ if (cmd.equals("OK")) {
+
+ m_program = m_programs.get(m_list.getSelectedIndex());
+
+ // set the program
+ setVisible(false);
+
+ } else if (cmd.equals("Cancel")) {
+ setVisible(false);
}
-
- JList m_list;
-
- Vector m_programs;
- Program m_program;
+ }
+
+ public Program getProgram() {
+ return m_program;
+ }
+
+ private JPanel createProgramPanel() {
+ JPanel panel = new JPanel();
+
+ m_list = new JList(m_programs);
+ m_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ m_list.setVisibleRowCount(10);
+ m_list.setSelectedIndex(0);
+ m_list.setPreferredSize(new Dimension(200, 250));
+
+ JScrollPane sc = new JScrollPane(m_list);
+ sc.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+
+ panel.add(sc);
+
+ return panel;
+ }
+
+ private JPanel createButtonPanel() {
+ JPanel panel = new JPanel();
+
+ JButton button = new JButton(" OK ");
+ button.addActionListener(this);
+ button.setActionCommand("OK");
+ panel.add(button);
+
+ button = new JButton("Cancel");
+ button.addActionListener(this);
+ button.setActionCommand("Cancel");
+ panel.add(button);
+
+ return panel;
+ }
+
+ JList m_list;
+
+ Vector m_programs;
+ Program m_program;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/Comment.java b/src/main/java/hexgui/gui/Comment.java
index 3d37449..fae2d24 100644
--- a/src/main/java/hexgui/gui/Comment.java
+++ b/src/main/java/hexgui/gui/Comment.java
@@ -1,73 +1,62 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
+import java.awt.*;
+import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
-import javax.swing.event.DocumentListener;
import javax.swing.event.DocumentEvent;
-import javax.swing.border.EtchedBorder;
-import java.awt.*;
-import java.awt.event.*;
+import javax.swing.event.DocumentListener;
/** Displays comment for current node. */
-public class Comment
- extends JScrollPane
- implements DocumentListener
-{
-
- public interface Listener
- {
- public void commentChanged(String msg);
- }
-
- public Comment(Listener listener)
- {
- m_listener = listener;
- m_textPane = new JTextArea();
- m_textPane.setFont(MONOSPACED_FONT);
- m_textPane.setLineWrap(true);
- m_textPane.setWrapStyleWord(true);
- setViewportView(m_textPane);
- setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- m_textPane.getDocument().addDocumentListener(this);
- //setPreferredSize(new Dimension(200, 400));
- }
-
- public void setText(String text)
- {
- m_textPane.setText(text);
- m_textPane.getCaret().setDot(0);
- }
-
- public void changedUpdate(DocumentEvent e)
- {
- notifyChanged();
- }
-
- public void removeUpdate(DocumentEvent e)
- {
- notifyChanged();
- }
-
- public void insertUpdate(DocumentEvent e)
- {
- notifyChanged();
- }
-
- private void notifyChanged()
- {
- m_listener.commentChanged(m_textPane.getText());
- }
-
- JTextArea m_textPane;
-
- Listener m_listener;
-
- private static final Font MONOSPACED_FONT = Font.decode("Monospaced");
+public class Comment extends JScrollPane implements DocumentListener {
+
+ public interface Listener {
+ public void commentChanged(String msg);
+ }
+
+ public Comment(Listener listener) {
+ m_listener = listener;
+ m_textPane = new JTextArea();
+ m_textPane.setFont(MONOSPACED_FONT);
+ m_textPane.setLineWrap(true);
+ m_textPane.setWrapStyleWord(true);
+ setViewportView(m_textPane);
+ setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ m_textPane.getDocument().addDocumentListener(this);
+ // setPreferredSize(new Dimension(200, 400));
+ }
+
+ public void setText(String text) {
+ m_textPane.setText(text);
+ m_textPane.getCaret().setDot(0);
+ }
+
+ public void changedUpdate(DocumentEvent e) {
+ notifyChanged();
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ notifyChanged();
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ notifyChanged();
+ }
+
+ private void notifyChanged() {
+ m_listener.commentChanged(m_textPane.getText());
+ }
+
+ JTextArea m_textPane;
+
+ Listener m_listener;
+
+ private static final Font MONOSPACED_FONT = Font.decode("Monospaced");
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/EditProgramDialog.java b/src/main/java/hexgui/gui/EditProgramDialog.java
index 8445969..6080811 100644
--- a/src/main/java/hexgui/gui/EditProgramDialog.java
+++ b/src/main/java/hexgui/gui/EditProgramDialog.java
@@ -1,140 +1,129 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
import hexgui.util.SpringUtilities;
-import hexgui.gui.ShowError;
-import hexgui.gui.Program;
-
-import java.util.Vector;
-import javax.swing.*;
-import javax.swing.text.html.HTMLEditorKit;
import java.awt.*;
import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.text.html.HTMLEditorKit;
/** Dialog for adding/editing new programs. */
-public final class EditProgramDialog
- extends JDialog implements ActionListener
-{
-
- public EditProgramDialog(Frame owner, Program program,
- String title, boolean is_new)
- {
- super(owner, true);
- m_program = program;
-
- setTitle(title);
- init(is_new);
+public final class EditProgramDialog extends JDialog implements ActionListener {
+
+ public EditProgramDialog(Frame owner, Program program, String title, boolean is_new) {
+ super(owner, true);
+ m_program = program;
+
+ setTitle(title);
+ init(is_new);
+ }
+
+ private void init(boolean is_new) {
+ JEditorPane info = new JEditorPane();
+ info.setEditable(false);
+ info.setEditorKit(new HTMLEditorKit());
+
+ if (!is_new) {
+ info.setText("Edit the program's fields.");
+ } else {
+ info.setText(
+ "Enter command for new Hex program
"
+ + "The command can be simply the name of the "
+ + "executable file, or the name plus any options "
+ + "you wish to set. The working directory can be left "
+ + "blank if the program does not need a special "
+ + "working directory. Enter a simple descriptive name "
+ + "to refer to this program.");
}
-
- private void init(boolean is_new)
- {
- JEditorPane info = new JEditorPane();
- info.setEditable(false);
- info.setEditorKit(new HTMLEditorKit());
-
- if (!is_new) {
- info.setText("Edit the program's fields.");
- } else {
- info.setText("
Enter command for new Hex program
"+
- "The command can be simply the name of the " +
- "executable file, or the name plus any options " +
- "you wish to set. The working directory can be left " +
- "blank if the program does not need a special " +
- "working directory. Enter a simple descriptive name " +
- "to refer to this program.");
- }
- add(info, BorderLayout.NORTH);
- add(createProgramPanel(m_program), BorderLayout.CENTER);
- add(createButtonPanel(), BorderLayout.SOUTH);
-
- if (!is_new) {
- setPreferredSize(new Dimension(500, 180));
- } else {
- setPreferredSize(new Dimension(500, 280));
- }
- pack();
-
- setResizable(false);
-
- setVisible(true);
+ add(info, BorderLayout.NORTH);
+ add(createProgramPanel(m_program), BorderLayout.CENTER);
+ add(createButtonPanel(), BorderLayout.SOUTH);
+
+ if (!is_new) {
+ setPreferredSize(new Dimension(500, 180));
+ } else {
+ setPreferredSize(new Dimension(500, 280));
}
+ pack();
- public void actionPerformed(ActionEvent e)
- {
- String cmd = e.getActionCommand();
- if (cmd.equals("OK")) {
+ setResizable(false);
- m_program.m_name = m_name.getText();
- m_program.m_command = m_command.getText();
- m_program.m_working = m_working.getText();
-
- dispose();
+ setVisible(true);
+ }
- } else if (cmd.equals("Cancel")) {
- dispose();
- }
- }
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+ if (cmd.equals("OK")) {
- private JPanel createProgramPanel(Program program)
- {
- JPanel panel = new JPanel(new SpringLayout());
- JLabel l;
-
- l = new JLabel("Name:", JLabel.TRAILING);
- panel.add(l);
-
- m_name = new JTextField(40);
- if (program != null) m_name.setText(program.m_name);
- l.setLabelFor(m_name);
- panel.add(m_name);
-
- l = new JLabel("Command:", JLabel.TRAILING);
- panel.add(l);
- m_command = new JTextField(40);
- if (program != null) m_command.setText(program.m_command);
- l.setLabelFor(m_command);
- panel.add(m_command);
-
- l = new JLabel("Working Directory:", JLabel.TRAILING);
- panel.add(l);
- m_working = new JTextField(40);
- if (program != null) m_working.setText(program.m_working);
- l.setLabelFor(m_working);
- panel.add(m_working);
-
- SpringUtilities.makeCompactGrid(panel,
- 3, 2, // rows, cols
- 6, 6, // initX, initY
- 6, 6); // xPad, yPad
-
- return panel;
- }
+ m_program.m_name = m_name.getText();
+ m_program.m_command = m_command.getText();
+ m_program.m_working = m_working.getText();
- private JPanel createButtonPanel()
- {
- JPanel panel = new JPanel();
-
- JButton button = new JButton(" OK ");
- button.addActionListener(this);
- button.setActionCommand("OK");
- panel.add(button);
-
- button = new JButton("Cancel");
- button.addActionListener(this);
- button.setActionCommand("Cancel");
- panel.add(button);
-
- return panel;
- }
+ dispose();
- JTextField m_name;
- JTextField m_command;
- JTextField m_working;
-
- Program m_program;
+ } else if (cmd.equals("Cancel")) {
+ dispose();
+ }
+ }
+
+ private JPanel createProgramPanel(Program program) {
+ JPanel panel = new JPanel(new SpringLayout());
+ JLabel l;
+
+ l = new JLabel("Name:", JLabel.TRAILING);
+ panel.add(l);
+
+ m_name = new JTextField(40);
+ if (program != null) m_name.setText(program.m_name);
+ l.setLabelFor(m_name);
+ panel.add(m_name);
+
+ l = new JLabel("Command:", JLabel.TRAILING);
+ panel.add(l);
+ m_command = new JTextField(40);
+ if (program != null) m_command.setText(program.m_command);
+ l.setLabelFor(m_command);
+ panel.add(m_command);
+
+ l = new JLabel("Working Directory:", JLabel.TRAILING);
+ panel.add(l);
+ m_working = new JTextField(40);
+ if (program != null) m_working.setText(program.m_working);
+ l.setLabelFor(m_working);
+ panel.add(m_working);
+
+ SpringUtilities.makeCompactGrid(
+ panel, 3, 2, // rows, cols
+ 6, 6, // initX, initY
+ 6, 6); // xPad, yPad
+
+ return panel;
+ }
+
+ private JPanel createButtonPanel() {
+ JPanel panel = new JPanel();
+
+ JButton button = new JButton(" OK ");
+ button.addActionListener(this);
+ button.setActionCommand("OK");
+ panel.add(button);
+
+ button = new JButton("Cancel");
+ button.addActionListener(this);
+ button.setActionCommand("Cancel");
+ panel.add(button);
+
+ return panel;
+ }
+
+ JTextField m_name;
+ JTextField m_command;
+ JTextField m_working;
+
+ Program m_program;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/FileDialogs.java b/src/main/java/hexgui/gui/FileDialogs.java
index f6534e9..37c4441 100644
--- a/src/main/java/hexgui/gui/FileDialogs.java
+++ b/src/main/java/hexgui/gui/FileDialogs.java
@@ -2,261 +2,189 @@
package hexgui.gui;
-import java.awt.BorderLayout;
+import hexgui.sgf.GameFileFilter;
+import hexgui.util.Platform;
import java.awt.Component;
-import java.awt.Container;
-import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Frame;
-import java.awt.Graphics;
-import java.awt.Image;
-import java.awt.MediaTracker;
-import java.awt.Toolkit;
-import java.awt.event.ActionListener;
-import java.awt.event.ActionEvent;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
import java.io.File;
-import java.net.URL;
-import java.net.MalformedURLException;
import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.prefs.Preferences;
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
-import javax.swing.JPanel;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import hexgui.sgf.GameFileFilter;
-import hexgui.util.ErrorMessage;
-import hexgui.util.Platform;
-import hexgui.util.StringUtils;
/** File dialogs. */
-public final class FileDialogs
-{
- public static File showOpen(Component parent, String title)
- {
- return showFileChooser(parent, Type.FILE_OPEN, null, false, title);
- }
-
- public static File showOpenSgf(Component parent)
- {
- return showFileChooser(parent, Type.FILE_OPEN, null, true, null);
+public final class FileDialogs {
+ public static File showOpen(Component parent, String title) {
+ return showFileChooser(parent, Type.FILE_OPEN, null, false, title);
+ }
+
+ public static File showOpenSgf(Component parent) {
+ return showFileChooser(parent, Type.FILE_OPEN, null, true, null);
+ }
+
+ public static File showSave(Component parent, String title, MessageDialogs messageDialogs) {
+ return showFileChooserSave(parent, null, false, title, messageDialogs);
+ }
+
+ public static File showSaveSgf(Frame parent, MessageDialogs messageDialogs) {
+ return showFileChooserSave(parent, s_lastFile, true, null, messageDialogs);
+ }
+
+ /** File selection, unknown whether for load or save. */
+ public static File showSelectFile(Component parent, String title) {
+ return showFileChooser(parent, Type.FILE_SELECT, s_lastFile, false, title);
+ }
+
+ public static void setLastFile(File file) {
+ s_lastFile = file;
+ }
+
+ private enum Type {
+ /** Dialog type for opening a file. */
+ FILE_OPEN,
+
+ /** Dialog type for saving to a file. */
+ FILE_SAVE,
+
+ /**
+ * Dialog type for selecting a file. Use this type, if a file name should be selected, but it is
+ * not known what the file name is used for and if the file already exists.
+ *
+ * @deprecated Not supported by native AWT FileDialog
+ */
+ FILE_SELECT
+ }
+
+ /**
+ * Use native AWT-dialogs. They are used on Mac OS X because JFileChooser looks too different from
+ * the native dialogs (Java 1.5), and on Windows because JFileChooser is too slow on Windows XP
+ * (startup and directory changing takes up to 10 sec; Java 1.6)
+ */
+ private static final boolean NATIVE_DIALOGS = (Platform.isMac() || Platform.isWindows());
+
+ private static File s_lastFile;
+
+ /** Make constructor unavailable; class is for namespace only. */
+ private FileDialogs() {}
+
+ /**
+ * Find first parent that is a Frame.
+ *
+ * @return null If no such parent.
+ */
+ private static Frame findParentFrame(Component component) {
+ while (component != null)
+ if (component instanceof Frame) return (Frame) component;
+ else component = component.getParent();
+ return null;
+ }
+
+ private static File showFileChooser(
+ Component parent, Type type, File lastFile, boolean setSgfFilter, String title) {
+ // Use native dialogs for some platforms. but not for type select
+ // There is no native dialog for select
+ if (NATIVE_DIALOGS && type != Type.FILE_SELECT) {
+ Frame frame = findParentFrame(parent);
+ return showFileChooserAWT(frame, type, title);
}
-
- public static File showSave(Component parent, String title,
- MessageDialogs messageDialogs)
- {
- return showFileChooserSave(parent, null, false, title,
- messageDialogs);
- }
-
- public static File showSaveSgf(Frame parent,
- MessageDialogs messageDialogs)
- {
- return showFileChooserSave(parent, s_lastFile, true, null,
- messageDialogs);
- }
-
- /** File selection, unknown whether for load or save. */
- public static File showSelectFile(Component parent, String title)
- {
- return showFileChooser(parent, Type.FILE_SELECT, s_lastFile, false,
- title);
- }
-
- public static void setLastFile(File file)
- {
- s_lastFile = file;
- }
-
- private enum Type
- {
- /** Dialog type for opening a file. */
- FILE_OPEN,
-
- /** Dialog type for saving to a file. */
- FILE_SAVE,
-
- /** Dialog type for selecting a file.
- Use this type, if a file name should be selected, but it is not
- known what the file name is used for and if the file already
- exists.
- @deprecated Not supported by native AWT FileDialog */
- FILE_SELECT
- }
-
- /** Use native AWT-dialogs.
- They are used on Mac OS X because JFileChooser looks too different
- from the native dialogs (Java 1.5), and on Windows because
- JFileChooser is too slow on Windows XP (startup and directory changing
- takes up to 10 sec; Java 1.6) */
- private static final boolean NATIVE_DIALOGS =
- (Platform.isMac() || Platform.isWindows());
-
- private static File s_lastFile;
-
- /** Make constructor unavailable; class is for namespace only. */
- private FileDialogs()
- {
- }
-
- /** Find first parent that is a Frame.
- @return null If no such parent. */
- private static Frame findParentFrame(Component component)
- {
- while (component != null)
- if (component instanceof Frame)
- return (Frame)component;
- else
- component = component.getParent();
- return null;
- }
-
- private static File showFileChooser(Component parent, Type type,
- File lastFile, boolean setSgfFilter,
- String title)
- {
- // Use native dialogs for some platforms. but not for type select
- // There is no native dialog for select
- if (NATIVE_DIALOGS && type != Type.FILE_SELECT)
- {
- Frame frame = findParentFrame(parent);
- return showFileChooserAWT(frame, type, title);
+ return showFileChooserSwing(parent, type, lastFile, setSgfFilter, title);
+ }
+
+ private static File showFileChooserSave(
+ Component parent,
+ File lastFile,
+ boolean setSgfFilter,
+ String title,
+ MessageDialogs messageDialogs) {
+ File file = showFileChooser(parent, Type.FILE_SAVE, lastFile, setSgfFilter, title);
+ if (NATIVE_DIALOGS)
+ // Overwrite warning is already part of FileDialog
+ return file;
+ while (file != null) {
+ if (file.exists()) {
+ String mainMessage = MessageFormat.format("Replace file \"{0}\"", file.getName());
+ String optionalMessage = "If you overwrite the file, the previous version will be lost.";
+ if (!messageDialogs.showQuestion(parent, mainMessage, optionalMessage, "Replace", true)) {
+ file = showFileChooser(parent, Type.FILE_SAVE, lastFile, setSgfFilter, title);
+ continue;
}
- return showFileChooserSwing(parent, type, lastFile, setSgfFilter,
- title);
+ }
+ break;
}
+ return file;
+ }
- private static File showFileChooserSave(Component parent,
- File lastFile,
- boolean setSgfFilter,
- String title,
- MessageDialogs messageDialogs)
- {
- File file = showFileChooser(parent, Type.FILE_SAVE, lastFile,
- setSgfFilter, title);
- if (NATIVE_DIALOGS)
- // Overwrite warning is already part of FileDialog
- return file;
- while (file != null)
- {
- if (file.exists())
- {
- String mainMessage =
- MessageFormat.format("Replace file \"{0}\"",
- file.getName());
- String optionalMessage = "If you overwrite the file, the previous version will be lost.";
- if (! messageDialogs.showQuestion(parent, mainMessage,
- optionalMessage,
- "Replace", true))
+ private static File showFileChooserAWT(Frame parent, Type type, String title) {
+ FileDialog dialog = new FileDialog(parent);
+ if (title == null) {
+ switch (type) {
+ case FILE_OPEN:
+ title = "Open";
+ break;
+ case FILE_SAVE:
+ title = "Save";
+ break;
+ default:
+ assert false;
+ }
+ }
+ dialog.setTitle(title);
+ int mode = FileDialog.LOAD;
+ if (type == Type.FILE_SAVE) mode = FileDialog.SAVE;
+ dialog.setMode(mode);
+ /* Commented out, because there is no way to change the filter by the
+ user (at least not on Linux)
+ if (setSgfFilter)
+ dialog.setFilenameFilter(new FilenameFilter() {
+ public boolean accept(File dir, String name)
{
- file = showFileChooser(parent, Type.FILE_SAVE, lastFile,
- setSgfFilter, title);
- continue;
+ return name.toLowerCase().endsWith("sgf");
}
- }
- break;
- }
- return file;
- }
-
- private static File showFileChooserAWT(Frame parent, Type type,
- String title)
- {
- FileDialog dialog = new FileDialog(parent);
- if (title == null)
- {
- switch (type)
- {
- case FILE_OPEN:
- title = "Open";
- break;
- case FILE_SAVE:
- title = "Save";
- break;
- default:
- assert false;
- }
- }
- dialog.setTitle(title);
- int mode = FileDialog.LOAD;
- if (type == Type.FILE_SAVE)
- mode = FileDialog.SAVE;
- dialog.setMode(mode);
- /* Commented out, because there is no way to change the filter by the
- user (at least not on Linux)
- if (setSgfFilter)
- dialog.setFilenameFilter(new FilenameFilter() {
- public boolean accept(File dir, String name)
- {
- return name.toLowerCase().endsWith("sgf");
- }
- });
- */
- //dialog.setLocationRelativeTo(parent); // Java <= 1.4
- dialog.setLocationByPlatform(true);
- dialog.setVisible(true);
- if (dialog.getFile() == null)
- return null;
- return new File(dialog.getDirectory(), dialog.getFile());
+ });
+ */
+ // dialog.setLocationRelativeTo(parent); // Java <= 1.4
+ dialog.setLocationByPlatform(true);
+ dialog.setVisible(true);
+ if (dialog.getFile() == null) return null;
+ return new File(dialog.getDirectory(), dialog.getFile());
+ }
+
+ private static File showFileChooserSwing(
+ Component parent, Type type, File lastFile, boolean setSgfFilter, String title) {
+ JFileChooser chooser;
+ if (s_lastFile == null) {
+ if (Platform.isMac())
+ // user.dir is application directory on Mac, which is bad
+ // I have not found a way to set it to user home in Info.plist
+ // so I use null here, which sets is to the user home
+ chooser = new JFileChooser((String) null);
+ else chooser = new JFileChooser(System.getProperty("user.dir"));
+ } else chooser = new JFileChooser(s_lastFile);
+ chooser.setMultiSelectionEnabled(false);
+ javax.swing.filechooser.FileFilter filter = new GameFileFilter();
+ chooser.addChoosableFileFilter(filter);
+ if (setSgfFilter) {
+ chooser.setFileFilter(filter);
+ } else chooser.setFileFilter(chooser.getAcceptAllFileFilter());
+ if (type == Type.FILE_SAVE) {
+ if (lastFile != null && lastFile.isFile() && lastFile.exists())
+ chooser.setSelectedFile(lastFile);
}
-
- private static File showFileChooserSwing(Component parent, Type type,
- File lastFile,
- boolean setSgfFilter,
- String title)
- {
- JFileChooser chooser;
- if (s_lastFile == null)
- {
- if (Platform.isMac())
- // user.dir is application directory on Mac, which is bad
- // I have not found a way to set it to user home in Info.plist
- // so I use null here, which sets is to the user home
- chooser = new JFileChooser((String)null);
- else
- chooser = new JFileChooser(System.getProperty("user.dir"));
- }
- else
- chooser = new JFileChooser(s_lastFile);
- chooser.setMultiSelectionEnabled(false);
- javax.swing.filechooser.FileFilter filter = new GameFileFilter();
- chooser.addChoosableFileFilter(filter);
- if (setSgfFilter)
- {
- chooser.setFileFilter(filter);
- }
- else
- chooser.setFileFilter(chooser.getAcceptAllFileFilter());
- if (type == Type.FILE_SAVE)
- {
- if (lastFile != null && lastFile.isFile() && lastFile.exists())
- chooser.setSelectedFile(lastFile);
- }
- if (title != null)
- chooser.setDialogTitle(title);
- int ret;
- switch (type)
- {
- case FILE_SAVE:
- ret = chooser.showSaveDialog(parent);
- break;
- case FILE_OPEN:
- ret = chooser.showOpenDialog(parent);
- break;
- default:
- ret = chooser.showDialog(parent, "Select");
- break;
- }
- if (ret != JFileChooser.APPROVE_OPTION)
- return null;
- File file = chooser.getSelectedFile();
- s_lastFile = file;
- return file;
+ if (title != null) chooser.setDialogTitle(title);
+ int ret;
+ switch (type) {
+ case FILE_SAVE:
+ ret = chooser.showSaveDialog(parent);
+ break;
+ case FILE_OPEN:
+ ret = chooser.showOpenDialog(parent);
+ break;
+ default:
+ ret = chooser.showDialog(parent, "Select");
+ break;
}
+ if (ret != JFileChooser.APPROVE_OPTION) return null;
+ File file = chooser.getSelectedFile();
+ s_lastFile = file;
+ return file;
+ }
}
diff --git a/src/main/java/hexgui/gui/GameInfoPanel.java b/src/main/java/hexgui/gui/GameInfoPanel.java
index 994bfdc..0dbf3c2 100644
--- a/src/main/java/hexgui/gui/GameInfoPanel.java
+++ b/src/main/java/hexgui/gui/GameInfoPanel.java
@@ -1,120 +1,102 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
-import hexgui.hex.HexColor;
import hexgui.game.Clock;
-
-import java.io.*;
-import java.util.*;
-import javax.swing.*;
-import javax.swing.event.DocumentListener;
-import javax.swing.border.EtchedBorder;
+import hexgui.hex.HexColor;
import java.awt.*;
import java.awt.event.*;
+import java.io.*;
import java.net.URL;
+import java.util.*;
+import javax.swing.*;
/** Displays info about the current game. */
-public class GameInfoPanel
- extends JPanel
-{
- public GameInfoPanel(Clock blackClock, Clock whiteClock)
- {
- JPanel panel = new JPanel();
- add(panel, BorderLayout.CENTER);
-
- JPanel bpanel = new JPanel();
- bpanel.setLayout(new BoxLayout(bpanel, BoxLayout.Y_AXIS));
- URL bURL = getURL("hexgui/images/black-24x24.png");
- JLabel blab = new JLabel(new ImageIcon(bURL));
- blab.setAlignmentX(Component.CENTER_ALIGNMENT);
- bpanel.add(blab);
- bpanel.add(new GuiClock(HexColor.BLACK, blackClock));
-
- JPanel wpanel = new JPanel();
- wpanel.setLayout(new BoxLayout(wpanel, BoxLayout.Y_AXIS));
- URL wURL = getURL("hexgui/images/white-24x24.png");
- JLabel wlab = new JLabel(new ImageIcon(wURL));
- wlab.setAlignmentX(Component.CENTER_ALIGNMENT);
- wpanel.add(wlab);
- wpanel.add(new GuiClock(HexColor.WHITE, whiteClock));
-
- panel.add(bpanel);
- panel.add(wpanel);
-
- //setPreferredSize(new Dimension(200, 150));
- }
-
- private URL getURL(String filename)
- {
- URL url = null;
- if (filename != null) {
- ClassLoader classLoader = getClass().getClassLoader();
- url = classLoader.getResource(filename);
- }
- return url;
+public class GameInfoPanel extends JPanel {
+ public GameInfoPanel(Clock blackClock, Clock whiteClock) {
+ JPanel panel = new JPanel();
+ add(panel, BorderLayout.CENTER);
+
+ JPanel bpanel = new JPanel();
+ bpanel.setLayout(new BoxLayout(bpanel, BoxLayout.Y_AXIS));
+ URL bURL = getURL("hexgui/images/black-24x24.png");
+ JLabel blab = new JLabel(new ImageIcon(bURL));
+ blab.setAlignmentX(Component.CENTER_ALIGNMENT);
+ bpanel.add(blab);
+ bpanel.add(new GuiClock(HexColor.BLACK, blackClock));
+
+ JPanel wpanel = new JPanel();
+ wpanel.setLayout(new BoxLayout(wpanel, BoxLayout.Y_AXIS));
+ URL wURL = getURL("hexgui/images/white-24x24.png");
+ JLabel wlab = new JLabel(new ImageIcon(wURL));
+ wlab.setAlignmentX(Component.CENTER_ALIGNMENT);
+ wpanel.add(wlab);
+ wpanel.add(new GuiClock(HexColor.WHITE, whiteClock));
+
+ panel.add(bpanel);
+ panel.add(wpanel);
+
+ // setPreferredSize(new Dimension(200, 150));
+ }
+
+ private URL getURL(String filename) {
+ URL url = null;
+ if (filename != null) {
+ ClassLoader classLoader = getClass().getClassLoader();
+ url = classLoader.getResource(filename);
}
-
-};
-
-class GuiClock
- extends JTextField
- implements Clock.Listener
-{
- public GuiClock(HexColor color, Clock clock)
- {
- super(COLUMNS);
-
- m_clock = clock;
- m_clock.addListener(this);
-
- //Monspace font doesn't center correctly on the Mac
- //GuiUtil.setMonospacedFont(this);
- setEditable(false);
- setFocusable(false);
- setHorizontalAlignment(SwingConstants.CENTER);
- //setMinimumSize(getPreferredSize());
- m_color = color;
- setText("00:00");
- }
-
- public final void setText(String text)
- {
- super.setText(text);
- String toolTip;
- if (m_color == HexColor.BLACK)
- toolTip = "Time for Black";
- else
- toolTip = "Time for White";
- if (text.length() > COLUMNS)
- toolTip = toolTip + " (" + text + ")";
- setToolTipText(toolTip);
- }
-
- public void clockChanged()
- {
- int elapsed = m_clock.elapsed();
- int minutes = elapsed / 60000;
- int seconds = (elapsed % 60000) / 1000;
- String min, sec;
-
- min = (minutes < 10) ? "0"+minutes : "" + minutes;
- sec = (seconds < 10) ? "0"+seconds : "" + seconds;
- setText(min+":"+sec);
- }
-
- /** Serial version to suppress compiler warning.
- Contains a marker comment for serialver.sf.net
- */
- private static final long serialVersionUID = 0L; // SUID
-
- private static final int COLUMNS = 5;
-
- private final HexColor m_color;
-
- private Clock m_clock;
+ return url;
+ }
+}
+;
+
+class GuiClock extends JTextField implements Clock.Listener {
+ public GuiClock(HexColor color, Clock clock) {
+ super(COLUMNS);
+
+ m_clock = clock;
+ m_clock.addListener(this);
+
+ // Monspace font doesn't center correctly on the Mac
+ // GuiUtil.setMonospacedFont(this);
+ setEditable(false);
+ setFocusable(false);
+ setHorizontalAlignment(SwingConstants.CENTER);
+ // setMinimumSize(getPreferredSize());
+ m_color = color;
+ setText("00:00");
+ }
+
+ public final void setText(String text) {
+ super.setText(text);
+ String toolTip;
+ if (m_color == HexColor.BLACK) toolTip = "Time for Black";
+ else toolTip = "Time for White";
+ if (text.length() > COLUMNS) toolTip = toolTip + " (" + text + ")";
+ setToolTipText(toolTip);
+ }
+
+ public void clockChanged() {
+ int elapsed = m_clock.elapsed();
+ int minutes = elapsed / 60000;
+ int seconds = (elapsed % 60000) / 1000;
+ String min, sec;
+
+ min = (minutes < 10) ? "0" + minutes : "" + minutes;
+ sec = (seconds < 10) ? "0" + seconds : "" + seconds;
+ setText(min + ":" + sec);
+ }
+
+ /** Serial version to suppress compiler warning. Contains a marker comment for serialver.sf.net */
+ private static final long serialVersionUID = 0L; // SUID
+
+ private static final int COLUMNS = 5;
+
+ private final HexColor m_color;
+
+ private Clock m_clock;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/GuiBoard.java b/src/main/java/hexgui/gui/GuiBoard.java
index e549822..ea0cae4 100644
--- a/src/main/java/hexgui/gui/GuiBoard.java
+++ b/src/main/java/hexgui/gui/GuiBoard.java
@@ -1,774 +1,701 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
+import hexgui.game.Node;
import hexgui.hex.*;
import hexgui.util.*;
-import hexgui.game.Node;
-
-import java.util.Vector;
-import java.util.Map;
-import java.util.TreeMap;
-import java.math.BigInteger;
-import javax.swing.*;
-import javax.swing.border.EtchedBorder;
-import java.awt.print.Printable;
-import java.awt.print.PageFormat;
-import java.awt.print.PrinterException;
import java.awt.*;
import java.awt.event.*;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.math.BigInteger;
import java.net.URL;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+import javax.swing.*;
+import javax.swing.border.EtchedBorder;
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
/** Gui Board. */
-public final class GuiBoard
- extends JPanel implements Printable
-{
- /** Callback for clicks on a field. */
- public interface Listener
- {
- void panelClicked();
- void fieldClicked(HexPoint point, boolean ctrl, boolean shift);
- void fieldDoubleClicked(HexPoint point, boolean ctrl, boolean shift);
- }
-
- private static final boolean DEFAULT_FLIPPED = true;
-
- public static final int HEXBOARD = 0;
- public static final int YBOARD = 1;
-
- /** Constructor. */
- public GuiBoard(Listener listener, GuiPreferences preferences)
- {
- m_image = null;
- m_listener = listener;
- m_preferences = preferences;
- m_arrows = new Vector>();
-
- initSize(HEXBOARD,
- m_preferences.getInt("gui-board-width"),
- m_preferences.getInt("gui-board-height"));
-
- setDrawType(m_preferences.get("gui-board-type"));
-
- setPreferredSize(new Dimension
- (m_preferences.getInt("gui-board-pixel-width"),
- m_preferences.getInt("gui-board-pixel-height")));
-
- setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
- setLayout(new BoardLayout());
- m_boardPanel = new BoardPanel();
- add(m_boardPanel);
-
- MouseAdapter mouseAdapter = new MouseAdapter()
- {
- public void mouseClicked(MouseEvent e)
- {
- // First inform the parent that we were clicked, to
- // handle things like keyboard focus.
- m_listener.panelClicked();
- GuiField f = m_drawer.getFieldContaining(e.getPoint(), m_field);
- if (f == null) return;
-
- int modifiers = e.getModifiers();
- boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0;
- boolean shift = (modifiers & ActionEvent.SHIFT_MASK) != 0;
- if (e.getClickCount() >= 2)
- m_listener.fieldDoubleClicked(f.getPoint(), ctrl, shift);
- else
- m_listener.fieldClicked(f.getPoint(), ctrl, shift);
- }
- };
- m_boardPanel.addMouseListener(mouseAdapter);
- setCursorType("default");
- setVisible(true);
- }
-
- // Set the cursor to one of: "default", "black", "white",
- // "black-setup", "white-setup".
- public void setCursorType(String name)
- {
- String path;
-
- if (name.equals("white")) {
- path = "hexgui/images/cursor-white.png";
- } else if (name.equals("black")) {
- path = "hexgui/images/cursor-black.png";
- } else if (name.equals("white-setup")) {
- path = "hexgui/images/cursor-white-setup.png";
- } else if (name.equals("black-setup")) {
- path = "hexgui/images/cursor-black-setup.png";
- } else {
- path = null;
+public final class GuiBoard extends JPanel implements Printable {
+ /** Callback for clicks on a field. */
+ public interface Listener {
+ void panelClicked();
+
+ void fieldClicked(HexPoint point, boolean ctrl, boolean shift);
+
+ void fieldDoubleClicked(HexPoint point, boolean ctrl, boolean shift);
+ }
+
+ private static final boolean DEFAULT_FLIPPED = true;
+
+ public static final int HEXBOARD = 0;
+ public static final int YBOARD = 1;
+
+ /** Constructor. */
+ public GuiBoard(Listener listener, GuiPreferences preferences) {
+ m_image = null;
+ m_listener = listener;
+ m_preferences = preferences;
+ m_arrows = new Vector>();
+
+ initSize(
+ HEXBOARD,
+ m_preferences.getInt("gui-board-width"),
+ m_preferences.getInt("gui-board-height"));
+
+ setDrawType(m_preferences.get("gui-board-type"));
+
+ setPreferredSize(
+ new Dimension(
+ m_preferences.getInt("gui-board-pixel-width"),
+ m_preferences.getInt("gui-board-pixel-height")));
+
+ setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
+ setLayout(new BoardLayout());
+ m_boardPanel = new BoardPanel();
+ add(m_boardPanel);
+
+ MouseAdapter mouseAdapter =
+ new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ // First inform the parent that we were clicked, to
+ // handle things like keyboard focus.
+ m_listener.panelClicked();
+ GuiField f = m_drawer.getFieldContaining(e.getPoint(), m_field);
+ if (f == null) return;
+
+ int modifiers = e.getModifiers();
+ boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0;
+ boolean shift = (modifiers & ActionEvent.SHIFT_MASK) != 0;
+ if (e.getClickCount() >= 2) m_listener.fieldDoubleClicked(f.getPoint(), ctrl, shift);
+ else m_listener.fieldClicked(f.getPoint(), ctrl, shift);
+ }
+ };
+ m_boardPanel.addMouseListener(mouseAdapter);
+ setCursorType("default");
+ setVisible(true);
+ }
+
+ // Set the cursor to one of: "default", "black", "white",
+ // "black-setup", "white-setup".
+ public void setCursorType(String name) {
+ String path;
+
+ if (name.equals("white")) {
+ path = "hexgui/images/cursor-white.png";
+ } else if (name.equals("black")) {
+ path = "hexgui/images/cursor-black.png";
+ } else if (name.equals("white-setup")) {
+ path = "hexgui/images/cursor-white-setup.png";
+ } else if (name.equals("black-setup")) {
+ path = "hexgui/images/cursor-black-setup.png";
+ } else {
+ path = null;
+ }
+
+ if (path == null) {
+ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ return;
+ }
+
+ ClassLoader classLoader = getClass().getClassLoader();
+ URL url = classLoader.getResource(path);
+ if (url == null) {
+ System.out.println(
+ "setCursorType: could not load '" + "hexgui/images/cursor-white.png" + "'!");
+ return;
+ }
+ Image img = new ImageIcon(url).getImage();
+ Point hot = new Point(8, 8);
+ Toolkit t = getToolkit();
+ Cursor c = t.createCustomCursor(img, hot, name);
+ setCursor(c);
+ }
+
+ /**
+ * Sets the type of board drawer to use. If name is not one of the known values,
+ * "Diamond" is used.
+ *
+ * @param name one of ("Diamond", "Flat", "Flat2", "Go").
+ */
+ public void setDrawType(String name) {
+ if (name.equals("Y")) {
+ m_drawer = new BoardDrawerY();
+ initSize(YBOARD, m_width, m_height);
+ } else if (name.equals("Go")) {
+ if (m_mode != HEXBOARD) initSize(HEXBOARD, m_width, m_height);
+ m_drawer = new BoardDrawerGo();
+ m_preferences.put("gui-board-type", "Go");
+ } else if (name.equals("Diamond")) {
+ if (m_mode != HEXBOARD) initSize(HEXBOARD, m_width, m_height);
+ m_drawer = new BoardDrawerDiamond();
+ m_preferences.put("gui-board-type", "Diamond");
+ } else if (name.equals("Flat")) {
+ if (m_mode != HEXBOARD) initSize(HEXBOARD, m_width, m_height);
+ m_drawer = new BoardDrawerFlat();
+ m_preferences.put("gui-board-type", "Flat");
+ } else if (name.equals("Flat2")) {
+ if (m_mode != HEXBOARD) initSize(HEXBOARD, m_width, m_height);
+ m_drawer = new BoardDrawerFlat2();
+ m_preferences.put("gui-board-type", "Flat2");
+ } else {
+ System.out.println("GuiBoard: unknown draw type '" + name + "'.");
+ m_drawer = new BoardDrawerDiamond();
+ }
+ repaint();
+ }
+
+ /**
+ * Sets whether black and letters is on top or if white and numbers is on top. If string is
+ * invalid defaults to positive.
+ *
+ * @param orient either "Positive" or "Negative".
+ */
+ public void setOrientation(String orient) {
+ if (orient.equals("Positive")) m_preferences.put("gui-board-orientation", "positive");
+ else if (orient.equals("Negative")) m_preferences.put("gui-board-orientation", "negative");
+ else {
+ System.out.println("GuiBoard: unknown orientation '" + orient + "'.");
+ }
+ repaint();
+ }
+
+ public void initSize(int w, int h) {
+ initSize(m_mode, w, h);
+ }
+
+ /**
+ * Creates a board of the given dimensions. Dirty flag is set to false.
+ *
+ * @param m type of board to create (HEX or Y)
+ * @param w width of the board in cells
+ * @param h height of the board in cells
+ */
+ private void initSize(int m, int w, int h) {
+ System.out.println("GuiBoard.initSize: " + (m == HEXBOARD ? "(HEX) " : "(Y) ") + w + " " + h);
+
+ m_mode = m;
+ m_width = w;
+ m_height = h;
+ m_size = new Dimension(m_width, m_height);
+
+ m_dirty_stones = false;
+ clearArrows();
+
+ if (m_mode == HEXBOARD) {
+ m_field = new GuiField[w * h + 4];
+ for (int x = 0; x < w * h; x++) {
+ m_field[x] = new GuiField(HexPoint.get(x % w, x / w));
+ m_field[x].setAttributes(GuiField.DRAW_CELL_OUTLINE);
+ }
+ m_field[w * h + 0] = new GuiField(HexPoint.NORTH);
+ m_field[w * h + 1] = new GuiField(HexPoint.SOUTH);
+ m_field[w * h + 2] = new GuiField(HexPoint.WEST);
+ m_field[w * h + 3] = new GuiField(HexPoint.EAST);
+ } else {
+ int n = w * (w + 1) / 2;
+ m_field = new GuiField[n + 3];
+ for (int y = 0, i = 0; y < w; y++) {
+ for (int x = 0; x <= y; x++, i++) {
+ m_field[i] = new GuiField(HexPoint.get(x, y));
+ m_field[i].setAttributes(GuiField.DRAW_CELL_OUTLINE);
}
-
- if (path == null) {
- setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
- return;
- }
-
- ClassLoader classLoader = getClass().getClassLoader();
- URL url = classLoader.getResource(path);
- if (url == null) {
- System.out.println("setCursorType: could not load '" +
- "hexgui/images/cursor-white.png" + "'!");
- return;
- }
- Image img = new ImageIcon(url).getImage();
- Point hot = new Point(8, 8);
- Toolkit t = getToolkit();
- Cursor c = t.createCustomCursor(img, hot, name);
- setCursor(c);
- }
-
- /** Sets the type of board drawer to use. If name is
- not one of the known values, "Diamond" is used.
- @param name one of ("Diamond", "Flat", "Flat2", "Go").
- */
- public void setDrawType(String name)
- {
- if (name.equals("Y")) {
- m_drawer = new BoardDrawerY();
- initSize(YBOARD, m_width, m_height);
- } else if (name.equals("Go")) {
- if (m_mode != HEXBOARD)
- initSize(HEXBOARD, m_width, m_height);
- m_drawer = new BoardDrawerGo();
- m_preferences.put("gui-board-type", "Go");
- } else if (name.equals("Diamond")) {
- if (m_mode != HEXBOARD)
- initSize(HEXBOARD, m_width, m_height);
- m_drawer = new BoardDrawerDiamond();
- m_preferences.put("gui-board-type", "Diamond");
- } else if (name.equals("Flat")) {
- if (m_mode != HEXBOARD)
- initSize(HEXBOARD, m_width, m_height);
- m_drawer = new BoardDrawerFlat();
- m_preferences.put("gui-board-type", "Flat");
- } else if (name.equals("Flat2")) {
- if (m_mode != HEXBOARD)
- initSize(HEXBOARD, m_width, m_height);
- m_drawer = new BoardDrawerFlat2();
- m_preferences.put("gui-board-type", "Flat2");
- } else {
- System.out.println("GuiBoard: unknown draw type '" + name + "'.");
- m_drawer = new BoardDrawerDiamond();
- }
- repaint();
- }
-
- /** Sets whether black and letters is on top or if white and
- numbers is on top. If string is invalid defaults to positive.
- @param orient either "Positive" or "Negative".
- */
- public void setOrientation(String orient)
- {
- if (orient.equals("Positive"))
- m_preferences.put("gui-board-orientation", "positive");
- else if (orient.equals("Negative"))
- m_preferences.put("gui-board-orientation", "negative");
- else {
- System.out.println("GuiBoard: unknown orientation '" +
- orient + "'.");
- }
- repaint();
- }
-
- public void initSize(int w, int h)
- {
- initSize(m_mode, w, h);
- }
-
- /** Creates a board of the given dimensions.
- Dirty flag is set to false.
- @param m type of board to create (HEX or Y)
- @param w width of the board in cells
- @param h height of the board in cells
- */
- private void initSize(int m, int w, int h)
- {
- System.out.println("GuiBoard.initSize: "
- + (m == HEXBOARD ? "(HEX) " : "(Y) ")
- + w + " " + h);
-
- m_mode = m;
- m_width = w;
- m_height = h;
- m_size = new Dimension(m_width, m_height);
-
- m_dirty_stones = false;
- clearArrows();
-
- if (m_mode == HEXBOARD)
- {
- m_field = new GuiField[w*h+4];
- for (int x=0; x(from, to));
+ repaint();
+ }
+
+ public void clearArrows() {
+ m_arrows.clear();
+ repaint();
+ }
+
+ /**
+ * Clears dynamic marks, leaving stones intact. If the dirty flag is set, revert the fields to the
+ * saved fields saved in markStonesDirty(). Dirty stones flag is set to false. See
+ * aboutToDirtyStones(). Empties the list of arrows.
+ */
+ public void clearMarks() {
+ if (m_dirty_stones) {
+ for (int i = 0; i < m_field.length; i++) {
+ m_field[i] = new GuiField(m_backup_field[i]);
+ }
+ }
+ m_dirty_stones = false;
+
+ clearArrows();
+
+ for (int x = 0; x < m_field.length; x++) {
+ m_field[x].clearAttributes(
+ GuiField.LAST_PLAYED | GuiField.SWAP_PLAYED | GuiField.DRAW_TEXT | GuiField.DRAW_ALPHA);
+ }
+ repaint();
+ }
+
+ /**
+ * Sets the given point to the given color. Special points are ignored (SWAP_SIDES, RESIGN, etc).
+ *
+ * @param point the point
+ * @param color the color to set it to.
+ */
+ public void setColor(HexPoint point, HexColor color) {
+ GuiField f = getField(point);
+ if (f != null) {
+ f.setColor(color);
+ repaint();
+ }
+ }
+
+ /**
+ * Gets the color of the specified point.
+ *
+ * @param point the point whose color we with to obtain.
+ * @return the color of point
+ */
+ public HexColor getColor(HexPoint point) {
+ GuiField f = getField(point);
+ return f.getColor();
+ }
+
+ /** Gets the field at the specified point. Special points are ignored (SWAP_SIDES, etc). */
+ public GuiField getField(HexPoint point) {
+ if (point == HexPoint.SWAP_SIDES
+ || point == HexPoint.SWAP_PIECES
+ || point == HexPoint.PASS
+ || point == HexPoint.RESIGN
+ || point == HexPoint.FORFEIT) {
+ return null;
+ }
+
+ for (int x = 0; x < m_field.length; x++) {
+ if (m_field[x].getPoint() == point) return m_field[x];
+ }
+ assert (false);
+ return null;
+ }
+
+ /**
+ * Marks the given point to show which move was played last, or clears the mark if point
+ * is null.
+ */
+ public void markLastPlayed(HexPoint point) {
+ assert (point != HexPoint.SWAP_SIDES && point != HexPoint.SWAP_PIECES);
+
+ if (m_last_played != null) {
+ m_last_played.clearAttributes(GuiField.LAST_PLAYED);
+ m_last_played = null;
+ }
+ if (point != null) {
+ m_last_played = getField(point);
+ if (m_last_played != null) {
+ m_last_played.setAttributes(GuiField.LAST_PLAYED);
+ }
+ }
+ repaint();
+ }
+
+ /** Clear swap marks */
+ public void clearSwapPlayed() {
+ for (int x = 0; x < m_field.length; x++) {
+ m_field[x].clearAttributes(GuiField.SWAP_PLAYED);
+ }
+ repaint();
+ }
+
+ /** Add swap mark to all pieces on the board (hopefully there is exactly one of them */
+ public void markSwapPlayed() {
+ for (int x = 0; x < m_field.length; x++) {
+ HexPoint p = m_field[x].getPoint();
+ if (p.is_cell() && m_field[x].getColor() != HexColor.EMPTY) {
+ m_field[x].setAttributes(GuiField.SWAP_PLAYED);
+ }
+ }
+ repaint();
+ }
+
+ /** Sets the given point's alpha color. */
+ public void setAlphaColor(HexPoint point, Color color) {
+ GuiField f = getField(point);
+ if (f != null) {
+ f.setAlphaColor(color);
+ repaint();
+ }
+ }
+
+ public void setAlphaColor(HexPoint point, Color color, float blend) {
+ GuiField f = getField(point);
+ if (f != null) {
+ f.setAlphaColor(color, blend);
+ repaint();
+ }
+ }
+
+ /** Returns the point's alpha color; null if it is 'swap-sides' or resign or similar. */
+ public Color getAlphaColor(HexPoint point) {
+ GuiField f = getField(point);
+ if (f != null) {
+ return f.getAlphaColor();
+ } else {
+ return null;
+ }
+ }
+
+ /** Sets the given point's text. */
+ public void setText(HexPoint point, String str) {
+ getField(point).setText(str);
+ repaint();
+ }
+
+ /** Sets whether this cell is selected. */
+ public void setSelected(HexPoint point, boolean selected) {
+ getField(point).setSelected(selected);
+ repaint();
+ }
+
+ /** Check if the board is full */
+ public boolean isBoardFull() {
+ for (int x = 0; x < m_field.length; x++) {
+ if (m_field[x].getColor() == HexColor.EMPTY) return false;
+ }
+ return true;
+ }
+
+ /** Count the number of pieces on the board */
+ public int numberOfPieces() {
+ int count = 0;
+ for (int x = 0; x < m_field.length; x++) {
+ HexPoint point = m_field[x].getPoint();
+ if (point == HexPoint.NORTH
+ || point == HexPoint.EAST
+ || point == HexPoint.SOUTH
+ || point == HexPoint.WEST) {
+ continue;
+ }
+ if (m_field[x].getColor() != HexColor.EMPTY) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ /** Change the pieces' colors without moving them. This is only used in Y. */
+ public void swapColors() {
+ for (int x = 0; x < m_field.length; x++) {
+ HexPoint point = m_field[x].getPoint();
+ if (point == HexPoint.NORTH
+ || point == HexPoint.EAST
+ || point == HexPoint.SOUTH
+ || point == HexPoint.WEST) {
+ continue;
+ }
+ HexColor color = m_field[x].getColor();
+ m_field[x].setColor(color.otherColor());
+ }
+ }
+
+ /** Change the pieces' colors and move them. This is only used in Hex. */
+ public void swapPieces() {
+ // Due to the weird way the data structures are set up, it
+ // is tricky to move pieces to another location on the board.
+ // In particular, there is no O(1) way to find the HexField
+ // attached to a given HexPoint.
+ Map colors = new TreeMap();
+ for (int x = 0; x < m_field.length; x++) {
+ HexPoint point = m_field[x].getPoint();
+ if (point == HexPoint.NORTH
+ || point == HexPoint.EAST
+ || point == HexPoint.SOUTH
+ || point == HexPoint.WEST) {
+ continue;
+ }
+ colors.put(point, m_field[x].getColor());
+ }
+ for (int x = 0; x < m_field.length; x++) {
+ HexPoint point = m_field[x].getPoint();
+ if (point == HexPoint.NORTH
+ || point == HexPoint.EAST
+ || point == HexPoint.SOUTH
+ || point == HexPoint.WEST) {
+ continue;
+ }
+ HexPoint otherpoint = point.reflect();
+ m_field[x].setColor(colors.get(otherpoint).otherColor());
+ }
+ }
+
+ /** Stores the current state as a setup position in the given sgf node. */
+ public void storePosition(Node node) {
+ for (int x = 0; x < m_field.length; x++) {
+ HexPoint point = m_field[x].getPoint();
+ if (point == HexPoint.NORTH
+ || point == HexPoint.EAST
+ || point == HexPoint.SOUTH
+ || point == HexPoint.WEST) continue;
+
+ HexColor color = m_field[x].getColor();
+ if (color == HexColor.EMPTY) continue;
+
+ node.addSetup(color, point);
+ }
+ }
+
+ public void paintImmediately() {
+ assert SwingUtilities.isEventDispatchThread();
+ super.paintImmediately(0, 0, getWidth(), getHeight());
+ }
+
+ /** Displays this vc on the board. */
+ public void displayVC(VC vc) {
+ getField(vc.getFrom()).setAlphaColor(Color.blue);
+ getField(vc.getTo()).setAlphaColor(Color.blue);
+
+ Vector carrier = vc.getCarrier();
+ for (int i = 0; i < carrier.size(); i++) getField(carrier.get(i)).setAlphaColor(Color.green);
+
+ Vector stones = vc.getStones();
+ for (int i = 0; i < stones.size(); i++) getField(stones.get(i)).setAlphaColor(Color.red);
+
+ Vector key = vc.getKey();
+ for (int i = 0; i < key.size(); i++) getField(key.get(i)).setAlphaColor(Color.yellow);
+ }
+
+ // ------------------------------------------------------------
+
+ public int print(Graphics g, PageFormat format, int page) throws PrinterException {
+ if (page >= 1) {
+ return Printable.NO_SUCH_PAGE;
+ }
+ double width = getWidth();
+ double height = getHeight();
+ double pageWidth = format.getImageableWidth();
+ double pageHeight = format.getImageableHeight();
+ double scale = 1;
+ if (width >= pageWidth) scale = pageWidth / width;
+ double xSpace = (pageWidth - width * scale) / 2;
+ double ySpace = (pageHeight - height * scale) / 2;
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.translate(format.getImageableX() + xSpace, format.getImageableY() + ySpace);
+ g2d.scale(scale, scale);
+ print(g2d);
+ return Printable.PAGE_EXISTS;
+ }
+
+ // ------------------------------------------------------------
+
+ /**
+ * Converts a hex string representing a bitset into a vector of HexPoints. This relies on m_field
+ * being ordered in a particular fashion.
+ *
+ * NOTE: THIS IS BROKEN SINCE HexPoint was changed in wolve, r182. USE BASE 64 INSTEAD!
+ *
+ *
FIXME: switch carriers to be printed as a list of HexPoints instead of as hex strings?
+ */
+ private Vector convertHexString(String str) {
+ Vector ret = new Vector();
+
+ for (int i = 0; i < str.length(); i++) {
+ BigInteger big = new BigInteger(StringUtils.reverse(str), 16);
+ for (int j = 0; j < m_field.length; j++) {
+ if (big.testBit(j)) ret.add(m_field[j].getPoint());
+ }
+ }
+
+ return ret;
+ }
+
+ /** Converts a base 64 string representing a bitset into a vector of HexPoints. */
+ private static final String m_base64 =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+ private Vector convertBase64String(String str) {
+
+ Vector ret = new Vector();
+ for (int i = 0; i < str.length(); i++) {
+ int v = m_base64.indexOf(str.charAt(i));
+ assert (v != -1);
+ for (int j = 0; j < 6 && i * 6 + j < HexPoint.MAX_POINTS; j++) {
+ if ((v & (1 << j)) != 0) ret.add(HexPoint.get(i * 6 + j));
+ }
+ }
+ return ret;
+ }
+
+ private GuiField[] flipFields(GuiField field[]) {
+ GuiField out[] = new GuiField[field.length];
+ for (int i = 0; i < field.length; i++) {
+ HexPoint p = field[i].getPoint();
+ out[i] = new GuiField(field[i]);
+ if (p == HexPoint.NORTH) out[i].setPoint(HexPoint.WEST);
+ else if (p == HexPoint.WEST) out[i].setPoint(HexPoint.NORTH);
+ else if (p == HexPoint.EAST) out[i].setPoint(HexPoint.SOUTH);
+ else if (p == HexPoint.SOUTH) out[i].setPoint(HexPoint.EAST);
+ else {
+ out[i].setPoint(HexPoint.get(p.y, p.x));
+ }
+ }
+ return out;
+ }
+
+ private class BoardPanel extends JPanel {
+ public BoardPanel() {
+ setFocusable(true);
+ }
+
+ public void paintComponent(Graphics graphics) {
+ int w = getWidth();
+ int h = getHeight();
+
+ if (m_image == null) {
+ m_image = createImage(w, h);
+ }
+
+ int bw = m_width;
+ int bh = m_height;
+ GuiField ff[] = m_field;
+ boolean alphaontop = true;
+ Vector> arrows = m_arrows;
+
+ boolean positive = true;
+ if (m_preferences.get("gui-board-orientation").equals("negative")) {
+ positive = false;
+ }
+ boolean flip;
+ if (m_preferences.get("gui-board-type").equals("Flat2")) {
+ flip = positive;
+ } else {
+ flip = !positive;
+ }
+
+ if (flip) {
+ bw = m_height;
+ bh = m_width;
+ alphaontop = false;
+ ff = flipFields(m_field);
+
+ arrows = new Vector>();
+ for (int i = 0; i < m_arrows.size(); i++) {
+ HexPoint p1 = m_arrows.get(i).first;
+ HexPoint p2 = m_arrows.get(i).second;
+ arrows.add(
+ new Pair(HexPoint.get(p1.y, p1.x), HexPoint.get(p2.y, p2.x)));
}
- m_dirty_stones = true;
- }
+ }
- public boolean areStonesDirty()
- {
- return m_dirty_stones;
+ m_drawer.draw(m_image.getGraphics(), w, h, bw, bh, alphaontop, ff, arrows);
+ graphics.drawImage(m_image, 0, 0, null);
}
- /** Adds an arrow. */
- public void addArrow(HexPoint from, HexPoint to)
- {
- m_arrows.add(new Pair(from, to));
- repaint();
+ public void setBounds(int x, int y, int w, int h) {
+ super.setBounds(x, y, w, h);
+ m_image = null;
}
+ }
- public void clearArrows()
- {
- m_arrows.clear();
- repaint();
- }
+ public void mousePressed(MouseEvent e) {}
- /** Clears dynamic marks, leaving stones intact. If the dirty flag is set,
- revert the fields to the saved fields saved in markStonesDirty().
- Dirty stones flag is set to false. See aboutToDirtyStones().
- Empties the list of arrows.
- */
- public void clearMarks()
- {
- if (m_dirty_stones) {
- for (int i=0; ipoint
- */
- public HexColor getColor(HexPoint point)
- {
- GuiField f = getField(point);
- return f.getColor();
- }
-
- /** Gets the field at the specified point.
- Special points are ignored (SWAP_SIDES, etc).
- */
- public GuiField getField(HexPoint point)
- {
- if (point == HexPoint.SWAP_SIDES
- || point == HexPoint.SWAP_PIECES
- || point == HexPoint.PASS
- || point == HexPoint.RESIGN
- || point == HexPoint.FORFEIT) {
- return null;
- }
+ public void mouseEntered(MouseEvent e) {}
- for (int x=0; xpoint is null. */
+ private int m_width, m_height;
+ private Dimension m_size;
+ private int m_mode;
- public void markLastPlayed(HexPoint point)
- {
- assert(point != HexPoint.SWAP_SIDES && point != HexPoint.SWAP_PIECES);
+ private Image m_image;
+ private GuiField m_field[];
+ private Vector> m_arrows;
- if (m_last_played != null) {
- m_last_played.clearAttributes(GuiField.LAST_PLAYED);
- m_last_played = null;
- }
- if (point != null) {
- m_last_played = getField(point);
- if (m_last_played != null) {
- m_last_played.setAttributes(GuiField.LAST_PLAYED);
- }
- }
- repaint();
- }
-
- /** Clear swap marks */
- public void clearSwapPlayed()
- {
- for (int x=0; x colors = new TreeMap();
- for (int x=0; x carrier = vc.getCarrier();
- for (int i=0; i stones = vc.getStones();
- for (int i=0; i key = vc.getKey();
- for (int i=0; i= 1)
- {
- return Printable.NO_SUCH_PAGE;
- }
- double width = getWidth();
- double height = getHeight();
- double pageWidth = format.getImageableWidth();
- double pageHeight = format.getImageableHeight();
- double scale = 1;
- if (width >= pageWidth)
- scale = pageWidth / width;
- double xSpace = (pageWidth - width * scale) / 2;
- double ySpace = (pageHeight - height * scale) / 2;
- Graphics2D g2d = (Graphics2D)g;
- g2d.translate(format.getImageableX() + xSpace,
- format.getImageableY() + ySpace);
- g2d.scale(scale, scale);
- print(g2d);
- return Printable.PAGE_EXISTS;
- }
-
- //------------------------------------------------------------
-
- /** Converts a hex string representing a bitset into a vector of
- HexPoints. This relies on m_field being ordered in a particular
- fashion.
-
- NOTE: THIS IS BROKEN SINCE HexPoint was changed in wolve, r182.
- USE BASE 64 INSTEAD!
-
- FIXME: switch carriers to be printed as a list of HexPoints instead of
- as hex strings?
- */
- private Vector convertHexString(String str)
- {
- Vector ret = new Vector();
-
- for (int i=0; i convertBase64String(String str)
- {
-
- Vector ret = new Vector();
- for (int i=0; i> arrows = m_arrows;
-
- boolean positive = true;
- if (m_preferences.get("gui-board-orientation").equals("negative")) {
- positive = false;
- }
- boolean flip;
- if (m_preferences.get("gui-board-type").equals("Flat2")) {
- flip = positive;
- } else {
- flip = !positive;
- }
-
- if (flip) {
- bw = m_height;
- bh = m_width;
- alphaontop = false;
- ff = flipFields(m_field);
-
- arrows = new Vector>();
- for (int i=0; i
- (HexPoint.get(p1.y, p1.x),
- HexPoint.get(p2.y, p2.x)));
- }
- }
-
- m_drawer.draw(m_image.getGraphics(),
- w, h, bw, bh, alphaontop,
- ff, arrows);
- graphics.drawImage(m_image, 0, 0, null);
- }
-
- public void setBounds(int x, int y, int w, int h)
- {
- super.setBounds(x, y, w, h);
- m_image = null;
- }
- }
-
- public void mousePressed(MouseEvent e) {}
- public void mouseReleased(MouseEvent e) {}
- public void mouseEntered(MouseEvent e) {}
- public void mouseExited(MouseEvent e) {}
-
- private int m_width, m_height;
- private Dimension m_size;
- private int m_mode;
-
- private Image m_image;
- private GuiField m_field[];
- private Vector> m_arrows;
-
- private boolean m_dirty_stones;
- private GuiField m_backup_field[];
-
- private GuiField m_last_played;
-
- private BoardDrawerBase m_drawer;
- private BoardPanel m_boardPanel;
-
- private Listener m_listener;
- private GuiPreferences m_preferences;
+ private Listener m_listener;
+ private GuiPreferences m_preferences;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/GuiField.java b/src/main/java/hexgui/gui/GuiField.java
index f673994..0813301 100644
--- a/src/main/java/hexgui/gui/GuiField.java
+++ b/src/main/java/hexgui/gui/GuiField.java
@@ -1,327 +1,288 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
-import javax.swing.*;
+import hexgui.hex.*;
+import hexgui.util.*;
+import java.awt.AlphaComposite;
import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
-import java.awt.AlphaComposite;
-import java.awt.FontMetrics;
-import java.awt.Font;
-
import java.awt.event.*;
import java.awt.geom.*;
-
-import hexgui.hex.*;
-import hexgui.util.*;
-
-//----------------------------------------------------------------------------
-
-public class GuiField
-{
- public static final int DRAW_CELL_OUTLINE = 1;
- public static final int LAST_PLAYED = 2;
- public static final int SWAP_PLAYED = 4;
- public static final int DRAW_TEXT = 8;
- public static final int DRAW_ALPHA = 16;
- public static final int SELECTED = 32;
-
- private static final Color COLOR_STONE_BLACK = Color.decode("#030303");
- private static final Color COLOR_STONE_BLACK_BRIGHT = Color.decode("#666666");
- private static final Color COLOR_STONE_WHITE = Color.decode("#d7d0c9");
- private static final Color COLOR_STONE_WHITE_BRIGHT = Color.decode("#ffffff");
-
-
- public GuiField(HexPoint p)
- {
- this(p, HexColor.EMPTY, 0, null, null, 0);
- }
-
- public GuiField(HexPoint p, HexColor c, int attributes,
- String text, Color alpha, float blend)
- {
- m_point = p;
- m_color = c;
- m_text = text;
- m_alpha_color = alpha;
- m_attributes = attributes;
- m_alpha_blend = blend;
- }
-
- /** Creates a copy of the given field. */
- public GuiField(GuiField f)
- {
- this(f.getPoint(), f.getColor(), f.getAttributes(),
- f.getText(), f.getAlphaColor(), f.getAlphaBlend());
+import javax.swing.*;
+
+// ----------------------------------------------------------------------------
+
+public class GuiField {
+ public static final int DRAW_CELL_OUTLINE = 1;
+ public static final int LAST_PLAYED = 2;
+ public static final int SWAP_PLAYED = 4;
+ public static final int DRAW_TEXT = 8;
+ public static final int DRAW_ALPHA = 16;
+ public static final int SELECTED = 32;
+
+ private static final Color COLOR_STONE_BLACK = Color.decode("#030303");
+ private static final Color COLOR_STONE_BLACK_BRIGHT = Color.decode("#666666");
+ private static final Color COLOR_STONE_WHITE = Color.decode("#d7d0c9");
+ private static final Color COLOR_STONE_WHITE_BRIGHT = Color.decode("#ffffff");
+
+ public GuiField(HexPoint p) {
+ this(p, HexColor.EMPTY, 0, null, null, 0);
+ }
+
+ public GuiField(HexPoint p, HexColor c, int attributes, String text, Color alpha, float blend) {
+ m_point = p;
+ m_color = c;
+ m_text = text;
+ m_alpha_color = alpha;
+ m_attributes = attributes;
+ m_alpha_blend = blend;
+ }
+
+ /** Creates a copy of the given field. */
+ public GuiField(GuiField f) {
+ this(
+ f.getPoint(),
+ f.getColor(),
+ f.getAttributes(),
+ f.getText(),
+ f.getAlphaColor(),
+ f.getAlphaBlend());
+ }
+
+ public static int getStoneMargin(int width) {
+ return width / 17 + 1;
+ }
+
+ public void clearAttributes() {
+ m_attributes = 0;
+ }
+
+ public void clearAttributes(int f) {
+ m_attributes &= ~f;
+ }
+
+ public void setAttributes(int f) {
+ m_attributes |= f;
+ }
+
+ public int getAttributes() {
+ return m_attributes;
+ }
+
+ public void setColor(HexColor c) {
+ m_color = c;
+ }
+
+ public HexColor getColor() {
+ return m_color;
+ }
+
+ public void setText(String str) {
+ m_text = str;
+ if (str == null) clearAttributes(DRAW_TEXT);
+ else setAttributes(DRAW_TEXT);
+ }
+
+ public String getText() {
+ return m_text;
+ }
+
+ public void setAlphaColor(Color c) {
+ m_alpha_color = c;
+ m_alpha_blend = 0.3f;
+ if (c == null) clearAttributes(DRAW_ALPHA);
+ else setAttributes(DRAW_ALPHA);
+ }
+
+ public void setAlphaColor(Color c, float blend) {
+ m_alpha_color = c;
+ m_alpha_blend = blend;
+ if (c == null) clearAttributes(DRAW_ALPHA);
+ else setAttributes(DRAW_ALPHA);
+ }
+
+ public Color getAlphaColor() {
+ return m_alpha_color;
+ }
+
+ public float getAlphaBlend() {
+ return m_alpha_blend;
+ }
+
+ public void setSelected(boolean f) {
+ if (f) {
+ setAttributes(SELECTED);
+ } else {
+ clearAttributes(SELECTED);
}
-
- public static int getStoneMargin(int width)
- {
- return width / 17 + 1;
+ }
+
+ public void setPoint(HexPoint p) {
+ m_point = p;
+ }
+
+ public HexPoint getPoint() {
+ return m_point;
+ }
+
+ public void clear() {
+ setColor(HexColor.EMPTY);
+ }
+
+ private RadialGradientPaint getPaint(
+ int width, int height, Color colorNormal, Color colorBright) {
+ RadialGradientPaint paint;
+ int paintSize;
+ int size = (width < height) ? width : height;
+ int radius = Math.max(size / 3, 1);
+ Point2D.Double centerPoint = new Point2D.Double(width / 2 - size / 6, height / 2 - size / 6);
+ Point2D.Double radiusPoint = new Point2D.Double(radius, radius);
+ paint =
+ new RadialGradientPaint(
+ centerPoint, colorBright,
+ radiusPoint, colorNormal);
+ return paint;
+ }
+
+ public void draw(Graphics g, int x, int y, int w, int h) {
+ if (!g.hitClip(x, y, w, h)) return;
+
+ m_width = w;
+ m_height = h;
+
+ m_radius = (h < w) ? h / 2 : w / 2;
+ m_margin = getStoneMargin(m_radius * 2);
+
+ m_graphics = g.create(x - w / 2, y - h / 2, w, h);
+ if (m_graphics instanceof Graphics2D) {
+ m_graphics2D = (Graphics2D) m_graphics;
+ } else {
+ m_graphics2D = null;
}
- public void clearAttributes()
- {
- m_attributes = 0;
- }
-
- public void clearAttributes(int f)
- {
- m_attributes &= ~f;
- }
-
- public void setAttributes(int f)
- {
- m_attributes |= f;
+ if (m_color == HexColor.WHITE) {
+ drawStone(COLOR_STONE_WHITE, COLOR_STONE_WHITE_BRIGHT);
+ } else if (m_color == HexColor.BLACK) {
+ drawStone(COLOR_STONE_BLACK, COLOR_STONE_BLACK_BRIGHT);
}
- public int getAttributes()
- {
- return m_attributes;
- }
-
- public void setColor(HexColor c)
- {
- m_color = c;
- }
-
- public HexColor getColor()
- {
- return m_color;
+ if ((m_attributes & LAST_PLAYED) != 0) {
+ drawLastPlayed();
}
- public void setText(String str)
- {
- m_text = str;
- if (str == null)
- clearAttributes(DRAW_TEXT);
- else
- setAttributes(DRAW_TEXT);
+ if ((m_attributes & SWAP_PLAYED) != 0) {
+ drawSwapPlayed();
}
- public String getText() {
- return m_text;
- }
+ // FIXME: this is done in BoardDrawer since we don't know
+ // anything about our shape and size and we want to cover the
+ // entire field. Should all drawing be done in board drawer?
+ // if ((m_attributes & DRAW_ALPHA) != 0) drawAlpha();
- public void setAlphaColor(Color c)
- {
- m_alpha_color = c;
- m_alpha_blend = 0.3f;
- if (c == null)
- clearAttributes(DRAW_ALPHA);
- else
- setAttributes(DRAW_ALPHA);
- }
+ if ((m_attributes & DRAW_TEXT) != 0) drawText();
+ }
- public void setAlphaColor(Color c, float blend)
- {
- m_alpha_color = c;
- m_alpha_blend = blend;
- if (c == null)
- clearAttributes(DRAW_ALPHA);
- else
- setAttributes(DRAW_ALPHA);
+ private void drawStone(Color normal, Color bright) {
+ if (m_graphics2D != null) {
+ RadialGradientPaint paint = getPaint(m_width, m_height, normal, bright);
+ m_graphics2D.setPaint(paint);
+ } else {
+ m_graphics.setColor(normal);
}
- public Color getAlphaColor() {
- return m_alpha_color;
+ int size = m_radius - m_margin;
+ m_graphics.fillOval(m_width / 2 - size, m_height / 2 - size, size * 2, size * 2);
+
+ m_graphics.setPaintMode();
+ }
+
+ private void drawLastPlayed() {
+ m_graphics.setColor(Color.gray);
+ int size = (m_radius - m_margin) / 6;
+ m_graphics.fillOval(m_width / 2 - size, m_height / 2 - size, 2 * size, 2 * size);
+ }
+
+ /**
+ * Draw the given string centered at the coordinates (x,y) in the current font, with the given
+ * relative size.
+ */
+ private void drawString(String str, double x, double y, double size) {
+ double abssize = (m_radius - m_margin) * size;
+ Font f = m_graphics.getFont();
+ Font f2 = f.deriveFont((float) abssize);
+ FontMetrics m = m_graphics.getFontMetrics(f2);
+ double width = m.stringWidth(str);
+ double height = m.getAscent();
+
+ m_graphics.setFont(f2);
+ m_graphics.drawString(str, (int) (x - width / 2), (int) (y + 0.8 * height / 2));
+ m_graphics.setFont(f);
+ }
+
+ private void drawSwapPlayed() {
+ if (m_color == HexColor.BLACK) {
+ m_graphics.setColor(Color.white);
+ } else {
+ m_graphics.setColor(Color.black);
}
+ this.drawString("S", m_width / 2.0, m_height / 2.0, 1);
+ }
- public float getAlphaBlend() {
- return m_alpha_blend;
- }
+ private void drawAlpha() {
+ if (m_alpha_color == null) return;
+ if (m_graphics2D == null) return;
- public void setSelected(boolean f)
- {
- if (f) {
- setAttributes(SELECTED);
- } else {
- clearAttributes(SELECTED);
- }
- }
+ m_graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
+ m_graphics.setColor(m_alpha_color);
+ m_graphics.fillRect(
+ m_width / 2 - m_width / 4, m_height / 2 - m_height / 4, m_width / 2, m_height / 2);
+ }
- public void setPoint(HexPoint p) {
- m_point = p;
- }
- public HexPoint getPoint() {
- return m_point;
- }
-
- public void clear()
- {
- setColor(HexColor.EMPTY);
- }
-
- private RadialGradientPaint getPaint(int width,
- int height,
- Color colorNormal,
- Color colorBright)
- {
- RadialGradientPaint paint;
- int paintSize;
- int size = (width < height) ? width : height;
- int radius = Math.max(size / 3, 1);
- Point2D.Double centerPoint =
- new Point2D.Double(width/2 - size/6, height/2 - size/6);
- Point2D.Double radiusPoint =
- new Point2D.Double(radius, radius);
- paint = new RadialGradientPaint(centerPoint, colorBright,
- radiusPoint, colorNormal);
- return paint;
- }
-
- public void draw(Graphics g, int x, int y, int w, int h)
- {
- if (!g.hitClip(x, y, w, h))
- return;
-
- m_width = w;
- m_height = h;
-
- m_radius = (h < w) ? h/2 : w/2;
- m_margin = getStoneMargin(m_radius*2);
-
- m_graphics = g.create(x-w/2,y-h/2,w,h);
- if (m_graphics instanceof Graphics2D) {
- m_graphics2D = (Graphics2D)m_graphics;
- } else {
- m_graphics2D = null;
- }
-
- if (m_color == HexColor.WHITE) {
- drawStone(COLOR_STONE_WHITE, COLOR_STONE_WHITE_BRIGHT);
- } else if (m_color == HexColor.BLACK) {
- drawStone(COLOR_STONE_BLACK, COLOR_STONE_BLACK_BRIGHT);
- }
-
- if ((m_attributes & LAST_PLAYED) != 0) {
- drawLastPlayed();
- }
-
- if ((m_attributes & SWAP_PLAYED) != 0) {
- drawSwapPlayed();
- }
-
- // FIXME: this is done in BoardDrawer since we don't know
- // anything about our shape and size and we want to cover the
- // entire field. Should all drawing be done in board drawer?
- // if ((m_attributes & DRAW_ALPHA) != 0) drawAlpha();
-
- if ((m_attributes & DRAW_TEXT) != 0)
- drawText();
-
- }
-
- private void drawStone(Color normal, Color bright)
- {
- if (m_graphics2D != null) {
- RadialGradientPaint paint = getPaint(m_width, m_height,
- normal, bright);
- m_graphics2D.setPaint(paint);
- } else {
- m_graphics.setColor(normal);
- }
-
- int size = m_radius - m_margin;
- m_graphics.fillOval(m_width/2 - size, m_height/2 - size,
- size*2, size*2);
-
- m_graphics.setPaintMode();
- }
+ private void drawText() {
+ String[] lines = m_text.split("@");
+ int nlines = lines.length;
- private void drawLastPlayed()
- {
- m_graphics.setColor(Color.gray);
- int size = (m_radius - m_margin) / 6;
- m_graphics.fillOval(m_width/2 - size, m_height/2 - size, 2*size, 2*size);
- }
+ double size = m_radius - m_margin;
+ double relheight = nlines > 1 ? 2.0 / nlines : 1.0;
+ double height = size * relheight;
- /** Draw the given string centered at the coordinates (x,y) in the
- current font, with the given relative size. */
- private void drawString(String str, double x, double y, double size)
- {
- double abssize = (m_radius - m_margin) * size;
- Font f = m_graphics.getFont();
- Font f2 = f.deriveFont((float)abssize);
- FontMetrics m = m_graphics.getFontMetrics(f2);
- double width = m.stringWidth(str);
- double height = m.getAscent();
-
- m_graphics.setFont(f2);
- m_graphics.drawString(str, (int)(x - width/2), (int)(y + 0.8*height/2));
- m_graphics.setFont(f);
- }
-
- private void drawSwapPlayed()
- {
- if (m_color == HexColor.BLACK) {
- m_graphics.setColor(Color.white);
- } else {
- m_graphics.setColor(Color.black);
- }
- this.drawString("S", m_width/2.0, m_height/2.0, 1);
- }
+ double y = m_height / 2 + ((nlines - 1) * height) / 2;
- private void drawAlpha()
- {
- if (m_alpha_color == null)
- return;
- if (m_graphics2D == null)
- return;
+ for (int i = lines.length - 1; i >= 0; --i) {
+ String str = lines[i].trim();
- m_graphics2D.setComposite(AlphaComposite.
- getInstance(AlphaComposite.SRC_OVER,
- 0.3f));
- m_graphics.setColor(m_alpha_color);
- m_graphics.fillRect(m_width/2 - m_width/4, m_height/2 - m_height/4,
- m_width/2, m_height/2);
+ Color color = Color.black;
+ if (getColor() == HexColor.BLACK) color = Color.white;
- }
+ m_graphics.setColor(color);
+ this.drawString(str, m_width / 2, y, relheight);
- private void drawText()
- {
- String[] lines = m_text.split("@");
- int nlines = lines.length;
-
- double size = m_radius - m_margin;
- double relheight = nlines > 1 ? 2.0/nlines : 1.0;
- double height = size * relheight;
-
- double y = m_height/2 + ((nlines-1)*height)/2;
-
- for (int i=lines.length-1; i>=0; --i) {
- String str = lines[i].trim();
-
- Color color = Color.black;
- if (getColor() == HexColor.BLACK)
- color = Color.white;
-
- m_graphics.setColor(color);
- this.drawString(str, m_width/2, y, relheight);
-
- y -= height;
- }
+ y -= height;
}
+ }
- private HexPoint m_point;
- private HexColor m_color;
- private int m_attributes;
+ private HexPoint m_point;
+ private HexColor m_color;
+ private int m_attributes;
- private Color m_alpha_color;
- private float m_alpha_blend;
+ private Color m_alpha_color;
+ private float m_alpha_blend;
- private String m_text;
+ private String m_text;
- private int m_width;
- private int m_height;
- private int m_radius;
- private int m_margin;
+ private int m_width;
+ private int m_height;
+ private int m_radius;
+ private int m_margin;
- private Graphics m_graphics;
- private Graphics2D m_graphics2D;
+ private Graphics m_graphics;
+ private Graphics2D m_graphics2D;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/GuiMenuBar.java b/src/main/java/hexgui/gui/GuiMenuBar.java
index 8b2ff16..739573a 100644
--- a/src/main/java/hexgui/gui/GuiMenuBar.java
+++ b/src/main/java/hexgui/gui/GuiMenuBar.java
@@ -1,633 +1,582 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
-import hexgui.game.Node;
-import java.util.*;
-import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
/** Menu bar. */
-public final class GuiMenuBar
-{
- public GuiMenuBar(ActionListener listener, GuiPreferences preferences)
- {
- m_preferences = preferences;
-
- m_menuBar = new JMenuBar();
-
- m_listener = listener;
- m_menuBar.add(createFileMenu());
- m_menuBar.add(createProgramMenu());
- m_menuBar.add(createGameMenu());
- m_menuBar.add(createEditMenu());
- m_menuBar.add(createViewMenu());
- m_menuBar.add(createHelpMenu());
-
- setProgramConnected(false);
- }
-
- public JMenuBar getJMenuBar()
- {
- return m_menuBar;
- }
-
- public void setProgramConnected(boolean f)
- {
- //m_connect_remote.setEnabled(!f);
- m_connect_local.setEnabled(!f);
- m_disconnect.setEnabled(f);
- m_reconnect.setEnabled(f);
- m_genmove.setEnabled(f);
-
- if (f == false) {
- setShellVisible(false);
- m_shell_visible.setEnabled(false);
- setAnalyzeVisible(false);
- m_analyze_visible.setEnabled(false);
- } else {
- m_shell_visible.setEnabled(true);
- m_analyze_visible.setEnabled(true);
-
- setShellVisible(m_preferences.
- getBoolean("shell-show-on-connect"));
- setAnalyzeVisible(m_preferences.
- getBoolean("analyze-show-on-connect"));
- }
- }
-
- public void updateMenuStates(HexGui current)
- {
- m_swap_pieces.setEnabled(current.isSwapAllowed());
- m_swap_sides.setEnabled(current.isSwapAllowed());
- }
-
- //----------------------------------------------------------------------
-
- private JMenu createFileMenu()
- {
- JMenu menu = new JMenu("File");
- menu.setMnemonic(KeyEvent.VK_F);
-
- JMenuItem item;
- item = new JMenuItem("Open...");
- item.setMnemonic(KeyEvent.VK_O);
- item.addActionListener(m_listener);
- item.setActionCommand("loadgame");
- menu.add(item);
-
- menu.addSeparator();
-
- item = new JMenuItem("Save Game");
- item.setMnemonic(KeyEvent.VK_S);
- item.addActionListener(m_listener);
- item.setActionCommand("savegame");
- menu.add(item);
-
- item = new JMenuItem("Save Game As...");
- item.setMnemonic(KeyEvent.VK_A);
- item.addActionListener(m_listener);
- item.setActionCommand("savegameas");
- menu.add(item);
-
- item = new JMenuItem("Save Position As...");
- item.addActionListener(m_listener);
- item.setActionCommand("save-position-as");
- menu.add(item);
-
- menu.addSeparator();
-
- item = new JMenuItem("Print Preview");
- item.addActionListener(m_listener);
- item.setActionCommand("print-preview");
- menu.add(item);
-
- item = new JMenuItem("Print...");
- item.addActionListener(m_listener);
- item.setActionCommand("print");
- menu.add(item);
-
- menu.addSeparator();
-
- item = new JMenuItem("Exit");
- item.setMnemonic(KeyEvent.VK_X);
- item.addActionListener(m_listener);
- item.setActionCommand("shutdown");
- menu.add(item);
-
- return menu;
- }
-
- //----------------------------------------------------------------------
- private JMenu createProgramMenu()
- {
- JMenu menu = new JMenu("Program");
- menu.setMnemonic(KeyEvent.VK_P);
-
- JMenuItem item;
-
- item = new JMenuItem("New Program...");
- item.addActionListener(m_listener);
- item.setActionCommand("new-program");
- menu.add(item);
-
- item = new JMenuItem("Edit Program...");
- item.addActionListener(m_listener);
- item.setActionCommand("edit-program");
- menu.add(item);
-
- item = new JMenuItem("Delete Program...");
- item.addActionListener(m_listener);
- item.setActionCommand("delete-program");
- menu.add(item);
-
- menu.addSeparator();
-
- item = new JMenuItem("Connect Local Program...");
- item.addActionListener(m_listener);
- item.setActionCommand("connect-local-program");
- m_connect_local = item;
- menu.add(item);
-
- // item = new JMenuItem("Connect Remote Program...");
- // item.addActionListener(m_listener);
- // item.setActionCommand("connect-program");
- // item.setEnabled(false);
- // m_connect_remote = item;
- // menu.add(item);
-
- menu.addSeparator();
-
- item = new JMenuItem("Reconnect Program");
- item.addActionListener(m_listener);
- item.setActionCommand("reconnect-program");
- m_reconnect = item;
- menu.add(item);
-
- item = new JMenuItem("Disconnect Program");
- item.addActionListener(m_listener);
- item.setActionCommand("disconnect-program");
- m_disconnect = item;
- menu.add(item);
-
- return menu;
- }
-
- //----------------------------------------------------------------------
-
- private JMenu createGameMenu()
- {
- JMenu menu = new JMenu("Game");
- menu.setMnemonic(KeyEvent.VK_G);
-
- JMenuItem item;
- item = new JMenuItem("New");
- item.setMnemonic(KeyEvent.VK_N);
- item.addActionListener(m_listener);
- item.setActionCommand("newgame");
- menu.add(item);
-
- JMenu submenu;
-
- menu.addSeparator();
-
- submenu = createClockMenu();
- menu.add(submenu);
-
- menu.addSeparator();
-
- submenu = createToMoveMenu();
- menu.add(submenu);
-
- menu.addSeparator();
-
- m_swap_pieces = new JMenuItem("Swap pieces");
- m_swap_pieces.addActionListener(m_listener);
- m_swap_pieces.setActionCommand("game_swap_pieces");
- menu.add(m_swap_pieces);
-
- m_swap_sides = new JMenuItem("Swap sides");
- m_swap_sides.addActionListener(m_listener);
- m_swap_sides.setActionCommand("game_swap_sides");
- menu.add(m_swap_sides);
-
- m_pass = new JMenuItem("Pass");
- m_pass.addActionListener(m_listener);
- m_pass.setActionCommand("game_pass");
- menu.add(m_pass);
-
- m_resign = new JMenuItem("Resign");
- m_resign.addActionListener(m_listener);
- m_resign.setActionCommand("game_resign");
- menu.add(m_resign);
-
- m_forfeit = new JMenuItem("Forfeit");
- m_forfeit.addActionListener(m_listener);
- m_forfeit.setActionCommand("game_forfeit");
- menu.add(m_forfeit);
-
- m_addsetup = new JMenuItem("Add setup node");
- m_addsetup.addActionListener(m_listener);
- m_addsetup.setActionCommand("game_addsetup");
- menu.add(m_addsetup);
-
- m_genmove = new JMenuItem("Generate Computer Move");
- m_genmove.addActionListener(m_listener);
- m_genmove.setActionCommand("genmove");
- menu.add(m_genmove);
-
- menu.addSeparator();
-
- item = new JMenuItem("Delete Current Branch");
- item.addActionListener(m_listener);
- item.setActionCommand("game_delete_branch");
- menu.add(item);
-
- item = new JMenuItem("Make Main Branch");
- item.addActionListener(m_listener);
- item.setActionCommand("game_make_main_branch");
- menu.add(item);
-
- return menu;
- }
-
- private JMenu createClockMenu()
- {
- JMenu menu = new JMenu("Clock");
- JMenuItem item;
-
- item = new JMenuItem("Start");
- item.addActionListener(m_listener);
- item.setActionCommand("game_start_clock");
- menu.add(item);
-
- item = new JMenuItem("Stop");
- item.addActionListener(m_listener);
- item.setActionCommand("game_stop_clock");
- menu.add(item);
-
- return menu;
- }
-
- private JMenu createToMoveMenu()
- {
- JMenu menu = new JMenu("Color To Move");
-
- m_colorGroup = new ButtonGroup();
- String pref = m_preferences.get("first-move-color");
-
- JRadioButtonMenuItem item;
- item = new JRadioButtonMenuItem("black");
- item.addActionListener(m_listener);
- item.setActionCommand("set_to_move");
- if (pref.equals("black")) item.setSelected(true);
- m_colorGroup.add(item);
- menu.add(item);
-
- item = new JRadioButtonMenuItem("white");
- item.addActionListener(m_listener);
- item.setActionCommand("set_to_move");
- if (pref.equals("white")) item.setSelected(true);
- m_colorGroup.add(item);
- menu.add(item);
-
- return menu;
+public final class GuiMenuBar {
+ public GuiMenuBar(ActionListener listener, GuiPreferences preferences) {
+ m_preferences = preferences;
+
+ m_menuBar = new JMenuBar();
+
+ m_listener = listener;
+ m_menuBar.add(createFileMenu());
+ m_menuBar.add(createProgramMenu());
+ m_menuBar.add(createGameMenu());
+ m_menuBar.add(createEditMenu());
+ m_menuBar.add(createViewMenu());
+ m_menuBar.add(createHelpMenu());
+
+ setProgramConnected(false);
+ }
+
+ public JMenuBar getJMenuBar() {
+ return m_menuBar;
+ }
+
+ public void setProgramConnected(boolean f) {
+ // m_connect_remote.setEnabled(!f);
+ m_connect_local.setEnabled(!f);
+ m_disconnect.setEnabled(f);
+ m_reconnect.setEnabled(f);
+ m_genmove.setEnabled(f);
+
+ if (f == false) {
+ setShellVisible(false);
+ m_shell_visible.setEnabled(false);
+ setAnalyzeVisible(false);
+ m_analyze_visible.setEnabled(false);
+ } else {
+ m_shell_visible.setEnabled(true);
+ m_analyze_visible.setEnabled(true);
+
+ setShellVisible(m_preferences.getBoolean("shell-show-on-connect"));
+ setAnalyzeVisible(m_preferences.getBoolean("analyze-show-on-connect"));
}
+ }
+
+ public void updateMenuStates(HexGui current) {
+ m_swap_pieces.setEnabled(current.isSwapAllowed());
+ m_swap_sides.setEnabled(current.isSwapAllowed());
+ }
+
+ // ----------------------------------------------------------------------
+
+ private JMenu createFileMenu() {
+ JMenu menu = new JMenu("File");
+ menu.setMnemonic(KeyEvent.VK_F);
+
+ JMenuItem item;
+ item = new JMenuItem("Open...");
+ item.setMnemonic(KeyEvent.VK_O);
+ item.addActionListener(m_listener);
+ item.setActionCommand("loadgame");
+ menu.add(item);
+
+ menu.addSeparator();
+
+ item = new JMenuItem("Save Game");
+ item.setMnemonic(KeyEvent.VK_S);
+ item.addActionListener(m_listener);
+ item.setActionCommand("savegame");
+ menu.add(item);
+
+ item = new JMenuItem("Save Game As...");
+ item.setMnemonic(KeyEvent.VK_A);
+ item.addActionListener(m_listener);
+ item.setActionCommand("savegameas");
+ menu.add(item);
+
+ item = new JMenuItem("Save Position As...");
+ item.addActionListener(m_listener);
+ item.setActionCommand("save-position-as");
+ menu.add(item);
- public String getToMove()
- {
- Enumeration e = m_colorGroup.getElements();
- AbstractButton b = (AbstractButton)e.nextElement();
- while (!b.isSelected() && e.hasMoreElements()) {
- b = (AbstractButton)e.nextElement();
- }
- return b.getText();
- }
-
- public void setToMove(String color)
- {
- Enumeration e = m_colorGroup.getElements();
- AbstractButton b = (AbstractButton)e.nextElement();
- while (true) {
- if (color.equalsIgnoreCase(b.getText())) {
- b.setSelected(true);
- } else {
- b.setSelected(false);
- }
- if (!e.hasMoreElements())
- break;
- b = (AbstractButton)e.nextElement();
- }
- }
+ menu.addSeparator();
- //----------------------------------------------------------------------
+ item = new JMenuItem("Print Preview");
+ item.addActionListener(m_listener);
+ item.setActionCommand("print-preview");
+ menu.add(item);
- private JMenu createEditMenu()
- {
- JMenu menu = new JMenu("Edit");
- menu.setMnemonic(KeyEvent.VK_E);
+ item = new JMenuItem("Print...");
+ item.addActionListener(m_listener);
+ item.setActionCommand("print");
+ menu.add(item);
- JMenu size = createBoardSizeMenu();
- menu.add(size);
+ menu.addSeparator();
- menu.addSeparator();
-
- JMenuItem item;
- item = new JMenuItem("Preferences...");
- item.addActionListener(m_listener);
- item.setActionCommand("show-preferences");
+ item = new JMenuItem("Exit");
+ item.setMnemonic(KeyEvent.VK_X);
+ item.addActionListener(m_listener);
+ item.setActionCommand("shutdown");
+ menu.add(item);
- menu.add(item);
+ return menu;
+ }
+
+ // ----------------------------------------------------------------------
+ private JMenu createProgramMenu() {
+ JMenu menu = new JMenu("Program");
+ menu.setMnemonic(KeyEvent.VK_P);
+
+ JMenuItem item;
+
+ item = new JMenuItem("New Program...");
+ item.addActionListener(m_listener);
+ item.setActionCommand("new-program");
+ menu.add(item);
+
+ item = new JMenuItem("Edit Program...");
+ item.addActionListener(m_listener);
+ item.setActionCommand("edit-program");
+ menu.add(item);
+
+ item = new JMenuItem("Delete Program...");
+ item.addActionListener(m_listener);
+ item.setActionCommand("delete-program");
+ menu.add(item);
+
+ menu.addSeparator();
+
+ item = new JMenuItem("Connect Local Program...");
+ item.addActionListener(m_listener);
+ item.setActionCommand("connect-local-program");
+ m_connect_local = item;
+ menu.add(item);
+
+ // item = new JMenuItem("Connect Remote Program...");
+ // item.addActionListener(m_listener);
+ // item.setActionCommand("connect-program");
+ // item.setEnabled(false);
+ // m_connect_remote = item;
+ // menu.add(item);
+
+ menu.addSeparator();
+
+ item = new JMenuItem("Reconnect Program");
+ item.addActionListener(m_listener);
+ item.setActionCommand("reconnect-program");
+ m_reconnect = item;
+ menu.add(item);
+
+ item = new JMenuItem("Disconnect Program");
+ item.addActionListener(m_listener);
+ item.setActionCommand("disconnect-program");
+ m_disconnect = item;
+ menu.add(item);
+
+ return menu;
+ }
+
+ // ----------------------------------------------------------------------
+
+ private JMenu createGameMenu() {
+ JMenu menu = new JMenu("Game");
+ menu.setMnemonic(KeyEvent.VK_G);
+
+ JMenuItem item;
+ item = new JMenuItem("New");
+ item.setMnemonic(KeyEvent.VK_N);
+ item.addActionListener(m_listener);
+ item.setActionCommand("newgame");
+ menu.add(item);
+
+ JMenu submenu;
+
+ menu.addSeparator();
+
+ submenu = createClockMenu();
+ menu.add(submenu);
+
+ menu.addSeparator();
+
+ submenu = createToMoveMenu();
+ menu.add(submenu);
+
+ menu.addSeparator();
+
+ m_swap_pieces = new JMenuItem("Swap pieces");
+ m_swap_pieces.addActionListener(m_listener);
+ m_swap_pieces.setActionCommand("game_swap_pieces");
+ menu.add(m_swap_pieces);
+
+ m_swap_sides = new JMenuItem("Swap sides");
+ m_swap_sides.addActionListener(m_listener);
+ m_swap_sides.setActionCommand("game_swap_sides");
+ menu.add(m_swap_sides);
+
+ m_pass = new JMenuItem("Pass");
+ m_pass.addActionListener(m_listener);
+ m_pass.setActionCommand("game_pass");
+ menu.add(m_pass);
+
+ m_resign = new JMenuItem("Resign");
+ m_resign.addActionListener(m_listener);
+ m_resign.setActionCommand("game_resign");
+ menu.add(m_resign);
+
+ m_forfeit = new JMenuItem("Forfeit");
+ m_forfeit.addActionListener(m_listener);
+ m_forfeit.setActionCommand("game_forfeit");
+ menu.add(m_forfeit);
+
+ m_addsetup = new JMenuItem("Add setup node");
+ m_addsetup.addActionListener(m_listener);
+ m_addsetup.setActionCommand("game_addsetup");
+ menu.add(m_addsetup);
+
+ m_genmove = new JMenuItem("Generate Computer Move");
+ m_genmove.addActionListener(m_listener);
+ m_genmove.setActionCommand("genmove");
+ menu.add(m_genmove);
+
+ menu.addSeparator();
+
+ item = new JMenuItem("Delete Current Branch");
+ item.addActionListener(m_listener);
+ item.setActionCommand("game_delete_branch");
+ menu.add(item);
+
+ item = new JMenuItem("Make Main Branch");
+ item.addActionListener(m_listener);
+ item.setActionCommand("game_make_main_branch");
+ menu.add(item);
+
+ return menu;
+ }
+
+ private JMenu createClockMenu() {
+ JMenu menu = new JMenu("Clock");
+ JMenuItem item;
+
+ item = new JMenuItem("Start");
+ item.addActionListener(m_listener);
+ item.setActionCommand("game_start_clock");
+ menu.add(item);
+
+ item = new JMenuItem("Stop");
+ item.addActionListener(m_listener);
+ item.setActionCommand("game_stop_clock");
+ menu.add(item);
+
+ return menu;
+ }
+
+ private JMenu createToMoveMenu() {
+ JMenu menu = new JMenu("Color To Move");
- return menu;
+ m_colorGroup = new ButtonGroup();
+ String pref = m_preferences.get("first-move-color");
+
+ JRadioButtonMenuItem item;
+ item = new JRadioButtonMenuItem("black");
+ item.addActionListener(m_listener);
+ item.setActionCommand("set_to_move");
+ if (pref.equals("black")) item.setSelected(true);
+ m_colorGroup.add(item);
+ menu.add(item);
+
+ item = new JRadioButtonMenuItem("white");
+ item.addActionListener(m_listener);
+ item.setActionCommand("set_to_move");
+ if (pref.equals("white")) item.setSelected(true);
+ m_colorGroup.add(item);
+ menu.add(item);
+
+ return menu;
+ }
+
+ public String getToMove() {
+ Enumeration e = m_colorGroup.getElements();
+ AbstractButton b = (AbstractButton) e.nextElement();
+ while (!b.isSelected() && e.hasMoreElements()) {
+ b = (AbstractButton) e.nextElement();
}
-
- private JMenu createBoardSizeMenu()
- {
- JMenu menu = new JMenu("Board Size");
- m_bsGroup = new ButtonGroup();
-
- String sizes[] = new String[]
- {
- "19 x 19",
- "15 x 15",
- "14 x 14",
- "13 x 13",
- "11 x 11",
- "10 x 10",
- "9 x 9",
- "8 x 8",
- "7 x 7",
- "6 x 6",
- "5 x 5",
- "4 x 4",
- "3 x 3"
- };
-
- String preferred = m_preferences.get("gui-board-width") + " x "
- + m_preferences.get("gui-board-height");
-
- boolean found = false;
- JRadioButtonMenuItem item;
- for (int i=0; i";
+ else return "";
+ }
+
+ /**
+ * Get size of default monspaced font. Can be used for setting the initial size of some GUI
+ * elements.
+ */
+ public static int getDefaultMonoFontSize() {
+ return MONOSPACED_FONT.getSize();
+ }
+
+ public static ImageIcon getIcon(String icon, String name) {
+ String resource = "hexgui/images/" + icon + ".png";
+ URL url = GuiUtil.class.getClassLoader().getResource(resource);
+ return new ImageIcon(url, name);
+ }
+
+ /**
+ * Manually break message into multiple lines for multi-line labels. Needed for multi-line
+ * messages in option panes, because pack() on JOptionPane does not compute the option pane size
+ * correctly, if a maximum width is set and the label text is automatically broken into multiple
+ * lines. The workaround with calling invalidate() and pack() a second time does not work either
+ * in this case. See also Sun Bug ID 4545951 (still in Linux JDK 1.5.0_04-b05 or Mac 1.4.2_12)
+ */
+ public static String insertLineBreaks(String message) {
+ final int MAX_CHAR_PER_LINE = 72;
+ int length = message.length();
+ if (length < MAX_CHAR_PER_LINE) return message;
+ StringBuilder buffer = new StringBuilder();
+ int startLine = 0;
+ int lastWhiteSpace = -1;
+ for (int pos = 0; pos < length; ++pos) {
+ char c = message.charAt(pos);
+ if (pos - startLine > 72) {
+ int endLine = (lastWhiteSpace > startLine ? lastWhiteSpace : pos);
+ if (buffer.length() > 0) buffer.append("
");
+ buffer.append(message.substring(startLine, endLine));
+ startLine = endLine;
+ }
+ if (Character.isWhitespace(c)) lastWhiteSpace = pos;
}
-
- /** Create empty box with size of small padding.
- @see #SMALL_PAD */
- public static Box.Filler createSmallFiller()
- {
- return new Box.Filler(SMALL_FILLER_DIMENSION, SMALL_FILLER_DIMENSION,
- SMALL_FILLER_DIMENSION);
+ if (buffer.length() > 0) buffer.append("
");
+ buffer.append(message.substring(startLine));
+ return buffer.toString();
+ }
+
+ /**
+ * Call SwingUtilities.invokeAndWait. Ignores possible exceptions (apart from printing a warning
+ * to System.err
+ */
+ public static void invokeAndWait(Runnable runnable) {
+ try {
+ SwingUtilities.invokeAndWait(runnable);
+ } catch (InterruptedException e) {
+ System.err.println("Thread interrupted");
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.err.println("InvocationTargetException");
}
-
- public static String getClipboardText()
- {
- Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
- Transferable content = clipboard.getContents(null);
- if (content == null
- || ! content.isDataFlavorSupported(DataFlavor.stringFlavor))
- return null;
- try
- {
- return (String)content.getTransferData(DataFlavor.stringFlavor);
- }
- catch (UnsupportedFlavorException e)
- {
- return null;
- }
- catch (IOException e)
- {
- return null;
- }
- }
-
-/** Return a style sheet for message labels using HTML.
- @return A string with a HTML-head tag containing a style tag
- with formatting options or an empty string. */
- public static String getMessageCss()
- {
- if (Platform.isMac())
- return
- "";
- else
- return
- "";
- }
-
- /** Get size of default monspaced font.
- Can be used for setting the initial size of some GUI elements. */
- public static int getDefaultMonoFontSize()
- {
- return MONOSPACED_FONT.getSize();
- }
-
- public static ImageIcon getIcon(String icon, String name)
- {
- String resource = "hexgui/images/" + icon + ".png";
- URL url = GuiUtil.class.getClassLoader().getResource(resource);
- return new ImageIcon(url, name);
- }
-
- /** Manually break message into multiple lines for multi-line labels.
- Needed for multi-line messages in option panes, because pack() on
- JOptionPane does not compute the option pane size correctly, if a
- maximum width is set and the label text is automatically broken into
- multiple lines. The workaround with calling invalidate() and pack() a
- second time does not work either in this case. See also Sun Bug ID
- 4545951 (still in Linux JDK 1.5.0_04-b05 or Mac 1.4.2_12) */
- public static String insertLineBreaks(String message)
- {
- final int MAX_CHAR_PER_LINE = 72;
- int length = message.length();
- if (length < MAX_CHAR_PER_LINE)
- return message;
- StringBuilder buffer = new StringBuilder();
- int startLine = 0;
- int lastWhiteSpace = -1;
- for (int pos = 0; pos < length; ++pos)
- {
- char c = message.charAt(pos);
- if (pos - startLine > 72)
- {
- int endLine =
- (lastWhiteSpace > startLine ? lastWhiteSpace : pos);
- if (buffer.length() > 0)
- buffer.append("
");
- buffer.append(message.substring(startLine, endLine));
- startLine = endLine;
- }
- if (Character.isWhitespace(c))
- lastWhiteSpace = pos;
- }
- if (buffer.length() > 0)
- buffer.append("
");
- buffer.append(message.substring(startLine));
- return buffer.toString();
- }
-
- /** Call SwingUtilities.invokeAndWait.
- Ignores possible exceptions (apart from printing a warning to
- System.err */
- public static void invokeAndWait(Runnable runnable)
- {
- try
- {
- SwingUtilities.invokeAndWait(runnable);
- }
- catch (InterruptedException e)
- {
- System.err.println("Thread interrupted");
- }
- catch (java.lang.reflect.InvocationTargetException e)
- {
- System.err.println("InvocationTargetException");
- }
- }
-
- public static boolean isActiveWindow(Window window)
- {
- KeyboardFocusManager manager =
- KeyboardFocusManager.getCurrentKeyboardFocusManager();
- return (manager.getActiveWindow() == window);
- }
-
- /** Check window for normal state.
- Checks if window is not maximized (in either or both directions) and
- not iconified. */
- public static boolean isNormalSizeMode(JFrame window)
- {
- int state = window.getExtendedState();
- int mask = Frame.MAXIMIZED_BOTH | Frame.MAXIMIZED_VERT
- | Frame.MAXIMIZED_HORIZ | Frame.ICONIFIED;
- return ((state & mask) == 0);
+ }
+
+ public static boolean isActiveWindow(Window window) {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ return (manager.getActiveWindow() == window);
+ }
+
+ /**
+ * Check window for normal state. Checks if window is not maximized (in either or both directions)
+ * and not iconified.
+ */
+ public static boolean isNormalSizeMode(JFrame window) {
+ int state = window.getExtendedState();
+ int mask =
+ Frame.MAXIMIZED_BOTH | Frame.MAXIMIZED_VERT | Frame.MAXIMIZED_HORIZ | Frame.ICONIFIED;
+ return ((state & mask) == 0);
+ }
+
+ public static void paintImmediately(JComponent component) {
+ component.paintImmediately(component.getVisibleRect());
+ }
+
+ public static void removeKeyBinding(JComponent component, String key) {
+ int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
+ InputMap inputMap = component.getInputMap(condition);
+ // According to the docs, null should remove the action, but it does
+ // not seem to work with Sun Java 1.4.2, new Object() works
+ inputMap.put(KeyStroke.getKeyStroke(key), new Object());
+ }
+
+ /** Set antialias rendering hint if graphics is instance of Graphics2D. */
+ public static void setAntiAlias(Graphics graphics) {
+ if (graphics instanceof Graphics2D) {
+ Graphics2D graphics2D = (Graphics2D) graphics;
+ graphics2D.setRenderingHint(
+ RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
-
- public static void paintImmediately(JComponent component)
- {
- component.paintImmediately(component.getVisibleRect());
- }
-
- public static void removeKeyBinding(JComponent component, String key)
- {
- int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
- InputMap inputMap = component.getInputMap(condition);
- // According to the docs, null should remove the action, but it does
- // not seem to work with Sun Java 1.4.2, new Object() works
- inputMap.put(KeyStroke.getKeyStroke(key), new Object());
- }
-
- /** Set antialias rendering hint if graphics is instance of Graphics2D. */
- public static void setAntiAlias(Graphics graphics)
- {
- if (graphics instanceof Graphics2D)
- {
- Graphics2D graphics2D = (Graphics2D)graphics;
- graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- }
- }
-
- /** Set text field non-editable.
- Also sets it non-focusable. */
- public static void setEditableFalse(JTextField field)
- {
- field.setEditable(false);
- field.setFocusable(false);
- }
-
- /** Set Go icon on frame. */
- public static void setGoIcon(Frame frame)
- {
- URL url = s_iconURL;
- if (url != null)
- frame.setIconImage(new ImageIcon(url).getImage());
- }
-
- /** Set property to render button in bevel style on the Mac.
- Only has an effect if Quaqua Look and Feel is used. */
- public static void setMacBevelButton(JButton button)
- {
- button.putClientProperty("Quaqua.Button.style", "bevel");
- }
-
- public static void setMonospacedFont(JComponent component)
- {
- if (MONOSPACED_FONT != null)
- component.setFont(MONOSPACED_FONT);
- }
-
- public static void addStyle(JTextPane textPane, String name,
- Color foreground)
- {
- addStyle(textPane, name, foreground, null, false);
- }
-
- public static void addStyle(JTextPane textPane, String name,
- Color foreground, Color background,
- boolean bold)
- {
- StyledDocument doc = textPane.getStyledDocument();
- StyleContext context = StyleContext.getDefaultStyleContext();
- Style def = context.getStyle(StyleContext.DEFAULT_STYLE);
- Style style = doc.addStyle(name, def);
- if (foreground != null)
- StyleConstants.setForeground(style, foreground);
- if (background != null)
- StyleConstants.setBackground(style, background);
- StyleConstants.setBold(style, bold);
- }
-
- public static void setStyle(JTextPane textPane, int start, int length,
- String name)
- {
- StyledDocument doc = textPane.getStyledDocument();
- Style style;
- if (name == null)
- {
- StyleContext context = StyleContext.getDefaultStyleContext();
- style = context.getStyle(StyleContext.DEFAULT_STYLE);
- }
- else
- style = doc.getStyle(name);
- doc.setCharacterAttributes(start, length, style, true);
- }
-
- public static void setUnlimitedSize(JComponent component)
- {
- Dimension size = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
- component.setMaximumSize(size);
- }
-
- static
- {
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- // There are problems on some platforms with transparency (e.g. Linux
- // Sun Java 1.5.0). Best solution for now is to take an icon without
- // transparency
- s_iconURL =
- loader.getResource("hexgui/images/hexgui-48x48-notrans.png");
- }
-
- private static final Font MONOSPACED_FONT = Font.decode("Monospaced");
-
- private static final Border EMPTY_BORDER =
- BorderFactory.createEmptyBorder(PAD, PAD, PAD, PAD);
-
- private static final Border SMALL_EMPTY_BORDER =
- BorderFactory.createEmptyBorder(SMALL_PAD, SMALL_PAD,
- SMALL_PAD, SMALL_PAD);
-
- private static final Dimension FILLER_DIMENSION =
- new Dimension(PAD, PAD);
-
- private static final Dimension SMALL_FILLER_DIMENSION =
- new Dimension(SMALL_PAD, SMALL_PAD);
-
- private static URL s_iconURL;
+ }
+
+ /** Set text field non-editable. Also sets it non-focusable. */
+ public static void setEditableFalse(JTextField field) {
+ field.setEditable(false);
+ field.setFocusable(false);
+ }
+
+ /** Set Go icon on frame. */
+ public static void setGoIcon(Frame frame) {
+ URL url = s_iconURL;
+ if (url != null) frame.setIconImage(new ImageIcon(url).getImage());
+ }
+
+ /**
+ * Set property to render button in bevel style on the Mac. Only has an effect if Quaqua Look and
+ * Feel is used.
+ */
+ public static void setMacBevelButton(JButton button) {
+ button.putClientProperty("Quaqua.Button.style", "bevel");
+ }
+
+ public static void setMonospacedFont(JComponent component) {
+ if (MONOSPACED_FONT != null) component.setFont(MONOSPACED_FONT);
+ }
+
+ public static void addStyle(JTextPane textPane, String name, Color foreground) {
+ addStyle(textPane, name, foreground, null, false);
+ }
+
+ public static void addStyle(
+ JTextPane textPane, String name, Color foreground, Color background, boolean bold) {
+ StyledDocument doc = textPane.getStyledDocument();
+ StyleContext context = StyleContext.getDefaultStyleContext();
+ Style def = context.getStyle(StyleContext.DEFAULT_STYLE);
+ Style style = doc.addStyle(name, def);
+ if (foreground != null) StyleConstants.setForeground(style, foreground);
+ if (background != null) StyleConstants.setBackground(style, background);
+ StyleConstants.setBold(style, bold);
+ }
+
+ public static void setStyle(JTextPane textPane, int start, int length, String name) {
+ StyledDocument doc = textPane.getStyledDocument();
+ Style style;
+ if (name == null) {
+ StyleContext context = StyleContext.getDefaultStyleContext();
+ style = context.getStyle(StyleContext.DEFAULT_STYLE);
+ } else style = doc.getStyle(name);
+ doc.setCharacterAttributes(start, length, style, true);
+ }
+
+ public static void setUnlimitedSize(JComponent component) {
+ Dimension size = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+ component.setMaximumSize(size);
+ }
+
+ static {
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ // There are problems on some platforms with transparency (e.g. Linux
+ // Sun Java 1.5.0). Best solution for now is to take an icon without
+ // transparency
+ s_iconURL = loader.getResource("hexgui/images/hexgui-48x48-notrans.png");
+ }
+
+ private static final Font MONOSPACED_FONT = Font.decode("Monospaced");
+
+ private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(PAD, PAD, PAD, PAD);
+
+ private static final Border SMALL_EMPTY_BORDER =
+ BorderFactory.createEmptyBorder(
+ SMALL_PAD, SMALL_PAD,
+ SMALL_PAD, SMALL_PAD);
+
+ private static final Dimension FILLER_DIMENSION = new Dimension(PAD, PAD);
+
+ private static final Dimension SMALL_FILLER_DIMENSION = new Dimension(SMALL_PAD, SMALL_PAD);
+
+ private static URL s_iconURL;
}
diff --git a/src/main/java/hexgui/gui/HexGui.java b/src/main/java/hexgui/gui/HexGui.java
index b090f85..391a2ac 100644
--- a/src/main/java/hexgui/gui/HexGui.java
+++ b/src/main/java/hexgui/gui/HexGui.java
@@ -1,2706 +1,2393 @@
package hexgui.gui;
-import hexgui.hex.*;
-import hexgui.util.Pair;
-import hexgui.util.StringUtils;
-import hexgui.game.Node;
-import hexgui.game.GameInfo;
+import static java.text.MessageFormat.format;
+
import hexgui.game.Clock;
-import hexgui.sgf.SgfWriter;
-import hexgui.sgf.SgfReader;
+import hexgui.game.GameInfo;
+import hexgui.game.Node;
+import hexgui.hex.*;
+import hexgui.htp.AnalyzeCommand;
+import hexgui.htp.AnalyzeDefinition;
+import hexgui.htp.AnalyzeType;
import hexgui.htp.HtpController;
import hexgui.htp.HtpError;
+import hexgui.sgf.SgfReader;
+import hexgui.sgf.SgfWriter;
+import hexgui.util.ErrorMessage;
+import hexgui.util.Pair;
import hexgui.util.StreamCopy;
+import hexgui.util.StringUtils;
import hexgui.version.Version;
-import hexgui.gui.ParameterDialog;
-import hexgui.htp.AnalyzeDefinition;
-import hexgui.htp.AnalyzeCommand;
-import hexgui.htp.AnalyzeType;
-import hexgui.util.ErrorMessage;
-import hexgui.gui.ShowAnalyzeText;
-
+import java.awt.*;
+import java.awt.event.*;
import java.io.*;
-import static java.text.MessageFormat.format;
+import java.net.*;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Semaphore;
import javax.swing.*;
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.awt.event.*;
-import java.net.*;
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
/** HexGui. */
-public final class HexGui
- extends JFrame
- implements ActionListener, GuiBoard.Listener,
- HtpShell.Callback, HtpController.GuiFxCallback,
- AnalyzeDialog.Listener, Comment.Listener
-{
- public HexGui(final File file, final String command)
- {
- super("HexGui");
- setIcon();
-
- System.out.println("HexGui v" + Version.id + "; " + Version.date
- + "\n");
-
- // Catch the close action and shutdown nicely
- setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
- addWindowListener(new java.awt.event.WindowAdapter()
- {
- public void windowClosing(WindowEvent winEvt) {
- cmdShutdown();
- }
- });
-
- m_selected_cells = new Vector();
-
- m_about = new AboutDialog(this);
-
- m_preferences = new GuiPreferences(getClass());
-
- m_menubar = new GuiMenuBar(this, m_preferences);
- setJMenuBar(m_menubar.getJMenuBar());
-
- m_toolbar = new GuiToolBar(this, m_preferences);
- getContentPane().add(m_toolbar.getJToolBar(), BorderLayout.NORTH);
-
- m_statusbar = new StatusBar();
- getContentPane().add(m_statusbar, BorderLayout.SOUTH);
-
- m_guiboard = new GuiBoard(this, m_preferences);
- getContentPane().add(m_guiboard, BorderLayout.CENTER);
-
- m_showAnalyzeText = new ShowAnalyzeText(this, m_guiboard);
-
- JPanel panel = new JPanel(new BorderLayout());
- getContentPane().add(panel, BorderLayout.EAST);
-
- m_blackClock = new Clock();
- m_whiteClock = new Clock();
- m_gameinfopanel = new GameInfoPanel(m_blackClock, m_whiteClock);
- m_comment = new Comment(this);
- panel.add(m_gameinfopanel, BorderLayout.NORTH);
- panel.add(m_comment, BorderLayout.CENTER);
-
- cmdNewGame();
-
- pack();
-
- m_locked = false;
-
- m_semaphore = new Semaphore(1);
- m_htp_queue = new ArrayBlockingQueue(256);
- new Thread(new CommandHandler(this, m_htp_queue)).start();
-
- setVisible(true);
- // After frame is visible, further code using Swing functions must
- // be run in the Swing event dispatch thread.
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- initialize(file, command);
- } });
- setCursorType();
- }
-
- //-------------------------------------------------------------------
-
- public void actionPerformed(ActionEvent e)
- {
- String cmd = e.getActionCommand();
-
- unFocus();
-
- //
- // system commands
- //
- if (cmd.equals("shutdown")) {
- cmdShutdown();
- } else if (cmd.equals("new-program")) {
- cmdNewProgram();
- } else if (cmd.equals("edit-program")) {
- cmdEditProgram();
- } else if (cmd.equals("delete-program")) {
- cmdDeleteProgram();
- } else if (cmd.equals("connect-program")) {
- cmdConnectRemoteProgram();
- } else if (cmd.equals("connect-local-program")) {
- cmdConnectLocalProgram();
- } else if (cmd.equals("disconnect-program")) {
- cmdDisconnectProgram();
- } else if (cmd.equals("reconnect-program")) {
- cmdReconnectProgram();
- //
- // file/help commands
- //
- } else if (cmd.equals("newgame")) {
- end_setup();
- cmdNewGame();
- } else if (cmd.equals("savegame")) {
- // We previously only saved when gameChanged() == true,
- // but this is dangerous because saving would fail
- // silently otherwise. It's better to simply save the game
- // when the user asks for it. An alternative use for
- // gameChanged() would be to disable the save button when
- // we think the game hasn't changed. But we shouldn't just
- // offer a button and then do nothing.
- cmdSaveGame();
- } else if (cmd.equals("savegameas")) {
- cmdSaveGameAs();
- } else if (cmd.equals("loadgame")) {
- cmdLoadGame();
- } else if (cmd.equals("save-position-as")) {
- cmdSavePositionAs();
- } else if (cmd.equals("print-preview")) {
- cmdPrintPreview();
- } else if (cmd.equals("print")) {
- cmdPrint();
- } else if (cmd.equals("about")) {
- cmdAbout();
- //
- // gui commands
- //
- } else if (cmd.equals("gui_toolbar_visible")) {
- cmdGuiToolbarVisible();
- } else if (cmd.equals("gui_shell_visible")) {
- cmdGuiShellVisible();
- } else if (cmd.equals("gui_analyze_visible")) {
- cmdGuiAnalyzeVisible();
- } else if (cmd.equals("gui_board_draw_type")) {
- cmdGuiBoardDrawType();
- } else if (cmd.equals("gui_board_orientation")) {
- cmdGuiBoardOrientation();
- } else if (cmd.equals("show-preferences")) {
- cmdShowPreferences();
- } else if (cmd.equals("gui-clear-marks")) {
- cmdClearMarks();
- //
- // game navigation commands
- //
- } else if (cmd.equals("game_beginning")) {
- end_setup();
- backward(-1);
- } else if (cmd.equals("game_backward10")) {
- end_setup();
- backward(10);
- } else if (cmd.equals("game_back")) {
- end_setup();
- backward(1);
- } else if (cmd.equals("game_forward")) {
- end_setup();
- forward(1);
- } else if (cmd.equals("game_forward10")) {
- end_setup();
- forward(10);
- } else if (cmd.equals("game_end")) {
- end_setup();
- forward(-1);
- } else if (cmd.equals("game_up")) {
- end_setup();
- up();
- } else if (cmd.equals("game_down")) {
- end_setup();
- down();
- } else if (cmd.equals("game_swap_sides")) {
- end_setup();
- humanMove(new Move(HexPoint.get("swap-sides"), m_tomove));
- } else if (cmd.equals("game_swap_pieces")) {
- end_setup();
- humanMove(new Move(HexPoint.get("swap-pieces"), m_tomove));
- } else if (cmd.equals("game_pass")) {
- end_setup();
- humanMove(new Move(HexPoint.get("pass"), m_tomove));
- } else if (cmd.equals("game_resign")) {
- end_setup();
- humanMove(new Move(HexPoint.get("resign"), m_tomove));
- } else if (cmd.equals("game_forfeit")) {
- end_setup();
- humanMove(new Move(HexPoint.get("forfeit"), m_tomove));
- } else if (cmd.equals("game_addsetup")) {
- end_setup();
- addSetupNode();
- } else if (cmd.equals("genmove")) {
- end_setup();
- htpGenMove(m_tomove);
- } else if (cmd.equals("game_delete_branch")) {
- end_setup();
- cmdDeleteBranch();
- } else if (cmd.equals("game_make_main_branch")) {
- end_setup();
- cmdMoveBranchTop();
- } else if (cmd.equals("game_start_clock")) {
- startClock();
- } else if (cmd.equals("game_stop_clock")) {
- stopClock();
- } else if (cmd.equals("stop")) {
- m_white.interrupt();
- } else if (cmd.equals("toggle_tomove")) {
- end_setup();
- cmdToggleToMove();
- } else if (cmd.equals("set_to_move")) {
- end_setup();
- cmdSetToMove();
- } else if (cmd.equals("setup-black")) {
- cmdSetupBlack();
- } else if (cmd.equals("setup-white")) {
- cmdSetupWhite();
- }
- //
- // other
- //
- else if (cmd.equals("show_consider_set"))
- {
- Runnable cb = new Runnable()
- { public void run() { cbShowInferiorCells(); } };
- Runnable callback = new GuiRunnable(cb);
- sendCommand("vc-build " + m_tomove.toString() + "\n", callback);
- }
- else if (cmd.equals("solve_state"))
- {
- sendCommand("param_dfpn use_guifx 1\n", null);
- Runnable callback = new GuiRunnable(new Runnable()
- {
- public void run() { cbSolveState(); }
- });
- sendCommand("dfpn-solve-state " + m_tomove + "\n", callback);
- }
- else if (cmd.equals("program_options"))
- {
- AnalyzeCommand command;
- if (m_white_name.equalsIgnoreCase("Mohex") || m_white_name.equalsIgnoreCase("HexHex"))
- {
- command = new AnalyzeCommand
- (new AnalyzeDefinition("param/blah/param_mohex"));
- Runnable cb = new Runnable()
- { public void run() { cbEditParameters(); } };
- Runnable callback = new GuiRunnable(cb);
- m_curAnalyzeCommand = command;
- sendCommand(command.getCommand() + "\n", callback);
- }
- else if (m_white_name.equalsIgnoreCase("Wolve"))
- {
- command = new AnalyzeCommand
- (new AnalyzeDefinition("param/blah/param_wolve"));
- Runnable cb = new Runnable()
- { public void run() { cbEditParameters(); } };
- Runnable callback = new GuiRunnable(cb);
- m_curAnalyzeCommand = command;
- sendCommand(command.getCommand() + "\n", callback);
- }
- else
- ShowError.msg(this, "Unknown program!");
- }
- //
- // unknown command
- //
- else
- {
- System.out.println("Unknown command: '" + cmd + "'.");
- }
- }
-
- //------------------------------------------------------------
- /** Return true if keyboard shortcuts should be enabled. This
- * should be the case unless the user is currently typing in the
- * text area. */
- public boolean shortcutsEnabled()
- {
- return !m_comment.m_textPane.isFocusOwner();
- }
-
- //------------------------------------------------------------
- private void cmdShutdown()
- {
- if (gameChanged() && !askSaveGame())
- return;
-
- System.out.println("Shutting down...");
-
- if (m_white_process != null)
- {
- System.out.println("Stopping [" + m_white_name + " " +
- m_white_version + "] process...");
- m_white_process.destroy();
- }
- System.exit(0);
- }
+public final class HexGui extends JFrame
+ implements ActionListener,
+ GuiBoard.Listener,
+ HtpShell.Callback,
+ HtpController.GuiFxCallback,
+ AnalyzeDialog.Listener,
+ Comment.Listener {
+ public HexGui(final File file, final String command) {
+ super("HexGui");
+ setIcon();
- private void cmdNewProgram()
- {
- Program program = new Program();
- new EditProgramDialog(this, program, "Add New Program", true);
+ System.out.println("HexGui v" + Version.id + "; " + Version.date + "\n");
- if (program.m_name == null) // user canceled
- return;
+ // Catch the close action and shutdown nicely
+ setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ addWindowListener(
+ new java.awt.event.WindowAdapter() {
+ public void windowClosing(WindowEvent winEvt) {
+ cmdShutdown();
+ }
+ });
- // add the program to the list of programs
- m_programs.add(program);
- Program.save(m_programs);
- }
+ m_selected_cells = new Vector();
- private void cmdEditProgram()
- {
- if (m_programs.isEmpty())
- {
- ShowError.msg(this, "No programs, add a program first.");
- return;
- }
+ m_about = new AboutDialog(this);
- ChooseProgramDialog dialog
- = new ChooseProgramDialog(this, "Choose program to edit", m_programs);
- dialog.setVisible(true);
- Program program = dialog.getProgram();
- dialog.dispose();
+ m_preferences = new GuiPreferences(getClass());
- if (program == null)
- return;
+ m_menubar = new GuiMenuBar(this, m_preferences);
+ setJMenuBar(m_menubar.getJMenuBar());
- new EditProgramDialog(this, program, "Edit Program", false);
+ m_toolbar = new GuiToolBar(this, m_preferences);
+ getContentPane().add(m_toolbar.getJToolBar(), BorderLayout.NORTH);
- Program.save(m_programs);
- }
+ m_statusbar = new StatusBar();
+ getContentPane().add(m_statusbar, BorderLayout.SOUTH);
- private void cmdDeleteProgram()
- {
- if (m_programs.isEmpty())
- {
- ShowError.msg(this, "No programs, add a program first.");
- return;
- }
+ m_guiboard = new GuiBoard(this, m_preferences);
+ getContentPane().add(m_guiboard, BorderLayout.CENTER);
- ChooseProgramDialog dialog
- = new ChooseProgramDialog(this, "Choose program to delete",
- m_programs);
- dialog.setVisible(true);
- Program program = dialog.getProgram();
- dialog.dispose();
+ m_showAnalyzeText = new ShowAnalyzeText(this, m_guiboard);
- if (program == null)
- return;
+ JPanel panel = new JPanel(new BorderLayout());
+ getContentPane().add(panel, BorderLayout.EAST);
- if (!m_programs.remove(program))
- System.out.println("cmdDeleteProgram: program was not in list!");
+ m_blackClock = new Clock();
+ m_whiteClock = new Clock();
+ m_gameinfopanel = new GameInfoPanel(m_blackClock, m_whiteClock);
+ m_comment = new Comment(this);
+ panel.add(m_gameinfopanel, BorderLayout.NORTH);
+ panel.add(m_comment, BorderLayout.CENTER);
- Program.save(m_programs);
- }
+ cmdNewGame();
- private void cmdConnectLocalProgram()
- {
- ChooseProgramDialog dialog
- = new ChooseProgramDialog(this, "Choose program to connect",
- m_programs);
- dialog.setVisible(true);
- Program program = dialog.getProgram();
- dialog.dispose();
+ pack();
- if (program == null) // user aborted
- return;
+ m_locked = false;
- cmdConnectLocalProgram(program);
- }
+ m_semaphore = new Semaphore(1);
+ m_htp_queue = new ArrayBlockingQueue(256);
+ new Thread(new CommandHandler(this, m_htp_queue)).start();
+ setVisible(true);
+ // After frame is visible, further code using Swing functions must
+ // be run in the Swing event dispatch thread.
+ SwingUtilities.invokeLater(
+ new Runnable() {
+ public void run() {
+ initialize(file, command);
+ }
+ });
+ setCursorType();
+ }
- /** @note NOT CURRENTLY USED! */
- private void cmdConnectRemoteProgram()
- {
- int port = 20000;
- String hostname = "localhost";
+ // -------------------------------------------------------------------
- String remote = m_preferences.get("remote-host-name");
- String name = RemoteProgramDialog.show(this, remote);
- if (name == null) // user aborted
- return;
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
- hostname = name;
- System.out.print("Connecting to HTP program at [" + hostname +
- "] on port " + port + "...");
- System.out.flush();
+ unFocus();
- try
- {
- m_white_socket = new Socket(hostname, port);
- }
- catch (UnknownHostException e)
- {
- ShowError.msg(this, "Unknown host: '" + e.getMessage() + "'");
- System.out.println("\nconnection attempt aborted.");
- return;
- }
- catch (IOException e)
- {
- ShowError.msg(this, "Error creating socket: '"
- + e.getMessage() + "'");
- System.out.println("\nconnection attempt aborted.");
- return;
- }
- System.out.println("connected.");
-
- InputStream in;
- OutputStream out;
- try
- {
- in = m_white_socket.getInputStream();
- out = m_white_socket.getOutputStream();
- }
- catch (IOException e)
- {
- ShowError.msg(this, "Error obtaining socket stream: "
- + e.getMessage());
- m_white = null;
- return;
- }
- m_preferences.put("remote-host-name", hostname);
- connectProgram(in, out);
+ //
+ // system commands
+ //
+ if (cmd.equals("shutdown")) {
+ cmdShutdown();
+ } else if (cmd.equals("new-program")) {
+ cmdNewProgram();
+ } else if (cmd.equals("edit-program")) {
+ cmdEditProgram();
+ } else if (cmd.equals("delete-program")) {
+ cmdDeleteProgram();
+ } else if (cmd.equals("connect-program")) {
+ cmdConnectRemoteProgram();
+ } else if (cmd.equals("connect-local-program")) {
+ cmdConnectLocalProgram();
+ } else if (cmd.equals("disconnect-program")) {
+ cmdDisconnectProgram();
+ } else if (cmd.equals("reconnect-program")) {
+ cmdReconnectProgram();
+ //
+ // file/help commands
+ //
+ } else if (cmd.equals("newgame")) {
+ end_setup();
+ cmdNewGame();
+ } else if (cmd.equals("savegame")) {
+ // We previously only saved when gameChanged() == true,
+ // but this is dangerous because saving would fail
+ // silently otherwise. It's better to simply save the game
+ // when the user asks for it. An alternative use for
+ // gameChanged() would be to disable the save button when
+ // we think the game hasn't changed. But we shouldn't just
+ // offer a button and then do nothing.
+ cmdSaveGame();
+ } else if (cmd.equals("savegameas")) {
+ cmdSaveGameAs();
+ } else if (cmd.equals("loadgame")) {
+ cmdLoadGame();
+ } else if (cmd.equals("save-position-as")) {
+ cmdSavePositionAs();
+ } else if (cmd.equals("print-preview")) {
+ cmdPrintPreview();
+ } else if (cmd.equals("print")) {
+ cmdPrint();
+ } else if (cmd.equals("about")) {
+ cmdAbout();
+ //
+ // gui commands
+ //
+ } else if (cmd.equals("gui_toolbar_visible")) {
+ cmdGuiToolbarVisible();
+ } else if (cmd.equals("gui_shell_visible")) {
+ cmdGuiShellVisible();
+ } else if (cmd.equals("gui_analyze_visible")) {
+ cmdGuiAnalyzeVisible();
+ } else if (cmd.equals("gui_board_draw_type")) {
+ cmdGuiBoardDrawType();
+ } else if (cmd.equals("gui_board_orientation")) {
+ cmdGuiBoardOrientation();
+ } else if (cmd.equals("show-preferences")) {
+ cmdShowPreferences();
+ } else if (cmd.equals("gui-clear-marks")) {
+ cmdClearMarks();
+ //
+ // game navigation commands
+ //
+ } else if (cmd.equals("game_beginning")) {
+ end_setup();
+ backward(-1);
+ } else if (cmd.equals("game_backward10")) {
+ end_setup();
+ backward(10);
+ } else if (cmd.equals("game_back")) {
+ end_setup();
+ backward(1);
+ } else if (cmd.equals("game_forward")) {
+ end_setup();
+ forward(1);
+ } else if (cmd.equals("game_forward10")) {
+ end_setup();
+ forward(10);
+ } else if (cmd.equals("game_end")) {
+ end_setup();
+ forward(-1);
+ } else if (cmd.equals("game_up")) {
+ end_setup();
+ up();
+ } else if (cmd.equals("game_down")) {
+ end_setup();
+ down();
+ } else if (cmd.equals("game_swap_sides")) {
+ end_setup();
+ humanMove(new Move(HexPoint.get("swap-sides"), m_tomove));
+ } else if (cmd.equals("game_swap_pieces")) {
+ end_setup();
+ humanMove(new Move(HexPoint.get("swap-pieces"), m_tomove));
+ } else if (cmd.equals("game_pass")) {
+ end_setup();
+ humanMove(new Move(HexPoint.get("pass"), m_tomove));
+ } else if (cmd.equals("game_resign")) {
+ end_setup();
+ humanMove(new Move(HexPoint.get("resign"), m_tomove));
+ } else if (cmd.equals("game_forfeit")) {
+ end_setup();
+ humanMove(new Move(HexPoint.get("forfeit"), m_tomove));
+ } else if (cmd.equals("game_addsetup")) {
+ end_setup();
+ addSetupNode();
+ } else if (cmd.equals("genmove")) {
+ end_setup();
+ htpGenMove(m_tomove);
+ } else if (cmd.equals("game_delete_branch")) {
+ end_setup();
+ cmdDeleteBranch();
+ } else if (cmd.equals("game_make_main_branch")) {
+ end_setup();
+ cmdMoveBranchTop();
+ } else if (cmd.equals("game_start_clock")) {
+ startClock();
+ } else if (cmd.equals("game_stop_clock")) {
+ stopClock();
+ } else if (cmd.equals("stop")) {
+ m_white.interrupt();
+ } else if (cmd.equals("toggle_tomove")) {
+ end_setup();
+ cmdToggleToMove();
+ } else if (cmd.equals("set_to_move")) {
+ end_setup();
+ cmdSetToMove();
+ } else if (cmd.equals("setup-black")) {
+ cmdSetupBlack();
+ } else if (cmd.equals("setup-white")) {
+ cmdSetupWhite();
}
-
- //------------------------------------------------------------
-
- private void cmdConnectLocalProgram(Program program)
- {
- Runtime runtime = Runtime.getRuntime();
-
- String cmd = program.m_command;
- System.out.println("Executing '" + program.m_name + "':");
- System.out.println("Command = '" + cmd + "'");
- System.out.println("Working directory = '" + program.m_working + "'");
-
- File working = null;
- if (!program.m_working.trim().equals(""))
- {
- ShowError.msg(this,
- "Working directory not implemented! " +
- "Running with no working directory.");
-
-// working = new File(program.m_working);
-// if (!working.isDirectory())
-// {
-// ShowError.msg(this, "Invalid working directory: '"
-// + working.getName() + "'");
-// }
- }
-
- try
- {
- // Create command array with StringUtil::splitArguments
- // because Runtime.exec(String) uses a default StringTokenizer
- // which does not respect ".
- String[] cmdArray = StringUtils.splitArguments(cmd);
- // Make file name absolute, if working directory is not current
- // directory. With Java 1.5, it seems that Runtime.exec succeeds
- // if the relative path is valid from the current, but not from
- // the given working directory, but the process is not usable
- // (reading from its input stream immediately returns
- // end-of-stream)
- if (cmdArray.length > 0)
- {
- File file = new File(cmdArray[0]);
- // Only replace if executable is a path to a file, not
- // an executable in the exec-path
- if (file.exists())
- cmdArray[0] = file.getAbsolutePath();
+ //
+ // other
+ //
+ else if (cmd.equals("show_consider_set")) {
+ Runnable cb =
+ new Runnable() {
+ public void run() {
+ cbShowInferiorCells();
}
-
- m_white_process = runtime.exec(cmdArray);
- //m_white_process = runtime.exec(cmdArray, null, workingDirectory);
- //m_white_process = runtime.exec(cmd);
- }
- catch (Throwable e)
- {
- ShowError.msg(this, "Error starting " + program.m_name + ": '"
- + e.getMessage() + "'");
- return;
- }
-
- m_program = program;
- m_preferences.put("is-program-attached", true);
- m_preferences.put("attached-program", program.m_name);
-
- Process proc = m_white_process;
-
- ///////////////////////////////
- /// FIXME: DEBUGING!!! REMOVE!
- Thread blah = new Thread(new StreamCopy(false, proc.getErrorStream(),
- System.out, false));
- blah.start();
- ///////////////////////////////
-
- connectProgram(proc.getInputStream(), proc.getOutputStream());
- }
-
- private void createAnalyzeDialog()
- {
- m_analyzeDialog = new AnalyzeDialog(this, this, m_analyzeCommands,
- m_messageDialogs);
- m_analyzeDialog.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- m_analyzeDialog.setVisible(false);
- m_menubar.setAnalyzeVisible(false);
+ };
+ Runnable callback = new GuiRunnable(cb);
+ sendCommand("vc-build " + m_tomove.toString() + "\n", callback);
+ } else if (cmd.equals("solve_state")) {
+ sendCommand("param_dfpn use_guifx 1\n", null);
+ Runnable callback =
+ new GuiRunnable(
+ new Runnable() {
+ public void run() {
+ cbSolveState();
}
- });
- m_analyzeDialog.setBoardSize(m_guiboard.getBoardSize().width);
- m_analyzeDialog.setSelectedColor(m_tomove);
+ });
+ sendCommand("dfpn-solve-state " + m_tomove + "\n", callback);
+ } else if (cmd.equals("program_options")) {
+ AnalyzeCommand command;
+ if (m_white_name.equalsIgnoreCase("Mohex") || m_white_name.equalsIgnoreCase("HexHex")) {
+ command = new AnalyzeCommand(new AnalyzeDefinition("param/blah/param_mohex"));
+ Runnable cb =
+ new Runnable() {
+ public void run() {
+ cbEditParameters();
+ }
+ };
+ Runnable callback = new GuiRunnable(cb);
+ m_curAnalyzeCommand = command;
+ sendCommand(command.getCommand() + "\n", callback);
+ } else if (m_white_name.equalsIgnoreCase("Wolve")) {
+ command = new AnalyzeCommand(new AnalyzeDefinition("param/blah/param_wolve"));
+ Runnable cb =
+ new Runnable() {
+ public void run() {
+ cbEditParameters();
+ }
+ };
+ Runnable callback = new GuiRunnable(cb);
+ m_curAnalyzeCommand = command;
+ sendCommand(command.getCommand() + "\n", callback);
+ } else ShowError.msg(this, "Unknown program!");
}
-
- public void actionDisposeAnalyzeDialog()
- {
- if (m_analyzeDialog != null)
- {
- m_analyzeDialog.dispose();
- m_analyzeDialog = null;
- m_menubar.setAnalyzeVisible(false);
- }
+ //
+ // unknown command
+ //
+ else {
+ System.out.println("Unknown command: '" + cmd + "'.");
}
+ }
- private void connectProgram(InputStream in, OutputStream out)
- {
- m_shell = new HtpShell(this, this);
- m_shell.addWindowListener(new WindowAdapter()
- {
- public void windowClosing(WindowEvent winEvt)
- {
- m_menubar.setShellVisible(false);
- }
- });
- m_white = new HtpController(in, out, m_shell, this);
-
- // get name and version information; block until
- // version is returned.
-
- acquireSemaphore();
- htpName();
- htpVersion(); // releases semaphore when finished.
- acquireSemaphore();
- releaseSemaphore();
+ // ------------------------------------------------------------
+ /**
+ * Return true if keyboard shortcuts should be enabled. This should be the case unless the user is
+ * currently typing in the text area.
+ */
+ public boolean shortcutsEnabled() {
+ return !m_comment.m_textPane.isFocusOwner();
+ }
- m_shell.setTitle("HexGui: [" + m_white_name + " "
- + m_white_version + "] Shell");
+ // ------------------------------------------------------------
+ private void cmdShutdown() {
+ if (gameChanged() && !askSaveGame()) return;
- // get list of accepted commands; block until
- // this is completed.
- acquireSemaphore();
- htpAnalyzeCommands(); // releases semaphore when finished
- acquireSemaphore();
- releaseSemaphore();
+ System.out.println("Shutting down...");
- createAnalyzeDialog();
+ if (m_white_process != null) {
+ System.out.println("Stopping [" + m_white_name + " " + m_white_version + "] process...");
+ m_white_process.destroy();
+ }
+ System.exit(0);
+ }
+
+ private void cmdNewProgram() {
+ Program program = new Program();
+ new EditProgramDialog(this, program, "Add New Program", true);
+
+ if (program.m_name == null) // user canceled
+ return;
+
+ // add the program to the list of programs
+ m_programs.add(program);
+ Program.save(m_programs);
+ }
- m_toolbar.setProgramConnected(true);
- m_menubar.setProgramConnected(true);
-
- m_shell.setVisible(m_preferences.getBoolean("shell-show-on-connect"));
- m_analyzeDialog.setVisible(m_preferences.getBoolean("analyze-show-on-connect"));
-
- htpBoardsize(m_guiboard.getBoardSize());
+ private void cmdEditProgram() {
+ if (m_programs.isEmpty()) {
+ ShowError.msg(this, "No programs, add a program first.");
+ return;
+ }
+
+ ChooseProgramDialog dialog =
+ new ChooseProgramDialog(this, "Choose program to edit", m_programs);
+ dialog.setVisible(true);
+ Program program = dialog.getProgram();
+ dialog.dispose();
+
+ if (program == null) return;
+
+ new EditProgramDialog(this, program, "Edit Program", false);
+
+ Program.save(m_programs);
+ }
+
+ private void cmdDeleteProgram() {
+ if (m_programs.isEmpty()) {
+ ShowError.msg(this, "No programs, add a program first.");
+ return;
+ }
+
+ ChooseProgramDialog dialog =
+ new ChooseProgramDialog(this, "Choose program to delete", m_programs);
+ dialog.setVisible(true);
+ Program program = dialog.getProgram();
+ dialog.dispose();
+
+ if (program == null) return;
+
+ if (!m_programs.remove(program))
+ System.out.println("cmdDeleteProgram: program was not in list!");
+
+ Program.save(m_programs);
+ }
+
+ private void cmdConnectLocalProgram() {
+ ChooseProgramDialog dialog =
+ new ChooseProgramDialog(this, "Choose program to connect", m_programs);
+ dialog.setVisible(true);
+ Program program = dialog.getProgram();
+ dialog.dispose();
+
+ if (program == null) // user aborted
+ return;
+
+ cmdConnectLocalProgram(program);
+ }
+
+ /**
+ * @note NOT CURRENTLY USED!
+ */
+ private void cmdConnectRemoteProgram() {
+ int port = 20000;
+ String hostname = "localhost";
+
+ String remote = m_preferences.get("remote-host-name");
+ String name = RemoteProgramDialog.show(this, remote);
+ if (name == null) // user aborted
+ return;
+
+ hostname = name;
+ System.out.print("Connecting to HTP program at [" + hostname + "] on port " + port + "...");
+ System.out.flush();
+
+ try {
+ m_white_socket = new Socket(hostname, port);
+ } catch (UnknownHostException e) {
+ ShowError.msg(this, "Unknown host: '" + e.getMessage() + "'");
+ System.out.println("\nconnection attempt aborted.");
+ return;
+ } catch (IOException e) {
+ ShowError.msg(this, "Error creating socket: '" + e.getMessage() + "'");
+ System.out.println("\nconnection attempt aborted.");
+ return;
+ }
+ System.out.println("connected.");
+
+ InputStream in;
+ OutputStream out;
+ try {
+ in = m_white_socket.getInputStream();
+ out = m_white_socket.getOutputStream();
+ } catch (IOException e) {
+ ShowError.msg(this, "Error obtaining socket stream: " + e.getMessage());
+ m_white = null;
+ return;
+ }
+ m_preferences.put("remote-host-name", hostname);
+ connectProgram(in, out);
+ }
+
+ // ------------------------------------------------------------
+
+ private void cmdConnectLocalProgram(Program program) {
+ Runtime runtime = Runtime.getRuntime();
+
+ String cmd = program.m_command;
+ System.out.println("Executing '" + program.m_name + "':");
+ System.out.println("Command = '" + cmd + "'");
+ System.out.println("Working directory = '" + program.m_working + "'");
+
+ File working = null;
+ if (!program.m_working.trim().equals("")) {
+ ShowError.msg(
+ this, "Working directory not implemented! " + "Running with no working directory.");
+
+ // working = new File(program.m_working);
+ // if (!working.isDirectory())
+ // {
+ // ShowError.msg(this, "Invalid working directory: '"
+ // + working.getName() + "'");
+ // }
+ }
+
+ try {
+ // Create command array with StringUtil::splitArguments
+ // because Runtime.exec(String) uses a default StringTokenizer
+ // which does not respect ".
+ String[] cmdArray = StringUtils.splitArguments(cmd);
+ // Make file name absolute, if working directory is not current
+ // directory. With Java 1.5, it seems that Runtime.exec succeeds
+ // if the relative path is valid from the current, but not from
+ // the given working directory, but the process is not usable
+ // (reading from its input stream immediately returns
+ // end-of-stream)
+ if (cmdArray.length > 0) {
+ File file = new File(cmdArray[0]);
+ // Only replace if executable is a path to a file, not
+ // an executable in the exec-path
+ if (file.exists()) cmdArray[0] = file.getAbsolutePath();
+ }
+
+ m_white_process = runtime.exec(cmdArray);
+ // m_white_process = runtime.exec(cmdArray, null, workingDirectory);
+ // m_white_process = runtime.exec(cmd);
+ } catch (Throwable e) {
+ ShowError.msg(this, "Error starting " + program.m_name + ": '" + e.getMessage() + "'");
+ return;
+ }
+
+ m_program = program;
+ m_preferences.put("is-program-attached", true);
+ m_preferences.put("attached-program", program.m_name);
+
+ Process proc = m_white_process;
+
+ ///////////////////////////////
+ /// FIXME: DEBUGING!!! REMOVE!
+ Thread blah = new Thread(new StreamCopy(false, proc.getErrorStream(), System.out, false));
+ blah.start();
+ ///////////////////////////////
+
+ connectProgram(proc.getInputStream(), proc.getOutputStream());
+ }
+
+ private void createAnalyzeDialog() {
+ m_analyzeDialog = new AnalyzeDialog(this, this, m_analyzeCommands, m_messageDialogs);
+ m_analyzeDialog.addWindowListener(
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ m_analyzeDialog.setVisible(false);
+ m_menubar.setAnalyzeVisible(false);
+ }
+ });
+ m_analyzeDialog.setBoardSize(m_guiboard.getBoardSize().width);
+ m_analyzeDialog.setSelectedColor(m_tomove);
+ }
+
+ public void actionDisposeAnalyzeDialog() {
+ if (m_analyzeDialog != null) {
+ m_analyzeDialog.dispose();
+ m_analyzeDialog = null;
+ m_menubar.setAnalyzeVisible(false);
+ }
+ }
+
+ private void connectProgram(InputStream in, OutputStream out) {
+ m_shell = new HtpShell(this, this);
+ m_shell.addWindowListener(
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent winEvt) {
+ m_menubar.setShellVisible(false);
+ }
+ });
+ m_white = new HtpController(in, out, m_shell, this);
+
+ // get name and version information; block until
+ // version is returned.
+
+ acquireSemaphore();
+ htpName();
+ htpVersion(); // releases semaphore when finished.
+ acquireSemaphore();
+ releaseSemaphore();
+
+ m_shell.setTitle("HexGui: [" + m_white_name + " " + m_white_version + "] Shell");
+
+ // get list of accepted commands; block until
+ // this is completed.
+ acquireSemaphore();
+ htpAnalyzeCommands(); // releases semaphore when finished
+ acquireSemaphore();
+ releaseSemaphore();
+
+ createAnalyzeDialog();
+
+ m_toolbar.setProgramConnected(true);
+ m_menubar.setProgramConnected(true);
+
+ m_shell.setVisible(m_preferences.getBoolean("shell-show-on-connect"));
+ m_analyzeDialog.setVisible(m_preferences.getBoolean("analyze-show-on-connect"));
+
+ htpBoardsize(m_guiboard.getBoardSize());
+
+ // Replay all moves up to the current node.
+ replayUpToNode(m_current);
+ htpShowboard();
+ }
+
+ // Replay all moves up to the given node. Do this without changing
+ // the current node.
+ private void replayUpToNode(Node node) {
+ Vector path = new Vector();
+ while (node != null) {
+ path.add(node);
+ node = node.getParent();
+ }
+ m_guiboard.clearAll();
+ htpClearBoard();
+ for (int i = path.size() - 1; i >= 0; i--) {
+ node = path.elementAt(i);
+ if (node.hasMove()) {
+ Move move = node.getMove();
+ guiPlay(move);
+ htpPlay(move);
+ }
+ if (node.hasSetup()) {
+ playSetup(node);
+ }
+ }
+ }
+
+ /**
+ * Run HTP commands to set up the current board position from scratch. This may be necessary when
+ * a setup move removes a piece, or changes the color of an existing piece, or when swap-pieces is
+ * played, since there is no valid HTP command to do so.
+ */
+ private void htpSetUpCurrentBoard() {
+ htpClearBoard();
+ Dimension size = m_guiboard.getBoardSize();
+ for (int y = 0; y < size.height; y++) {
+ for (int x = 0; x < size.width; x++) {
+ HexPoint point = HexPoint.get(x, y);
+ HexColor c = m_guiboard.getColor(point);
+ if (c == HexColor.BLACK || c == HexColor.WHITE) {
+ htpPlay(new Move(point, c));
+ }
+ }
+ }
+ }
+
+ private void cmdDisconnectProgram() {
+ if (m_white == null) return;
+
+ htpQuit();
+ try {
+ if (m_white_process != null) {
+ m_white_process.waitFor();
+ m_white_process = null;
+ }
+ if (m_white_socket != null) {
+ m_white_socket.close();
+ m_white_socket = null;
+ }
+ m_white = null;
+ m_shell.dispose();
+ m_shell = null;
+ actionDisposeAnalyzeDialog();
+ m_program = null;
+ m_menubar.setProgramConnected(false);
+ m_toolbar.setProgramConnected(false);
+ m_preferences.put("is-program-attached", false);
+ } catch (Throwable e) {
+ ShowError.msg(this, "Error: " + e.getMessage());
+ }
+ }
+
+ private void cmdReconnectProgram() {
+ Program prog = m_program;
+ cmdDisconnectProgram();
+ cmdConnectLocalProgram(prog);
+ }
+
+ // ------------------------------------------------------------
+
+ private void cmdNewGame() {
+ if (gameChanged() && !askSaveGame()) return;
+
+ String size = m_menubar.getSelectedBoardSize();
+ Dimension dim = new Dimension(-1, -1);
+ if (size.equals("Other...")) {
+ size = BoardSizeDialog.show(this, m_guiboard.getBoardSize());
+ if (size == null) return;
+ }
+
+ try {
+ StringTokenizer st = new StringTokenizer(size);
+ int w = Integer.parseInt(st.nextToken());
+ st.nextToken();
+ int h = Integer.parseInt(st.nextToken());
+ dim.setSize(w, h);
+ } catch (Throwable t) {
+ ShowError.msg(this, "Size should be in format 'w x h'.");
+ return;
+ }
+
+ if (dim.width < 1 || dim.height < 1) {
+ ShowError.msg(this, "Invalid board size.");
+ } else {
+ m_tomove = HexColor.BLACK;
+ m_toolbar.setToMove(m_tomove.toString());
+
+ m_root = new Node();
+ m_current = m_root;
+ m_gameinfo = new GameInfo();
+ m_gameinfo.setBoardSize(dim);
+ stopClock(HexColor.BLACK);
+ stopClock(HexColor.WHITE);
+ m_blackClock.setElapsed(0);
+ m_whiteClock.setElapsed(0);
+ setComment(m_current);
+
+ m_file = null;
+ resetGameChanged();
+ setFrameTitle();
+
+ m_guiboard.initSize(dim.width, dim.height);
+ m_guiboard.repaint();
+
+ m_preferences.put("gui-board-width", dim.width);
+ m_preferences.put("gui-board-height", dim.height);
+
+ m_toolbar.updateButtonStates(m_current, this);
+ m_menubar.updateMenuStates(this);
+
+ htpBoardsize(m_guiboard.getBoardSize());
+ htpShowboard();
+
+ setCursorType();
+ }
+ }
+
+ private boolean cmdSaveGame() {
+ if (m_file == null) m_file = showSaveAsDialog();
+
+ if (m_file != null) {
+ System.out.println("Saving to file: " + m_file.getName());
+ if (save(m_file)) {
+ resetGameChanged();
+ setFrameTitle();
+ m_preferences.put("path-save-game", m_file.getPath());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean cmdSaveGameAs() {
+ File file = showSaveAsDialog();
+ if (file == null) return false;
+
+ m_file = file;
+ return cmdSaveGame();
+ }
+
+ private void cmdSavePositionAs() {
+ File file = showSaveAsDialog();
+ if (file != null) savePosition(file);
+ }
+
+ private void cmdLoadGame() {
+ if (gameChanged() && !askSaveGame()) return;
+ File file = showOpenDialog();
+ if (file != null) loadGame(file);
+ }
+
+ private void cmdPrintPreview() {
+ JFrame frame = new JFrame();
+ // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ Container con = frame.getContentPane();
+
+ PrintPreview pp = new PrintPreview(m_guiboard);
+ con.add(pp, BorderLayout.CENTER);
+
+ frame.pack();
+ frame.setVisible(true);
+ frame.toFront();
+ }
+
+ private void cmdPrint() {
+ Print.run(this, m_guiboard);
+ }
+
+ private void cmdAbout() {
+ m_about.setVisible(true);
+ }
+
+ // ------------------------------------------------------------
+
+ private void cmdGuiToolbarVisible() {
+ boolean visible = m_menubar.getToolbarVisible();
+ m_toolbar.setVisible(visible);
+ }
+
+ private void cmdGuiShellVisible() {
+ if (m_shell == null) return;
+ boolean visible = m_menubar.getShellVisible();
+ m_shell.setVisible(visible);
+ }
+
+ private void cmdGuiAnalyzeVisible() {
+ if (m_analyzeDialog == null) return;
+ boolean visible = m_menubar.getAnalyzeVisible();
+ m_analyzeDialog.setVisible(visible);
+ }
+
+ private void cmdGuiBoardDrawType() {
+ String type = m_menubar.getCurrentBoardDrawType();
+ System.out.println(type);
+ m_guiboard.setDrawType(type);
+ m_guiboard.repaint();
+ }
+
+ private void cmdGuiBoardOrientation() {
+ String type = m_menubar.getCurrentBoardOrientation();
+ System.out.println(type);
+ m_guiboard.setOrientation(type);
+ m_guiboard.repaint();
+ }
+
+ private void cmdClearMarks() {
+ m_guiboard.clearMarks();
+ m_guiboard.repaint();
+ }
+
+ private void cmdShowPreferences() {
+ new PreferencesDialog(this, m_preferences);
+ }
+
+ /**
+ * Toggle the player to move, by explicit user request. This also updates the PL property in the
+ * current node.
+ */
+ private void cmdToggleToMove() {
+ this.toggleToMove();
+ m_current.setPlayerToMove(m_tomove);
+ }
+
+ /** Toggle the player to move, without setting the PL property */
+ private void toggleToMove() {
+ m_tomove = m_tomove.otherColor();
+ m_toolbar.setToMove(m_tomove.toString());
+ m_menubar.setToMove(m_tomove.toString());
+ setCursorType();
+ }
+
+ /**
+ * Set the player to move, by explicit user request. This also updates the PL property in the
+ * current node.
+ */
+ private void cmdSetToMove() {
+ this.setToMove();
+ m_current.setPlayerToMove(m_tomove);
+ }
+
+ /** Set the player to move, without setting the PL property */
+ private void setToMove() {
+ m_tomove = HexColor.get(m_menubar.getToMove());
+ m_toolbar.setToMove(m_tomove.toString());
+ setCursorType();
+ }
+
+ private void cmdSetupBlack() {
+ setCursorType();
+ }
+
+ private void cmdSetupWhite() {
+ setCursorType();
+ }
+
+ // Update the cursor according to the current move type.
+ public void setCursorType() {
+ String clickContext = m_toolbar.getClickContext();
+ if (clickContext == "black") {
+ m_guiboard.setCursorType("black-setup");
+ } else if (clickContext == "white") {
+ m_guiboard.setCursorType("white-setup");
+ } else {
+ if (m_tomove == HexColor.BLACK) {
+ m_guiboard.setCursorType("black");
+ } else {
+ m_guiboard.setCursorType("white");
+ }
+ }
+ }
+
+ // ------------------------------------------------------------
+
+ public void actionClearAnalyzeCommand() {}
+
+ public void actionSetAnalyzeCommand(AnalyzeCommand command) {
+ actionSetAnalyzeCommand(command, false, true, true, false);
+ }
+
+ public void actionSetAnalyzeCommand(
+ AnalyzeCommand command,
+ boolean autoRun,
+ boolean clearBoard,
+ boolean oneRunOnly,
+ boolean reuseTextWindow) {
+ AnalyzeType type = command.getType();
+ if (command.needsPointArg()) {
+ Vector selected = getSelectedCells();
+ if (selected.size() < 1) {
+ m_statusbar.setMessage("Please select a cell before " + "running.");
+ return;
+ }
+ command.setPointArg(selected.get(0));
+ }
+ if (command.needsPointListArg()) {
+ Vector selected = getSelectedCells();
+ if (type == AnalyzeType.VC && selected.size() != 2) {
+ m_statusbar.setMessage("Please select a pair of cells before " + "running.");
+ return;
+ }
+ PointList blah = new PointList(selected);
+ command.setPointListArg(blah);
+ }
+ String cmd = command.replaceWildCards(m_tomove);
+ String cleaned = StringUtils.cleanWhiteSpace(cmd.trim());
+ String args[] = cleaned.split(" ");
+ String c = args[0];
+ m_curAnalyzeCommand = command;
+
+ Runnable cb = null;
+ switch (type) {
+ case GROUP:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbGroupGet();
+ }
+ };
+ break;
+ case GFX:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbGfx();
+ }
+ };
+ break;
+ case INFERIOR:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbShowInferiorCells();
+ }
+ };
+ break;
+ case MOVE:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbGenMove();
+ }
+ };
+ break;
+ case PLIST:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbDisplayPointList();
+ }
+ };
+ break;
+ case PSPAIRS:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbDisplayPointText();
+ }
+ };
+ break;
+ case PARAM:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbEditParameters();
+ }
+ };
+ break;
+ case VC:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbVCs();
+ }
+ };
+ break;
+ case STRING:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbString();
+ }
+ };
+ break;
+ case VAR:
+ cb =
+ new Runnable() {
+ public void run() {
+ cbVar();
+ }
+ };
+ break;
+ }
+ // if (c.equals("dfpn-get-bounds"))
+ // cb = new Runnable() { public void run() { cbDfpnDisplayBounds();} };
+ // else if (c.equals("book-scores"))
+ // cb = new Runnable() { public void run() { cbDisplayBookScores(); } };
+ // else if (c.equals("eval-resist"))
+ // cb = new Runnable() { public void run() { cbEvalResist(); } };
+ Runnable callback = null;
+ if (cb != null) callback = new GuiRunnable(cb);
+ sendCommand(cmd + "\n", callback);
+ }
+
+ /**
+ * HtpShell Callback. By the name of the command it choose the proper callback function. Arguments
+ * are passed as given.
+ */
+ public void commandEntered(String cmd) {
+ sendCommand(cmd, null);
+ }
+
+ // ----------------------------------------------------------------------
+
+ private boolean commandNeedsToLockGUI(String cmd) {
+ if ((cmd.length() > 7 && cmd.substring(0, 7).equals("genmove"))
+ || (cmd.length() > 15 && cmd.substring(0, 15).equals("dfs-solve-state"))
+ || (cmd.length() > 16 && cmd.substring(0, 16).equals("dfpn-solve-state"))
+ || (cmd.length() > 23 && cmd.substring(0, 23).equals("dfs-solver-find-winning"))
+ || (cmd.length() > 24 && cmd.substring(0, 24).equals("dfpn-solver-find-winning")))
+ return true;
+ return false;
+ }
+
+ private void lockGUI() {
+ m_locked = true;
+ m_toolbar.lockToolbar();
+ }
+
+ private void unlockGUI() {
+ m_toolbar.unlockToolbar(m_current, this);
+ m_locked = false;
+ }
+
+ /** A (command, callback) pair. */
+ private class HtpCommand {
+ public HtpCommand() {}
+
+ public HtpCommand(String cmd, Runnable callback) {
+ this.str = cmd;
+ this.callback = callback;
+ }
+
+ public String str;
+ public Runnable callback;
+ }
+
+ /** Waits for commands to be added to the queue, then processes each in turn. */
+ private class CommandHandler implements Runnable {
+
+ public CommandHandler(Component parent, ArrayBlockingQueue queue) {
+ m_parent = parent;
+ m_queue = queue;
+ }
+
+ public void run() {
+ while (true) {
+ HtpCommand cmd = null;
+ try {
+ // block until queue contains an element
+ cmd = m_queue.take();
+ } catch (InterruptedException e) {
+ System.out.println("INTERRUPTED! HUH?");
+ }
- // Replay all moves up to the current node.
- replayUpToNode(m_current);
- htpShowboard();
- }
+ if (m_white != null && m_white.connected()) {
+ if (commandNeedsToLockGUI(cmd.str)) lockGUI();
- // Replay all moves up to the given node. Do this without changing
- // the current node.
- private void replayUpToNode(Node node)
- {
- Vector path = new Vector();
- while (node != null) {
- path.add(node);
- node = node.getParent();
- }
- m_guiboard.clearAll();
- htpClearBoard();
- for (int i = path.size()-1; i>=0; i--) {
- node = path.elementAt(i);
- if (node.hasMove()) {
- Move move = node.getMove();
- guiPlay(move);
- htpPlay(move);
- }
- if (node.hasSetup()) {
- playSetup(node);
+ try {
+ m_white.sendCommand(cmd.str);
+ if (cmd.callback != null) {
+ cmd.callback.run();
}
- }
- }
+ } catch (HtpError e) {
+ System.out.println("Caught error '" + e.getMessage() + "'");
+ ShowError.msg(m_parent, e.getMessage());
+ }
- /** Run HTP commands to set up the current board position from
- scratch. This may be necessary when a setup move removes a
- piece, or changes the color of an existing piece, or when
- swap-pieces is played, since there is no valid HTP command to
- do so. */
- private void htpSetUpCurrentBoard()
- {
- htpClearBoard();
- Dimension size = m_guiboard.getBoardSize();
- for (int y = 0; y < size.height; y++) {
- for (int x = 0; x < size.width; x++) {
- HexPoint point = HexPoint.get(x, y);
- HexColor c = m_guiboard.getColor(point);
- if (c == HexColor.BLACK || c == HexColor.WHITE) {
- htpPlay(new Move(point, c));
- }
- }
+ if (commandNeedsToLockGUI(cmd.str)) unlockGUI();
+ } else {
+ System.out.println("Not sending to disconnected: '" + cmd.str.trim() + "'");
+ }
+ }
+ }
+
+ Component m_parent;
+ ArrayBlockingQueue m_queue;
+ }
+
+ private void sendCommand(String cmd, Runnable callback) {
+ if (m_white == null) return;
+
+ try {
+ System.out.println("sendCommand: '" + cmd.trim() + "'");
+ m_htp_queue.put(new HtpCommand(cmd, callback));
+ } catch (InterruptedException e) {
+ System.out.println("Interrupted while adding!");
+ }
+ }
+
+ // FIXME: add callback?
+ private void htpQuit() {
+ sendCommand("quit\n", null);
+ }
+
+ private void htpName() {
+ Runnable cb =
+ new Runnable() {
+ public void run() {
+ cbName();
+ }
+ };
+ sendCommand("name\n", cb);
+ }
+
+ private void htpVersion() {
+ Runnable cb =
+ new Runnable() {
+ public void run() {
+ cbVersion();
+ }
+ };
+ sendCommand("version\n", cb);
+ }
+
+ private void htpAnalyzeCommands() {
+ Runnable cb =
+ new Runnable() {
+ public void run() {
+ cbAnalyzeCommands();
+ }
+ };
+ sendCommand("hexgui-analyze_commands\n", cb);
+ }
+
+ private void htpClearBoard() {
+ sendCommand("clear_board\n", null);
+ }
+
+ private void htpShowboard() {
+ sendCommand("showboard\n", null);
+ }
+
+ /**
+ * Play a move on the attached HTP backend. This only works if move is a legal move of color black
+ * or white. There is no HTP command for setup moves that remove a piece, or that change the color
+ * of an already existing piece, and swap, pass, resign, and forfeit moves are possibly not
+ * implemented in HTP, or may not be undoable correctly. If the move is swap-pieces, just update
+ * HTP to the current board position; so gui should always be updated before calling this.
+ */
+ private void htpPlay(Move move) {
+ if (move.getPoint() == HexPoint.RESIGN
+ || move.getPoint() == HexPoint.FORFEIT
+ || move.getPoint() == HexPoint.SWAP_SIDES
+ || move.getPoint() == HexPoint.PASS) {
+ return;
+ }
+ if (move.getPoint() == HexPoint.SWAP_PIECES) {
+ htpSetUpCurrentBoard();
+ return;
+ }
+ sendCommand(
+ "play " + move.getColor().toString() + " " + move.getPoint().toString() + "\n", null);
+ }
+
+ /** GUI must already be updated prior to calling this. */
+ private void htpUndo(Move move) {
+ if (move.getPoint() == HexPoint.RESIGN
+ || move.getPoint() == HexPoint.FORFEIT
+ || move.getPoint() == HexPoint.SWAP_SIDES
+ || move.getPoint() == HexPoint.PASS) {
+ return;
+ }
+ sendCommand("undo\n", null);
+ }
+
+ private void htpGenMove(HexColor color) {
+ if (!checkBoardSizeSupported()) return;
+ m_statusbar.setMessage(format("{0} is thinking...", m_white_name));
+ Runnable callback =
+ new GuiRunnable(
+ new Runnable() {
+ public void run() {
+ cbGenMove();
+ }
+ });
+ sendCommand("genmove " + color.toString() + "\n", callback);
+ }
+
+ private void htpBoardsize(Dimension size) {
+ Runnable callback =
+ new Runnable() {
+ public void run() {
+ m_unsupportedBoardSize = !m_white.wasSuccess();
+ checkBoardSizeSupported();
+ }
+ };
+ sendCommand("boardsize " + size.width + " " + size.height + "\n", callback);
+ m_statusbar.setMessage("New game");
+ }
+
+ //
+ // Callbacks
+ //
+ public void cbName() {
+ String str = m_white.getResponse();
+ // FIXME: handle errors!
+ m_white_name = str.trim();
+ }
+
+ public void cbVersion() {
+ String str = m_white.getResponse();
+ // FIXME: handle errors!
+ m_white_version = str.trim();
+ releaseSemaphore();
+ }
+
+ private void cbAnalyzeCommands() {
+ String programAnalyzeCommands = m_white.getResponse();
+ try {
+ m_analyzeCommands = AnalyzeDefinition.read(programAnalyzeCommands);
+ } catch (ErrorMessage e) {
+ ShowError.msg(this, "Could not parse analyze commands!");
+ }
+ releaseSemaphore();
+ }
+
+ public void cbGenMove() {
+ if (!m_white.wasSuccess()) return;
+ m_guiboard.clearMarks();
+ String str = m_white.getResponse();
+ HexPoint point = HexPoint.get(str.trim());
+ if (point == null) {
+ System.out.println("Invalid move!!");
+ } else {
+ play(new Move(point, m_tomove));
+ }
+ }
+
+ public void cbDisplayPointList() {
+ if (!m_white.wasSuccess()) return;
+ String str = m_white.getResponse();
+ Vector points = StringUtils.parsePointList(str);
+ m_guiboard.clearMarks();
+ for (int i = 0; i < points.size(); i++) {
+ m_guiboard.setAlphaColor(points.get(i), Color.green);
+ }
+ m_guiboard.repaint();
+ }
+
+ private void cbDfpnDisplayBounds() {
+ if (!m_white.wasSuccess()) return;
+ String str = m_white.getResponse();
+ showDfpnBounds(str);
+ m_guiboard.repaint();
+ }
+
+ public void cbGroupGet() {
+ if (!m_white.wasSuccess()) return;
+ String str = m_white.getResponse();
+ Vector points = StringUtils.parsePointList(str);
+ m_guiboard.clearMarks();
+ if (points.size() > 0) {
+ m_guiboard.setAlphaColor(points.get(0), Color.blue);
+ for (int i = 1; i < points.size(); i++) {
+ m_guiboard.setAlphaColor(points.get(i), Color.green);
+ }
+ }
+ m_guiboard.repaint();
+ }
+
+ public void cbGfx() {
+ if (!m_white.wasSuccess()) return;
+ m_guiboard.clearMarks();
+ m_guiboard.aboutToDirtyStones();
+
+ String fx = m_white.getResponse();
+ int inf = fx.indexOf("INFLUENCE");
+ if (inf < 0) return;
+ boolean hasText = false;
+ int text = fx.indexOf("TEXT");
+ if (text < 0) text = fx.length();
+ else {
+ hasText = true;
+ }
+
+ Vector> pairs =
+ StringUtils.parseStringPairList(fx.substring(inf + 10, text));
+ for (int i = 0; i < pairs.size(); i++) {
+ HexPoint point = HexPoint.get(pairs.get(i).first);
+ String value = pairs.get(i).second;
+ float v = new Float(value).floatValue();
+ m_guiboard.setAlphaColor(point, new Color(0, v, 1 - v), 0.7f);
+ }
+ if (hasText) m_statusbar.setMessage(fx.substring(text + 5));
+ m_guiboard.repaint();
+ }
+
+ public void cbShowInferiorCells() {
+ if (!m_white.wasSuccess()) return;
+ m_guiboard.clearMarks();
+ m_guiboard.aboutToDirtyStones();
+ showInferiorCells(m_white.getResponse());
+ m_guiboard.repaint();
+ }
+
+ public void cbVCs() {
+ if (!m_white.wasSuccess()) return;
+ String str = m_white.getResponse();
+ Vector vcs = StringUtils.parseVCList(str);
+ new VCDisplayDialog(this, m_guiboard, vcs);
+ }
+
+ public void cbString() {
+ if (!m_white.wasSuccess()) return;
+ String showText = m_white.getResponse();
+ String title = m_curAnalyzeCommand.getResultTitle();
+ if (showText != null) {
+ if (showText.indexOf("\n") < 0) {
+ if (showText.trim().equals("")) showText = "(empty response)";
+ m_statusbar.setMessage(format("{0}: {1}", title, showText));
+ } else {
+ HexPoint pointArg = null;
+ m_showAnalyzeText.show(m_curAnalyzeCommand.getType(), pointArg, title, showText, false);
+ }
+ }
+ }
+
+ public void cbVar() {
+ if (!m_white.wasSuccess()) return;
+ String str = m_white.getResponse();
+ Vector points = StringUtils.parsePointList(str, " ");
+ m_guiboard.clearMarks();
+ m_guiboard.aboutToDirtyStones();
+ HexColor color = m_tomove;
+ for (int i = 0; i < points.size(); i++) {
+ m_guiboard.setColor(points.get(i), color);
+ m_guiboard.setText(points.get(i), Integer.toString(i + 1));
+ color = color.otherColor();
+ }
+ m_guiboard.repaint();
+ }
+
+ public void cbDisplayPointText() {
+ if (!m_white.wasSuccess()) return;
+ String str = m_white.getResponse();
+ Vector> pairs = StringUtils.parseStringPairList(str);
+ m_guiboard.clearMarks();
+ for (int i = 0; i < pairs.size(); i++) {
+ HexPoint point = HexPoint.get(pairs.get(i).first);
+ String value = pairs.get(i).second;
+ m_guiboard.setText(point, value);
+ }
+ m_guiboard.repaint();
+ }
+
+ public void cbDisplayBookScores() {
+ if (!m_white.wasSuccess()) return;
+ String str = m_white.getResponse();
+ Vector> pairs = StringUtils.parseStringPairList(str);
+ m_guiboard.clearMarks();
+ for (int i = 0; i < pairs.size(); i++) {
+ HexPoint point = HexPoint.get(pairs.get(i).first);
+ String value = pairs.get(i).second;
+ m_guiboard.setText(point, value);
+ if (i == 0) m_guiboard.setAlphaColor(point, Color.red);
+ else if (1 <= i && i <= 3) m_guiboard.setAlphaColor(point, Color.green);
+ }
+ m_guiboard.repaint();
+ }
+
+ public void cbEvalResist() {
+ if (!m_white.wasSuccess()) return;
+ String str = m_white.getResponse();
+ Vector> pairs = StringUtils.parseStringPairList(str);
+ String res = "";
+ String rew = "";
+ String reb = "";
+ m_guiboard.clearMarks();
+ for (int i = 0; i < pairs.size(); i++) {
+ if (pairs.get(i).first.equals("res")) {
+ res = pairs.get(i).second;
+ } else if (pairs.get(i).first.equals("rew")) {
+ rew = pairs.get(i).second;
+ } else if (pairs.get(i).first.equals("reb")) {
+ reb = pairs.get(i).second;
+ } else {
+ HexPoint point = HexPoint.get(pairs.get(i).first);
+
+ String value = pairs.get(i).second;
+ m_guiboard.setText(point, value);
+ }
+ }
+ m_guiboard.repaint();
+ m_statusbar.setMessage("Resistance: " + res + " (" + rew + " - " + reb + ")");
+ }
+
+ public void cbEditParameters() {
+ if (!m_white.wasSuccess()) return;
+ String response = m_white.getResponse();
+ ParameterDialog.editParameters(
+ m_curAnalyzeCommand.getCommand(),
+ this,
+ "Edit Parameters",
+ response,
+ m_white,
+ m_messageDialogs);
+ }
+
+ public void cbSolveState() {
+ if (!m_white.wasSuccess()) return;
+ String response = m_white.getResponse();
+ m_statusbar.setMessage(format("Winning: {0}", response));
+ }
+
+ // ==================================================
+ // gfx commands
+ // ==================================================
+ public void guifx(String fx) {
+ System.out.println("gogui-gfx:\n'" + fx + "'");
+
+ if (fx.length() > 3 && fx.substring(0, 3).equals("uct")) guifx_uct(fx.substring(3));
+ else if (fx.length() > 2 && fx.substring(0, 2).equals("ab")) guifx_ab(fx.substring(2));
+ else if (fx.length() > 4 && fx.substring(0, 4).equals("dfpn")) guifx_dfpn(fx.substring(4));
+ else if (fx.length() > 6 && fx.substring(0, 6).equals("solver")) guifx_solver(fx.substring(6));
+ }
+
+ private void guifx_uct(String fx) {
+ String[] tk = fx.trim().split(" ");
+ int i = 0;
+
+ m_guiboard.clearMarks();
+ m_guiboard.aboutToDirtyStones();
+
+ /**
+ * @todo Fix this to parse like guifx_ab() and guifx_solver().
+ */
+
+ //////////////////////////////////////
+ // display variation
+ for (; i < tk.length; ++i) {
+ String s = tk[i].trim();
+ if (s.equals("VAR")) break;
+ }
+ if (i == tk.length) return;
+ ++i; // skip "VAR";
+
+ Vector var = new Vector();
+ Vector col = new Vector();
+ for (; i < tk.length; ) {
+ String s = tk[i].trim();
+ if (s.equals("INFLUENCE")) break;
+ ++i; // skip 'B' and 'W'
+
+ col.add((s.charAt(0) == 'B') ? HexColor.BLACK : HexColor.WHITE);
+ HexPoint point = HexPoint.get(tk[i++].trim());
+ var.add(point);
+ }
+
+ m_guiboard.setColor(var.get(0), col.get(0));
+ m_guiboard.setAlphaColor(var.get(0), Color.cyan);
+ if (var.size() > 1) {
+ m_guiboard.setColor(var.get(1), col.get(1));
+ m_guiboard.setAlphaColor(var.get(1), Color.blue);
+ }
+
+ /////////////////////////////////////////
+ // display score/search counts
+
+ TreeMap map = new TreeMap();
+
+ ++i; // skip 'INFLUENCE'
+ for (; i < tk.length; ) {
+ String s = tk[i].trim();
+ if (s.equals("LABEL")) break;
+
+ HexPoint point = HexPoint.get(tk[i++].trim());
+ String score = tk[i++].trim();
+ map.put(point, score);
+ if (score.equals("W")) m_guiboard.setAlphaColor(point, Color.green);
+ else if (score.equals("L")) m_guiboard.setAlphaColor(point, Color.red);
+ }
+
+ ++i; // skip "LABEL";
+ for (; i < tk.length; ) {
+ String s = tk[i].trim();
+ if (s.equals("TEXT")) break;
+
+ HexPoint point = HexPoint.get(tk[i++].trim());
+
+ String old = map.get(point);
+ if (old == null) old = "";
+ map.put(point, old + "@" + tk[i++].trim());
+ }
+
+ Iterator> it = map.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry e = it.next();
+ m_guiboard.setText(e.getKey(), e.getValue());
+ }
+
+ m_guiboard.repaint();
+ m_statusbar.setMessage(fx.substring(fx.indexOf("TEXT") + 5));
+ }
+
+ private void guifx_ab(String fx) {
+ m_guiboard.clearMarks();
+ m_guiboard.aboutToDirtyStones();
+
+ int var = fx.indexOf("VAR");
+ int label = fx.indexOf("LABEL");
+ int text = fx.indexOf("TEXT");
+
+ Vector> vr = StringUtils.parseVariation(fx.substring(var + 3, label));
+ if (vr.size() > 0) {
+ m_guiboard.setColor(vr.get(0).second, vr.get(0).first);
+ m_guiboard.setAlphaColor(vr.get(0).second, Color.green);
+ if (vr.size() >= 2) {
+ m_guiboard.setColor(vr.get(1).second, vr.get(1).first);
+ m_guiboard.setAlphaColor(vr.get(1).second, Color.red);
+ }
+ }
+ String label_str = fx.substring(label + 5, text).trim();
+ Vector> labels = StringUtils.parseStringPairList(label_str);
+ for (int i = 0; i < labels.size(); ++i) {
+ HexPoint pt = HexPoint.get(labels.get(i).first);
+ m_guiboard.setText(pt, labels.get(i).second);
+ }
+ m_guiboard.repaint();
+ m_statusbar.setMessage(fx.substring(text + 5));
+ }
+
+ private void guifx_solver(String fx) {
+ m_guiboard.clearMarks();
+ m_guiboard.aboutToDirtyStones();
+ m_statusbar.setProgressVisible(true);
+
+ int var = fx.indexOf("VAR");
+ int label = fx.indexOf("LABEL");
+ int text = fx.indexOf("TEXT");
+
+ Vector> vr = StringUtils.parseVariation(fx.substring(var + 3, label));
+ for (int i = 0; i < vr.size(); ++i) {
+ m_guiboard.setColor(vr.get(i).second, vr.get(i).first);
+ m_guiboard.setText(vr.get(i).second, Integer.toString(i + 1));
+ }
+
+ String label_str = fx.substring(label + 5, text).trim();
+ showInferiorCells(label_str);
+
+ String prog_str = fx.substring(text + 4).trim();
+ String[] levels = prog_str.split(" ");
+
+ double contribution = 1.0;
+ double progress = 0.0;
+ for (int i = 0; i < levels.length; ++i) {
+ String[] nums = levels[i].trim().split("/");
+ int cur = Integer.decode(nums[0]).intValue();
+ int max = Integer.decode(nums[1]).intValue();
+ progress += contribution * cur / max;
+ contribution *= 1.0 / max;
+ }
+ m_guiboard.repaint();
+ m_statusbar.setMessage(fx.substring(text + 5));
+ m_statusbar.setProgress(progress);
+ }
+
+ private void guifx_dfpn(String fx) {
+ m_guiboard.clearMarks();
+ m_guiboard.aboutToDirtyStones();
+
+ int var = fx.indexOf("VAR");
+ int label = fx.indexOf("LABEL");
+ int text = fx.indexOf("TEXT");
+
+ Vector> vr = StringUtils.parseVariation(fx.substring(var + 3, label));
+ for (int i = 0; i < vr.size(); ++i) {
+ m_guiboard.setColor(vr.get(i).second, vr.get(i).first);
+ m_guiboard.setText(vr.get(i).second, Integer.toString(i + 1));
+ m_guiboard.setAlphaColor(vr.get(i).second, Color.blue);
+ }
+ String label_str = fx.substring(label + 5, text).trim();
+ showDfpnBounds(label_str);
+
+ m_guiboard.repaint();
+ m_statusbar.setMessage(fx.substring(text + 5));
+ }
+
+ private void showDfpnBounds(String str) {
+ Vector> pairs = StringUtils.parseStringPairList(str);
+ for (int i = 0; i < pairs.size(); i++) {
+ HexPoint point = HexPoint.get(pairs.get(i).first);
+ String value = pairs.get(i).second;
+ m_guiboard.setText(point, value);
+ if (value.trim().equals("W")) m_guiboard.setAlphaColor(point, Color.green);
+ else if (value.trim().equals("L")) m_guiboard.setAlphaColor(point, Color.red);
+ }
+ }
+
+ /** Draws the inferior cells to the gui board. */
+ private void showInferiorCells(String str) {
+ Vector> pairs = StringUtils.parseStringPairList(str);
+ for (int i = 0; i < pairs.size(); i++) {
+ HexPoint point = HexPoint.get(pairs.get(i).first);
+ String value = pairs.get(i).second;
+
+ if (value.charAt(0) == 'f') // fill-in
+ {
+ assert (3 == value.length());
+ if (value.charAt(1) == 'd') // dead
+ m_guiboard.setAlphaColor(point, Color.cyan);
+ else if (value.charAt(1) == 'p') // permanently inferior
+ m_guiboard.setAlphaColor(point, Color.gray);
+ else // captured
+ {
+ assert (value.charAt(1) == 'c');
+ m_guiboard.setAlphaColor(point, Color.red);
+ }
+ if (value.charAt(2) == 'b') m_guiboard.setColor(point, HexColor.BLACK);
+ else {
+ assert (value.charAt(2) == 'w');
+ m_guiboard.setColor(point, HexColor.WHITE);
+ }
+ } else if (value.charAt(0) == 'i') // ignorable
+ {
+ assert (4 <= value.length());
+ if (value.charAt(1) == 'v') // vulnerable
+ m_guiboard.setAlphaColor(point, Color.green);
+ else if (value.charAt(1) == 'r') // reversible
+ m_guiboard.setAlphaColor(point, Color.magenta);
+ else // dominated
+ {
+ assert (value.charAt(1) == 'd');
+ m_guiboard.setAlphaColor(point, Color.yellow);
+ }
+ assert (value.charAt(2) == '[' && value.charAt(value.length() - 1) == ']');
+ String pts = value.substring(3, value.length() - 1);
+ Vector pp = StringUtils.parsePointList(pts, "-");
+ for (int j = 0; j < pp.size(); ++j) m_guiboard.addArrow(point, pp.get(j));
+ } else // not in consider set
+ {
+ assert (value.charAt(0) == 'x');
+ m_guiboard.setAlphaColor(point, Color.gray);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------
+
+ // Remove keyboard focus from all text components, so that
+ // keyboard shortcuts can work.
+ private void unFocus() {
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ }
+
+ /** Callback from GuiBoard. Handle a mouse click. */
+ public void panelClicked() {
+ unFocus();
+ }
+
+ /** Callback from GuiBoard. Handle a mouse click. */
+ public void fieldClicked(HexPoint point, boolean ctrl, boolean shift) {
+ // do not modify the board in any way if an htp command is in progress!
+ if (m_locked) {
+ m_statusbar.setMessage("Board is locked until HTP command is completed.");
+ return;
+ }
+
+ if (m_guiboard.areStonesDirty()) {
+ m_guiboard.clearMarks();
+ }
+ if (ctrl) {
+ if (!shift) {
+ for (int i = 0; i < m_selected_cells.size(); i++) {
+ HexPoint p = m_selected_cells.get(i);
+ m_guiboard.setSelected(p, false);
+ }
+ m_selected_cells.clear();
+ m_guiboard.setSelected(point, true);
+ m_selected_cells.add(point);
+ } else {
+ int found_at = -1;
+ for (int i = 0; i < m_selected_cells.size() && found_at == -1; i++) {
+ if (m_selected_cells.get(i) == point) found_at = i;
+ }
+
+ if (found_at != -1) {
+ m_guiboard.setSelected(point, false);
+ m_selected_cells.remove(found_at);
+ } else {
+ m_guiboard.setSelected(point, true);
+ m_selected_cells.add(point);
}
- }
-
- private void cmdDisconnectProgram()
- {
- if (m_white == null)
- return;
-
- htpQuit();
- try
- {
- if (m_white_process != null)
- {
- m_white_process.waitFor();
- m_white_process = null;
- }
- if (m_white_socket != null)
- {
- m_white_socket.close();
- m_white_socket = null;
- }
- m_white = null;
- m_shell.dispose();
- m_shell = null;
- actionDisposeAnalyzeDialog();
- m_program = null;
- m_menubar.setProgramConnected(false);
- m_toolbar.setProgramConnected(false);
- m_preferences.put("is-program-attached", false);
- }
- catch (Throwable e)
- {
- ShowError.msg(this, "Error: " + e.getMessage());
- }
- }
-
- private void cmdReconnectProgram()
- {
- Program prog = m_program;
- cmdDisconnectProgram();
- cmdConnectLocalProgram(prog);
- }
-
- //------------------------------------------------------------
-
- private void cmdNewGame()
- {
- if (gameChanged() && !askSaveGame())
- return;
-
- String size = m_menubar.getSelectedBoardSize();
- Dimension dim = new Dimension(-1,-1);
- if (size.equals("Other..."))
- {
- size = BoardSizeDialog.show(this, m_guiboard.getBoardSize());
- if (size == null) return;
- }
-
- try
- {
- StringTokenizer st = new StringTokenizer(size);
- int w = Integer.parseInt(st.nextToken());
- st.nextToken();
- int h = Integer.parseInt(st.nextToken());
- dim.setSize(w,h);
- }
- catch (Throwable t)
- {
- ShowError.msg(this, "Size should be in format 'w x h'.");
- return;
- }
-
- if (dim.width < 1 || dim.height < 1)
- {
- ShowError.msg(this, "Invalid board size.");
- }
- else
- {
- m_tomove = HexColor.BLACK;
- m_toolbar.setToMove(m_tomove.toString());
-
- m_root = new Node();
- m_current = m_root;
- m_gameinfo = new GameInfo();
- m_gameinfo.setBoardSize(dim);
- stopClock(HexColor.BLACK);
- stopClock(HexColor.WHITE);
- m_blackClock.setElapsed(0);
- m_whiteClock.setElapsed(0);
- setComment(m_current);
-
- m_file = null;
- resetGameChanged();
- setFrameTitle();
-
- m_guiboard.initSize(dim.width, dim.height);
- m_guiboard.repaint();
-
- m_preferences.put("gui-board-width", dim.width);
- m_preferences.put("gui-board-height", dim.height);
-
- m_toolbar.updateButtonStates(m_current, this);
- m_menubar.updateMenuStates(this);
-
- htpBoardsize(m_guiboard.getBoardSize());
- htpShowboard();
-
- setCursorType();
- }
- }
-
- private boolean cmdSaveGame()
- {
- if (m_file == null)
- m_file = showSaveAsDialog();
-
- if (m_file != null)
- {
- System.out.println("Saving to file: " + m_file.getName());
- if (save(m_file))
- {
- resetGameChanged();
- setFrameTitle();
- m_preferences.put("path-save-game", m_file.getPath());
- return true;
- }
- }
- return false;
- }
-
- private boolean cmdSaveGameAs()
- {
- File file = showSaveAsDialog();
- if (file == null)
- return false;
-
- m_file = file;
- return cmdSaveGame();
- }
-
- private void cmdSavePositionAs()
- {
- File file = showSaveAsDialog();
- if (file != null)
- savePosition(file);
- }
-
- private void cmdLoadGame()
- {
- if (gameChanged() && !askSaveGame())
- return;
- File file = showOpenDialog();
- if (file != null)
- loadGame(file);
- }
-
- private void cmdPrintPreview()
- {
- JFrame frame = new JFrame();
- //frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- Container con = frame.getContentPane();
+ }
- PrintPreview pp = new PrintPreview(m_guiboard);
- con.add(pp, BorderLayout.CENTER);
+ m_guiboard.repaint();
- frame.pack();
- frame.setVisible(true);
- frame.toFront();
- }
-
- private void cmdPrint()
- {
- Print.run(this, m_guiboard);
- }
-
- private void cmdAbout()
- {
- m_about.setVisible(true);
- }
-
- //------------------------------------------------------------
-
- private void cmdGuiToolbarVisible()
- {
- boolean visible = m_menubar.getToolbarVisible();
- m_toolbar.setVisible(visible);
- }
-
- private void cmdGuiShellVisible()
- {
- if (m_shell == null) return;
- boolean visible = m_menubar.getShellVisible();
- m_shell.setVisible(visible);
- }
-
- private void cmdGuiAnalyzeVisible()
- {
- if (m_analyzeDialog == null) return;
- boolean visible = m_menubar.getAnalyzeVisible();
- m_analyzeDialog.setVisible(visible);
- }
-
- private void cmdGuiBoardDrawType()
- {
- String type = m_menubar.getCurrentBoardDrawType();
- System.out.println(type);
- m_guiboard.setDrawType(type);
- m_guiboard.repaint();
- }
-
- private void cmdGuiBoardOrientation()
- {
- String type = m_menubar.getCurrentBoardOrientation();
- System.out.println(type);
- m_guiboard.setOrientation(type);
- m_guiboard.repaint();
- }
-
- private void cmdClearMarks()
- {
- m_guiboard.clearMarks();
- m_guiboard.repaint();
- }
-
- private void cmdShowPreferences()
- {
- new PreferencesDialog(this, m_preferences);
- }
-
- /** Toggle the player to move, by explicit user request. This
- also updates the PL property in the current node. */
- private void cmdToggleToMove()
- {
- this.toggleToMove();
- m_current.setPlayerToMove(m_tomove);
- }
-
- /** Toggle the player to move, without setting the PL property */
- private void toggleToMove()
- {
- m_tomove = m_tomove.otherColor();
- m_toolbar.setToMove(m_tomove.toString());
- m_menubar.setToMove(m_tomove.toString());
- setCursorType();
- }
-
- /** Set the player to move, by explicit user request. This
- also updates the PL property in the current node. */
- private void cmdSetToMove()
- {
- this.setToMove();
- m_current.setPlayerToMove(m_tomove);
- }
-
- /** Set the player to move, without setting the PL property */
- private void setToMove()
- {
- m_tomove = HexColor.get(m_menubar.getToMove());
- m_toolbar.setToMove(m_tomove.toString());
- setCursorType();
- }
-
- private void cmdSetupBlack()
- {
- setCursorType();
- }
-
- private void cmdSetupWhite()
- {
- setCursorType();
- }
-
- // Update the cursor according to the current move type.
- public void setCursorType()
- {
- String clickContext = m_toolbar.getClickContext();
- if (clickContext == "black") {
- m_guiboard.setCursorType("black-setup");
- } else if (clickContext == "white") {
- m_guiboard.setCursorType("white-setup");
+ } else {
+ String context = m_toolbar.getClickContext();
+ if (context.equals("play")) {
+ if (m_guiboard.getColor(point) == HexColor.EMPTY) {
+ humanMove(new Move(point, m_tomove));
+ } else if (isSwapAllowed()) {
+ humanMove(new Move(HexPoint.get("swap-pieces"), m_tomove));
+ }
+ } else if (context.equals("black")) {
+ if (m_guiboard.getColor(point) == HexColor.BLACK) {
+ addSetupMove(new Move(point, HexColor.EMPTY));
} else {
- if (m_tomove == HexColor.BLACK) {
- m_guiboard.setCursorType("black");
- } else {
- m_guiboard.setCursorType("white");
- }
+ addSetupMove(new Move(point, HexColor.BLACK));
}
+ } else if (context.equals("white")) {
+ if (m_guiboard.getColor(point) == HexColor.WHITE) {
+ addSetupMove(new Move(point, HexColor.EMPTY));
+ } else {
+ addSetupMove(new Move(point, HexColor.WHITE));
+ }
+ }
+ }
+ }
+
+ public void fieldDoubleClicked(HexPoint point, boolean ctrl, boolean shift) {
+ fieldClicked(point, ctrl, shift);
+ }
+
+ public Vector getSelectedCells() {
+ return m_selected_cells;
+ }
+
+ public HexColor getColorToMove() {
+ return m_tomove;
+ }
+
+ public void humanMove(Move move) {
+ play(move);
+ htpPlay(move);
+ htpShowboard();
+ if (!m_guiboard.isBoardFull() && m_preferences.getBoolean("auto-respond") && m_program != null)
+ htpGenMove(m_tomove);
+ }
+
+ /**
+ * Update the GUI to reflect the given move. Do this without any changes to the game tree or the
+ * HTP.
+ */
+ private void guiPlay(Move move) {
+ if (m_guiboard.isYBoard() && move.getPoint() == HexPoint.SWAP_PIECES) {
+ m_guiboard.swapColors();
+ } else if (move.getPoint() == HexPoint.SWAP_PIECES) {
+ m_guiboard.swapPieces();
+ } else {
+ m_guiboard.setColor(move.getPoint(), move.getColor());
+ }
+ m_guiboard.clearMarks();
+ markLastPlayedStone();
+ }
+
+ public boolean isSwapAllowed() {
+ // Count the number of pieces on the board.
+ int count = m_guiboard.numberOfPieces();
+ // Check whether the game tree allows swapping.
+ boolean isswap = m_current.isSwap();
+ return count == 1 && !isswap;
+ }
+
+ private void play(Move move) {
+ // see if variation already exists; if so, do not add a duplicate
+ int variation = -1;
+ for (int i = 0; i < m_current.numChildren(); i++) {
+ Node child = m_current.getChild(i);
+ if (child.hasMove() && move.equals(child.getMove())) {
+ variation = i;
+ break;
+ }
+ }
+
+ if (variation != -1) {
+ // variation already exists
+ m_current = m_current.getChild(variation);
+
+ } else {
+ if (move.getPoint() == HexPoint.SWAP_SIDES || move.getPoint() == HexPoint.SWAP_PIECES) {
+ if (!this.isSwapAllowed()) {
+ ShowError.msg(this, "Swap move not allowed!");
+ return;
+ }
+ } else if (move.getPoint() == HexPoint.PASS) {
+ // for simplicity, passing is always possible (even
+ // twice in a row!)
+ } else if (move.getPoint() == HexPoint.RESIGN) {
+ // for simplicity, resigning is always possible (even
+ // twice in a row!)
+ } else if (move.getPoint() == HexPoint.FORFEIT) {
+ // for simplicity, forfeiting is always possible
+ // (even twice in a row!)
+ } else {
+ if (m_guiboard.getColor(move.getPoint()) != HexColor.EMPTY) {
+ ShowError.msg(this, "Cell '" + move.getPoint().toString() + "' already occupied.");
+ return;
+ }
+ }
+
+ // add new node
+ Node node = new Node(move);
+ m_current.addChild(node);
+ m_current = node;
+ }
+ m_current.markRecent();
+
+ stopClock(m_tomove);
+
+ if (m_guiboard.isYBoard()) {
+ toggleToMove();
+ } else if (m_current.getMove().getPoint() != HexPoint.SWAP_SIDES
+ && m_current.getMove().getPoint() != HexPoint.RESIGN
+ && m_current.getMove().getPoint() != HexPoint.FORFEIT) {
+ toggleToMove();
+ }
+ startClock(m_tomove);
+
+ guiPlay(move);
+ m_toolbar.updateButtonStates(m_current, this);
+ m_menubar.updateMenuStates(this);
+ m_statusbar.setMessage(
+ m_current.getDepth() + " " + move.getColor().toString() + " " + move.getPoint().toString());
+ setComment(m_current);
+
+ setFrameTitle();
+
+ m_guiboard.paintImmediately();
+ if (m_current.hasLabel()) {
+ displayLabels(m_current);
+ m_guiboard.paintImmediately();
+ }
+ }
+
+ /**
+ * Add a new empty setup node as a child of the current node. This allows the creation of
+ * consecutive setup nodes.
+ */
+ private void addSetupNode() {
+ Node setup = new Node();
+ setup.setPlayerToMove(m_tomove);
+ m_current.addChild(setup);
+ m_current = setup;
+ m_current.markRecent();
+ refreshGuiForBoardState();
+ m_statusbar.setMessage("Added a new setup node");
+ }
+
+ private void addSetupMove(Move move) {
+ // if current node doesn't permit setup to be edited, create a
+ // new setup node.
+ if (!m_current.canSetup()) {
+ Node setup = new Node();
+ setup.setPlayerToMove(m_tomove);
+ m_current.addChild(setup);
+ m_current = setup;
+ }
+
+ m_guiboard.clearMarks();
+
+ // add the setup stone to the set of setup stones
+ m_current.addSetup(move.getColor(), move.getPoint());
+
+ m_guiboard.setColor(move.getPoint(), move.getColor());
+ m_guiboard.paintImmediately();
+
+ htpSetUpCurrentBoard();
+ htpShowboard();
+
+ setFrameTitle();
+ m_current.markRecent();
+ refreshGuiForBoardState();
+
+ m_statusbar.setMessage(
+ "Added setup stone ("
+ + move.getColor().toString()
+ + ", "
+ + move.getPoint().toString()
+ + ")");
+ }
+
+ // ----------------------------------------------------------------------
+
+ private void displayLabels(Node node) {
+ Vector labels = node.getLabels();
+ for (int i = 0; i < labels.size(); ++i) {
+ String lb = labels.get(i);
+ String[] strs = lb.split(":");
+ HexPoint p = HexPoint.get(strs[0].trim());
+ m_guiboard.setText(p, strs[1].trim());
+ }
+ }
+
+ // Play the setup moves of the given node in the Gui, not HTP.
+ private void guiPlaySetup(Node node) {
+ Vector black = node.getSetup(HexColor.BLACK);
+ Vector white = node.getSetup(HexColor.WHITE);
+ Vector empty = node.getSetup(HexColor.EMPTY);
+ for (int j = 0; j < black.size(); j++) {
+ HexPoint point = black.get(j);
+ m_guiboard.setColor(point, HexColor.BLACK);
+ }
+ for (int j = 0; j < white.size(); j++) {
+ HexPoint point = white.get(j);
+ m_guiboard.setColor(point, HexColor.WHITE);
+ }
+ for (int j = 0; j < empty.size(); j++) {
+ HexPoint point = empty.get(j);
+ m_guiboard.setColor(point, HexColor.EMPTY);
+ }
+ }
+
+ private void playSetup(Node node) {
+ guiPlaySetup(node);
+ htpSetUpCurrentBoard();
+ }
+
+ // Undo the setup moves of the given node. Since the setup moves
+ // don't contain enough information to know the previous state
+ // (they can involve deleting pieces or recoloring pieces), we do
+ // this by replaying all moves up to the node's parent.
+ private void undoSetup(Node node) {
+ replayUpToNode(node.getParent());
+ }
+
+ // Play the given node in the Gui, not HTP.
+ private void guiPlayNode(Node node) {
+ node.markRecent();
+ if (node.hasMove()) {
+ Move move = node.getMove();
+ m_guiboard.setColor(move.getPoint(), move.getColor());
+ if (move.getPoint() == HexPoint.SWAP_PIECES) {
+ m_guiboard.swapPieces();
+ }
+ m_statusbar.setMessage(
+ node.getDepth() + " " + move.getColor().toString() + " " + move.getPoint().toString());
+ }
+ if (node.hasSetup()) {
+ guiPlaySetup(node);
+ }
+ }
+
+ // Play the given node in the Gui and HTP. For HTP, setup moves
+ // and swap-pieces moves are special cases, as they aren't in
+ // general supported by HTP. So we rebuild the board from scratch
+ // in these cases.
+ private void playNode(Node node) {
+ guiPlayNode(node);
+ if (node.hasMove()) {
+ Move move = node.getMove();
+ if (move.getPoint() == HexPoint.SWAP_PIECES) {
+ htpSetUpCurrentBoard();
+ } else {
+ htpPlay(move);
+ }
+ }
+ if (node.hasSetup()) {
+ htpSetUpCurrentBoard();
+ }
+ }
+
+ private void undoNode(Node node) {
+ if (node.hasMove()) {
+ Move move = node.getMove();
+ if (m_guiboard.isYBoard() && move.getPoint() == HexPoint.SWAP_PIECES) {
+ m_guiboard.swapColors();
+ } else if (move.getPoint() == HexPoint.SWAP_PIECES) {
+ m_guiboard.swapPieces();
+ } else {
+ m_guiboard.setColor(move.getPoint(), HexColor.EMPTY);
+ }
+ if (move.getPoint() == HexPoint.SWAP_PIECES) {
+ replayUpToNode(node.getParent());
+ } else {
+ htpUndo(move);
+ }
+ }
+ if (node.hasSetup()) {
+ undoSetup(node);
+ m_statusbar.setMessage("Undo setup stones");
+ }
+ }
+
+ private void refreshGuiForBoardState() {
+ markLastPlayedStone();
+ m_guiboard.repaint();
+ m_toolbar.updateButtonStates(m_current, this);
+ m_menubar.updateMenuStates(this);
+ setFrameTitle();
+
+ setComment(m_current);
+ if (m_current.hasMove()) {
+ Move move = m_current.getMove();
+ m_statusbar.setMessage(
+ m_current.getDepth()
+ + " "
+ + move.getColor().toString()
+ + " "
+ + move.getPoint().toString());
+ } else if (m_current.hasSetup()) {
+ m_statusbar.setMessage(m_current.getDepth() + " " + "setup");
+ } else {
+ m_statusbar.setMessage(m_current.getDepth() + "");
+ }
+ if (m_current.hasLabel()) displayLabels(m_current);
+ if (m_current.hasCount()) System.out.println("Count: " + m_current.getCount());
+ determineColorToMove();
+ htpShowboard();
+ }
+
+ /** Unselect the setup buttons. Most other actions trigger this. */
+ private void end_setup() {
+ m_toolbar.deselectSetup();
+ }
+
+ /** Forward by n moves, or to the very end if n == -1 */
+ private void forward(int n) {
+ m_guiboard.clearMarks();
+
+ for (int i = 0; i < n || n == -1; ++i) {
+ Node child = m_current.getRecentChild();
+ if (child == null) break;
+
+ playNode(child);
+ m_current = child;
+ }
+ stopClock();
+ refreshGuiForBoardState();
+ }
+
+ /** Rewind by n moves, or to the very start if n == -1 */
+ private void backward(int n) {
+ m_guiboard.clearMarks();
+
+ for (int i = 0; i < n || n == -1; ++i) {
+ if (m_current == m_root) break;
+
+ undoNode(m_current);
+ m_current = m_current.getParent();
+ }
+ stopClock();
+ refreshGuiForBoardState();
+ }
+
+ private void down() {
+ if (m_current.getNext() != null) {
+ m_guiboard.clearMarks();
+ undoNode(m_current);
+ m_current = m_current.getNext();
+ playNode(m_current);
+
+ stopClock();
+ refreshGuiForBoardState();
+ }
+ }
+
+ private void up() {
+ if (m_current.getPrev() != null) {
+ m_guiboard.clearMarks();
+ undoNode(m_current);
+ m_current = m_current.getPrev();
+ playNode(m_current);
+
+ stopClock();
+ refreshGuiForBoardState();
+ }
+ }
+
+ private void cmdDeleteBranch() {
+ if (m_current == m_root) {
+ m_statusbar.setMessage("May not delete root node!");
+ System.out.println("May not delete root node!");
+ return;
+ }
+
+ Node to_be_deleted = m_current;
+ backward(1);
+
+ to_be_deleted.removeSelf();
+ m_toolbar.updateButtonStates(m_current, this);
+ m_menubar.updateMenuStates(this);
+ setFrameTitle();
+ }
+
+ private void cmdMoveBranchTop() {
+ m_current.makeMain();
+ refreshGuiForBoardState();
+ }
+
+ private void determineColorToMove() {
+ // Usually the game tree determines the color to move.
+ HexColor color = m_current.getPlayerToMove();
+ m_tomove = color;
+ m_toolbar.setToMove(m_tomove.toString());
+ setCursorType();
+ }
+
+ // ------------------------------------------------------------
+
+ private void markLastPlayedStone() {
+ if (m_current == m_root || !m_current.hasMove()) {
+ m_guiboard.clearSwapPlayed();
+ m_guiboard.markLastPlayed(null);
+ return;
+ }
+
+ Move move = m_current.getMove();
+
+ if (move.getPoint() == HexPoint.RESIGN
+ || move.getPoint() == HexPoint.FORFEIT
+ || move.getPoint() == HexPoint.PASS) {
+ m_guiboard.clearSwapPlayed();
+ m_guiboard.markLastPlayed(null);
+ return;
+ }
+
+ if (move.getPoint() == HexPoint.SWAP_SIDES) {
+ Node parent = m_current.getParent();
+ assert (parent != null);
+
+ m_guiboard.markLastPlayed(null);
+ m_guiboard.markSwapPlayed();
+ } else if (move.getPoint() == HexPoint.SWAP_PIECES) {
+ Node parent = m_current.getParent();
+ assert (parent != null);
+
+ m_guiboard.markLastPlayed(null);
+ m_guiboard.markSwapPlayed();
+ } else {
+ m_guiboard.markLastPlayed(move.getPoint());
+ m_guiboard.clearSwapPlayed();
+ }
+ }
+
+ // Record a snapshot of the current game state. This can later be
+ // used to check if the game has changed or not.
+ private void resetGameChanged() {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ new SgfWriter(out, m_root, m_gameinfo);
+
+ m_gameSnapshot = out.toString();
+ }
+
+ private boolean gameChanged() {
+ if (m_gameSnapshot == null) {
+ return false;
+ }
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ new SgfWriter(out, m_root, m_gameinfo);
+
+ return !m_gameSnapshot.equals(out.toString());
+ }
+
+ private void setFrameTitle() {
+ String filename = "untitled";
+ if (m_file != null) filename = m_file.getName();
+ if (gameChanged()) filename = filename + "*";
+ String name = "HexGui " + Version.id;
+ if (m_white != null) name += " - [" + m_white_name + " " + m_white_version + "]";
+ setTitle(name + " - " + filename);
+ }
+
+ /** Returns false if action was aborted. */
+ private boolean askSaveGame() {
+ Object options[] = {"Save", "Discard", "Cancel"};
+ int n =
+ JOptionPane.showOptionDialog(
+ this,
+ "Game has changed. Save changes?",
+ "Save Game?",
+ JOptionPane.YES_NO_CANCEL_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]);
+ if (n == 0) {
+ if (cmdSaveGame()) return true;
+ return false;
+ } else if (n == 1) {
+ return true;
+ }
+ return false;
+ }
+
+ /** Saves the current game state as a position in the specified sgf file. */
+ private boolean savePosition(File file) {
+ Node root = new Node();
+
+ GameInfo info = new GameInfo();
+ info.setBoardSize(m_guiboard.getBoardSize());
+ m_guiboard.storePosition(root);
+ root.setPlayerToMove(m_tomove);
+ return save_tree(file, root, info);
+ }
+
+ /**
+ * Save game to file.
+ *
+ * @return true If successful.
+ */
+ private boolean save(File file) {
+ return save_tree(file, m_root, m_gameinfo);
+ }
+
+ private boolean save_tree(File file, Node root, GameInfo gameinfo) {
+ FileOutputStream out;
+ try {
+ out = new FileOutputStream(file);
+ } catch (FileNotFoundException e) {
+ ShowError.msg(this, "File not found!");
+ return false;
+ }
+
+ new SgfWriter(out, root, gameinfo);
+ return true;
+ }
+
+ /* Load game from file. */
+ private SgfReader load(File file) {
+ FileInputStream in;
+ try {
+ in = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ ShowError.msg(this, "File not found!");
+ return null;
+ }
+
+ SgfReader sgf;
+ try {
+ sgf = new SgfReader(in);
+ } catch (SgfReader.SgfError e) {
+ ShowError.msg(this, "Error reading SGF file:\n \"" + e.getMessage() + "\"");
+ return null;
+ }
+ return sgf;
+ }
+
+ // ------------------------------------------------------------
+
+ /**
+ * Show save dialog, return File of selected filename.
+ *
+ * @return null If aborted.
+ */
+ private File showSaveAsDialog() {
+ JFileChooser fc = new JFileChooser(m_preferences.get("path-save-game"));
+ if (m_file != null) fc.setSelectedFile(m_file);
+ int ret = fc.showSaveDialog(this);
+ if (ret == JFileChooser.APPROVE_OPTION) return fc.getSelectedFile();
+ return null;
+ }
+
+ /**
+ * Show open dialog, return File of selected filename.
+ *
+ * @return null If aborted.
+ */
+ private File showOpenDialog() {
+ JFileChooser fc = new JFileChooser(m_preferences.get("path-load-game"));
+ int ret = fc.showOpenDialog(this);
+ if (ret == JFileChooser.APPROVE_OPTION) return fc.getSelectedFile();
+ return null;
+ }
+
+ // ------------------------------------------------------------
+
+ private void acquireSemaphore() {
+ try {
+ m_semaphore.acquire();
+ } catch (InterruptedException e) {
+ System.out.println("Acquire interrupted!");
+ }
+ }
+
+ private void releaseSemaphore() {
+ m_semaphore.release();
+ }
+
+ // ------------------------------------------------------------
+
+ private void stopClock() {
+ stopClock(HexColor.BLACK);
+ stopClock(HexColor.WHITE);
+ }
+
+ private void stopClock(HexColor color) {
+ if (color == HexColor.BLACK) m_blackClock.stop();
+ else m_whiteClock.stop();
+ }
+
+ private void startClock() {
+ startClock(m_tomove);
+ }
+
+ private void startClock(HexColor color) {
+ if (color == HexColor.BLACK) m_blackClock.start();
+ else m_whiteClock.start();
+ }
+
+ private void setComment(Node node) {
+ String comment = node.getComment();
+ m_comment.setText(comment);
+ }
+
+ public void commentChanged(String string) {
+ m_current.setComment(string);
+ }
+
+ private boolean checkBoardSizeSupported() {
+ if (m_unsupportedBoardSize) {
+ ShowError.msg(HexGui.this, format("{0} does not support this board size.", m_white_name));
+ return false;
+ }
+ return true;
+ }
+
+ private void initialize(File file, String command) {
+ // attach program from the last run of HexGui
+ m_program = null;
+ if (command != null) {
+ cmdConnectLocalProgram(new Program("", command, ""));
+ setFrameTitle();
+ }
+ m_programs = Program.load();
+ /*
+ if (m_preferences.getBoolean("is-program-attached"))
+ {
+ String name = m_preferences.get("attached-program");
+ Program prog = Program.findWithName(name, m_programs);
+ if (prog != null)
+ cmdConnectLocalProgram(prog);
}
-
- //------------------------------------------------------------
-
- public void actionClearAnalyzeCommand()
- {
-
- }
-
- public void actionSetAnalyzeCommand(AnalyzeCommand command)
- {
- actionSetAnalyzeCommand(command, false, true, true, false);
- }
+ */
- public void actionSetAnalyzeCommand(AnalyzeCommand command,
- boolean autoRun, boolean clearBoard,
- boolean oneRunOnly,
- boolean reuseTextWindow)
- {
- AnalyzeType type = command.getType();
- if (command.needsPointArg())
- {
- Vector selected = getSelectedCells();
- if (selected.size() < 1)
- {
- m_statusbar.setMessage("Please select a cell before " +
- "running.");
- return;
- }
- command.setPointArg(selected.get(0));
- }
- if (command.needsPointListArg())
- {
- Vector selected = getSelectedCells();
- if (type == AnalyzeType.VC && selected.size() != 2)
- {
- m_statusbar.setMessage("Please select a pair of cells before " +
- "running.");
- return;
- }
- PointList blah = new PointList(selected);
- command.setPointListArg(blah);
- }
- String cmd = command.replaceWildCards(m_tomove);
- String cleaned = StringUtils.cleanWhiteSpace(cmd.trim());
- String args[] = cleaned.split(" ");
- String c = args[0];
- m_curAnalyzeCommand = command;
-
- Runnable cb = null;
- switch(type)
- {
- case GROUP:
- cb = new Runnable() { public void run() { cbGroupGet(); } };
- break;
- case GFX:
- cb = new Runnable() { public void run() { cbGfx(); } };
- break;
- case INFERIOR:
- cb = new Runnable() { public void run() {cbShowInferiorCells();}};
- break;
- case MOVE:
- cb = new Runnable() { public void run() { cbGenMove(); } };
- break;
- case PLIST:
- cb = new Runnable() { public void run() { cbDisplayPointList(); } };
- break;
- case PSPAIRS:
- cb = new Runnable() { public void run() { cbDisplayPointText(); } };
- break;
- case PARAM:
- cb = new Runnable() { public void run() { cbEditParameters(); } };
- break;
- case VC:
- cb = new Runnable() { public void run() { cbVCs(); } };
- break;
- case STRING:
- cb = new Runnable() { public void run() { cbString(); } };
- break;
- case VAR:
- cb = new Runnable() { public void run() { cbVar(); } };
- break;
- }
- // if (c.equals("dfpn-get-bounds"))
- // cb = new Runnable() { public void run() { cbDfpnDisplayBounds();} };
- // else if (c.equals("book-scores"))
- // cb = new Runnable() { public void run() { cbDisplayBookScores(); } };
- // else if (c.equals("eval-resist"))
- // cb = new Runnable() { public void run() { cbEvalResist(); } };
- Runnable callback = null;
- if (cb != null)
- callback = new GuiRunnable(cb);
- sendCommand(cmd + "\n", callback);
- }
-
- /** HtpShell Callback.
- By the name of the command it choose the proper callback function.
- Arguments are passed as given.
- */
- public void commandEntered(String cmd)
- {
- sendCommand(cmd, null);
- }
-
- //----------------------------------------------------------------------
-
- private boolean commandNeedsToLockGUI(String cmd)
- {
- if ((cmd.length() > 7 && cmd.substring(0, 7).equals("genmove")) ||
- (cmd.length() > 15 && cmd.substring(0, 15).equals("dfs-solve-state")) ||
- (cmd.length() > 16 && cmd.substring(0, 16).equals("dfpn-solve-state")) ||
- (cmd.length() > 23 && cmd.substring(0, 23).equals("dfs-solver-find-winning")) ||
- (cmd.length() > 24 && cmd.substring(0, 24).equals("dfpn-solver-find-winning")))
- return true;
- return false;
- }
-
- private void lockGUI()
- {
- m_locked = true;
- m_toolbar.lockToolbar();
- }
-
- private void unlockGUI()
- {
- m_toolbar.unlockToolbar(m_current, this);
- m_locked = false;
- }
-
- /** A (command, callback) pair. */
- private class HtpCommand
- {
- public HtpCommand()
- {
- }
-
- public HtpCommand(String cmd, Runnable callback)
- {
- this.str = cmd;
- this.callback = callback;
- }
-
- public String str;
- public Runnable callback;
- }
-
- /** Waits for commands to be added to the queue, then processes
- each in turn. */
- private class CommandHandler
- implements Runnable
- {
-
- public CommandHandler(Component parent,
- ArrayBlockingQueue queue)
- {
- m_parent = parent;
- m_queue = queue;
- }
-
- public void run()
- {
- while (true)
- {
- HtpCommand cmd = null;
- try
- {
- // block until queue contains an element
- cmd = m_queue.take();
- }
- catch(InterruptedException e)
- {
- System.out.println("INTERRUPTED! HUH?");
- }
-
- if (m_white != null && m_white.connected())
- {
- if (commandNeedsToLockGUI(cmd.str))
- lockGUI();
-
- try {
- m_white.sendCommand(cmd.str);
- if (cmd.callback != null) {
- cmd.callback.run();
- }
- }
- catch (HtpError e) {
- System.out.println("Caught error '"
- + e.getMessage() + "'");
- ShowError.msg(m_parent, e.getMessage());
- }
-
- if (commandNeedsToLockGUI(cmd.str))
- unlockGUI();
- }
- else
- {
- System.out.println("Not sending to disconnected: '"
- + cmd.str.trim() + "'");
- }
- }
- }
-
- Component m_parent;
- ArrayBlockingQueue m_queue;
- }
-
- private void sendCommand(String cmd, Runnable callback)
- {
- if (m_white == null)
- return;
-
- try {
- System.out.println("sendCommand: '" + cmd.trim() + "'");
- m_htp_queue.put(new HtpCommand(cmd, callback));
- }
- catch (InterruptedException e)
- {
- System.out.println("Interrupted while adding!");
- }
- }
-
- // FIXME: add callback?
- private void htpQuit()
- {
- sendCommand("quit\n", null);
- }
-
- private void htpName()
- {
- Runnable cb = new Runnable() { public void run() { cbName(); } };
- sendCommand("name\n", cb);
- }
-
- private void htpVersion()
- {
- Runnable cb = new Runnable() { public void run() { cbVersion(); } };
- sendCommand("version\n", cb);
- }
-
- private void htpAnalyzeCommands()
- {
- Runnable cb = new Runnable()
- { public void run() { cbAnalyzeCommands(); } };
- sendCommand("hexgui-analyze_commands\n", cb);
- }
-
- private void htpClearBoard()
- {
- sendCommand("clear_board\n", null);
- }
-
- private void htpShowboard()
- {
- sendCommand("showboard\n", null);
- }
-
- /** Play a move on the attached HTP backend. This only works if
- * move is a legal move of color black or white. There is no HTP
- * command for setup moves that remove a piece, or that change the
- * color of an already existing piece, and swap, pass, resign, and
- * forfeit moves are possibly not implemented in HTP, or may not
- * be undoable correctly. If the move is swap-pieces, just
- * update HTP to the current board position; so gui should always
- * be updated before calling this. */
- private void htpPlay(Move move)
- {
- if (move.getPoint() == HexPoint.RESIGN
- || move.getPoint() == HexPoint.FORFEIT
- || move.getPoint() == HexPoint.SWAP_SIDES
- || move.getPoint() == HexPoint.PASS) {
- return;
- }
- if (move.getPoint() == HexPoint.SWAP_PIECES) {
- htpSetUpCurrentBoard();
- return;
- }
- sendCommand("play " + move.getColor().toString() +
- " " + move.getPoint().toString() + "\n", null);
- }
-
- /** GUI must already be updated prior to calling this. */
- private void htpUndo(Move move)
- {
- if (move.getPoint() == HexPoint.RESIGN
- || move.getPoint() == HexPoint.FORFEIT
- || move.getPoint() == HexPoint.SWAP_SIDES
- || move.getPoint() == HexPoint.PASS) {
- return;
- }
- sendCommand("undo\n", null);
- }
-
- private void htpGenMove(HexColor color)
- {
- if (! checkBoardSizeSupported())
- return;
- m_statusbar.setMessage(format("{0} is thinking...", m_white_name));
- Runnable callback = new GuiRunnable(new Runnable()
- {
- public void run() { cbGenMove(); }
- });
- sendCommand("genmove " + color.toString() + "\n", callback);
- }
-
- private void htpBoardsize(Dimension size)
- {
- Runnable callback = new Runnable()
- {
- public void run() {
- m_unsupportedBoardSize = ! m_white.wasSuccess();
- checkBoardSizeSupported();
- }
- };
- sendCommand("boardsize " + size.width + " " + size.height + "\n",
- callback);
- m_statusbar.setMessage("New game");
- }
-
- //
- // Callbacks
- //
- public void cbName()
- {
- String str = m_white.getResponse();
- // FIXME: handle errors!
- m_white_name = str.trim();
- }
-
- public void cbVersion()
- {
- String str = m_white.getResponse();
- // FIXME: handle errors!
- m_white_version = str.trim();
- releaseSemaphore();
- }
-
- private void cbAnalyzeCommands()
- {
- String programAnalyzeCommands = m_white.getResponse();
- try
- {
- m_analyzeCommands
- = AnalyzeDefinition.read(programAnalyzeCommands);
- }
- catch (ErrorMessage e)
- {
- ShowError.msg(this, "Could not parse analyze commands!");
- }
- releaseSemaphore();
- }
-
- public void cbGenMove()
- {
- if (!m_white.wasSuccess())
- return;
- m_guiboard.clearMarks();
- String str = m_white.getResponse();
- HexPoint point = HexPoint.get(str.trim());
- if (point == null)
- {
- System.out.println("Invalid move!!");
- }
- else
- {
- play(new Move(point, m_tomove));
- }
- }
-
- public void cbDisplayPointList()
- {
- if (!m_white.wasSuccess())
- return;
- String str = m_white.getResponse();
- Vector points = StringUtils.parsePointList(str);
- m_guiboard.clearMarks();
- for (int i=0; i points = StringUtils.parsePointList(str);
- m_guiboard.clearMarks();
- if (points.size() > 0)
- {
- m_guiboard.setAlphaColor(points.get(0), Color.blue);
- for (int i=1; i > pairs =
- StringUtils.parseStringPairList(fx.substring(inf + 10, text));
- for (int i=0; i vcs = StringUtils.parseVCList(str);
- new VCDisplayDialog(this, m_guiboard, vcs);
- }
-
- public void cbString()
- {
- if (!m_white.wasSuccess())
- return;
- String showText = m_white.getResponse();
- String title = m_curAnalyzeCommand.getResultTitle();
- if (showText != null)
- {
- if (showText.indexOf("\n") < 0)
- {
- if (showText.trim().equals(""))
- showText = "(empty response)";
- m_statusbar.setMessage(format("{0}: {1}", title, showText));
- }
- else
- {
- HexPoint pointArg = null;
- m_showAnalyzeText.show(m_curAnalyzeCommand.getType(),
- pointArg, title, showText, false);
- }
- }
- }
-
- public void cbVar()
- {
- if (!m_white.wasSuccess())
- return;
- String str = m_white.getResponse();
- Vector points = StringUtils.parsePointList(str, " ");
- m_guiboard.clearMarks();
- m_guiboard.aboutToDirtyStones();
- HexColor color = m_tomove;
- for (int i = 0; i < points.size(); i++)
- {
- m_guiboard.setColor(points.get(i), color);
- m_guiboard.setText(points.get(i), Integer.toString(i + 1));
- color = color.otherColor();
- }
- m_guiboard.repaint();
- }
-
- public void cbDisplayPointText()
- {
- if (!m_white.wasSuccess())
- return;
- String str = m_white.getResponse();
- Vector > pairs =
- StringUtils.parseStringPairList(str);
- m_guiboard.clearMarks();
- for (int i=0; i > pairs =
- StringUtils.parseStringPairList(str);
- m_guiboard.clearMarks();
- for (int i=0; i > pairs =
- StringUtils.parseStringPairList(str);
- String res = "";
- String rew = "";
- String reb = "";
- m_guiboard.clearMarks();
- for (int i=0; i 3 && fx.substring(0, 3).equals("uct"))
- guifx_uct(fx.substring(3));
- else if (fx.length() > 2 && fx.substring(0, 2).equals("ab"))
- guifx_ab(fx.substring(2));
- else if (fx.length() > 4 && fx.substring(0, 4).equals("dfpn"))
- guifx_dfpn(fx.substring(4));
- else if (fx.length() > 6 && fx.substring(0, 6).equals("solver"))
- guifx_solver(fx.substring(6));
- }
-
- private void guifx_uct(String fx)
- {
- String[] tk = fx.trim().split(" ");
- int i=0;
-
- m_guiboard.clearMarks();
- m_guiboard.aboutToDirtyStones();
-
- /** @todo Fix this to parse like guifx_ab() and
- guifx_solver(). */
-
- //////////////////////////////////////
- // display variation
- for (; i < tk.length; ++i)
- {
- String s = tk[i].trim();
- if (s.equals("VAR"))
- break;
- }
- if (i == tk.length)
- return;
- ++i; // skip "VAR";
-
- Vector var = new Vector();
- Vector col = new Vector();
- for (; i < tk.length; )
- {
- String s = tk[i].trim();
- if (s.equals("INFLUENCE"))
- break;
- ++i; // skip 'B' and 'W'
-
- col.add((s.charAt(0) == 'B') ? HexColor.BLACK : HexColor.WHITE);
- HexPoint point = HexPoint.get(tk[i++].trim());
- var.add(point);
- }
-
- m_guiboard.setColor(var.get(0), col.get(0));
- m_guiboard.setAlphaColor(var.get(0), Color.cyan);
- if (var.size() > 1)
- {
- m_guiboard.setColor(var.get(1), col.get(1));
- m_guiboard.setAlphaColor(var.get(1), Color.blue);
- }
-
- /////////////////////////////////////////
- // display score/search counts
-
- TreeMap map = new TreeMap();
-
- ++i; // skip 'INFLUENCE'
- for (; i > it = map.entrySet().iterator();
- while(it.hasNext()) {
- Map.Entry e = it.next();
- m_guiboard.setText(e.getKey(), e.getValue());
- }
-
- m_guiboard.repaint();
- m_statusbar.setMessage(fx.substring(fx.indexOf("TEXT")+5));
- }
-
- private void guifx_ab(String fx)
- {
- m_guiboard.clearMarks();
- m_guiboard.aboutToDirtyStones();
-
- int var = fx.indexOf("VAR");
- int label = fx.indexOf("LABEL");
- int text = fx.indexOf("TEXT");
-
- Vector > vr
- = StringUtils.parseVariation(fx.substring(var+3, label));
- if (vr.size() > 0)
- {
- m_guiboard.setColor(vr.get(0).second, vr.get(0).first);
- m_guiboard.setAlphaColor(vr.get(0).second, Color.green);
- if (vr.size() >= 2)
- {
- m_guiboard.setColor(vr.get(1).second, vr.get(1).first);
- m_guiboard.setAlphaColor(vr.get(1).second, Color.red);
- }
- }
- String label_str = fx.substring(label+5, text).trim();
- Vector > labels =
- StringUtils.parseStringPairList(label_str);
- for (int i = 0; i < labels.size(); ++i)
- {
- HexPoint pt = HexPoint.get(labels.get(i).first);
- m_guiboard.setText(pt, labels.get(i).second);
- }
- m_guiboard.repaint();
- m_statusbar.setMessage(fx.substring(text+5));
- }
-
- private void guifx_solver(String fx)
- {
- m_guiboard.clearMarks();
- m_guiboard.aboutToDirtyStones();
- m_statusbar.setProgressVisible(true);
-
- int var = fx.indexOf("VAR");
- int label = fx.indexOf("LABEL");
- int text = fx.indexOf("TEXT");
-
- Vector > vr
- = StringUtils.parseVariation(fx.substring(var+3, label));
- for (int i = 0; i < vr.size(); ++i)
- {
- m_guiboard.setColor(vr.get(i).second, vr.get(i).first);
- m_guiboard.setText(vr.get(i).second, Integer.toString(i+1));
- }
-
- String label_str = fx.substring(label+5, text).trim();
- showInferiorCells(label_str);
-
- String prog_str = fx.substring(text+4).trim();
- String[] levels = prog_str.split(" ");
-
- double contribution = 1.0;
- double progress = 0.0;
- for (int i = 0; i < levels.length; ++i)
- {
- String[] nums = levels[i].trim().split("/");
- int cur = Integer.decode(nums[0]).intValue();
- int max = Integer.decode(nums[1]).intValue();
- progress += contribution*cur/max;
- contribution *= 1.0/max;
- }
- m_guiboard.repaint();
- m_statusbar.setMessage(fx.substring(text+5));
- m_statusbar.setProgress(progress);
- }
-
- private void guifx_dfpn(String fx)
- {
- m_guiboard.clearMarks();
- m_guiboard.aboutToDirtyStones();
-
- int var = fx.indexOf("VAR");
- int label = fx.indexOf("LABEL");
- int text = fx.indexOf("TEXT");
-
- Vector > vr
- = StringUtils.parseVariation(fx.substring(var+3, label));
- for (int i = 0; i < vr.size(); ++i)
- {
- m_guiboard.setColor(vr.get(i).second, vr.get(i).first);
- m_guiboard.setText(vr.get(i).second, Integer.toString(i+1));
- m_guiboard.setAlphaColor(vr.get(i).second, Color.blue);
- }
- String label_str = fx.substring(label+5, text).trim();
- showDfpnBounds(label_str);
-
- m_guiboard.repaint();
- m_statusbar.setMessage(fx.substring(text+5));
- }
-
- private void showDfpnBounds(String str)
- {
- Vector > pairs =
- StringUtils.parseStringPairList(str);
- for (int i = 0; i < pairs.size(); i++)
- {
- HexPoint point = HexPoint.get(pairs.get(i).first);
- String value = pairs.get(i).second;
- m_guiboard.setText(point, value);
- if (value.trim().equals("W"))
- m_guiboard.setAlphaColor(point, Color.green);
- else if (value.trim().equals("L"))
- m_guiboard.setAlphaColor(point, Color.red);
- }
- }
-
- /** Draws the inferior cells to the gui board. */
- private void showInferiorCells(String str)
- {
- Vector > pairs =
- StringUtils.parseStringPairList(str);
- for (int i = 0; i < pairs.size(); i++)
- {
- HexPoint point = HexPoint.get(pairs.get(i).first);
- String value = pairs.get(i).second;
-
- if (value.charAt(0) == 'f') // fill-in
- {
- assert(3 == value.length());
- if (value.charAt(1) == 'd') // dead
- m_guiboard.setAlphaColor(point, Color.cyan);
- else if (value.charAt(1) == 'p') // permanently inferior
- m_guiboard.setAlphaColor(point, Color.gray);
- else // captured
- {
- assert(value.charAt(1) == 'c');
- m_guiboard.setAlphaColor(point, Color.red);
- }
- if (value.charAt(2) == 'b')
- m_guiboard.setColor(point, HexColor.BLACK);
- else
- {
- assert(value.charAt(2) == 'w');
- m_guiboard.setColor(point, HexColor.WHITE);
- }
- }
- else if (value.charAt(0) == 'i') // ignorable
- {
- assert(4 <= value.length());
- if (value.charAt(1) == 'v') // vulnerable
- m_guiboard.setAlphaColor(point, Color.green);
- else if (value.charAt(1) == 'r') // reversible
- m_guiboard.setAlphaColor(point, Color.magenta);
- else // dominated
- {
- assert(value.charAt(1) == 'd');
- m_guiboard.setAlphaColor(point, Color.yellow);
- }
- assert(value.charAt(2) == '[' &&
- value.charAt(value.length()-1) == ']');
- String pts = value.substring(3, value.length()-1);
- Vector pp = StringUtils.parsePointList(pts,"-");
- for (int j=0; j getSelectedCells()
- {
- return m_selected_cells;
- }
-
- public HexColor getColorToMove()
- {
- return m_tomove;
- }
-
- public void humanMove(Move move)
- {
- play(move);
- htpPlay(move);
- htpShowboard();
- if (! m_guiboard.isBoardFull()
- && m_preferences.getBoolean("auto-respond")
- && m_program != null)
- htpGenMove(m_tomove);
- }
-
- /** Update the GUI to reflect the given move. Do this without any
- * changes to the game tree or the HTP. */
- private void guiPlay(Move move)
- {
- if (m_guiboard.isYBoard() && move.getPoint() == HexPoint.SWAP_PIECES) {
- m_guiboard.swapColors();
- } else if (move.getPoint() == HexPoint.SWAP_PIECES) {
- m_guiboard.swapPieces();
- } else {
- m_guiboard.setColor(move.getPoint(),
- move.getColor());
- }
- m_guiboard.clearMarks();
- markLastPlayedStone();
- }
-
- public boolean isSwapAllowed()
- {
- // Count the number of pieces on the board.
- int count = m_guiboard.numberOfPieces();
- // Check whether the game tree allows swapping.
- boolean isswap = m_current.isSwap();
- return count == 1 && !isswap;
- }
-
- private void play(Move move)
- {
- // see if variation already exists; if so, do not add a duplicate
- int variation = -1;
- for (int i=0; i labels = node.getLabels();
- for (int i = 0; i < labels.size(); ++i)
- {
- String lb = labels.get(i);
- String[] strs = lb.split(":");
- HexPoint p = HexPoint.get(strs[0].trim());
- m_guiboard.setText(p, strs[1].trim());
- }
- }
-
- // Play the setup moves of the given node in the Gui, not HTP.
- private void guiPlaySetup(Node node)
- {
- Vector black = node.getSetup(HexColor.BLACK);
- Vector white = node.getSetup(HexColor.WHITE);
- Vector empty = node.getSetup(HexColor.EMPTY);
- for (int j=0; j m_analyzeCommands;
-
- private final MessageDialogs m_messageDialogs =
- new MessageDialogs("HexGui");
-
- private Vector m_selected_cells;
-
- private Program m_program;
- private Vector m_programs;
-
- private ShowAnalyzeText m_showAnalyzeText;
-
- private ArrayBlockingQueue m_htp_queue;
- private Semaphore m_semaphore;
- private HtpController m_white;
- private String m_white_name;
- private String m_white_version;
- private AnalyzeCommand m_curAnalyzeCommand;
- private Process m_white_process;
- private Socket m_white_socket;
-
- private File m_file;
+ if (file != null) loadGame(file);
+ }
+
+ private void loadGame(File file) {
+ System.out.println("Loading sgf from file: " + file.getName());
+ SgfReader sgf = load(file);
+ if (sgf != null) {
+ m_root = sgf.getGameTree();
+ m_gameinfo = sgf.getGameInfo();
+ m_current = m_root;
+
+ m_guiboard.initSize(m_gameinfo.getBoardSize());
+ htpBoardsize(m_guiboard.getBoardSize());
+
+ // Play the root node, since it may contain setup.
+ playNode(m_root);
+
+ forward(-1);
+
+ m_file = file;
+ resetGameChanged();
+ setFrameTitle();
+
+ m_preferences.put("path-load-game", file.getPath());
+ end_setup();
+ }
+ }
+
+ private void setIcon() {
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ // There are problems on some platforms with transparency (e.g. Linux
+ // Sun Java 1.5.0). Best solution for now is to take an icon without
+ // transparency
+ URL url = loader.getResource("hexgui/images/hexgui-48x48-notrans.png");
+ setIconImage(new ImageIcon(url).getImage());
+ }
+
+ private AboutDialog m_about;
+ private GuiPreferences m_preferences;
+ private GuiBoard m_guiboard;
+ private GuiToolBar m_toolbar;
+ private StatusBar m_statusbar;
+ private GuiMenuBar m_menubar;
+ private HtpShell m_shell;
+ private AnalyzeDialog m_analyzeDialog;
+ private GameInfoPanel m_gameinfopanel;
+ private Comment m_comment;
+ private boolean m_locked;
+ private boolean m_unsupportedBoardSize;
+ private Node m_root;
+ private Node m_current;
+ private GameInfo m_gameinfo;
+ private HexColor m_tomove;
+ private Clock m_blackClock;
+ private Clock m_whiteClock;
+ private String m_gameSnapshot;
+
+ private ArrayList m_analyzeCommands;
+
+ private final MessageDialogs m_messageDialogs = new MessageDialogs("HexGui");
+
+ private Vector m_selected_cells;
+
+ private Program m_program;
+ private Vector m_programs;
+
+ private ShowAnalyzeText m_showAnalyzeText;
+
+ private ArrayBlockingQueue m_htp_queue;
+ private Semaphore m_semaphore;
+ private HtpController m_white;
+ private String m_white_name;
+ private String m_white_version;
+ private AnalyzeCommand m_curAnalyzeCommand;
+ private Process m_white_process;
+ private Socket m_white_socket;
+
+ private File m_file;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/HtpShell.java b/src/main/java/hexgui/gui/HtpShell.java
index 6f2f142..3ddf53f 100644
--- a/src/main/java/hexgui/gui/HtpShell.java
+++ b/src/main/java/hexgui/gui/HtpShell.java
@@ -1,129 +1,112 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
import hexgui.hex.*;
import hexgui.htp.HtpController;
-
-import javax.swing.*;
-import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.text.*;
-/** Non-modal dialog displaying the communication between HexGui and a
- HTP compatible program. */
-public class HtpShell
- extends JDialog implements ActionListener, HtpController.IOInterface
-{
- public interface Callback
- {
- void commandEntered(String str);
- }
+/** Non-modal dialog displaying the communication between HexGui and a HTP compatible program. */
+public class HtpShell extends JDialog implements ActionListener, HtpController.IOInterface {
+ public interface Callback {
+ void commandEntered(String str);
+ }
- public HtpShell(JFrame owner, Callback callback)
- {
- super(owner, "HexGui: Shell");
- m_callback = callback;
-
- m_editor = new JTextPane();
- m_editor.setEditable(false);
- m_document = m_editor.getStyledDocument();
- addStylesToDocument(m_document);
-
- m_scrollpane = new JScrollPane(m_editor);
- m_scrollpane.setVerticalScrollBarPolicy(
- JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
-
- Dimension size = owner.getSize();
- getContentPane().add(m_scrollpane, BorderLayout.CENTER);
-
- setPreferredSize(new Dimension(400, size.height));
- setMinimumSize(new Dimension(400, 200));
- setLocation(size.width, 0);
-
- m_field = new JTextField();
- m_field.addActionListener(this);
- m_field.setActionCommand("command-entered");
- getContentPane().add(m_field, BorderLayout.SOUTH);
-
- pack();
- }
+ public HtpShell(JFrame owner, Callback callback) {
+ super(owner, "HexGui: Shell");
+ m_callback = callback;
- public void appendText(String text)
- {
- appendText(text, null);
- }
+ m_editor = new JTextPane();
+ m_editor.setEditable(false);
+ m_document = m_editor.getStyledDocument();
+ addStylesToDocument(m_document);
- public void appendText(String text, AttributeSet style)
- {
- try {
- m_document.insertString(m_document.getLength(), text, style);
- }
- catch (BadLocationException e) {
- System.out.println("Bad location!");
- }
- }
+ m_scrollpane = new JScrollPane(m_editor);
+ m_scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ Dimension size = owner.getSize();
+ getContentPane().add(m_scrollpane, BorderLayout.CENTER);
- /** HtpController.IOInterface */
- public void sentCommand(String str)
- {
- appendText(str, m_document.getStyle("blue"));
- }
+ setPreferredSize(new Dimension(400, size.height));
+ setMinimumSize(new Dimension(400, 200));
+ setLocation(size.width, 0);
- public void receivedResponse(String str)
- {
- appendText(str, m_document.getStyle("bold"));
- }
+ m_field = new JTextField();
+ m_field.addActionListener(this);
+ m_field.setActionCommand("command-entered");
+ getContentPane().add(m_field, BorderLayout.SOUTH);
- public void receivedError(String str)
- {
- appendText(str, m_document.getStyle("red"));
- }
+ pack();
+ }
+
+ public void appendText(String text) {
+ appendText(text, null);
+ }
- protected void addStylesToDocument(StyledDocument doc) {
- Style def = StyleContext.getDefaultStyleContext().
- getStyle(StyleContext.DEFAULT_STYLE);
-
- Style regular = doc.addStyle("regular", def);
- StyleConstants.setFontFamily(def, "Monospaced");
- StyleConstants.setFontSize(def, 12);
-
- Style s = doc.addStyle("italic", regular);
- StyleConstants.setItalic(s, true);
-
- s = doc.addStyle("bold", regular);
- StyleConstants.setBold(s, true);
-
- s = doc.addStyle("blue", regular);
- StyleConstants.setForeground(s, Color.blue);
-
- s = doc.addStyle("red", regular);
- StyleConstants.setForeground(s, Color.RED);
-
- s = doc.addStyle("gray", regular);
- StyleConstants.setForeground(s, Color.gray);
-
- s = doc.addStyle("yellow", regular);
- StyleConstants.setForeground(s, Color.YELLOW);
+ public void appendText(String text, AttributeSet style) {
+ try {
+ m_document.insertString(m_document.getLength(), text, style);
+ } catch (BadLocationException e) {
+ System.out.println("Bad location!");
}
+ }
+
+ /** HtpController.IOInterface */
+ public void sentCommand(String str) {
+ appendText(str, m_document.getStyle("blue"));
+ }
- public void actionPerformed(ActionEvent e)
- {
- String cmd = e.getActionCommand();
- if (cmd.equals("command-entered")) {
- String text = m_field.getText() + "\n";
- m_callback.commandEntered(text);
- m_field.setText(null);
- }
+ public void receivedResponse(String str) {
+ appendText(str, m_document.getStyle("bold"));
+ }
+
+ public void receivedError(String str) {
+ appendText(str, m_document.getStyle("red"));
+ }
+
+ protected void addStylesToDocument(StyledDocument doc) {
+ Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
+
+ Style regular = doc.addStyle("regular", def);
+ StyleConstants.setFontFamily(def, "Monospaced");
+ StyleConstants.setFontSize(def, 12);
+
+ Style s = doc.addStyle("italic", regular);
+ StyleConstants.setItalic(s, true);
+
+ s = doc.addStyle("bold", regular);
+ StyleConstants.setBold(s, true);
+
+ s = doc.addStyle("blue", regular);
+ StyleConstants.setForeground(s, Color.blue);
+
+ s = doc.addStyle("red", regular);
+ StyleConstants.setForeground(s, Color.RED);
+
+ s = doc.addStyle("gray", regular);
+ StyleConstants.setForeground(s, Color.gray);
+
+ s = doc.addStyle("yellow", regular);
+ StyleConstants.setForeground(s, Color.YELLOW);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+ if (cmd.equals("command-entered")) {
+ String text = m_field.getText() + "\n";
+ m_callback.commandEntered(text);
+ m_field.setText(null);
}
+ }
- JTextPane m_editor;
- JTextField m_field;
- JScrollPane m_scrollpane;
- StyledDocument m_document;
- Callback m_callback;
+ JTextPane m_editor;
+ JTextField m_field;
+ JScrollPane m_scrollpane;
+ StyledDocument m_document;
+ Callback m_callback;
}
-
diff --git a/src/main/java/hexgui/gui/MessageDialogs.java b/src/main/java/hexgui/gui/MessageDialogs.java
index f2621b7..964e53e 100644
--- a/src/main/java/hexgui/gui/MessageDialogs.java
+++ b/src/main/java/hexgui/gui/MessageDialogs.java
@@ -2,358 +2,389 @@
package hexgui.gui;
+import static hexgui.gui.GuiUtil.insertLineBreaks;
+
+import hexgui.util.Platform;
+import hexgui.util.PrefUtil;
+import hexgui.util.StringUtils;
import java.awt.Component;
-import java.util.TreeSet;
import java.util.Set;
+import java.util.TreeSet;
import java.util.prefs.Preferences;
import javax.swing.Box;
-import javax.swing.JComponent;
import javax.swing.JCheckBox;
+import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
-import static hexgui.gui.GuiUtil.insertLineBreaks;
-import hexgui.util.Platform;
-import hexgui.util.PrefUtil;
-import hexgui.util.StringUtils;
/** Simple message dialogs. */
-public final class MessageDialogs
-{
- public MessageDialogs(String applicationName)
- {
- m_applicationName = applicationName;
- }
+public final class MessageDialogs {
+ public MessageDialogs(String applicationName) {
+ m_applicationName = applicationName;
+ }
- public void showError(Component frame, String mainMessage,
- String optionalMessage)
- {
- showError(frame, mainMessage, optionalMessage, true);
- }
+ public void showError(Component frame, String mainMessage, String optionalMessage) {
+ showError(frame, mainMessage, optionalMessage, true);
+ }
- public void showError(Component frame, String mainMessage,
- String optionalMessage, boolean isCritical)
- {
- int type;
- if (isCritical)
- type = JOptionPane.ERROR_MESSAGE;
- else
- type = JOptionPane.PLAIN_MESSAGE;
- Object[] options = { "Close" };
- Object defaultOption = options[0];
- String title = "Error" + " - " + m_applicationName;
- show(null, frame, title, mainMessage, optionalMessage, type,
- JOptionPane.DEFAULT_OPTION, options, defaultOption, -1);
- }
+ public void showError(
+ Component frame, String mainMessage, String optionalMessage, boolean isCritical) {
+ int type;
+ if (isCritical) type = JOptionPane.ERROR_MESSAGE;
+ else type = JOptionPane.PLAIN_MESSAGE;
+ Object[] options = {"Close"};
+ Object defaultOption = options[0];
+ String title = "Error" + " - " + m_applicationName;
+ show(
+ null,
+ frame,
+ title,
+ mainMessage,
+ optionalMessage,
+ type,
+ JOptionPane.DEFAULT_OPTION,
+ options,
+ defaultOption,
+ -1);
+ }
- public void showError(Component frame, String message, Exception e)
- {
- showError(frame, message, e, true);
- }
+ public void showError(Component frame, String message, Exception e) {
+ showError(frame, message, e, true);
+ }
- public void showError(Component frame, String message, Exception e,
- boolean isCritical)
- {
- showError(frame, message, StringUtils.getErrorMessage(e), isCritical);
- }
+ public void showError(Component frame, String message, Exception e, boolean isCritical) {
+ showError(frame, message, StringUtils.getErrorMessage(e), isCritical);
+ }
- public void showInfo(Component frame, String mainMessage,
- String optionalMessage, boolean isCritical)
- {
- showInfo(null, frame, mainMessage, optionalMessage, isCritical);
- }
+ public void showInfo(
+ Component frame, String mainMessage, String optionalMessage, boolean isCritical) {
+ showInfo(null, frame, mainMessage, optionalMessage, isCritical);
+ }
- public void showInfo(String disableKey, Component frame,
- String mainMessage, String optionalMessage,
- boolean isCritical)
- {
- if (checkDisabled(disableKey))
- return;
- int type;
- if (isCritical)
- type = JOptionPane.INFORMATION_MESSAGE;
- else
- type = JOptionPane.PLAIN_MESSAGE;
- Object[] options = { "Close" };
- Object defaultOption = options[0];
- String title = "Information" + " - " + m_applicationName;
- show(disableKey, frame, title, mainMessage, optionalMessage,
- type, JOptionPane.DEFAULT_OPTION, options, defaultOption, -1);
- }
+ public void showInfo(
+ String disableKey,
+ Component frame,
+ String mainMessage,
+ String optionalMessage,
+ boolean isCritical) {
+ if (checkDisabled(disableKey)) return;
+ int type;
+ if (isCritical) type = JOptionPane.INFORMATION_MESSAGE;
+ else type = JOptionPane.PLAIN_MESSAGE;
+ Object[] options = {"Close"};
+ Object defaultOption = options[0];
+ String title = "Information" + " - " + m_applicationName;
+ show(
+ disableKey,
+ frame,
+ title,
+ mainMessage,
+ optionalMessage,
+ type,
+ JOptionPane.DEFAULT_OPTION,
+ options,
+ defaultOption,
+ -1);
+ }
- public int showYesNoCancelQuestion(Component parent, String mainMessage,
- String optionalMessage,
- String destructiveOption,
- String nonDestructiveOption)
- {
- return showYesNoCancelQuestion(null, parent, mainMessage,
- optionalMessage, destructiveOption,
- nonDestructiveOption);
- }
+ public int showYesNoCancelQuestion(
+ Component parent,
+ String mainMessage,
+ String optionalMessage,
+ String destructiveOption,
+ String nonDestructiveOption) {
+ return showYesNoCancelQuestion(
+ null, parent, mainMessage, optionalMessage, destructiveOption, nonDestructiveOption);
+ }
- /** Show a question with two options and cancel.
- @return 0 for the destructive option; 1 for the non-destructive
- option; 2 for cancel */
- public int showYesNoCancelQuestion(String disableKey, Component parent,
- String mainMessage,
- String optionalMessage,
- String destructiveOption,
- String nonDestructiveOption)
- {
- if (checkDisabled(disableKey))
- return 0;
- Object[] options = new Object[3];
- int destructiveIndex;
- if (Platform.isMac())
- {
- options[0] = nonDestructiveOption;
- options[1] = "Cancel";
- options[2] = destructiveOption;
- destructiveIndex = 2;
- }
- else
- {
- options[0] = nonDestructiveOption;
- options[1] = destructiveOption;
- options[2] = "Cancel";
- destructiveIndex = -1;
- }
- Object defaultOption = options[0];
- int type = JOptionPane.QUESTION_MESSAGE;
- String title = "Question" + " - " + m_applicationName;
- Object value = show(disableKey, parent, title, mainMessage,
- optionalMessage, type,
- JOptionPane.YES_NO_CANCEL_OPTION, options,
- defaultOption, destructiveIndex);
- int result;
- if (value == destructiveOption)
- result = 0;
- else if (value == nonDestructiveOption)
- result = 1;
- else
- result = 2;
- return result;
+ /**
+ * Show a question with two options and cancel.
+ *
+ * @return 0 for the destructive option; 1 for the non-destructive option; 2 for cancel
+ */
+ public int showYesNoCancelQuestion(
+ String disableKey,
+ Component parent,
+ String mainMessage,
+ String optionalMessage,
+ String destructiveOption,
+ String nonDestructiveOption) {
+ if (checkDisabled(disableKey)) return 0;
+ Object[] options = new Object[3];
+ int destructiveIndex;
+ if (Platform.isMac()) {
+ options[0] = nonDestructiveOption;
+ options[1] = "Cancel";
+ options[2] = destructiveOption;
+ destructiveIndex = 2;
+ } else {
+ options[0] = nonDestructiveOption;
+ options[1] = destructiveOption;
+ options[2] = "Cancel";
+ destructiveIndex = -1;
}
+ Object defaultOption = options[0];
+ int type = JOptionPane.QUESTION_MESSAGE;
+ String title = "Question" + " - " + m_applicationName;
+ Object value =
+ show(
+ disableKey,
+ parent,
+ title,
+ mainMessage,
+ optionalMessage,
+ type,
+ JOptionPane.YES_NO_CANCEL_OPTION,
+ options,
+ defaultOption,
+ destructiveIndex);
+ int result;
+ if (value == destructiveOption) result = 0;
+ else if (value == nonDestructiveOption) result = 1;
+ else result = 2;
+ return result;
+ }
- public void showWarning(Component parent, String mainMessage,
- String optionalMessage, boolean isCritical)
- {
- showWarning(null, parent, mainMessage, optionalMessage, isCritical);
- }
+ public void showWarning(
+ Component parent, String mainMessage, String optionalMessage, boolean isCritical) {
+ showWarning(null, parent, mainMessage, optionalMessage, isCritical);
+ }
- public void showWarning(String disableKey, Component parent,
- String mainMessage, String optionalMessage,
- boolean isCritical)
- {
- if (checkDisabled(disableKey))
- return;
- int type;
- if (isCritical)
- type = JOptionPane.WARNING_MESSAGE;
- else
- type = JOptionPane.PLAIN_MESSAGE;
- Object[] options = { "Close" };
- Object defaultOption = options[0];
- String title = "Warning" + " - " + m_applicationName;
- show(disableKey, parent, title, mainMessage, optionalMessage, type,
- JOptionPane.DEFAULT_OPTION, options, defaultOption, -1);
- }
+ public void showWarning(
+ String disableKey,
+ Component parent,
+ String mainMessage,
+ String optionalMessage,
+ boolean isCritical) {
+ if (checkDisabled(disableKey)) return;
+ int type;
+ if (isCritical) type = JOptionPane.WARNING_MESSAGE;
+ else type = JOptionPane.PLAIN_MESSAGE;
+ Object[] options = {"Close"};
+ Object defaultOption = options[0];
+ String title = "Warning" + " - " + m_applicationName;
+ show(
+ disableKey,
+ parent,
+ title,
+ mainMessage,
+ optionalMessage,
+ type,
+ JOptionPane.DEFAULT_OPTION,
+ options,
+ defaultOption,
+ -1);
+ }
- public boolean showQuestion(Component parent, String mainMessage,
- String optionalMessage,
- String destructiveOption, boolean isCritical)
- {
- return showQuestion(null, parent, mainMessage, optionalMessage,
- destructiveOption, isCritical);
- }
+ public boolean showQuestion(
+ Component parent,
+ String mainMessage,
+ String optionalMessage,
+ String destructiveOption,
+ boolean isCritical) {
+ return showQuestion(null, parent, mainMessage, optionalMessage, destructiveOption, isCritical);
+ }
- public boolean showQuestion(String disableKey, Component parent,
- String mainMessage,
- String optionalMessage,
- String destructiveOption,
- boolean isCritical)
- {
- return showQuestion(disableKey, parent, mainMessage, optionalMessage,
- destructiveOption, "Cancel",
- isCritical);
- }
+ public boolean showQuestion(
+ String disableKey,
+ Component parent,
+ String mainMessage,
+ String optionalMessage,
+ String destructiveOption,
+ boolean isCritical) {
+ return showQuestion(
+ disableKey, parent, mainMessage, optionalMessage, destructiveOption, "Cancel", isCritical);
+ }
- /** Show warning message to confirm destructive actions.
- @return true, if destructive was chosen; false if cancel was
- chosen. */
- public boolean showQuestion(String disableKey, Component parent,
- String mainMessage,
- String optionalMessage,
- String affirmativeOption,
- String cancelOption,
- boolean isCritical)
- {
- if (checkDisabled(disableKey))
- return true;
- Object[] options = new Object[2];
- if (Platform.isMac())
- {
- options[0] = cancelOption;
- options[1] = affirmativeOption;
- }
- else
- {
- options[0] = affirmativeOption;
- options[1] = cancelOption;
- }
- Object defaultOption = affirmativeOption;
- int type;
- if (isCritical)
- // No reason to show a warning icon for confirmation dialogs
- // of frequent actions
- type = JOptionPane.QUESTION_MESSAGE;
- else
- type = JOptionPane.PLAIN_MESSAGE;
- String title = "Question" + " - " + m_applicationName;
- Object result = show(disableKey, parent, title, mainMessage,
- optionalMessage, type, JOptionPane.YES_NO_OPTION,
- options, defaultOption, -1);
- return (result == affirmativeOption);
+ /**
+ * Show warning message to confirm destructive actions.
+ *
+ * @return true, if destructive was chosen; false if cancel was chosen.
+ */
+ public boolean showQuestion(
+ String disableKey,
+ Component parent,
+ String mainMessage,
+ String optionalMessage,
+ String affirmativeOption,
+ String cancelOption,
+ boolean isCritical) {
+ if (checkDisabled(disableKey)) return true;
+ Object[] options = new Object[2];
+ if (Platform.isMac()) {
+ options[0] = cancelOption;
+ options[1] = affirmativeOption;
+ } else {
+ options[0] = affirmativeOption;
+ options[1] = cancelOption;
}
+ Object defaultOption = affirmativeOption;
+ int type;
+ if (isCritical)
+ // No reason to show a warning icon for confirmation dialogs
+ // of frequent actions
+ type = JOptionPane.QUESTION_MESSAGE;
+ else type = JOptionPane.PLAIN_MESSAGE;
+ String title = "Question" + " - " + m_applicationName;
+ Object result =
+ show(
+ disableKey,
+ parent,
+ title,
+ mainMessage,
+ optionalMessage,
+ type,
+ JOptionPane.YES_NO_OPTION,
+ options,
+ defaultOption,
+ -1);
+ return (result == affirmativeOption);
+ }
- public boolean showWarningQuestion(Component parent, String mainMessage,
- String optionalMessage,
- String destructiveOption,
- boolean isCritical)
- {
- return showWarningQuestion(null, parent, mainMessage, optionalMessage,
- destructiveOption, isCritical);
- }
+ public boolean showWarningQuestion(
+ Component parent,
+ String mainMessage,
+ String optionalMessage,
+ String destructiveOption,
+ boolean isCritical) {
+ return showWarningQuestion(
+ null, parent, mainMessage, optionalMessage, destructiveOption, isCritical);
+ }
- public boolean showWarningQuestion(String disableKey, Component parent,
- String mainMessage,
- String optionalMessage,
- String destructiveOption,
- boolean isCritical)
- {
- return showWarningQuestion(disableKey, parent, mainMessage,
- optionalMessage, destructiveOption,
- "Cancel", isCritical);
- }
+ public boolean showWarningQuestion(
+ String disableKey,
+ Component parent,
+ String mainMessage,
+ String optionalMessage,
+ String destructiveOption,
+ boolean isCritical) {
+ return showWarningQuestion(
+ disableKey, parent, mainMessage, optionalMessage, destructiveOption, "Cancel", isCritical);
+ }
- /** Show warning message to confirm destructive actions.
- @return true, if destructive was chosen; false if cancel was chosen. */
- public boolean showWarningQuestion(String disableKey, Component parent,
- String mainMessage,
- String optionalMessage,
- String destructiveOption,
- String nonDestructiveOption,
- boolean isCritical)
- {
- if (checkDisabled(disableKey))
- return true;
- Object[] options = new Object[2];
- if (Platform.isMac())
- {
- options[0] = nonDestructiveOption;
- options[1] = destructiveOption;
- }
- else
- {
- options[0] = destructiveOption;
- options[1] = nonDestructiveOption;
- }
- Object defaultOption = nonDestructiveOption;
- int type;
- if (isCritical)
- type = JOptionPane.WARNING_MESSAGE;
- else
- type = JOptionPane.PLAIN_MESSAGE;
- String title = "Warning" + " - " + m_applicationName;
- Object result = show(disableKey, parent, title, mainMessage,
- optionalMessage, type, JOptionPane.YES_NO_OPTION,
- options, defaultOption, -1);
- return (result == destructiveOption);
+ /**
+ * Show warning message to confirm destructive actions.
+ *
+ * @return true, if destructive was chosen; false if cancel was chosen.
+ */
+ public boolean showWarningQuestion(
+ String disableKey,
+ Component parent,
+ String mainMessage,
+ String optionalMessage,
+ String destructiveOption,
+ String nonDestructiveOption,
+ boolean isCritical) {
+ if (checkDisabled(disableKey)) return true;
+ Object[] options = new Object[2];
+ if (Platform.isMac()) {
+ options[0] = nonDestructiveOption;
+ options[1] = destructiveOption;
+ } else {
+ options[0] = destructiveOption;
+ options[1] = nonDestructiveOption;
}
+ Object defaultOption = nonDestructiveOption;
+ int type;
+ if (isCritical) type = JOptionPane.WARNING_MESSAGE;
+ else type = JOptionPane.PLAIN_MESSAGE;
+ String title = "Warning" + " - " + m_applicationName;
+ Object result =
+ show(
+ disableKey,
+ parent,
+ title,
+ mainMessage,
+ optionalMessage,
+ type,
+ JOptionPane.YES_NO_OPTION,
+ options,
+ defaultOption,
+ -1);
+ return (result == destructiveOption);
+ }
- private final String m_applicationName;
+ private final String m_applicationName;
- private final Set m_disabled = new TreeSet();
+ private final Set m_disabled = new TreeSet();
- private static void addFiller(JComponent component)
- {
- Box.Filler filler = GuiUtil.createFiller();
- filler.setAlignmentX(Component.LEFT_ALIGNMENT);
- component.add(filler);
- }
+ private static void addFiller(JComponent component) {
+ Box.Filler filler = GuiUtil.createFiller();
+ filler.setAlignmentX(Component.LEFT_ALIGNMENT);
+ component.add(filler);
+ }
- private boolean checkDisabled(String disableKey)
- {
- if (disableKey == null)
- return false;
- Preferences prefs =
- PrefUtil.createNode("net/sf/hexgui/gui/messagedialogs/disabled");
- boolean permanentlyDisabled = prefs.getBoolean(disableKey, false);
- if (permanentlyDisabled)
- return true;
- // Make sure this entry exists (right now these settings can only
- // be directly edited in the backing store)
- prefs.putBoolean(disableKey, permanentlyDisabled);
- return m_disabled.contains(disableKey);
- }
+ private boolean checkDisabled(String disableKey) {
+ if (disableKey == null) return false;
+ Preferences prefs = PrefUtil.createNode("net/sf/hexgui/gui/messagedialogs/disabled");
+ boolean permanentlyDisabled = prefs.getBoolean(disableKey, false);
+ if (permanentlyDisabled) return true;
+ // Make sure this entry exists (right now these settings can only
+ // be directly edited in the backing store)
+ prefs.putBoolean(disableKey, permanentlyDisabled);
+ return m_disabled.contains(disableKey);
+ }
- private Object show(String disableKey, Component parent, String title,
- String mainMessage, String optionalMessage,
- int messageType, int optionType, Object[] options,
- Object defaultOption, int destructiveIndex)
- {
- if (optionalMessage == null)
- optionalMessage = "";
- boolean isMac = Platform.isMac();
- Box box = Box.createVerticalBox();
+ private Object show(
+ String disableKey,
+ Component parent,
+ String title,
+ String mainMessage,
+ String optionalMessage,
+ int messageType,
+ int optionType,
+ Object[] options,
+ Object defaultOption,
+ int destructiveIndex) {
+ if (optionalMessage == null) optionalMessage = "";
+ boolean isMac = Platform.isMac();
+ Box box = Box.createVerticalBox();
- String css = GuiUtil.getMessageCss();
+ String css = GuiUtil.getMessageCss();
- JLabel label =
- new JLabel("" + css + "" + insertLineBreaks(mainMessage)
- + ""
- + insertLineBreaks(optionalMessage) + "
");
- label.setAlignmentX(Component.LEFT_ALIGNMENT);
- box.add(label);
+ JLabel label =
+ new JLabel(
+ ""
+ + css
+ + ""
+ + insertLineBreaks(mainMessage)
+ + ""
+ + insertLineBreaks(optionalMessage)
+ + "
");
+ label.setAlignmentX(Component.LEFT_ALIGNMENT);
+ box.add(label);
- addFiller(box);
- addFiller(box);
- JCheckBox disableCheckBox = null;
- if (disableKey != null)
- {
- if (messageType == JOptionPane.QUESTION_MESSAGE)
- disableCheckBox = new JCheckBox("Do not show this message again");
- else if (messageType == JOptionPane.WARNING_MESSAGE)
- disableCheckBox =
- new JCheckBox("Do not show this warning again");
- else
- disableCheckBox =
- new JCheckBox("Do not show this message again");
- disableCheckBox.setToolTipText("Do not show this message again");
- disableCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
- box.add(disableCheckBox);
- }
- if (isMac)
- // Don't show icons on Mac, problem with icon generation in
- // Quaqua 3.7.2
- messageType = JOptionPane.PLAIN_MESSAGE;
- JOptionPane optionPane =
- new JOptionPane(box, messageType, optionType, null, options,
- defaultOption);
- if (destructiveIndex >= 0)
- {
- String key = "Quaqua.OptionPane.destructiveOption";
- optionPane.putClientProperty(key,
- Integer.valueOf(destructiveIndex));
- }
- if (isMac && parent.isVisible())
- // Dialogs don't have titles on the Mac
- title = null;
- JDialog dialog = optionPane.createDialog(parent, title);
- dialog.setVisible(true);
- dialog.dispose();
- if (disableKey != null && disableCheckBox.isSelected())
- m_disabled.add(disableKey);
- return optionPane.getValue();
+ addFiller(box);
+ addFiller(box);
+ JCheckBox disableCheckBox = null;
+ if (disableKey != null) {
+ if (messageType == JOptionPane.QUESTION_MESSAGE)
+ disableCheckBox = new JCheckBox("Do not show this message again");
+ else if (messageType == JOptionPane.WARNING_MESSAGE)
+ disableCheckBox = new JCheckBox("Do not show this warning again");
+ else disableCheckBox = new JCheckBox("Do not show this message again");
+ disableCheckBox.setToolTipText("Do not show this message again");
+ disableCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
+ box.add(disableCheckBox);
+ }
+ if (isMac)
+ // Don't show icons on Mac, problem with icon generation in
+ // Quaqua 3.7.2
+ messageType = JOptionPane.PLAIN_MESSAGE;
+ JOptionPane optionPane =
+ new JOptionPane(box, messageType, optionType, null, options, defaultOption);
+ if (destructiveIndex >= 0) {
+ String key = "Quaqua.OptionPane.destructiveOption";
+ optionPane.putClientProperty(key, Integer.valueOf(destructiveIndex));
}
+ if (isMac && parent.isVisible())
+ // Dialogs don't have titles on the Mac
+ title = null;
+ JDialog dialog = optionPane.createDialog(parent, title);
+ dialog.setVisible(true);
+ dialog.dispose();
+ if (disableKey != null && disableCheckBox.isSelected()) m_disabled.add(disableKey);
+ return optionPane.getValue();
+ }
}
diff --git a/src/main/java/hexgui/gui/ParameterDialog.java b/src/main/java/hexgui/gui/ParameterDialog.java
index b2012e7..ce6daf9 100644
--- a/src/main/java/hexgui/gui/ParameterDialog.java
+++ b/src/main/java/hexgui/gui/ParameterDialog.java
@@ -2,429 +2,359 @@
package hexgui.gui;
+import static java.lang.Math.max;
+import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
+import static javax.swing.JOptionPane.PLAIN_MESSAGE;
+import static javax.swing.JOptionPane.UNINITIALIZED_VALUE;
+import static javax.swing.JOptionPane.VALUE_PROPERTY;
+
+import hexgui.htp.AnalyzeUtil;
+import hexgui.htp.HtpController;
+import hexgui.htp.HtpError;
+import hexgui.htp.ParameterType;
+import hexgui.util.ObjectUtil;
+import hexgui.util.StringUtils;
import java.awt.Component;
+import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
-import static java.lang.Math.max;
import java.text.MessageFormat;
import java.util.ArrayList;
import javax.swing.Box;
-import javax.swing.JDialog;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
+import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
-import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
-import static javax.swing.JOptionPane.PLAIN_MESSAGE;
-import static javax.swing.JOptionPane.UNINITIALIZED_VALUE;
-import static javax.swing.JOptionPane.VALUE_PROPERTY;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
-import hexgui.htp.AnalyzeUtil;
-import hexgui.htp.HtpError;
-import hexgui.htp.ParameterType;
-import hexgui.util.ObjectUtil;
-import hexgui.util.StringUtils;
-import hexgui.htp.HtpController;
-/** Dialog for editing parameters in response to an analyze command of type
- param. */
-public class ParameterDialog
-{
- public static void editParameters(final String paramCommand, Frame owner,
- String title, String response,
- final HtpController htp,
- final MessageDialogs messageDialogs)
- {
- final ArrayList parameters = parseResponse(response);
- Component mainComponent = createMainComponent(parameters);
- final Object options[] = { "OK", "Cancel" };
- final JOptionPane optionPane =
- new JOptionPane(mainComponent, PLAIN_MESSAGE, OK_CANCEL_OPTION,
- null, options, options[0]);
- final JDialog dialog = new JDialog(owner, title, true);
- dialog.setContentPane(optionPane);
-
- optionPane.addPropertyChangeListener(new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent event) {
- String prop = event.getPropertyName();
- if (dialog.isVisible() && event.getSource() == optionPane
- && prop.equals(VALUE_PROPERTY))
- {
- Object value = optionPane.getValue();
- if (ObjectUtil.equals(value, UNINITIALIZED_VALUE))
- return;
- if (ObjectUtil.equals(value, options[0]))
- {
- for (int i = 0; i < parameters.size(); ++i)
- {
- Parameter parameter = parameters.get(i);
- if (! parameter.isChanged())
- continue;
- try
- {
- String command =
- getNewValueCommand(paramCommand,
- parameter);
- htp.sendCommand(command);
- }
- catch (HtpError e)
- {
- showError(dialog, messageDialogs,
- parameter, e);
- optionPane.setValue(UNINITIALIZED_VALUE);
- return;
- }
- }
- }
- dialog.setVisible(false);
- }
+/** Dialog for editing parameters in response to an analyze command of type param. */
+public class ParameterDialog {
+ public static void editParameters(
+ final String paramCommand,
+ Frame owner,
+ String title,
+ String response,
+ final HtpController htp,
+ final MessageDialogs messageDialogs) {
+ final ArrayList parameters = parseResponse(response);
+ Component mainComponent = createMainComponent(parameters);
+ final Object options[] = {"OK", "Cancel"};
+ final JOptionPane optionPane =
+ new JOptionPane(mainComponent, PLAIN_MESSAGE, OK_CANCEL_OPTION, null, options, options[0]);
+ final JDialog dialog = new JDialog(owner, title, true);
+ dialog.setContentPane(optionPane);
+
+ optionPane.addPropertyChangeListener(
+ new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ String prop = event.getPropertyName();
+ if (dialog.isVisible()
+ && event.getSource() == optionPane
+ && prop.equals(VALUE_PROPERTY)) {
+ Object value = optionPane.getValue();
+ if (ObjectUtil.equals(value, UNINITIALIZED_VALUE)) return;
+ if (ObjectUtil.equals(value, options[0])) {
+ for (int i = 0; i < parameters.size(); ++i) {
+ Parameter parameter = parameters.get(i);
+ if (!parameter.isChanged()) continue;
+ try {
+ String command = getNewValueCommand(paramCommand, parameter);
+ htp.sendCommand(command);
+ } catch (HtpError e) {
+ showError(
+ dialog, messageDialogs,
+ parameter, e);
+ optionPane.setValue(UNINITIALIZED_VALUE);
+ return;
+ }
}
- });
- dialog.pack();
- dialog.setLocationByPlatform(true);
- dialog.addWindowListener(new WindowAdapter() {
- public void windowOpened(WindowEvent e) {
- // JDK 1.5 docs require to invoke selectInitialValue after
- // the window is made visible
- optionPane.selectInitialValue();
- } });
- dialog.setVisible(true);
+ }
+ dialog.setVisible(false);
+ }
+ }
+ });
+ dialog.pack();
+ dialog.setLocationByPlatform(true);
+ dialog.addWindowListener(
+ new WindowAdapter() {
+ public void windowOpened(WindowEvent e) {
+ // JDK 1.5 docs require to invoke selectInitialValue after
+ // the window is made visible
+ optionPane.selectInitialValue();
+ }
+ });
+ dialog.setVisible(true);
+ }
+
+ /** Length of a textfield for editing string parameters. */
+ private static final int TEXTFIELD_LEN = 13;
+
+ private static final int MAX_PARAM_PER_COLUMN = 15;
+
+ private abstract static class Parameter {
+ public Parameter(String key, String value) {
+ m_key = key;
+ m_value = value;
+ m_label = StringUtils.capitalize(key.replace('_', ' '));
}
- /** Length of a textfield for editing string parameters. */
- private static final int TEXTFIELD_LEN = 13;
-
- private static final int MAX_PARAM_PER_COLUMN = 15;
-
- private abstract static class Parameter
- {
- public Parameter(String key, String value)
- {
- m_key = key;
- m_value = value;
- m_label = StringUtils.capitalize(key.replace('_', ' '));
- }
+ public String getKey() {
+ return m_key;
+ }
- public String getKey()
- {
- return m_key;
- }
+ public String getLabel() {
+ return m_label;
+ }
- public String getLabel()
- {
- return m_label;
- }
+ public String getValue() {
+ return m_value;
+ }
- public String getValue()
- {
- return m_value;
- }
+ public abstract String getNewValue();
- public abstract String getNewValue();
+ public abstract boolean isChanged();
- public abstract boolean isChanged();
+ public abstract void createComponents(int gridy, JPanel panel, GridBagLayout gridbag);
- public abstract void createComponents(int gridy, JPanel panel,
- GridBagLayout gridbag);
+ private final String m_key;
- private final String m_key;
+ private final String m_label;
- private final String m_label;
+ private final String m_value;
+ }
- private final String m_value;
+ private static class BoolParameter extends Parameter {
+ public BoolParameter(String key, String value) {
+ super(key, value);
+ try {
+ m_initialValue = (Integer.parseInt(value) != 0);
+ } catch (NumberFormatException e) {
+ m_initialValue = false;
+ }
}
- private static class BoolParameter
- extends Parameter
- {
- public BoolParameter(String key, String value)
- {
- super(key, value);
- try
- {
- m_initialValue = (Integer.parseInt(value) != 0);
- }
- catch (NumberFormatException e)
- {
- m_initialValue = false;
- }
- }
-
- public String getNewValue()
- {
- if (m_checkBox.isSelected())
- return "1";
- return "0";
- }
-
- public boolean isChanged()
- {
- return (m_checkBox.isSelected() != m_initialValue);
- }
+ public String getNewValue() {
+ if (m_checkBox.isSelected()) return "1";
+ return "0";
+ }
- public void createComponents(int gridy, JPanel panel,
- GridBagLayout gridbag)
- {
- m_checkBox = new JCheckBox(getLabel(), m_initialValue);
- GridBagConstraints constraints = new GridBagConstraints();
- constraints.gridx = 0;
- constraints.gridy = gridy;
- constraints.gridwidth = GridBagConstraints.REMAINDER;
- constraints.weightx = 1.0;
- constraints.anchor = GridBagConstraints.WEST;
- gridbag.setConstraints(m_checkBox, constraints);
- panel.add(m_checkBox);
- }
+ public boolean isChanged() {
+ return (m_checkBox.isSelected() != m_initialValue);
+ }
- private boolean m_initialValue;
+ public void createComponents(int gridy, JPanel panel, GridBagLayout gridbag) {
+ m_checkBox = new JCheckBox(getLabel(), m_initialValue);
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.gridx = 0;
+ constraints.gridy = gridy;
+ constraints.gridwidth = GridBagConstraints.REMAINDER;
+ constraints.weightx = 1.0;
+ constraints.anchor = GridBagConstraints.WEST;
+ gridbag.setConstraints(m_checkBox, constraints);
+ panel.add(m_checkBox);
+ }
- private JCheckBox m_checkBox;
+ private boolean m_initialValue;
+
+ private JCheckBox m_checkBox;
+ }
+
+ private static class ListParameter extends Parameter {
+ public ListParameter(String type, String key, String value) {
+ super(key, value);
+ String[] args = type.split("/");
+ assert args[0].equals("list");
+ m_items = new String[args.length - 1];
+ m_labels = new String[args.length - 1];
+ int initialIndex = 0;
+ int maxLength = 0;
+ for (int i = 1; i < args.length; ++i) {
+ String item = args[i];
+ if (item.equals(value)) initialIndex = i - 1;
+ maxLength = max(item.length(), maxLength);
+ m_items[i - 1] = item;
+ m_labels[i - 1] = StringUtils.capitalize(item.replace('_', ' '));
+ }
+ m_initialIndex = initialIndex;
}
- private static class ListParameter
- extends Parameter
- {
- public ListParameter(String type, String key, String value)
- {
- super(key, value);
- String[] args = type.split("/");
- assert args[0].equals("list");
- m_items = new String[args.length - 1];
- m_labels = new String[args.length - 1];
- int initialIndex = 0;
- int maxLength = 0;
- for (int i = 1; i < args.length; ++i)
- {
- String item = args[i];
- if (item.equals(value))
- initialIndex = i - 1;
- maxLength = max(item.length(), maxLength);
- m_items[i - 1] = item;
- m_labels[i - 1] =
- StringUtils.capitalize(item.replace('_', ' '));
- }
- m_initialIndex = initialIndex;
- }
+ public String getNewValue() {
+ return m_items[m_comboBox.getSelectedIndex()];
+ }
- public String getNewValue()
- {
- return m_items[m_comboBox.getSelectedIndex()];
- }
+ public boolean isChanged() {
+ return (m_comboBox.getSelectedIndex() != m_initialIndex);
+ }
- public boolean isChanged()
- {
- return (m_comboBox.getSelectedIndex() != m_initialIndex);
- }
+ public void createComponents(int gridy, JPanel panel, GridBagLayout gridbag) {
+ JLabel label = new JLabel(getLabel() + ":");
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.gridx = 0;
+ constraints.gridy = gridy;
+ constraints.weightx = 1.0;
+ constraints.ipadx = SMALL_PAD;
+ constraints.insets = new Insets(SMALL_PAD, 0, 0, 0);
+ constraints.anchor = GridBagConstraints.EAST;
+ gridbag.setConstraints(label, constraints);
+ panel.add(label);
+
+ m_comboBox = new JComboBox(m_labels);
+ m_comboBox.setSelectedIndex(m_initialIndex);
+ constraints = new GridBagConstraints();
+ constraints.gridx = 1;
+ constraints.gridy = gridy;
+ constraints.weightx = 1.0;
+ constraints.insets = new Insets(SMALL_PAD, 0, 0, 0);
+ constraints.anchor = GridBagConstraints.WEST;
+ gridbag.setConstraints(m_comboBox, constraints);
+ panel.add(m_comboBox);
+ }
- public void createComponents(int gridy, JPanel panel,
- GridBagLayout gridbag)
- {
- JLabel label = new JLabel(getLabel() + ":");
- GridBagConstraints constraints = new GridBagConstraints();
- constraints.gridx = 0;
- constraints.gridy = gridy;
- constraints.weightx = 1.0;
- constraints.ipadx = SMALL_PAD;
- constraints.insets = new Insets(SMALL_PAD, 0, 0, 0);
- constraints.anchor = GridBagConstraints.EAST;
- gridbag.setConstraints(label, constraints);
- panel.add(label);
-
- m_comboBox = new JComboBox(m_labels);
- m_comboBox.setSelectedIndex(m_initialIndex);
- constraints = new GridBagConstraints();
- constraints.gridx = 1;
- constraints.gridy = gridy;
- constraints.weightx = 1.0;
- constraints.insets = new Insets(SMALL_PAD, 0, 0, 0);
- constraints.anchor = GridBagConstraints.WEST;
- gridbag.setConstraints(m_comboBox, constraints);
- panel.add(m_comboBox);
- }
+ private final int m_initialIndex;
- private final int m_initialIndex;
+ private final String[] m_items;
- private final String[] m_items;
+ private final String[] m_labels;
- private final String[] m_labels;
+ private JComboBox m_comboBox;
+ }
- private JComboBox m_comboBox;
+ private static class StringParameter extends Parameter {
+ public StringParameter(String key, String value) {
+ super(key, value);
}
- private static class StringParameter
- extends Parameter
- {
- public StringParameter(String key, String value)
- {
- super(key, value);
- }
-
- public String getNewValue()
- {
- return m_textField.getText().trim();
- }
-
- public boolean isChanged()
- {
- return ! getNewValue().equals(getValue());
- }
-
- public void createComponents(int gridy, JPanel panel,
- GridBagLayout gridbag)
- {
- JLabel label = new JLabel(getLabel() + ":");
- GridBagConstraints constraints = new GridBagConstraints();
- constraints.gridx = 0;
- constraints.gridy = gridy;
- constraints.weightx = 1.0;
- constraints.ipadx = SMALL_PAD;
- constraints.insets = new Insets(SMALL_PAD, 0, 0, 0);
- constraints.anchor = GridBagConstraints.EAST;
- gridbag.setConstraints(label, constraints);
- panel.add(label);
-
- m_textField = new JTextField(TEXTFIELD_LEN);
- m_textField.setText(getValue());
- constraints = new GridBagConstraints();
- constraints.gridx = 1;
- constraints.gridy = gridy;
- constraints.weightx = 1.0;
- constraints.insets = new Insets(SMALL_PAD, 0, 0, 0);
- constraints.anchor = GridBagConstraints.WEST;
- gridbag.setConstraints(m_textField, constraints);
- panel.add(m_textField);
- }
+ public String getNewValue() {
+ return m_textField.getText().trim();
+ }
- private JTextField m_textField;
+ public boolean isChanged() {
+ return !getNewValue().equals(getValue());
}
- private static ArrayList parseResponse(String response)
- {
- ArrayList parameters = new ArrayList();
- BufferedReader reader =
- new BufferedReader(new StringReader(response));
- while (true)
- {
- String line = null;
- try
- {
- line = reader.readLine();
- }
- catch (IOException e)
- {
- }
- if (line == null)
- break;
- AnalyzeUtil.Result result = AnalyzeUtil.parseParameterLine(line);
- if (result == null)
- continue;
- if (result.m_type == ParameterType.BOOL)
- parameters.add(new BoolParameter(result.m_key,
- result.m_value));
- else if (result.m_type == ParameterType.LIST)
- parameters.add(new ListParameter(result.m_typeInfo,
- result.m_key,
- result.m_value));
- else
- // Treat unknown types as string for compatibility with future
- // types
- parameters.add(new StringParameter(result.m_key,
- result.m_value));
- }
- return parameters;
+ public void createComponents(int gridy, JPanel panel, GridBagLayout gridbag) {
+ JLabel label = new JLabel(getLabel() + ":");
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.gridx = 0;
+ constraints.gridy = gridy;
+ constraints.weightx = 1.0;
+ constraints.ipadx = SMALL_PAD;
+ constraints.insets = new Insets(SMALL_PAD, 0, 0, 0);
+ constraints.anchor = GridBagConstraints.EAST;
+ gridbag.setConstraints(label, constraints);
+ panel.add(label);
+
+ m_textField = new JTextField(TEXTFIELD_LEN);
+ m_textField.setText(getValue());
+ constraints = new GridBagConstraints();
+ constraints.gridx = 1;
+ constraints.gridy = gridy;
+ constraints.weightx = 1.0;
+ constraints.insets = new Insets(SMALL_PAD, 0, 0, 0);
+ constraints.anchor = GridBagConstraints.WEST;
+ gridbag.setConstraints(m_textField, constraints);
+ panel.add(m_textField);
}
- private static Component
- createMainComponent(ArrayList parameters)
- {
- int numberParameters = parameters.size();
- Box outerBox = Box.createHorizontalBox();
- int i = 0;
- int numberColumns = 0;
- JPanel panel = null;
- GridBagLayout gridbag = null;
- int gridy = 0;
- int paramPerColumn =
- (numberParameters + 1)
- / (numberParameters / MAX_PARAM_PER_COLUMN + 1);
- while (i < numberParameters)
- {
- if (i % paramPerColumn == 0)
- {
- if (panel != null)
- {
- if (numberColumns > 0)
- {
- outerBox.add(createFiller());
- outerBox.add(new JSeparator(SwingConstants.VERTICAL));
- outerBox.add(createFiller());
- }
- outerBox.add(panel);
- ++numberColumns;
- }
- gridbag = new GridBagLayout();
- panel = new JPanel(gridbag);
- gridy = 0;
- }
- parameters.get(i).createComponents(gridy, panel, gridbag);
- ++gridy;
- ++i;
- }
- if (panel != null)
- {
- if (numberColumns > 0)
- {
- outerBox.add(createFiller());
- outerBox.add(new JSeparator(SwingConstants.VERTICAL));
- outerBox.add(createFiller());
- }
- outerBox.add(panel);
+ private JTextField m_textField;
+ }
+
+ private static ArrayList parseResponse(String response) {
+ ArrayList parameters = new ArrayList();
+ BufferedReader reader = new BufferedReader(new StringReader(response));
+ while (true) {
+ String line = null;
+ try {
+ line = reader.readLine();
+ } catch (IOException e) {
+ }
+ if (line == null) break;
+ AnalyzeUtil.Result result = AnalyzeUtil.parseParameterLine(line);
+ if (result == null) continue;
+ if (result.m_type == ParameterType.BOOL)
+ parameters.add(new BoolParameter(result.m_key, result.m_value));
+ else if (result.m_type == ParameterType.LIST)
+ parameters.add(new ListParameter(result.m_typeInfo, result.m_key, result.m_value));
+ else
+ // Treat unknown types as string for compatibility with future
+ // types
+ parameters.add(new StringParameter(result.m_key, result.m_value));
+ }
+ return parameters;
+ }
+
+ private static Component createMainComponent(ArrayList parameters) {
+ int numberParameters = parameters.size();
+ Box outerBox = Box.createHorizontalBox();
+ int i = 0;
+ int numberColumns = 0;
+ JPanel panel = null;
+ GridBagLayout gridbag = null;
+ int gridy = 0;
+ int paramPerColumn = (numberParameters + 1) / (numberParameters / MAX_PARAM_PER_COLUMN + 1);
+ while (i < numberParameters) {
+ if (i % paramPerColumn == 0) {
+ if (panel != null) {
+ if (numberColumns > 0) {
+ outerBox.add(createFiller());
+ outerBox.add(new JSeparator(SwingConstants.VERTICAL));
+ outerBox.add(createFiller());
+ }
+ outerBox.add(panel);
+ ++numberColumns;
}
- return outerBox;
+ gridbag = new GridBagLayout();
+ panel = new JPanel(gridbag);
+ gridy = 0;
+ }
+ parameters.get(i).createComponents(gridy, panel, gridbag);
+ ++gridy;
+ ++i;
}
-
- private static String getNewValueCommand(String paramCommand,
- Parameter parameter)
- {
- String key = parameter.getKey();
- String value = parameter.getNewValue();
- return AnalyzeUtil.getParameterCommand(paramCommand, key, value);
+ if (panel != null) {
+ if (numberColumns > 0) {
+ outerBox.add(createFiller());
+ outerBox.add(new JSeparator(SwingConstants.VERTICAL));
+ outerBox.add(createFiller());
+ }
+ outerBox.add(panel);
}
+ return outerBox;
+ }
- private static void showError(JDialog owner, MessageDialogs messageDialogs,
- Parameter parameter, HtpError e)
- {
- String mainMessage =
- MessageFormat.format("Could not change ",
- parameter.getLabel());
- String optionalMessage = StringUtils.capitalize(e.getMessage());
- messageDialogs.showError(owner, mainMessage, optionalMessage);
- }
+ private static String getNewValueCommand(String paramCommand, Parameter parameter) {
+ String key = parameter.getKey();
+ String value = parameter.getNewValue();
+ return AnalyzeUtil.getParameterCommand(paramCommand, key, value);
+ }
- private static final int SMALL_PAD = 2;
-
- private static final int PAD = 5;
+ private static void showError(
+ JDialog owner, MessageDialogs messageDialogs, Parameter parameter, HtpError e) {
+ String mainMessage = MessageFormat.format("Could not change ", parameter.getLabel());
+ String optionalMessage = StringUtils.capitalize(e.getMessage());
+ messageDialogs.showError(owner, mainMessage, optionalMessage);
+ }
- private static final Dimension FILLER_DIMENSION =
- new Dimension(PAD, PAD);
+ private static final int SMALL_PAD = 2;
- public static Box.Filler createFiller()
- {
- return new Box.Filler(FILLER_DIMENSION, FILLER_DIMENSION,
- FILLER_DIMENSION);
- }
+ private static final int PAD = 5;
+
+ private static final Dimension FILLER_DIMENSION = new Dimension(PAD, PAD);
+ public static Box.Filler createFiller() {
+ return new Box.Filler(FILLER_DIMENSION, FILLER_DIMENSION, FILLER_DIMENSION);
+ }
}
diff --git a/src/main/java/hexgui/gui/PreferencesDialog.java b/src/main/java/hexgui/gui/PreferencesDialog.java
index dc7c375..9fbd960 100644
--- a/src/main/java/hexgui/gui/PreferencesDialog.java
+++ b/src/main/java/hexgui/gui/PreferencesDialog.java
@@ -1,152 +1,127 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
import hexgui.hex.*;
-import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
-
-/** Dialog for changes user preferences.
- */
-public final class PreferencesDialog
- extends JDialog implements ItemListener, ActionListener
-{
- public PreferencesDialog(Frame owner, GuiPreferences preferences)
- {
- super(owner, true);
-
- m_preferences = preferences;
-
- JPanel generalPanel = createGeneralPanel();
- JPanel boardPanel = createBoardPanel();
- JPanel drawPanel = createDrawPanel();
- JPanel buttonPane = createButtonPanel();
-
- JTabbedPane tabbedPane = new JTabbedPane();
- tabbedPane.addTab("General", null,
- generalPanel,
- "General preferences");
- tabbedPane.addTab("Board", null,
- boardPanel,
- "Board preferences");
- tabbedPane.addTab("Draw", null,
- drawPanel,
- "Drawing preferences");
-
- add(tabbedPane, BorderLayout.CENTER);
- add(buttonPane, BorderLayout.SOUTH);
- pack();
-
- setVisible(true);
+import javax.swing.*;
+
+/** Dialog for changes user preferences. */
+public final class PreferencesDialog extends JDialog implements ItemListener, ActionListener {
+ public PreferencesDialog(Frame owner, GuiPreferences preferences) {
+ super(owner, true);
+
+ m_preferences = preferences;
+
+ JPanel generalPanel = createGeneralPanel();
+ JPanel boardPanel = createBoardPanel();
+ JPanel drawPanel = createDrawPanel();
+ JPanel buttonPane = createButtonPanel();
+
+ JTabbedPane tabbedPane = new JTabbedPane();
+ tabbedPane.addTab("General", null, generalPanel, "General preferences");
+ tabbedPane.addTab("Board", null, boardPanel, "Board preferences");
+ tabbedPane.addTab("Draw", null, drawPanel, "Drawing preferences");
+
+ add(tabbedPane, BorderLayout.CENTER);
+ add(buttonPane, BorderLayout.SOUTH);
+ pack();
+
+ setVisible(true);
+ }
+
+ public void itemStateChanged(ItemEvent e) {
+ System.out.println("ItemEvent!");
+ Object source = e.getItemSelectable();
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+ if (cmd.equals("OK")) {
+ savePreferences();
+ dispose();
+ } else if (cmd.equals("Cancel")) {
+ dispose();
}
+ }
- public void itemStateChanged(ItemEvent e)
- {
- System.out.println("ItemEvent!");
- Object source = e.getItemSelectable();
+ private void savePreferences() {
+ System.out.println("Saving preferences...");
- }
+ m_preferences.put("shell-show-on-connect", (showShellOnConnect.getSelectedObjects() != null));
+ m_preferences.put(
+ "analyze-show-on-connect", (showAnalyzeOnConnect.getSelectedObjects() != null));
+ m_preferences.put("auto-respond", (autoRespond.getSelectedObjects() != null));
+ }
- public void actionPerformed(ActionEvent e)
- {
- String cmd = e.getActionCommand();
- if (cmd.equals("OK")) {
- savePreferences();
- dispose();
- } else if (cmd.equals("Cancel")) {
- dispose();
- }
- }
+ private JPanel createGeneralPanel() {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
- private void savePreferences()
- {
- System.out.println("Saving preferences...");
-
- m_preferences.put("shell-show-on-connect",
- (showShellOnConnect.getSelectedObjects() != null));
- m_preferences.put("analyze-show-on-connect",
- (showAnalyzeOnConnect.getSelectedObjects() != null));
- m_preferences.put("auto-respond",
- (autoRespond.getSelectedObjects() != null));
-
- }
+ showShellOnConnect = createCheckBox("Show Shell on Program Connect", "shell-show-on-connect");
- private JPanel createGeneralPanel()
- {
- JPanel panel = new JPanel();
- panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ showAnalyzeOnConnect =
+ createCheckBox("Show Analyze on Program Connect", "analyze-show-on-connect");
- showShellOnConnect = createCheckBox("Show Shell on Program Connect",
- "shell-show-on-connect");
+ autoRespond = createCheckBox("Auto-respond", "auto-respond");
- showAnalyzeOnConnect = createCheckBox("Show Analyze on Program Connect",
- "analyze-show-on-connect");
+ panel.add(showShellOnConnect);
+ panel.add(showAnalyzeOnConnect);
+ panel.add(autoRespond);
- autoRespond = createCheckBox("Auto-respond", "auto-respond");
+ return panel;
+ }
- panel.add(showShellOnConnect);
- panel.add(showAnalyzeOnConnect);
- panel.add(autoRespond);
+ private JPanel createDrawPanel() {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
- return panel;
- }
+ // JLabel label;
- private JPanel createDrawPanel()
- {
- JPanel panel = new JPanel();
- panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ // label = new JLabel("Field alpha percentage");
+ // SpinnerNumberModel model =
+ // new SpinnerNumberModel(m_preferences.getDouble("");
+ // fieldAlpha = new JSpinner(new );
-// JLabel label;
+ return panel;
+ }
-// label = new JLabel("Field alpha percentage");
-// SpinnerNumberModel model =
-// new SpinnerNumberModel(m_preferences.getDouble("");
-// fieldAlpha = new JSpinner(new );
+ private JPanel createBoardPanel() {
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(new JLabel("Board stuff"));
+ return panel;
+ }
- return panel;
- }
+ private JPanel createButtonPanel() {
+ JPanel panel = new JPanel();
+ JButton button = new JButton(" OK ");
+ button.addActionListener(this);
+ button.setActionCommand("OK");
+ panel.add(button);
- private JPanel createBoardPanel()
- {
- JPanel panel = new JPanel(new BorderLayout());
- panel.add(new JLabel("Board stuff"));
- return panel;
- }
+ button = new JButton("Cancel");
+ button.addActionListener(this);
+ button.setActionCommand("Cancel");
+ panel.add(button);
- private JPanel createButtonPanel()
- {
- JPanel panel = new JPanel();
-
- JButton button = new JButton(" OK ");
- button.addActionListener(this);
- button.setActionCommand("OK");
- panel.add(button);
-
- button = new JButton("Cancel");
- button.addActionListener(this);
- button.setActionCommand("Cancel");
- panel.add(button);
-
- return panel;
- }
+ return panel;
+ }
- private JCheckBox createCheckBox(String name, String prefname)
- {
- JCheckBox box = new JCheckBox(name);
- box.setSelected(m_preferences.getBoolean(prefname));
- box.addItemListener(this);
- return box;
- }
+ private JCheckBox createCheckBox(String name, String prefname) {
+ JCheckBox box = new JCheckBox(name);
+ box.setSelected(m_preferences.getBoolean(prefname));
+ box.addItemListener(this);
+ return box;
+ }
- JCheckBox showShellOnConnect, showAnalyzeOnConnect;
- JCheckBox autoRespond;
+ JCheckBox showShellOnConnect, showAnalyzeOnConnect;
+ JCheckBox autoRespond;
- JSpinner fieldAlpha;
+ JSpinner fieldAlpha;
- GuiPreferences m_preferences;
+ GuiPreferences m_preferences;
}
-
diff --git a/src/main/java/hexgui/gui/Print.java b/src/main/java/hexgui/gui/Print.java
index ab9b247..d0dd0e9 100644
--- a/src/main/java/hexgui/gui/Print.java
+++ b/src/main/java/hexgui/gui/Print.java
@@ -1,6 +1,6 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
import java.awt.Component;
@@ -8,28 +8,20 @@
import java.awt.print.PrinterJob;
/** Print a printable. */
-public final class Print
-{
- public static void run(Component parent, Printable printable)
- {
- PrinterJob job = PrinterJob.getPrinterJob();
- job.setPrintable(printable);
- if (! job.printDialog())
- return;
- try
- {
- job.print();
- }
- catch (Exception e)
- {
- System.out.println("Printing failed!");
- }
+public final class Print {
+ public static void run(Component parent, Printable printable) {
+ PrinterJob job = PrinterJob.getPrinterJob();
+ job.setPrintable(printable);
+ if (!job.printDialog()) return;
+ try {
+ job.print();
+ } catch (Exception e) {
+ System.out.println("Printing failed!");
}
+ }
- /** Make constructor unavailable; class is for namespace only. */
- private Print()
- {
- }
+ /** Make constructor unavailable; class is for namespace only. */
+ private Print() {}
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/PrintPreview.java b/src/main/java/hexgui/gui/PrintPreview.java
index 3a64fe9..75816d2 100644
--- a/src/main/java/hexgui/gui/PrintPreview.java
+++ b/src/main/java/hexgui/gui/PrintPreview.java
@@ -1,86 +1,87 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
-//
+//
// The basis of this was stolen from the thread:
// http://forum.java.sun.com/thread.jspa?threadID=601884&messageID=4215335
//
package hexgui.gui;
-import javax.swing.*;
import java.awt.*;
-import javax.swing.event.*;
-import javax.swing.table.*;
-import javax.swing.border.*;
import java.awt.event.*;
-import java.awt.print.*;
import java.awt.image.*;
-
-public class PrintPreview
- extends JPanel implements ActionListener
-{
+import java.awt.print.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import javax.swing.table.*;
+
+public class PrintPreview extends JPanel implements ActionListener {
static final double INITIAL_SCALE_DIVISOR = 1.0; // scale factor
-
+
Component targetComponent;
PageFormat pageFormat = new PageFormat();
double scaleDivisor = INITIAL_SCALE_DIVISOR;
BufferedImage pcImage;
-
+
JPanel hold = new JPanel();
PreviewPage prp;
-
+
ButtonGroup pf = new ButtonGroup();
JRadioButton pf1;
JRadioButton pf2;
JLabel xsl = new JLabel("Scale:", JLabel.LEFT);
JButton preview = new JButton("PREVIEW");
JButton print = new JButton("PRINT");
-
+
JSpinner xsp;
SpinnerNumberModel snmx;
-
+
JFrame workFrame;
-
+
Color bgColor = Color.white;
-
+
int pcw, pch;
double wh, hw;
-
- public PrintPreview(Component pc){
+
+ public PrintPreview(Component pc) {
setBackground(bgColor);
-
+
targetComponent = pc;
-
+
// for a JTable, we can't use simple component.paint(g) call
// because it doesn't paint table header !!
- if (pc instanceof JTable){
- TableModel tm = ((JTable)pc).getModel();
+ if (pc instanceof JTable) {
+ TableModel tm = ((JTable) pc).getModel();
JTable workTable = new JTable(tm); // make pure clone
targetComponent = getTableComponent(workTable);
}
-
- pcImage = new BufferedImage(pcw = targetComponent.getWidth(),
- pch = targetComponent.getHeight(), BufferedImage.TYPE_INT_ARGB);
+
+ pcImage =
+ new BufferedImage(
+ pcw = targetComponent.getWidth(),
+ pch = targetComponent.getHeight(),
+ BufferedImage.TYPE_INT_ARGB);
Graphics g = pcImage.createGraphics();
targetComponent.paint(g);
g.dispose();
- wh = (double)pcw / (double)pch;
- hw = (double)pch / (double)pcw;
+ wh = (double) pcw / (double) pch;
+ hw = (double) pch / (double) pcw;
/* workFrame is used in getTableComponent() method
* only for visualizing the table component and its header
*/
- if (workFrame != null){ // if you don't use table clone here,
- workFrame.dispose(); // calling dispose() delete the table
- } // from original app window
-
+ if (workFrame != null) { // if you don't use table clone here,
+ workFrame.dispose(); // calling dispose() delete the table
+ } // from original app window
+
pageFormat.setOrientation(PageFormat.LANDSCAPE);
prp = new PreviewPage();
-
+
snmx = new SpinnerNumberModel(INITIAL_SCALE_DIVISOR, 1.0, 10.0, 0.1);
xsp = new JSpinner(snmx);
-
+
pf2 = new JRadioButton("Landscape");
pf2.setActionCommand("2");
pf2.setSelected(true);
@@ -91,76 +92,77 @@ public PrintPreview(Component pc){
pf.add(pf1);
pf2.setBackground(bgColor);
pf1.setBackground(bgColor);
-
+
preview.addActionListener(this);
print.addActionListener(this);
-
+
prp.setBackground(bgColor);
hold.setBorder(BorderFactory.createLineBorder(Color.black, 2));
hold.setBackground(bgColor);
hold.setLayout(new GridBagLayout());
-
+
GridBagConstraints c1 = new GridBagConstraints();
-
+
c1.insets = new Insets(15, 45, 0, 5);
c1 = buildConstraints(c1, 0, 0, 2, 1, 0.0, 0.0);
hold.add(pf1, c1);
-
+
c1.insets = new Insets(2, 45, 0, 5);
c1 = buildConstraints(c1, 0, 1, 2, 1, 0.0, 0.0);
hold.add(pf2, c1);
-
+
c1.insets = new Insets(25, 5, 0, 5);
c1 = buildConstraints(c1, 0, 2, 1, 1, 0.0, 0.0);
hold.add(xsl, c1);
-
+
c1.insets = new Insets(25, 5, 0, 35);
c1 = buildConstraints(c1, 1, 2, 1, 1, 0.0, 0.0);
hold.add(xsp, c1);
-
+
c1.insets = new Insets(25, 35, 0, 35);
c1 = buildConstraints(c1, 0, 6, 2, 1, 0.0, 0.0);
hold.add(preview, c1);
-
+
c1.insets = new Insets(5, 35, 25, 35);
c1 = buildConstraints(c1, 0, 7, 2, 1, 0.0, 0.0);
hold.add(print, c1);
-
+
add(hold);
add(prp);
}
-
- Component getTableComponent(JTable table){
+
+ Component getTableComponent(JTable table) {
Box box = new Box(BoxLayout.Y_AXIS);
JTableHeader jth = table.getTableHeader();
-
+
Dimension dh = jth.getPreferredSize();
Dimension dt = table.getPreferredSize();
Dimension db = new Dimension(dh.width, dh.height + dt.height);
box.setPreferredSize(db);
-
- jth.setBorder(new LineBorder(Color.black, 1){
- public Insets getBorderInsets(Component c){
- return new Insets(2, 2, 2, 2);
- }
- });
-
+
+ jth.setBorder(
+ new LineBorder(Color.black, 1) {
+ public Insets getBorderInsets(Component c) {
+ return new Insets(2, 2, 2, 2);
+ }
+ });
+
table.setBorder(new PartialLineBorder(false, true, false, false));
-
+
box.add(jth);
box.add(table);
-
+
// visualize table for getting non-zero sizes(width, height)
workFrame = new JFrame();
workFrame.getContentPane().add(box);
workFrame.pack();
workFrame.setVisible(true);
-
+
return box;
}
-
- GridBagConstraints buildConstraints(GridBagConstraints gbc, int gx, int gy,
- int gw, int gh, double wx, double wy){
+
+ GridBagConstraints buildConstraints(
+ GridBagConstraints gbc, int gx, int gy, int gw, int gh, double wx, double wy) {
gbc.gridx = gx;
gbc.gridy = gy;
gbc.gridwidth = gw;
@@ -170,34 +172,32 @@ GridBagConstraints buildConstraints(GridBagConstraints gbc, int gx, int gy,
gbc.fill = GridBagConstraints.BOTH;
return gbc;
}
-
- public class PreviewPage extends JPanel{
+
+ public class PreviewPage extends JPanel {
int x1, y1, l1, h1, x2, y2;
Image image;
-
- public PreviewPage(){
+
+ public PreviewPage() {
setPreferredSize(new Dimension(460, 460));
setBorder(BorderFactory.createLineBorder(Color.black, 2));
}
-
- public void paintComponent(Graphics g){
+
+ public void paintComponent(Graphics g) {
super.paintComponent(g);
-
+
// PORTRAIT
- if(pageFormat.getOrientation() == PageFormat.PORTRAIT){
+ if (pageFormat.getOrientation() == PageFormat.PORTRAIT) {
g.setColor(Color.black);
g.drawRect(60, 10, 340, 440);
- x1 = (int)Math.rint(((double)pageFormat.getImageableX() / 72) * 40);
- y1 = (int)Math.rint(((double)pageFormat.getImageableY() / 72) * 40);
- l1
- = (int)Math.rint(((double)pageFormat.getImageableWidth() / 72) * 40);
- h1
- = (int)Math.rint(((double)pageFormat.getImageableHeight() / 72) * 40);
+ x1 = (int) Math.rint(((double) pageFormat.getImageableX() / 72) * 40);
+ y1 = (int) Math.rint(((double) pageFormat.getImageableY() / 72) * 40);
+ l1 = (int) Math.rint(((double) pageFormat.getImageableWidth() / 72) * 40);
+ h1 = (int) Math.rint(((double) pageFormat.getImageableHeight() / 72) * 40);
g.setColor(Color.red);
g.drawRect(x1 + 60, y1 + 10, l1, h1);
// setScales(); // commenting-out suppresses too frequent paint updates
- x2 = (int)Math.rint((double)l1 / scaleDivisor);
- y2 = (int)Math.rint(((double)l1 * hw) / scaleDivisor);
+ x2 = (int) Math.rint((double) l1 / scaleDivisor);
+ y2 = (int) Math.rint(((double) l1 * hw) / scaleDivisor);
image = pcImage.getScaledInstance(x2, y2, Image.SCALE_AREA_AVERAGING);
int xspace = (l1 - x2) / 2;
@@ -205,62 +205,58 @@ public void paintComponent(Graphics g){
g.drawImage(image, x1 + 60 + xspace, y1 + 10 + yspace, this);
}
// LANDSCAPE
- else{
+ else {
g.setColor(Color.black);
g.drawRect(10, 60, 440, 340);
- x1 = (int)Math.rint(((double)pageFormat.getImageableX() / 72) * 40);
- y1 = (int)Math.rint(((double)pageFormat.getImageableY() / 72) * 40);
- l1
- = (int)Math.rint(((double)pageFormat.getImageableWidth() / 72) * 40);
- h1
- = (int)Math.rint(((double)pageFormat.getImageableHeight() / 72) * 40);
+ x1 = (int) Math.rint(((double) pageFormat.getImageableX() / 72) * 40);
+ y1 = (int) Math.rint(((double) pageFormat.getImageableY() / 72) * 40);
+ l1 = (int) Math.rint(((double) pageFormat.getImageableWidth() / 72) * 40);
+ h1 = (int) Math.rint(((double) pageFormat.getImageableHeight() / 72) * 40);
g.setColor(Color.red);
g.drawRect(x1 + 10, y1 + 60, l1, h1);
// setScales();
- x2 = (int)Math.rint((double)l1 / scaleDivisor);
- y2 = (int)Math.rint(((double)l1 * hw) / scaleDivisor);
+ x2 = (int) Math.rint((double) l1 / scaleDivisor);
+ y2 = (int) Math.rint(((double) l1 * hw) / scaleDivisor);
image = pcImage.getScaledInstance(x2, y2, Image.SCALE_AREA_AVERAGING);
int xspace = (l1 - x2) / 2;
int yspace = (h1 - y2) / 2;
g.drawImage(image, x1 + 10 + xspace, y1 + 60 + yspace, this);
}
- }
+ }
}
-
- public void actionPerformed(ActionEvent e){
- if(e.getSource() == preview){
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == preview) {
setProperties();
}
- if(e.getSource() == print){
+ if (e.getSource() == print) {
doPrint();
}
}
-
- public void setProperties(){
- if(pf1.isSelected()){
+
+ public void setProperties() {
+ if (pf1.isSelected()) {
pageFormat.setOrientation(PageFormat.PORTRAIT);
- }
- else if(pf2.isSelected()){
+ } else if (pf2.isSelected()) {
pageFormat.setOrientation(PageFormat.LANDSCAPE);
}
setScales();
prp.repaint();
}
-
- public void setScales(){
- try{
- scaleDivisor = ((Double)xsp.getValue()).doubleValue();
- }
- catch (NumberFormatException e) {
+
+ public void setScales() {
+ try {
+ scaleDivisor = ((Double) xsp.getValue()).doubleValue();
+ } catch (NumberFormatException e) {
}
}
-
- public void doPrint(){
+
+ public void doPrint() {
PrintThis();
}
-
- public void PrintThis(){
+
+ public void PrintThis() {
PrinterJob printerJob = PrinterJob.getPrinterJob();
Book book = new Book();
book.append(new PrintPage(), pageFormat);
@@ -269,24 +265,23 @@ public void PrintThis(){
if (doPrint) {
try {
printerJob.print();
- }
- catch (PrinterException exception) {
+ } catch (PrinterException exception) {
System.err.println("Printing error: " + exception);
}
}
}
-
- //public class PrintPage implements Printable{
- class PrintPage implements Printable{
-
+
+ // public class PrintPage implements Printable{
+ class PrintPage implements Printable {
+
public int print(Graphics g, PageFormat format, int pageIndex) {
Graphics2D g2D = (Graphics2D) g;
- g2D.translate(format.getImageableX (), format.getImageableY ());
-// disableDoubleBuffering(mp);
- System.out.println("get i x " + format.getImageableX ());
- System.out.println("get i x " + format.getImageableY ());
- System.out.println("getx: " + format.getImageableWidth() );
- System.out.println("getx: " + format.getImageableHeight() );
+ g2D.translate(format.getImageableX(), format.getImageableY());
+ // disableDoubleBuffering(mp);
+ System.out.println("get i x " + format.getImageableX());
+ System.out.println("get i x " + format.getImageableY());
+ System.out.println("getx: " + format.getImageableWidth());
+ System.out.println("getx: " + format.getImageableHeight());
// scale to fill the page
double dw = format.getImageableWidth();
double dh = format.getImageableHeight();
@@ -296,59 +291,57 @@ public int print(Graphics g, PageFormat format, int pageIndex) {
double yScale = dh / (768 / scaleDivisor);
double scale = Math.min(xScale, yScale);
System.out.println("" + scale);
- g2D.scale( xScale, yScale);
+ g2D.scale(xScale, yScale);
targetComponent.paint(g);
-// enableDoubleBuffering(mp);
+ // enableDoubleBuffering(mp);
return Printable.PAGE_EXISTS;
}
-
+
public void disableDoubleBuffering(Component c) {
RepaintManager currentManager = RepaintManager.currentManager(c);
currentManager.setDoubleBufferingEnabled(false);
}
-
+
public void enableDoubleBuffering(Component c) {
RepaintManager currentManager = RepaintManager.currentManager(c);
currentManager.setDoubleBufferingEnabled(true);
}
}
-
}
-
-class PartialLineBorder extends AbstractBorder{
+
+class PartialLineBorder extends AbstractBorder {
boolean top, left, bottom, right;
-
- public PartialLineBorder(boolean t, boolean l, boolean b, boolean r){
+
+ public PartialLineBorder(boolean t, boolean l, boolean b, boolean r) {
top = t;
left = l;
bottom = b;
right = r;
}
-
- public boolean isBorderOpaque(){
+
+ public boolean isBorderOpaque() {
return true;
}
-
- public Insets getBorderInsets(Component c){
+
+ public Insets getBorderInsets(Component c) {
return new Insets(2, 2, 2, 2);
}
-
- public void paintBorder
- (Component c, Graphics g, int x, int y, int width, int height){
-
- Graphics2D g2 = (Graphics2D)g;
+
+ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+
+ Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(1.0f));
-
- if (top){
+
+ if (top) {
g2.drawLine(x, y, x + width, y);
}
- if (left){
+ if (left) {
g2.drawLine(x, y, x, y + height);
}
- if (bottom){
+ if (bottom) {
g2.drawLine(x, y + height, x + width, y + height);
}
- if (right){
+ if (right) {
g2.drawLine(x + width, y, x + width, y + height);
}
}
diff --git a/src/main/java/hexgui/gui/Program.java b/src/main/java/hexgui/gui/Program.java
index 5101dc9..c37f3e2 100644
--- a/src/main/java/hexgui/gui/Program.java
+++ b/src/main/java/hexgui/gui/Program.java
@@ -1,87 +1,71 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
import hexgui.util.PrefUtil;
-
import java.util.Vector;
import java.util.prefs.Preferences;
/** Hex playing Program. */
-public class Program
-{
- public String m_name;
- public String m_command;
- public String m_working;
+public class Program {
+ public String m_name;
+ public String m_command;
+ public String m_working;
- public Program()
- {
- }
+ public Program() {}
- public Program(String name, String command, String working)
- {
- m_name = name;
- m_command = command;
- m_working = working;
- }
+ public Program(String name, String command, String working) {
+ m_name = name;
+ m_command = command;
+ m_working = working;
+ }
- public String toString()
- {
- return m_name;
- }
+ public String toString() {
+ return m_name;
+ }
- //------------------------------------------------------------------------
+ // ------------------------------------------------------------------------
- public static Vector load()
- {
- Vector programs = new Vector();
- Preferences prefs = PrefUtil.getNode("hexgui/gui/program");
- if (prefs == null)
- return programs;
- int size = prefs.getInt("size", 0);
- for (int i = 0; i < size; ++i)
- {
- prefs = PrefUtil.getNode("hexgui/gui/program/" + i);
- if (prefs == null)
- break;
- String name = prefs.get("name", "");
- String version = prefs.get("version", "");
- String command = prefs.get("command", "");
- String workingDirectory = prefs.get("working-directory", "");
- programs.add(new Program(name, command, workingDirectory));
- }
- return programs;
+ public static Vector load() {
+ Vector programs = new Vector();
+ Preferences prefs = PrefUtil.getNode("hexgui/gui/program");
+ if (prefs == null) return programs;
+ int size = prefs.getInt("size", 0);
+ for (int i = 0; i < size; ++i) {
+ prefs = PrefUtil.getNode("hexgui/gui/program/" + i);
+ if (prefs == null) break;
+ String name = prefs.get("name", "");
+ String version = prefs.get("version", "");
+ String command = prefs.get("command", "");
+ String workingDirectory = prefs.get("working-directory", "");
+ programs.add(new Program(name, command, workingDirectory));
}
+ return programs;
+ }
- public static void save(Vector programs)
- {
- Preferences prefs = PrefUtil.createNode("hexgui/gui/program");
- if (prefs == null)
- return;
- prefs.putInt("size", programs.size());
- for (int i = 0; i < programs.size(); ++i)
- {
- prefs = PrefUtil.createNode("hexgui/gui/program/" + i);
- if (prefs == null)
- break;
- Program p = programs.get(i);
- prefs.put("name", p.m_name);
- prefs.put("command", p.m_command);
- prefs.put("working-directory", p.m_working);
- }
+ public static void save(Vector programs) {
+ Preferences prefs = PrefUtil.createNode("hexgui/gui/program");
+ if (prefs == null) return;
+ prefs.putInt("size", programs.size());
+ for (int i = 0; i < programs.size(); ++i) {
+ prefs = PrefUtil.createNode("hexgui/gui/program/" + i);
+ if (prefs == null) break;
+ Program p = programs.get(i);
+ prefs.put("name", p.m_name);
+ prefs.put("command", p.m_command);
+ prefs.put("working-directory", p.m_working);
}
+ }
- public static Program findWithName(String name, Vector programs)
- {
- for (int i=0; i programs) {
+ for (int i = 0; i < programs.size(); ++i) {
+ Program p = programs.get(i);
+ if (p.m_name.equals(name)) return p;
}
+ return null;
+ }
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/RemoteProgramDialog.java b/src/main/java/hexgui/gui/RemoteProgramDialog.java
index 784a650..b48abdc 100644
--- a/src/main/java/hexgui/gui/RemoteProgramDialog.java
+++ b/src/main/java/hexgui/gui/RemoteProgramDialog.java
@@ -1,34 +1,26 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
import hexgui.hex.*;
-import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
+import javax.swing.*;
-/** Dialog for entering a remote program hostname.
- FIXME: allow port to be set.
- */
-public final class RemoteProgramDialog
-{
- /** Run dialog.
- @return command to run.
- if user aborted.
- */
- public static String show(Component parent, String value)
- {
- String ret = JOptionPane.showInputDialog(parent,
- "Remote Host",
- value);
- return ret;
- }
+/** Dialog for entering a remote program hostname. FIXME: allow port to be set. */
+public final class RemoteProgramDialog {
+ /**
+ * Run dialog.
+ *
+ * @return command to run. if user aborted.
+ */
+ public static String show(Component parent, String value) {
+ String ret = JOptionPane.showInputDialog(parent, "Remote Host", value);
+ return ret;
+ }
- /** Make constructor unavailable; class is for namespace only. */
- private RemoteProgramDialog()
- {
- }
+ /** Make constructor unavailable; class is for namespace only. */
+ private RemoteProgramDialog() {}
}
-
diff --git a/src/main/java/hexgui/gui/ShowAnalyzeText.java b/src/main/java/hexgui/gui/ShowAnalyzeText.java
index a0589a4..6b148a8 100644
--- a/src/main/java/hexgui/gui/ShowAnalyzeText.java
+++ b/src/main/java/hexgui/gui/ShowAnalyzeText.java
@@ -2,84 +2,66 @@
package hexgui.gui;
+import hexgui.hex.HexPoint;
+import hexgui.htp.AnalyzeType;
+// import hexgui.htp.GtpUtil;
+// import hexgui.gui.GuiBoardUtil;
import java.awt.Frame;
-import java.awt.Point;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-import hexgui.hex.HexPoint;
-import hexgui.hex.PointList;
-import hexgui.htp.AnalyzeType;
-//import hexgui.htp.GtpUtil;
-import hexgui.gui.GuiBoard;
-//import hexgui.gui.GuiBoardUtil;
-import hexgui.gui.TextViewer;
-/** Show multi-line text output from analyze command.
- Optionally can reuse window of last output. */
-public final class ShowAnalyzeText
-{
- public ShowAnalyzeText(Frame owner, GuiBoard guiBoard)
- {
- m_owner = owner;
- m_guiBoard = guiBoard;
- }
+/** Show multi-line text output from analyze command. Optionally can reuse window of last output. */
+public final class ShowAnalyzeText {
+ public ShowAnalyzeText(Frame owner, GuiBoard guiBoard) {
+ m_owner = owner;
+ m_guiBoard = guiBoard;
+ }
- public void show(AnalyzeType type, HexPoint pointArg, String title,
- String response, boolean reuseWindow)
- {
- boolean highlight = (type == AnalyzeType.HSTRING
- || type == AnalyzeType.HPSTRING);
- TextViewer.Listener listener = null;
- if (type == AnalyzeType.PSTRING || type == AnalyzeType.HPSTRING)
- listener = new PointSelectionMarker(m_guiBoard);
- // Remove first line, if empty (formatted responses frequently start
- // with an empty line to avoid text on the line with the status
- // character)
- response = response.replaceAll("\\A *\n", "");
- if (reuseWindow && m_textViewer != null)
- m_textViewer.setText(title, response, highlight);
- else
- {
- m_textViewer = new TextViewer(m_owner, title, response, highlight,
- listener);
- m_textViewer.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- m_textViewer = null;
- }
- });
- if (pointArg == null)
- m_textViewer.setLocationByPlatform(true);
- else
- {
- //Point location = m_guiBoard.getLocationOnScreen(pointArg);
- //m_textViewer.setLocation(location);
+ public void show(
+ AnalyzeType type, HexPoint pointArg, String title, String response, boolean reuseWindow) {
+ boolean highlight = (type == AnalyzeType.HSTRING || type == AnalyzeType.HPSTRING);
+ TextViewer.Listener listener = null;
+ if (type == AnalyzeType.PSTRING || type == AnalyzeType.HPSTRING)
+ listener = new PointSelectionMarker(m_guiBoard);
+ // Remove first line, if empty (formatted responses frequently start
+ // with an empty line to avoid text on the line with the status
+ // character)
+ response = response.replaceAll("\\A *\n", "");
+ if (reuseWindow && m_textViewer != null) m_textViewer.setText(title, response, highlight);
+ else {
+ m_textViewer = new TextViewer(m_owner, title, response, highlight, listener);
+ m_textViewer.addWindowListener(
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ m_textViewer = null;
}
- m_textViewer.setVisible(true);
- }
+ });
+ if (pointArg == null) m_textViewer.setLocationByPlatform(true);
+ else {
+ // Point location = m_guiBoard.getLocationOnScreen(pointArg);
+ // m_textViewer.setLocation(location);
+ }
+ m_textViewer.setVisible(true);
}
+ }
- private static class PointSelectionMarker
- implements TextViewer.Listener
- {
- public PointSelectionMarker(GuiBoard guiBoard)
- {
- m_guiBoard = guiBoard;
- }
-
- public void textSelected(String text)
- {
- if (! m_guiBoard.isShowing())
- return;
- //PointList points = GtpUtil.parsePointString(text);
- //GuiBoardUtil.showPointList(m_guiBoard, points);
- }
+ private static class PointSelectionMarker implements TextViewer.Listener {
+ public PointSelectionMarker(GuiBoard guiBoard) {
+ m_guiBoard = guiBoard;
+ }
- private final GuiBoard m_guiBoard;
+ public void textSelected(String text) {
+ if (!m_guiBoard.isShowing()) return;
+ // PointList points = GtpUtil.parsePointString(text);
+ // GuiBoardUtil.showPointList(m_guiBoard, points);
}
- private Frame m_owner;
+ private final GuiBoard m_guiBoard;
+ }
+
+ private Frame m_owner;
- private GuiBoard m_guiBoard;
+ private GuiBoard m_guiBoard;
- private TextViewer m_textViewer;
+ private TextViewer m_textViewer;
}
diff --git a/src/main/java/hexgui/gui/ShowError.java b/src/main/java/hexgui/gui/ShowError.java
index 3d4f3cb..7fba3e0 100644
--- a/src/main/java/hexgui/gui/ShowError.java
+++ b/src/main/java/hexgui/gui/ShowError.java
@@ -1,25 +1,20 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
import java.awt.Component;
import javax.swing.JOptionPane;
-/** Displays a simple error message dialog. */
-public class ShowError
-{
- public static void msg(Component parent, String msg)
- {
- JOptionPane.showMessageDialog(parent, msg, "Error",
- JOptionPane.ERROR_MESSAGE);
- }
+/** Displays a simple error message dialog. */
+public class ShowError {
+ public static void msg(Component parent, String msg) {
+ JOptionPane.showMessageDialog(parent, msg, "Error", JOptionPane.ERROR_MESSAGE);
+ }
- /** No constructor; class is for namespace only. */
- private ShowError()
- {
- }
+ /** No constructor; class is for namespace only. */
+ private ShowError() {}
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/StatusBar.java b/src/main/java/hexgui/gui/StatusBar.java
index 89d8fce..45c4061 100644
--- a/src/main/java/hexgui/gui/StatusBar.java
+++ b/src/main/java/hexgui/gui/StatusBar.java
@@ -1,74 +1,67 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
-import java.io.*;
-import java.util.*;
-import javax.swing.*;
-import javax.swing.border.EtchedBorder;
import java.awt.*;
import java.awt.event.*;
-import java.text.NumberFormat;
+import java.io.*;
import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.border.EtchedBorder;
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
-public class StatusBar
- extends JPanel
-{
- public StatusBar()
- {
- super();
- setLayout(new BorderLayout());
- setMinimumSize(new Dimension(0,25));
- setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
- //setLayout(new FlowLayout(FlowLayout.RIGHT));
+public class StatusBar extends JPanel {
+ public StatusBar() {
+ super();
+ setLayout(new BorderLayout());
+ setMinimumSize(new Dimension(0, 25));
+ setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
+ // setLayout(new FlowLayout(FlowLayout.RIGHT));
- m_message = new JLabel();
- m_message.setHorizontalTextPosition(JLabel.LEFT);
- add(m_message, BorderLayout.WEST);
+ m_message = new JLabel();
+ m_message.setHorizontalTextPosition(JLabel.LEFT);
+ add(m_message, BorderLayout.WEST);
- m_progress = new JProgressBar(0, 1000000);
- m_progress.setValue(0);
- m_progress.setMinimumSize(new Dimension(100, 25));
- m_progress.setStringPainted(true);
- m_progress.setString("");
- m_progress.setVisible(false);
- add(m_progress, BorderLayout.EAST);
+ m_progress = new JProgressBar(0, 1000000);
+ m_progress.setValue(0);
+ m_progress.setMinimumSize(new Dimension(100, 25));
+ m_progress.setStringPainted(true);
+ m_progress.setString("");
+ m_progress.setVisible(false);
+ add(m_progress, BorderLayout.EAST);
- setMessage("Ready");
- setVisible(true);
- }
+ setMessage("Ready");
+ setVisible(true);
+ }
- public void setMessage(String msg)
- {
- assert SwingUtilities.isEventDispatchThread();
- m_message.setText(msg);
- }
+ public void setMessage(String msg) {
+ assert SwingUtilities.isEventDispatchThread();
+ m_message.setText(msg);
+ }
- public void setProgressVisible(boolean visible)
- {
- assert SwingUtilities.isEventDispatchThread();
- m_progress.setVisible(visible);
- }
+ public void setProgressVisible(boolean visible) {
+ assert SwingUtilities.isEventDispatchThread();
+ m_progress.setVisible(visible);
+ }
- public void setProgress(double pct)
- {
- assert SwingUtilities.isEventDispatchThread();
- m_progress.setValue((int)(pct*1000000.0));
+ public void setProgress(double pct) {
+ assert SwingUtilities.isEventDispatchThread();
+ m_progress.setValue((int) (pct * 1000000.0));
- // show 4 decimal places of accuracy
- NumberFormat nf = NumberFormat.getInstance();
- if (nf instanceof DecimalFormat)
- ((DecimalFormat)nf).applyPattern("##0.0000");
+ // show 4 decimal places of accuracy
+ NumberFormat nf = NumberFormat.getInstance();
+ if (nf instanceof DecimalFormat) ((DecimalFormat) nf).applyPattern("##0.0000");
- m_progress.setString(nf.format(pct*100.0)+"%");
- }
+ m_progress.setString(nf.format(pct * 100.0) + "%");
+ }
- JLabel m_message;
- JProgressBar m_progress;
+ JLabel m_message;
+ JProgressBar m_progress;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/gui/TextViewer.java b/src/main/java/hexgui/gui/TextViewer.java
index 5b2f2fe..72d11b0 100644
--- a/src/main/java/hexgui/gui/TextViewer.java
+++ b/src/main/java/hexgui/gui/TextViewer.java
@@ -23,179 +23,147 @@
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
-/** Dialog for displaying text.
- Allows syntax highlighting for analyze commands of type hstring.
-*/
-public final class TextViewer
- extends JDialog
-{
- /** Callback for events generated by TextViewer. */
- public interface Listener
- {
- /** Callback if some text is selected.
- If text is unselected again this function will be called
- with the complete text content of the window.
- */
- void textSelected(String text);
- }
+/**
+ * Dialog for displaying text. Allows syntax highlighting for analyze commands of type
+ * hstring.
+ */
+public final class TextViewer extends JDialog {
+ /** Callback for events generated by TextViewer. */
+ public interface Listener {
+ /**
+ * Callback if some text is selected. If text is unselected again this function will be called
+ * with the complete text content of the window.
+ */
+ void textSelected(String text);
+ }
- public TextViewer(Frame owner, String title, String text,
- boolean highlight, Listener listener)
- {
- super(owner, title);
- initialize(text, highlight, listener);
- }
+ public TextViewer(Frame owner, String title, String text, boolean highlight, Listener listener) {
+ super(owner, title);
+ initialize(text, highlight, listener);
+ }
- public TextViewer(Dialog owner, String title, String text,
- boolean highlight, Listener listener)
- {
- super(owner, title);
- initialize(text, highlight, listener);
- }
+ public TextViewer(Dialog owner, String title, String text, boolean highlight, Listener listener) {
+ super(owner, title);
+ initialize(text, highlight, listener);
+ }
- public void setText(String title, String text, boolean highlight)
- {
- setTitle(title);
- insertText(text);
- if (highlight)
- doSyntaxHighlight();
- }
+ public void setText(String title, String text, boolean highlight) {
+ setTitle(title);
+ insertText(text);
+ if (highlight) doSyntaxHighlight();
+ }
- private JTextPane m_textPane;
+ private JTextPane m_textPane;
- private Listener m_listener;
+ private Listener m_listener;
- private void insertText(String text)
- {
- Document doc = m_textPane.getDocument();
- while (text.charAt(text.length() - 1) == '\n')
- text = text.substring(0, text.length() - 1);
- try
- {
- doc.remove(0, doc.getLength());
- doc.insertString(0, text, null);
- }
- catch (BadLocationException e)
- {
- assert false;
- }
+ private void insertText(String text) {
+ Document doc = m_textPane.getDocument();
+ while (text.charAt(text.length() - 1) == '\n') text = text.substring(0, text.length() - 1);
+ try {
+ doc.remove(0, doc.getLength());
+ doc.insertString(0, text, null);
+ } catch (BadLocationException e) {
+ assert false;
}
+ }
- private void doSyntaxHighlight()
- {
- GuiUtil.addStyle(m_textPane, "title", null, null, true);
- GuiUtil.addStyle(m_textPane, "point", new Color(0.25f, 0.5f, 0.7f));
- GuiUtil.addStyle(m_textPane, "number", new Color(0f, 0.54f, 0f));
- GuiUtil.addStyle(m_textPane, "const", new Color(0.8f, 0f, 0f));
- GuiUtil.addStyle(m_textPane, "color", new Color(0.54f, 0f, 0.54f));
- m_textPane.setEditable(true);
- highlight("number", "\\b-?\\d+\\.?\\d*([Ee][+-]\\d+)?\\b");
- highlight("const", "\\b[A-Z_][A-Z_]+[A-Z]\\b");
- highlight("color",
- "\\b([Bb][Ll][Aa][Cc][Kk]|[Ww][Hh][Ii][Tt][Ee])\\b");
- highlight("point", "\\b([Pp][Aa][Ss][Ss]|[A-Ta-t](1\\d|[1-9]))\\b");
- highlight("title", "^\\S+:(\\s|$)");
- m_textPane.setEditable(false);
- }
+ private void doSyntaxHighlight() {
+ GuiUtil.addStyle(m_textPane, "title", null, null, true);
+ GuiUtil.addStyle(m_textPane, "point", new Color(0.25f, 0.5f, 0.7f));
+ GuiUtil.addStyle(m_textPane, "number", new Color(0f, 0.54f, 0f));
+ GuiUtil.addStyle(m_textPane, "const", new Color(0.8f, 0f, 0f));
+ GuiUtil.addStyle(m_textPane, "color", new Color(0.54f, 0f, 0.54f));
+ m_textPane.setEditable(true);
+ highlight("number", "\\b-?\\d+\\.?\\d*([Ee][+-]\\d+)?\\b");
+ highlight("const", "\\b[A-Z_][A-Z_]+[A-Z]\\b");
+ highlight("color", "\\b([Bb][Ll][Aa][Cc][Kk]|[Ww][Hh][Ii][Tt][Ee])\\b");
+ highlight("point", "\\b([Pp][Aa][Ss][Ss]|[A-Ta-t](1\\d|[1-9]))\\b");
+ highlight("title", "^\\S+:(\\s|$)");
+ m_textPane.setEditable(false);
+ }
- private void highlight(String styleName, String regex)
- {
- Document doc = m_textPane.getDocument();
- Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
- try
- {
- CharSequence text = doc.getText(0, doc.getLength());
- Matcher matcher = pattern.matcher(text);
- while (matcher.find())
- {
- int start = matcher.start();
- int end = matcher.end();
- GuiUtil.setStyle(m_textPane, start, end - start, styleName);
- }
- }
- catch (BadLocationException e)
- {
- assert false;
- }
+ private void highlight(String styleName, String regex) {
+ Document doc = m_textPane.getDocument();
+ Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
+ try {
+ CharSequence text = doc.getText(0, doc.getLength());
+ Matcher matcher = pattern.matcher(text);
+ while (matcher.find()) {
+ int start = matcher.start();
+ int end = matcher.end();
+ GuiUtil.setStyle(m_textPane, start, end - start, styleName);
+ }
+ } catch (BadLocationException e) {
+ assert false;
}
+ }
- private void initialize(String text, boolean highlight, Listener listener)
- {
- m_listener = listener;
- JPanel panel = new JPanel(new BorderLayout());
- Container contentPane = getContentPane();
- contentPane.add(panel, BorderLayout.CENTER);
- m_textPane = new JTextPane();
- GuiUtil.setMonospacedFont(m_textPane);
- insertText(text);
- JScrollPane scrollPane = new JScrollPane(m_textPane);
- panel.add(scrollPane, BorderLayout.CENTER);
- setDefaultCloseOperation(DISPOSE_ON_CLOSE);
- KeyListener keyListener = new KeyAdapter()
- {
- public void keyReleased(KeyEvent e)
- {
- int c = e.getKeyCode();
- if (c == KeyEvent.VK_ESCAPE)
- dispose();
- }
- };
- m_textPane.addKeyListener(keyListener);
- CaretListener caretListener = new CaretListener()
- {
- public void caretUpdate(CaretEvent event)
- {
- if (m_listener == null)
- return;
- int start = m_textPane.getSelectionStart();
- int end = m_textPane.getSelectionEnd();
- Document doc = m_textPane.getDocument();
- try
- {
- if (start == end)
- {
- String text = doc.getText(0, doc.getLength());
- m_listener.textSelected(text);
- return;
- }
- String text = doc.getText(start, end - start);
- m_listener.textSelected(text);
- }
- catch (BadLocationException e)
- {
- assert false;
- }
- }
- };
- m_textPane.addCaretListener(caretListener);
- if (highlight)
- doSyntaxHighlight();
- m_textPane.setCaretPosition(0);
- m_textPane.setEditable(false);
- packTextViewer();
- }
+ private void initialize(String text, boolean highlight, Listener listener) {
+ m_listener = listener;
+ JPanel panel = new JPanel(new BorderLayout());
+ Container contentPane = getContentPane();
+ contentPane.add(panel, BorderLayout.CENTER);
+ m_textPane = new JTextPane();
+ GuiUtil.setMonospacedFont(m_textPane);
+ insertText(text);
+ JScrollPane scrollPane = new JScrollPane(m_textPane);
+ panel.add(scrollPane, BorderLayout.CENTER);
+ setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+ KeyListener keyListener =
+ new KeyAdapter() {
+ public void keyReleased(KeyEvent e) {
+ int c = e.getKeyCode();
+ if (c == KeyEvent.VK_ESCAPE) dispose();
+ }
+ };
+ m_textPane.addKeyListener(keyListener);
+ CaretListener caretListener =
+ new CaretListener() {
+ public void caretUpdate(CaretEvent event) {
+ if (m_listener == null) return;
+ int start = m_textPane.getSelectionStart();
+ int end = m_textPane.getSelectionEnd();
+ Document doc = m_textPane.getDocument();
+ try {
+ if (start == end) {
+ String text = doc.getText(0, doc.getLength());
+ m_listener.textSelected(text);
+ return;
+ }
+ String text = doc.getText(start, end - start);
+ m_listener.textSelected(text);
+ } catch (BadLocationException e) {
+ assert false;
+ }
+ }
+ };
+ m_textPane.addCaretListener(caretListener);
+ if (highlight) doSyntaxHighlight();
+ m_textPane.setCaretPosition(0);
+ m_textPane.setEditable(false);
+ packTextViewer();
+ }
- private void packTextViewer()
- {
- pack();
- // Workaround for problems with oversized windows on some platforms
- // Also increase width by 10%, because automatic computation of
- // JTextPane/JTextArea width according to content text does not
- // work (maybe related to Sun Bug 4829215)
- Dimension size = getSize();
- size.width *= 1.1;
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
- int maxHeight = (int)(0.9 * screenSize.height);
- int maxWidth = (int)(0.9 * screenSize.width);
- if (size.height > maxHeight || size.width > maxWidth)
- {
- size.width = Math.min(size.width, maxWidth);
- size.height = Math.min(size.height, maxHeight);
- }
- setMinimumSize(new Dimension(128, 96));
- size.height = Math.max(size.height, 96);
- size.width = Math.max(size.width, 128);
- setPreferredSize(size);
- setSize(size);
+ private void packTextViewer() {
+ pack();
+ // Workaround for problems with oversized windows on some platforms
+ // Also increase width by 10%, because automatic computation of
+ // JTextPane/JTextArea width according to content text does not
+ // work (maybe related to Sun Bug 4829215)
+ Dimension size = getSize();
+ size.width *= 1.1;
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ int maxHeight = (int) (0.9 * screenSize.height);
+ int maxWidth = (int) (0.9 * screenSize.width);
+ if (size.height > maxHeight || size.width > maxWidth) {
+ size.width = Math.min(size.width, maxWidth);
+ size.height = Math.min(size.height, maxHeight);
}
+ setMinimumSize(new Dimension(128, 96));
+ size.height = Math.max(size.height, 96);
+ size.width = Math.max(size.width, 128);
+ setPreferredSize(size);
+ setSize(size);
+ }
}
diff --git a/src/main/java/hexgui/gui/VCDisplayDialog.java b/src/main/java/hexgui/gui/VCDisplayDialog.java
index 2e1119c..7eae615 100644
--- a/src/main/java/hexgui/gui/VCDisplayDialog.java
+++ b/src/main/java/hexgui/gui/VCDisplayDialog.java
@@ -1,100 +1,84 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.gui;
import hexgui.hex.*;
-import hexgui.htp.HtpController;
-
-import javax.swing.*;
-import javax.swing.text.*;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.event.ListSelectionEvent;
-
import java.awt.*;
import java.awt.event.*;
-
import java.util.*;
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.text.*;
+
+// ----------------------------------------------------------------------------
+
+/** Non-modal dialog displaying list of VCs. Clicking on a vc displays it to the given GuiBoard. */
+public class VCDisplayDialog extends JDialog implements ListSelectionListener, FocusListener {
+ public VCDisplayDialog(JFrame owner, GuiBoard board, Vector vcs) {
+ super(owner, "HexGui: VCs");
+
+ addWindowListener(
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent winEvt) {
+ dispose();
+ }
+ });
+
+ m_guiboard = board;
+
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+
+ m_list = new JList();
+ m_list.addFocusListener(this);
+ m_list.addListSelectionListener(this);
+ m_list.setDragEnabled(false);
+ m_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+ m_scrollpane = new JScrollPane(m_list);
+ m_scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+
+ panel.add(m_scrollpane);
+ add(panel);
+
+ pack();
+
+ Dimension size = owner.getSize();
+ setLocation(0, size.height);
+
+ setVCs(vcs);
+ setVisible(true);
+ }
+
+ public void setVCs(Vector vcs) {
+ m_vcs = vcs;
+ m_list.setListData(vcs);
+ }
+
+ public void valueChanged(ListSelectionEvent e) {
+ if (m_list.isSelectionEmpty()) return;
+
+ VC vc = m_vcs.get(m_list.getSelectedIndex());
+ if (vc.getType().equals("softlimit")) // do nothing on this
+ return;
+ m_guiboard.clearMarks();
+ m_guiboard.displayVC(vc);
+ m_guiboard.repaint();
+ }
+
+ public void focusGained(FocusEvent e) {}
+
+ public void focusLost(FocusEvent e) {
+ m_list.clearSelection();
+ }
-//----------------------------------------------------------------------------
-
-/** Non-modal dialog displaying list of VCs. Clicking on a vc displays
- it to the given GuiBoard. */
-public class VCDisplayDialog
- extends JDialog implements ListSelectionListener,
- FocusListener
-{
- public VCDisplayDialog(JFrame owner, GuiBoard board, Vector vcs)
- {
- super(owner, "HexGui: VCs");
-
- addWindowListener(new WindowAdapter()
- {
- public void windowClosing(WindowEvent winEvt) {
- dispose();
- }
- });
-
- m_guiboard = board;
-
- JPanel panel = new JPanel();
- panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
-
- m_list = new JList();
- m_list.addFocusListener(this);
- m_list.addListSelectionListener(this);
- m_list.setDragEnabled(false);
- m_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-
- m_scrollpane = new JScrollPane(m_list);
- m_scrollpane.setVerticalScrollBarPolicy(
- JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
-
- panel.add(m_scrollpane);
- add(panel);
-
- pack();
-
- Dimension size = owner.getSize();
- setLocation(0, size.height);
-
- setVCs(vcs);
- setVisible(true);
- }
-
- public void setVCs(Vector vcs)
- {
- m_vcs = vcs;
- m_list.setListData(vcs);
- }
-
- public void valueChanged(ListSelectionEvent e)
- {
- if (m_list.isSelectionEmpty())
- return;
-
- VC vc = m_vcs.get(m_list.getSelectedIndex());
- if (vc.getType().equals("softlimit")) // do nothing on this
- return;
- m_guiboard.clearMarks();
- m_guiboard.displayVC(vc);
- m_guiboard.repaint();
- }
-
- public void focusGained(FocusEvent e)
- {
- }
-
- public void focusLost(FocusEvent e)
- {
- m_list.clearSelection();
- }
-
- private JList m_list;
- private JScrollPane m_scrollpane;
- private Vector m_vcs;
- private GuiBoard m_guiboard;
+ private JList m_list;
+ private JScrollPane m_scrollpane;
+ private Vector m_vcs;
+ private GuiBoard m_guiboard;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/hex/ConstPointList.java b/src/main/java/hexgui/hex/ConstPointList.java
index e70b203..2dc0ada 100644
--- a/src/main/java/hexgui/hex/ConstPointList.java
+++ b/src/main/java/hexgui/hex/ConstPointList.java
@@ -4,24 +4,25 @@
import java.util.Iterator;
-/** Const functions of go.PointList.
- @see PointList */
-public interface ConstPointList
- extends Iterable
-{
- boolean contains(Object elem);
+/**
+ * Const functions of go.PointList.
+ *
+ * @see PointList
+ */
+public interface ConstPointList extends Iterable {
+ boolean contains(Object elem);
- boolean equals(Object object);
+ boolean equals(Object object);
- HexPoint get(int index);
+ HexPoint get(int index);
- int hashCode();
+ int hashCode();
- boolean isEmpty();
+ boolean isEmpty();
- Iterator iterator();
+ Iterator iterator();
- int size();
+ int size();
- String toString();
+ String toString();
}
diff --git a/src/main/java/hexgui/hex/HexColor.java b/src/main/java/hexgui/hex/HexColor.java
index bd19fe5..bb15f3a 100644
--- a/src/main/java/hexgui/hex/HexColor.java
+++ b/src/main/java/hexgui/hex/HexColor.java
@@ -1,55 +1,53 @@
package hexgui.hex;
/** Possible states of a cell on a Hex board (black, white, or empty). */
-public final class HexColor
-{
- public static final HexColor EMPTY;
- public static final HexColor WHITE;
- public static final HexColor BLACK;
-
- /** Returns a string representation of this color.
- @return "black", "white", or "empty".
- */
- public String toString()
- {
- return m_string;
- }
-
- /** Returns the other opposite color.
- @return WHITE for BLACK, BLACK for WHITE, EMPTY otherwise.
- */
- public HexColor otherColor()
- {
- return m_otherColor;
- }
-
- public static HexColor get(String name)
- {
- if (name.equals("black")) return BLACK;
- if (name.equals("white")) return WHITE;
- if (name.equals("empty")) return EMPTY;
- return null;
- }
-
- private final String m_string;
- private HexColor m_otherColor;
-
- static
- {
- BLACK = new HexColor("black");
- WHITE = new HexColor("white");
- EMPTY = new HexColor("empty");
- BLACK.setOtherColor(WHITE);
- WHITE.setOtherColor(BLACK);
- EMPTY.setOtherColor(EMPTY);
- }
-
- private HexColor(String string)
- {
- m_string = string;
- }
- private void setOtherColor(HexColor color)
- {
- m_otherColor = color;
- }
+public final class HexColor {
+ public static final HexColor EMPTY;
+ public static final HexColor WHITE;
+ public static final HexColor BLACK;
+
+ /**
+ * Returns a string representation of this color.
+ *
+ * @return "black", "white", or "empty".
+ */
+ public String toString() {
+ return m_string;
+ }
+
+ /**
+ * Returns the other opposite color.
+ *
+ * @return WHITE for BLACK, BLACK for WHITE, EMPTY otherwise.
+ */
+ public HexColor otherColor() {
+ return m_otherColor;
+ }
+
+ public static HexColor get(String name) {
+ if (name.equals("black")) return BLACK;
+ if (name.equals("white")) return WHITE;
+ if (name.equals("empty")) return EMPTY;
+ return null;
+ }
+
+ private final String m_string;
+ private HexColor m_otherColor;
+
+ static {
+ BLACK = new HexColor("black");
+ WHITE = new HexColor("white");
+ EMPTY = new HexColor("empty");
+ BLACK.setOtherColor(WHITE);
+ WHITE.setOtherColor(BLACK);
+ EMPTY.setOtherColor(EMPTY);
+ }
+
+ private HexColor(String string) {
+ m_string = string;
+ }
+
+ private void setOtherColor(HexColor color) {
+ m_otherColor = color;
+ }
}
diff --git a/src/main/java/hexgui/hex/HexPoint.java b/src/main/java/hexgui/hex/HexPoint.java
index 838f75d..542895c 100644
--- a/src/main/java/hexgui/hex/HexPoint.java
+++ b/src/main/java/hexgui/hex/HexPoint.java
@@ -1,185 +1,165 @@
package hexgui.hex;
-import java.lang.Exception;
-import java.lang.NumberFormatException;
-import java.awt.Dimension;
-
-/** A cell on a Hex board.
- In addition to each playable cell, HexPoints are created for each edge of
- the board and for some special cases like swap moves, resignations, and
- forfeitures. */
-public final class HexPoint implements Comparable
-{
- /** Exception. */
- public static class InvalidHexPointException
- extends Exception
- {
- public InvalidHexPointException(String message)
- {
- super("Invalid point: " + message);
- }
- }
-
- public static final HexPoint NORTH;
- public static final HexPoint SOUTH;
- public static final HexPoint WEST;
- public static final HexPoint EAST;
- public static final HexPoint SWAP_SIDES;
- public static final HexPoint SWAP_PIECES;
- public static final HexPoint PASS;
- public static final HexPoint RESIGN;
- public static final HexPoint FORFEIT;
- public static final HexPoint INVALID;
-
- public static final int MAX_WIDTH = 19;
- public static final int MAX_HEIGHT = 19;
- public static final int MAX_POINTS = MAX_WIDTH*MAX_HEIGHT + 10;
-
- public static final int DEFAULT_SIZE = 11;
-
- private static HexPoint s_points[];
-
- static
- {
- s_points = new HexPoint[MAX_POINTS];
-
- INVALID = s_points[0] = new HexPoint(0, "invalid");
- RESIGN = s_points[1] = new HexPoint(1, "resign");
- FORFEIT = s_points[2] = new HexPoint(2, "forfeit");
- SWAP_SIDES = s_points[3] = new HexPoint(3, "swap-sides");
- SWAP_PIECES = s_points[4] = new HexPoint(4, "swap-pieces");
- PASS = s_points[5] = new HexPoint(5, "pass");
-
- NORTH = s_points[6] = new HexPoint(6, "north");
- EAST = s_points[7] = new HexPoint(7, "east");
- SOUTH = s_points[8] = new HexPoint(8, "south");
- WEST = s_points[9] = new HexPoint(9, "west");
-
- for (int y=0; y= 0);
- assert(i < MAX_POINTS);
- return s_points[i];
- }
-
- /** Returns the point with the given coordinates. Note that it is
- not possible to obtain points for board edges and special
- moves with this method. Use the get(String)
- method for these types of points.
-
- @param x x-coordinate of point
- @param y y-coordinate of point
- @return point with coordinates (x,y).
- */
- public static HexPoint get(int x, int y)
- {
- assert(x >= 0);
- assert(y >= 0);
- assert(x < MAX_WIDTH);
- assert(y < MAX_HEIGHT);
- return s_points[10 + y*MAX_WIDTH + x];
- }
-
- /** Returns the point with the given string representation.
- Valid special moves include: "north", "south", "east", "west"
- "swap-sides", "swap-pieces", "pass", "resign", and "forfeit".
- @param name The name of the point to return
- @return the point or null if name is invalid.
- */
- public static HexPoint get(String name)
- {
- if (name.equalsIgnoreCase("swap"))
- return SWAP_SIDES;
-
- for (int x=0; x= 0);
+ assert (i < MAX_POINTS);
+ return s_points[i];
+ }
+
+ /**
+ * Returns the point with the given coordinates. Note that it is not possible to obtain points for
+ * board edges and special moves with this method. Use the get(String) method for
+ * these types of points.
+ *
+ * @param x x-coordinate of point
+ * @param y y-coordinate of point
+ * @return point with coordinates (x,y).
+ */
+ public static HexPoint get(int x, int y) {
+ assert (x >= 0);
+ assert (y >= 0);
+ assert (x < MAX_WIDTH);
+ assert (y < MAX_HEIGHT);
+ return s_points[10 + y * MAX_WIDTH + x];
+ }
+
+ /**
+ * Returns the point with the given string representation. Valid special moves include: "north",
+ * "south", "east", "west" "swap-sides", "swap-pieces", "pass", "resign", and "forfeit".
+ *
+ * @param name The name of the point to return
+ * @return the point or null if name is invalid.
+ */
+ public static HexPoint get(String name) {
+ if (name.equalsIgnoreCase("swap")) return SWAP_SIDES;
+
+ for (int x = 0; x < MAX_POINTS; x++) {
+ if (name.equalsIgnoreCase(s_points[x].toString())) {
+ return s_points[x];
+ }
}
-
- private HexPoint(int p, String name)
- {
- this.x = -1;
- this.y = p-10;
- m_string = name;
+ assert (false);
+ return null;
+ }
+
+ /** Returns the string representation of the point. */
+ public String toString() {
+ return m_string;
+ }
+
+ /**
+ * Convert a list of points to a string. Points are separated by a single space. If pointList is
+ * null, "(null)" is returned.
+ */
+ public static String toString(ConstPointList pointList) {
+ if (pointList == null) return "(null)";
+ int length = pointList.size();
+ StringBuilder buffer = new StringBuilder(length * 4);
+ for (int i = 0; i < length; ++i) {
+ buffer.append(pointList.get(i));
+ if (i < length - 1) buffer.append(' ');
}
-
- private HexPoint(int x, int y, String name)
- {
- this.x = x;
- this.y = y;
- m_string = name;
+ return buffer.toString();
+ }
+
+ public int compareTo(Object other) {
+ if (other instanceof HexPoint) {
+ HexPoint o = (HexPoint) other;
+ if (this.x == o.x && this.y == o.y) return 0;
+ if (this.x != o.x) return this.x - o.x;
+ return this.y - o.y;
}
-
- /** return the HexPoint that is opposite to this one, across the
- long diagonal. */
- public HexPoint reflect()
- {
- return HexPoint.get(this.y, this.x);
- }
-
- /** return true is the point is a ordinary cell on the board (i.e.,
- * not something like NORTH, SWAP_SIDES, PASS, RESIGN, etc */
- public boolean is_cell()
- {
- return this.x >= 0;
- }
-
-
-
- public final int x, y;
- private final String m_string;
+ return -1;
+ }
+
+ private HexPoint(int p, String name) {
+ this.x = -1;
+ this.y = p - 10;
+ m_string = name;
+ }
+
+ private HexPoint(int x, int y, String name) {
+ this.x = x;
+ this.y = y;
+ m_string = name;
+ }
+
+ /** return the HexPoint that is opposite to this one, across the long diagonal. */
+ public HexPoint reflect() {
+ return HexPoint.get(this.y, this.x);
+ }
+
+ /**
+ * return true is the point is a ordinary cell on the board (i.e., not something like NORTH,
+ * SWAP_SIDES, PASS, RESIGN, etc
+ */
+ public boolean is_cell() {
+ return this.x >= 0;
+ }
+
+ public final int x, y;
+ private final String m_string;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/hex/Move.java b/src/main/java/hexgui/hex/Move.java
index a7c4067..2fa0f5b 100644
--- a/src/main/java/hexgui/hex/Move.java
+++ b/src/main/java/hexgui/hex/Move.java
@@ -1,63 +1,63 @@
-//----------------------------------------------------------------------------
-// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+// $Id$
+// ----------------------------------------------------------------------------
package hexgui.hex;
-//----------------------------------------------------------------------------
-
-/** Move.
- Contains a HexPoint and a HexColor. To construct swap moves or
- other special moves use the appropriate HexPoint. Immutable.
-*/
-public final class Move
-{
- /** Constructs a move with the given point and color.
- @param p location of move
- @param c black or white.
- */
- public Move(HexPoint p, HexColor c)
- {
- m_point = p;
- m_color = c;
- }
-
- /** Convert to string */
- public String toString()
- {
- return "Move(" + m_point + ", " + m_color + ")";
- }
-
- /** Determines whether this move is equal to the given move.
- @param other move to compare it to.
- @return true if points and colors are equal, false otherwise.
- */
- public boolean equals(Move other)
- {
- if (m_point == other.getPoint() && m_color == other.getColor())
- return true;
- return false;
- }
-
- /** Returns the point of this move.
- @return HexPoint of the location.
- */
- public HexPoint getPoint()
- {
- return m_point;
- }
-
- /** Returns the color of the move.
- @return HexColor of the move (WHITE or BLACK or, in case of a
- setup move, sometimes EMPTY).
- */
- public HexColor getColor()
- {
- return m_color;
- }
-
- private final HexPoint m_point;
- private final HexColor m_color;
+// ----------------------------------------------------------------------------
+
+/**
+ * Move. Contains a HexPoint and a HexColor. To construct swap moves or other special moves use the
+ * appropriate HexPoint. Immutable.
+ */
+public final class Move {
+ /**
+ * Constructs a move with the given point and color.
+ *
+ * @param p location of move
+ * @param c black or white.
+ */
+ public Move(HexPoint p, HexColor c) {
+ m_point = p;
+ m_color = c;
+ }
+
+ /** Convert to string */
+ public String toString() {
+ return "Move(" + m_point + ", " + m_color + ")";
+ }
+
+ /**
+ * Determines whether this move is equal to the given move.
+ *
+ * @param other move to compare it to.
+ * @return true if points and colors are equal, false otherwise.
+ */
+ public boolean equals(Move other) {
+ if (m_point == other.getPoint() && m_color == other.getColor()) return true;
+ return false;
+ }
+
+ /**
+ * Returns the point of this move.
+ *
+ * @return HexPoint of the location.
+ */
+ public HexPoint getPoint() {
+ return m_point;
+ }
+
+ /**
+ * Returns the color of the move.
+ *
+ * @return HexColor of the move (WHITE or BLACK or, in case of a setup move, sometimes EMPTY).
+ */
+ public HexColor getColor() {
+ return m_color;
+ }
+
+ private final HexPoint m_point;
+ private final HexColor m_color;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/hex/PointList.java b/src/main/java/hexgui/hex/PointList.java
index 6e0f7df..aea45d5 100644
--- a/src/main/java/hexgui/hex/PointList.java
+++ b/src/main/java/hexgui/hex/PointList.java
@@ -7,124 +7,108 @@
import java.util.Vector;
/** List containing points. */
-public final class PointList
- extends ArrayList
- implements ConstPointList
-{
- public class ConstIterator
- implements Iterator
- {
- public boolean hasNext()
- {
- return (m_index < size());
- }
-
- public HexPoint next()
- {
- return get(m_index++);
- }
-
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
-
- private int m_index;
+public final class PointList extends ArrayList implements ConstPointList {
+ public class ConstIterator implements Iterator {
+ public boolean hasNext() {
+ return (m_index < size());
}
- /** Construct empty point list. */
- public PointList()
- {
- this(0);
+ public HexPoint next() {
+ return get(m_index++);
}
- /** Construct empty point list with initial capacity.
- @param initialCapacity The number of points to reserve memory for. */
- public PointList(int initialCapacity)
- {
- super(initialCapacity);
+ public void remove() {
+ throw new UnsupportedOperationException();
}
- /** Construct point list with a single element.
- @param p The initial point element. */
- public PointList(HexPoint p)
- {
- this(1);
- add(p);
+ private int m_index;
+ }
+
+ /** Construct empty point list. */
+ public PointList() {
+ this(0);
+ }
+
+ /**
+ * Construct empty point list with initial capacity.
+ *
+ * @param initialCapacity The number of points to reserve memory for.
+ */
+ public PointList(int initialCapacity) {
+ super(initialCapacity);
+ }
+
+ /**
+ * Construct point list with a single element.
+ *
+ * @param p The initial point element.
+ */
+ public PointList(HexPoint p) {
+ this(1);
+ add(p);
+ }
+
+ /**
+ * Construct point list as a copy of another point list.
+ *
+ * @param list The list to copy the points from.
+ */
+ public PointList(ConstPointList list) {
+ super((PointList) list);
+ }
+
+ public PointList(Vector v) {
+ for (int i = 0; i < v.size(); i++) add(v.get(i));
+ }
+
+ /** Add points of another list at the end of this list. */
+ public void addAllFromConst(ConstPointList list) {
+ addAll((PointList) list);
+ }
+
+ /**
+ * Get an empty constant point list. Can be used at places where an empty temporary point list is
+ * needed that is never modified to avoid memory allocation.
+ */
+ public static ConstPointList getEmptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * Returns an iterator over the points elements in this list. An iterator of type
+ * PointList.ConstIterator is returned, which does not support Iterator.remove(), to allow
+ * for-each-loops for ConstPointList references.
+ */
+ public Iterator iterator() {
+ return new ConstIterator();
+ }
+
+ /** Remove and return last element. Requires that list is not empty. */
+ public HexPoint pop() {
+ int index = size() - 1;
+ if (index < 0) {
+ assert false;
+ return null;
}
-
- /** Construct point list as a copy of another point list.
- @param list The list to copy the points from. */
- public PointList(ConstPointList list)
- {
- super((PointList)list);
- }
-
- public PointList(Vector v)
- {
- for (int i = 0; i < v.size(); i++)
- add(v.get(i));
- }
-
- /** Add points of another list at the end of this list. */
- public void addAllFromConst(ConstPointList list)
- {
- addAll((PointList)list);
- }
-
- /** Get an empty constant point list.
- Can be used at places where an empty temporary point list is needed
- that is never modified to avoid memory allocation. */
- public static ConstPointList getEmptyList()
- {
- return EMPTY_LIST;
+ HexPoint p = get(index);
+ remove(index);
+ return p;
+ }
+
+ public String toString() {
+ StringBuilder buffer = new StringBuilder();
+ for (int i = 0; i < size(); ++i) {
+ if (i > 0) buffer.append(' ');
+ buffer.append(get(i));
}
+ return buffer.toString();
+ }
- /** Returns an iterator over the points elements in this list.
- An iterator of type PointList.ConstIterator is returned, which
- does not support Iterator.remove(), to allow for-each-loops for
- ConstPointList references. */
- public Iterator iterator()
- {
- return new ConstIterator();
- }
-
- /** Remove and return last element.
- Requires that list is not empty. */
- public HexPoint pop()
- {
- int index = size() - 1;
- if (index < 0)
- {
- assert false;
- return null;
- }
- HexPoint p = get(index);
- remove(index);
- return p;
- }
-
- public String toString()
- {
- StringBuilder buffer = new StringBuilder();
- for (int i = 0; i < size(); ++i)
- {
- if (i > 0)
- buffer.append(' ');
- buffer.append(get(i));
- }
- return buffer.toString();
- }
-
- /** Convert point list to string.
- Null arguments will be converted to an empty string. */
- public static String toString(ConstPointList list)
- {
- if (list == null)
- return "";
- else
- return list.toString();
- }
+ /** Convert point list to string. Null arguments will be converted to an empty string. */
+ public static String toString(ConstPointList list) {
+ if (list == null) return "";
+ else return list.toString();
+ }
- private static final ConstPointList EMPTY_LIST = new PointList();
+ private static final ConstPointList EMPTY_LIST = new PointList();
}
diff --git a/src/main/java/hexgui/hex/VC.java b/src/main/java/hexgui/hex/VC.java
index 067570e..fa4784c 100644
--- a/src/main/java/hexgui/hex/VC.java
+++ b/src/main/java/hexgui/hex/VC.java
@@ -1,107 +1,133 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.hex;
import java.util.Vector;
-//----------------------------------------------------------------------------
-
-/**
- VC.
- A connection between two cells.
-*/
-public class VC
-{
- /** Constructs a VC. */
- public VC(HexPoint from, HexPoint to, HexColor c, String type)
- {
- this(from, to, c, type, "unknown", 0,
- new Vector(),
- new Vector(),
- new Vector());
+// ----------------------------------------------------------------------------
+
+/** VC. A connection between two cells. */
+public class VC {
+ /** Constructs a VC. */
+ public VC(HexPoint from, HexPoint to, HexColor c, String type) {
+ this(
+ from,
+ to,
+ c,
+ type,
+ "unknown",
+ 0,
+ new Vector(),
+ new Vector(),
+ new Vector());
+ }
+
+ public VC(
+ HexPoint from,
+ HexPoint to,
+ HexColor c,
+ String type,
+ String source,
+ int moves,
+ Vector carrier,
+ Vector stones,
+ Vector key) {
+ m_from = from;
+ m_to = to;
+ m_color = c;
+ m_type = type;
+ m_source = source;
+ m_moves = moves;
+ m_carrier = carrier;
+ m_stones = stones;
+ m_key = key;
+ }
+
+ public String toString() {
+ StringBuilder ret = new StringBuilder();
+
+ if (m_type.equals("softlimit")) {
+ return "---------------- softlimit ----------------";
}
- public VC(HexPoint from, HexPoint to,
- HexColor c, String type,
- String source, int moves,
- Vector carrier,
- Vector stones,
- Vector key)
- {
- m_from = from;
- m_to = to;
- m_color = c;
- m_type = type;
- m_source = source;
- m_moves = moves;
- m_carrier = carrier;
- m_stones = stones;
- m_key = key;
+ ret.append(m_from.toString());
+ ret.append(" ");
+ ret.append(m_to.toString());
+ ret.append(" ");
+ ret.append(m_color.toString());
+ ret.append(" ");
+ ret.append(m_type);
+ ret.append(" ");
+ ret.append(m_source);
+ ret.append(" ");
+ ret.append(Integer.toString(m_moves));
+ ret.append(" ");
+
+ ret.append("[");
+ for (int i = 0; i < m_carrier.size(); i++) {
+ ret.append(" ");
+ ret.append(m_carrier.get(i).toString());
+ }
+ ret.append(" ] ");
+
+ ret.append("[");
+ for (int i = 0; i < m_stones.size(); i++) {
+ ret.append(" ");
+ ret.append(m_stones.get(i).toString());
}
+ ret.append(" ] ");
- public String toString()
- {
- StringBuilder ret = new StringBuilder();
-
- if (m_type.equals("softlimit")) {
- return "---------------- softlimit ----------------";
- }
-
- ret.append(m_from.toString());
- ret.append(" ");
- ret.append(m_to.toString());
- ret.append(" ");
- ret.append(m_color.toString());
- ret.append(" ");
- ret.append(m_type);
- ret.append(" ");
- ret.append(m_source);
- ret.append(" ");
- ret.append(Integer.toString(m_moves));
- ret.append(" ");
-
- ret.append("[");
- for (int i=0; i getCarrier() { return m_carrier; }
- public Vector getStones() { return m_stones; }
- public Vector getKey() { return m_key; }
- public String getSource() { return m_source; }
-
- private HexPoint m_from;
- private HexPoint m_to;
- private HexColor m_color;
- private String m_type;
- private int m_moves;
- private Vector m_carrier;
- private Vector m_stones;
- private Vector m_key;
- private String m_source;
+ return ret.toString();
+ }
+
+ public HexPoint getFrom() {
+ return m_from;
+ }
+
+ public HexPoint getTo() {
+ return m_to;
+ }
+
+ public HexColor getColor() {
+ return m_color;
+ }
+
+ public String getType() {
+ return m_type;
+ }
+
+ public Vector getCarrier() {
+ return m_carrier;
+ }
+
+ public Vector getStones() {
+ return m_stones;
+ }
+
+ public Vector getKey() {
+ return m_key;
+ }
+
+ public String getSource() {
+ return m_source;
+ }
+
+ private HexPoint m_from;
+ private HexPoint m_to;
+ private HexColor m_color;
+ private String m_type;
+ private int m_moves;
+ private Vector m_carrier;
+ private Vector m_stones;
+ private Vector m_key;
+ private String m_source;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/htp/AnalyzeCommand.java b/src/main/java/hexgui/htp/AnalyzeCommand.java
index d378c79..c0eca69 100644
--- a/src/main/java/hexgui/htp/AnalyzeCommand.java
+++ b/src/main/java/hexgui/htp/AnalyzeCommand.java
@@ -2,271 +2,219 @@
package hexgui.htp;
-import java.io.File;
-import hexgui.hex.ConstPointList;
-import hexgui.hex.HexColor;
import static hexgui.hex.HexColor.BLACK;
import static hexgui.hex.HexColor.WHITE;
+
+import hexgui.hex.ConstPointList;
+import hexgui.hex.HexColor;
import hexgui.hex.HexPoint;
import hexgui.hex.PointList;
+import java.io.File;
-/** Concrete analyze command including data for wildcard replacements.
- See GoGui documentation, chapter "Analyze Commands" */
-public class AnalyzeCommand
-{
- public AnalyzeCommand(AnalyzeDefinition definition)
- {
- m_definition = definition;
- }
-
- public String getLabel()
- {
- return m_definition.getLabel();
- }
-
- public String getCommand()
- {
- return m_definition.getCommand();
- }
-
- public HexColor getColorArg()
- {
- return m_colorArg;
- }
-
- public HexPoint getPointArg()
- {
- return m_pointArg;
- }
-
- public PointList getPointListArg()
- {
- return m_pointListArg;
- }
-
- public AnalyzeType getType()
- {
- return m_definition.getType();
- }
-
- public String getResultTitle()
- {
- StringBuilder buffer = new StringBuilder(getLabel());
- if (needsColorArg() && m_colorArg != null)
- {
- if (m_colorArg == BLACK)
- buffer.append(" Black");
- else
- {
- assert m_colorArg == WHITE;
- buffer.append(" White");
- }
- }
- if (needsPointArg() && m_pointArg != null)
- {
- buffer.append(' ');
- buffer.append(m_pointArg);
- }
- else if (needsPointListArg())
- {
- for (HexPoint p : m_pointListArg)
- {
- buffer.append(' ');
- buffer.append(p);
- }
- }
- if (needsStringArg() && m_stringArg != null)
- {
- buffer.append(' ');
- buffer.append(m_stringArg);
- }
- return buffer.toString();
- }
-
- public boolean isPointArgMissing()
- {
- if (needsPointArg())
- return (m_pointArg == null);
- if (needsPointListArg())
- return m_pointListArg.isEmpty();
- return false;
- }
-
- public boolean isTextType()
- {
- return m_definition.isTextType();
- }
-
- public boolean needsColorArg()
- {
- return m_definition.needsColorArg();
- }
-
- public boolean needsFileArg()
- {
- return m_definition.needsFileArg();
- }
-
- public boolean needsFileOpenArg()
- {
- return m_definition.needsFileOpenArg();
- }
-
- public boolean needsFileSaveArg()
- {
- return m_definition.needsFileSaveArg();
- }
-
- public boolean needsOnlyPointArg()
- {
- return m_definition.needsOnlyPointArg();
- }
-
- public boolean needsOnlyPointAndColorArg()
- {
- return m_definition.needsOnlyPointAndColorArg();
- }
-
- public boolean needsPointArg()
- {
- return m_definition.needsPointArg();
- }
-
- public boolean needsPointListArg()
- {
- return m_definition.needsPointListArg();
- }
-
- public boolean needsStringArg()
- {
- return m_definition.needsStringArg();
+/**
+ * Concrete analyze command including data for wildcard replacements. See GoGui documentation,
+ * chapter "Analyze Commands"
+ */
+public class AnalyzeCommand {
+ public AnalyzeCommand(AnalyzeDefinition definition) {
+ m_definition = definition;
+ }
+
+ public String getLabel() {
+ return m_definition.getLabel();
+ }
+
+ public String getCommand() {
+ return m_definition.getCommand();
+ }
+
+ public HexColor getColorArg() {
+ return m_colorArg;
+ }
+
+ public HexPoint getPointArg() {
+ return m_pointArg;
+ }
+
+ public PointList getPointListArg() {
+ return m_pointListArg;
+ }
+
+ public AnalyzeType getType() {
+ return m_definition.getType();
+ }
+
+ public String getResultTitle() {
+ StringBuilder buffer = new StringBuilder(getLabel());
+ if (needsColorArg() && m_colorArg != null) {
+ if (m_colorArg == BLACK) buffer.append(" Black");
+ else {
+ assert m_colorArg == WHITE;
+ buffer.append(" White");
+ }
+ }
+ if (needsPointArg() && m_pointArg != null) {
+ buffer.append(' ');
+ buffer.append(m_pointArg);
+ } else if (needsPointListArg()) {
+ for (HexPoint p : m_pointListArg) {
+ buffer.append(' ');
+ buffer.append(p);
+ }
+ }
+ if (needsStringArg() && m_stringArg != null) {
+ buffer.append(' ');
+ buffer.append(m_stringArg);
+ }
+ return buffer.toString();
+ }
+
+ public boolean isPointArgMissing() {
+ if (needsPointArg()) return (m_pointArg == null);
+ if (needsPointListArg()) return m_pointListArg.isEmpty();
+ return false;
+ }
+
+ public boolean isTextType() {
+ return m_definition.isTextType();
+ }
+
+ public boolean needsColorArg() {
+ return m_definition.needsColorArg();
+ }
+
+ public boolean needsFileArg() {
+ return m_definition.needsFileArg();
+ }
+
+ public boolean needsFileOpenArg() {
+ return m_definition.needsFileOpenArg();
+ }
+
+ public boolean needsFileSaveArg() {
+ return m_definition.needsFileSaveArg();
+ }
+
+ public boolean needsOnlyPointArg() {
+ return m_definition.needsOnlyPointArg();
+ }
+
+ public boolean needsOnlyPointAndColorArg() {
+ return m_definition.needsOnlyPointAndColorArg();
+ }
+
+ public boolean needsPointArg() {
+ return m_definition.needsPointArg();
+ }
+
+ public boolean needsPointListArg() {
+ return m_definition.needsPointListArg();
+ }
+
+ public boolean needsStringArg() {
+ return m_definition.needsStringArg();
+ }
+
+ public boolean needsOptStringArg() {
+ return m_definition.needsOptStringArg();
+ }
+
+ public String replaceWildCards(HexColor toMove) {
+ String command = m_definition.getCommand();
+ String toMoveString = (toMove == BLACK ? "b" : "w");
+ String result = command.replace("%m", toMoveString);
+ if (needsPointArg() && m_pointArg != null) result = result.replace("%p", m_pointArg.toString());
+ if (needsPointListArg()) {
+ String pointList = HexPoint.toString(m_pointListArg);
+ if (getType() == AnalyzeType.EPLIST && m_pointListArg.size() > 0)
+ result = result + ' ' + pointList;
+ else result = result.replace("%P", pointList);
+ }
+ if (needsFileArg()) {
+ String fileArg = m_fileArg.toString();
+ if (fileArg.indexOf(' ') >= 0) fileArg = "\"" + fileArg + "\"";
+ result = result.replace("%f", fileArg);
+ }
+ if (needsFileOpenArg()) {
+ String fileOpenArg = m_fileOpenArg.toString();
+ if (fileOpenArg.indexOf(' ') >= 0) fileOpenArg = "\"" + fileOpenArg + "\"";
+ result = result.replace("%r", fileOpenArg);
+ }
+ if (needsFileSaveArg()) {
+ String fileSaveArg = m_fileSaveArg.toString();
+ if (fileSaveArg.indexOf(' ') >= 0) fileSaveArg = "\"" + fileSaveArg + "\"";
+ result = result.replace("%w", fileSaveArg);
+ }
+ if (needsStringArg()) {
+ assert m_stringArg != null;
+ result = result.replace("%s", m_stringArg);
+ }
+ if (needsOptStringArg()) {
+ assert m_optStringArg != null;
+ result = result.replace("%o", m_optStringArg);
+ }
+ if (needsColorArg()) {
+ String colorString = "empty";
+ if (m_colorArg == BLACK) colorString = "b";
+ else if (m_colorArg == WHITE) colorString = "w";
+ result = result.replace("%c", colorString);
}
+ return result;
+ }
- public boolean needsOptStringArg()
- {
- return m_definition.needsOptStringArg();
- }
+ public void setColorArg(HexColor color) {
+ assert needsColorArg();
+ m_colorArg = color;
+ }
- public String replaceWildCards(HexColor toMove)
- {
- String command = m_definition.getCommand();
- String toMoveString = (toMove == BLACK ? "b" : "w");
- String result = command.replace("%m", toMoveString);
- if (needsPointArg() && m_pointArg != null)
- result = result.replace("%p", m_pointArg.toString());
- if (needsPointListArg())
- {
- String pointList = HexPoint.toString(m_pointListArg);
- if (getType() == AnalyzeType.EPLIST
- && m_pointListArg.size() > 0)
- result = result + ' ' + pointList;
- else
- result = result.replace("%P", pointList);
- }
- if (needsFileArg())
- {
- String fileArg = m_fileArg.toString();
- if (fileArg.indexOf(' ') >= 0)
- fileArg = "\"" + fileArg + "\"";
- result = result.replace("%f", fileArg);
- }
- if (needsFileOpenArg())
- {
- String fileOpenArg = m_fileOpenArg.toString();
- if (fileOpenArg.indexOf(' ') >= 0)
- fileOpenArg = "\"" + fileOpenArg + "\"";
- result = result.replace("%r", fileOpenArg);
- }
- if (needsFileSaveArg())
- {
- String fileSaveArg = m_fileSaveArg.toString();
- if (fileSaveArg.indexOf(' ') >= 0)
- fileSaveArg = "\"" + fileSaveArg + "\"";
- result = result.replace("%w", fileSaveArg);
- }
- if (needsStringArg())
- {
- assert m_stringArg != null;
- result = result.replace("%s", m_stringArg);
- }
- if (needsOptStringArg())
- {
- assert m_optStringArg != null;
- result = result.replace("%o", m_optStringArg);
- }
- if (needsColorArg())
- {
- String colorString = "empty";
- if (m_colorArg == BLACK)
- colorString = "b";
- else if (m_colorArg == WHITE)
- colorString = "w";
- result = result.replace("%c", colorString);
- }
- return result;
- }
+ public void setFileArg(File file) {
+ assert needsFileArg();
+ m_fileArg = file;
+ }
- public void setColorArg(HexColor color)
- {
- assert needsColorArg();
- m_colorArg = color;
- }
+ public void setFileOpenArg(File file) {
+ assert needsFileOpenArg();
+ m_fileOpenArg = file;
+ }
- public void setFileArg(File file)
- {
- assert needsFileArg();
- m_fileArg = file;
- }
+ public void setFileSaveArg(File file) {
+ assert needsFileSaveArg();
+ m_fileSaveArg = file;
+ }
- public void setFileOpenArg(File file)
- {
- assert needsFileOpenArg();
- m_fileOpenArg = file;
- }
+ public void setPointArg(HexPoint point) {
+ m_pointArg = point;
+ }
- public void setFileSaveArg(File file)
- {
- assert needsFileSaveArg();
- m_fileSaveArg = file;
- }
+ public void setPointListArg(ConstPointList pointList) {
+ m_pointListArg = new PointList(pointList);
+ }
- public void setPointArg(HexPoint point)
- {
- m_pointArg = point;
- }
-
- public void setPointListArg(ConstPointList pointList)
- {
- m_pointListArg = new PointList(pointList);
- }
+ public void setStringArg(String value) {
+ assert needsStringArg();
+ m_stringArg = value;
+ }
- public void setStringArg(String value)
- {
- assert needsStringArg();
- m_stringArg = value;
- }
-
- public void setOptStringArg(String value)
- {
- assert needsOptStringArg();
- m_optStringArg = value;
- }
+ public void setOptStringArg(String value) {
+ assert needsOptStringArg();
+ m_optStringArg = value;
+ }
- private final AnalyzeDefinition m_definition;
+ private final AnalyzeDefinition m_definition;
- private HexColor m_colorArg;
+ private HexColor m_colorArg;
- private File m_fileArg;
+ private File m_fileArg;
- private File m_fileOpenArg;
+ private File m_fileOpenArg;
- private File m_fileSaveArg;
+ private File m_fileSaveArg;
- private String m_optStringArg;
+ private String m_optStringArg;
- private String m_stringArg;
+ private String m_stringArg;
- private HexPoint m_pointArg;
+ private HexPoint m_pointArg;
- private PointList m_pointListArg = new PointList();
+ private PointList m_pointListArg = new PointList();
}
diff --git a/src/main/java/hexgui/htp/AnalyzeDefinition.java b/src/main/java/hexgui/htp/AnalyzeDefinition.java
index dda889e..a16758b 100644
--- a/src/main/java/hexgui/htp/AnalyzeDefinition.java
+++ b/src/main/java/hexgui/htp/AnalyzeDefinition.java
@@ -2,256 +2,187 @@
package hexgui.htp;
+import hexgui.util.ErrorMessage;
+import hexgui.util.StringUtils;
import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
-import java.net.URL;
import java.util.ArrayList;
-import hexgui.util.ErrorMessage;
-import hexgui.util.StringUtils;
-
-/** Definition of an analyze command.
- See GoGui documentation, chapter "Analyze Commands".
- This class is immutable. */
-public class AnalyzeDefinition
-{
- public AnalyzeDefinition(String line)
- {
- String array[] = line.split("/");
- String typeStr = array[0];
- if (typeStr.equals("bwboard"))
- m_type = AnalyzeType.BWBOARD;
- else if (typeStr.equals("cboard"))
- m_type = AnalyzeType.CBOARD;
- else if (typeStr.equals("dboard"))
- m_type = AnalyzeType.DBOARD;
- else if (typeStr.equals("eplist"))
- m_type = AnalyzeType.EPLIST;
- else if (typeStr.equals("gfx"))
- m_type = AnalyzeType.GFX;
- else if (typeStr.equals("group"))
- m_type = AnalyzeType.GROUP;
- else if (typeStr.equals("hstring"))
- m_type = AnalyzeType.HSTRING;
- else if (typeStr.equals("hpstring"))
- m_type = AnalyzeType.HPSTRING;
- else if (typeStr.equals("inferior"))
- m_type = AnalyzeType.INFERIOR;
- else if (typeStr.equals("move"))
- m_type = AnalyzeType.MOVE;
- else if (typeStr.equals("param"))
- m_type = AnalyzeType.PARAM;
- else if (typeStr.equals("plist"))
- m_type = AnalyzeType.PLIST;
- else if (typeStr.equals("pspairs"))
- m_type = AnalyzeType.PSPAIRS;
- else if (typeStr.equals("pstring"))
- m_type = AnalyzeType.PSTRING;
- else if (typeStr.equals("string"))
- m_type = AnalyzeType.STRING;
- else if (typeStr.equals("sboard"))
- m_type = AnalyzeType.SBOARD;
- else if (typeStr.equals("var"))
- m_type = AnalyzeType.VAR;
- else if (typeStr.equals("varb"))
- m_type = AnalyzeType.VARB;
- else if (typeStr.equals("varc"))
- m_type = AnalyzeType.VARC;
- else if (typeStr.equals("varp"))
- m_type = AnalyzeType.VARP;
- else if (typeStr.equals("varpo"))
- m_type = AnalyzeType.VARPO;
- else if (typeStr.equals("varw"))
- m_type = AnalyzeType.VARW;
- else if (typeStr.equals("vc"))
- m_type = AnalyzeType.VC;
- else
- m_type = AnalyzeType.NONE;
- m_label = array[1];
- m_command = array[2];
- }
-
- public AnalyzeDefinition(AnalyzeType type, String label, String command)
- {
- m_type = type;
- m_label = label;
- m_command = command;
- }
-
- public String getCommand()
- {
- return m_command;
- }
-
- public String getLabel()
- {
- return m_label;
- }
- public AnalyzeType getType()
- {
- return m_type;
- }
-
- /** Should the response be shown as text.
- Returns true for types that should be shown (not necessarily only)
- as text to the user.
- That is string and variation commands. */
- public boolean isTextType()
- {
- return m_type == AnalyzeType.STRING
- || m_type == AnalyzeType.HSTRING
- || m_type == AnalyzeType.HPSTRING
- || m_type == AnalyzeType.PSTRING
- || m_type == AnalyzeType.VAR
- || m_type == AnalyzeType.VARC
- || m_type == AnalyzeType.VARW
- || m_type == AnalyzeType.VARB
- || m_type == AnalyzeType.VARP
- || m_type == AnalyzeType.VARPO;
- }
-
- public boolean needsColorArg()
- {
- return (m_command.indexOf("%c") >= 0);
- }
-
- public boolean needsFileArg()
- {
- return (m_command.indexOf("%f") >= 0);
- }
-
- public boolean needsFileOpenArg()
- {
- return (m_command.indexOf("%r") >= 0);
- }
-
- public boolean needsFileSaveArg()
- {
- return (m_command.indexOf("%w") >= 0);
- }
-
- public boolean needsOnlyPointArg()
- {
- return (needsPointArg()
- && ! needsColorArg()
- && ! needsFileArg()
- && ! needsFileOpenArg()
- && ! needsFileSaveArg()
- && ! needsPointListArg()
- && ! needsStringArg()
- && ! needsOptStringArg());
- }
-
- public boolean needsOnlyPointAndColorArg()
- {
- return (needsPointArg() && needsColorArg()
- && ! needsFileArg()
- && ! needsFileOpenArg()
- && ! needsFileSaveArg()
- && ! needsPointListArg()
- && ! needsStringArg()
- && ! needsOptStringArg());
- }
-
- public boolean needsPointArg()
- {
- return (m_command.indexOf("%p") >= 0);
- }
-
- public boolean needsPointListArg()
- {
- return (m_command.indexOf("%P") >= 0 || m_type == AnalyzeType.EPLIST);
- }
-
- public boolean needsStringArg()
- {
- return (m_command.indexOf("%s") >= 0);
- }
-
- public boolean needsOptStringArg()
- {
- return (m_command.indexOf("%o") >= 0);
- }
-
- public static ArrayList
- read(String programAnalyzeCommands)
- throws ErrorMessage
- {
- if (programAnalyzeCommands == null)
- throw new ErrorMessage("no analyze commands!");
-
- Reader stringReader = new StringReader(programAnalyzeCommands);
- BufferedReader reader = new BufferedReader(stringReader);
- return readConfig(reader,
- "program response to hexgui-analyze_commands",
- null);
- }
-
- private final AnalyzeType m_type;
-
- private final String m_label;
-
- private final String m_command;
-
- private static ArrayList
- readConfig(BufferedReader reader, String name,
- ArrayList supportedCommands) throws ErrorMessage
- {
- ArrayList result
- = new ArrayList();
- ArrayList labels = new ArrayList();
- try
- {
- String line;
- int lineNumber = 0;
- while ((line = reader.readLine()) != null)
- {
- ++lineNumber;
- line = line.trim();
- if (line.length() > 0 && line.charAt(0) != '#')
- {
- String array[] = line.split("/");
- if (array.length < 3 || array.length > 5)
- throw new ErrorMessage("Error in " + name + " line "
- + lineNumber);
- if (supportedCommands != null)
- {
- String[] cmdArray
- = StringUtils.splitArguments(array[2].trim());
- if (cmdArray.length == 0
- || ! supportedCommands.contains(cmdArray[0]))
- continue;
- }
- String label = array[1];
- if (labels.contains(label))
- continue;
- labels.add(label);
- result.add(new AnalyzeDefinition(line));
- }
- }
- return result;
- }
- catch (IOException e)
- {
- throw new ErrorMessage("Error reading " + name);
+/**
+ * Definition of an analyze command. See GoGui documentation, chapter "Analyze Commands". This class
+ * is immutable.
+ */
+public class AnalyzeDefinition {
+ public AnalyzeDefinition(String line) {
+ String array[] = line.split("/");
+ String typeStr = array[0];
+ if (typeStr.equals("bwboard")) m_type = AnalyzeType.BWBOARD;
+ else if (typeStr.equals("cboard")) m_type = AnalyzeType.CBOARD;
+ else if (typeStr.equals("dboard")) m_type = AnalyzeType.DBOARD;
+ else if (typeStr.equals("eplist")) m_type = AnalyzeType.EPLIST;
+ else if (typeStr.equals("gfx")) m_type = AnalyzeType.GFX;
+ else if (typeStr.equals("group")) m_type = AnalyzeType.GROUP;
+ else if (typeStr.equals("hstring")) m_type = AnalyzeType.HSTRING;
+ else if (typeStr.equals("hpstring")) m_type = AnalyzeType.HPSTRING;
+ else if (typeStr.equals("inferior")) m_type = AnalyzeType.INFERIOR;
+ else if (typeStr.equals("move")) m_type = AnalyzeType.MOVE;
+ else if (typeStr.equals("param")) m_type = AnalyzeType.PARAM;
+ else if (typeStr.equals("plist")) m_type = AnalyzeType.PLIST;
+ else if (typeStr.equals("pspairs")) m_type = AnalyzeType.PSPAIRS;
+ else if (typeStr.equals("pstring")) m_type = AnalyzeType.PSTRING;
+ else if (typeStr.equals("string")) m_type = AnalyzeType.STRING;
+ else if (typeStr.equals("sboard")) m_type = AnalyzeType.SBOARD;
+ else if (typeStr.equals("var")) m_type = AnalyzeType.VAR;
+ else if (typeStr.equals("varb")) m_type = AnalyzeType.VARB;
+ else if (typeStr.equals("varc")) m_type = AnalyzeType.VARC;
+ else if (typeStr.equals("varp")) m_type = AnalyzeType.VARP;
+ else if (typeStr.equals("varpo")) m_type = AnalyzeType.VARPO;
+ else if (typeStr.equals("varw")) m_type = AnalyzeType.VARW;
+ else if (typeStr.equals("vc")) m_type = AnalyzeType.VC;
+ else m_type = AnalyzeType.NONE;
+ m_label = array[1];
+ m_command = array[2];
+ }
+
+ public AnalyzeDefinition(AnalyzeType type, String label, String command) {
+ m_type = type;
+ m_label = label;
+ m_command = command;
+ }
+
+ public String getCommand() {
+ return m_command;
+ }
+
+ public String getLabel() {
+ return m_label;
+ }
+
+ public AnalyzeType getType() {
+ return m_type;
+ }
+
+ /**
+ * Should the response be shown as text. Returns true for types that should be shown (not
+ * necessarily only) as text to the user. That is string and variation commands.
+ */
+ public boolean isTextType() {
+ return m_type == AnalyzeType.STRING
+ || m_type == AnalyzeType.HSTRING
+ || m_type == AnalyzeType.HPSTRING
+ || m_type == AnalyzeType.PSTRING
+ || m_type == AnalyzeType.VAR
+ || m_type == AnalyzeType.VARC
+ || m_type == AnalyzeType.VARW
+ || m_type == AnalyzeType.VARB
+ || m_type == AnalyzeType.VARP
+ || m_type == AnalyzeType.VARPO;
+ }
+
+ public boolean needsColorArg() {
+ return (m_command.indexOf("%c") >= 0);
+ }
+
+ public boolean needsFileArg() {
+ return (m_command.indexOf("%f") >= 0);
+ }
+
+ public boolean needsFileOpenArg() {
+ return (m_command.indexOf("%r") >= 0);
+ }
+
+ public boolean needsFileSaveArg() {
+ return (m_command.indexOf("%w") >= 0);
+ }
+
+ public boolean needsOnlyPointArg() {
+ return (needsPointArg()
+ && !needsColorArg()
+ && !needsFileArg()
+ && !needsFileOpenArg()
+ && !needsFileSaveArg()
+ && !needsPointListArg()
+ && !needsStringArg()
+ && !needsOptStringArg());
+ }
+
+ public boolean needsOnlyPointAndColorArg() {
+ return (needsPointArg()
+ && needsColorArg()
+ && !needsFileArg()
+ && !needsFileOpenArg()
+ && !needsFileSaveArg()
+ && !needsPointListArg()
+ && !needsStringArg()
+ && !needsOptStringArg());
+ }
+
+ public boolean needsPointArg() {
+ return (m_command.indexOf("%p") >= 0);
+ }
+
+ public boolean needsPointListArg() {
+ return (m_command.indexOf("%P") >= 0 || m_type == AnalyzeType.EPLIST);
+ }
+
+ public boolean needsStringArg() {
+ return (m_command.indexOf("%s") >= 0);
+ }
+
+ public boolean needsOptStringArg() {
+ return (m_command.indexOf("%o") >= 0);
+ }
+
+ public static ArrayList read(String programAnalyzeCommands)
+ throws ErrorMessage {
+ if (programAnalyzeCommands == null) throw new ErrorMessage("no analyze commands!");
+
+ Reader stringReader = new StringReader(programAnalyzeCommands);
+ BufferedReader reader = new BufferedReader(stringReader);
+ return readConfig(reader, "program response to hexgui-analyze_commands", null);
+ }
+
+ private final AnalyzeType m_type;
+
+ private final String m_label;
+
+ private final String m_command;
+
+ private static ArrayList readConfig(
+ BufferedReader reader, String name, ArrayList supportedCommands) throws ErrorMessage {
+ ArrayList result = new ArrayList();
+ ArrayList labels = new ArrayList();
+ try {
+ String line;
+ int lineNumber = 0;
+ while ((line = reader.readLine()) != null) {
+ ++lineNumber;
+ line = line.trim();
+ if (line.length() > 0 && line.charAt(0) != '#') {
+ String array[] = line.split("/");
+ if (array.length < 3 || array.length > 5)
+ throw new ErrorMessage("Error in " + name + " line " + lineNumber);
+ if (supportedCommands != null) {
+ String[] cmdArray = StringUtils.splitArguments(array[2].trim());
+ if (cmdArray.length == 0 || !supportedCommands.contains(cmdArray[0])) continue;
+ }
+ String label = array[1];
+ if (labels.contains(label)) continue;
+ labels.add(label);
+ result.add(new AnalyzeDefinition(line));
}
- finally
- {
- try
- {
- reader.close();
- }
- catch (IOException e)
- {
- throw new ErrorMessage("Error reading " + name);
- }
- }
- }
+ }
+ return result;
+ } catch (IOException e) {
+ throw new ErrorMessage("Error reading " + name);
+ } finally {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ throw new ErrorMessage("Error reading " + name);
+ }
+ }
+ }
}
diff --git a/src/main/java/hexgui/htp/AnalyzeType.java b/src/main/java/hexgui/htp/AnalyzeType.java
index 47680de..4952df2 100644
--- a/src/main/java/hexgui/htp/AnalyzeType.java
+++ b/src/main/java/hexgui/htp/AnalyzeType.java
@@ -3,53 +3,52 @@
package hexgui.htp;
/** Type of an analyze command. */
-public enum AnalyzeType
-{
- BWBOARD,
+public enum AnalyzeType {
+ BWBOARD,
- CBOARD,
+ CBOARD,
- DBOARD,
+ DBOARD,
- EPLIST,
+ EPLIST,
- GFX,
+ GFX,
- GROUP,
+ GROUP,
- HSTRING,
+ HSTRING,
- HPSTRING,
-
- INFERIOR,
+ HPSTRING,
- MOVE,
+ INFERIOR,
- NONE,
+ MOVE,
- PARAM,
+ NONE,
- PLIST,
+ PARAM,
- PSTRING,
+ PLIST,
- PSPAIRS,
+ PSTRING,
- STRING,
+ PSPAIRS,
- SBOARD,
+ STRING,
- VAR,
+ SBOARD,
- VARB,
+ VAR,
- VARC,
+ VARB,
- VARP,
+ VARC,
- VARPO,
+ VARP,
- VARW,
-
- VC
+ VARPO,
+
+ VARW,
+
+ VC
}
diff --git a/src/main/java/hexgui/htp/AnalyzeUtil.java b/src/main/java/hexgui/htp/AnalyzeUtil.java
index 75ec916..bd85007 100644
--- a/src/main/java/hexgui/htp/AnalyzeUtil.java
+++ b/src/main/java/hexgui/htp/AnalyzeUtil.java
@@ -2,86 +2,71 @@
package hexgui.htp;
-import java.util.ArrayList;
-import java.util.Scanner;
import java.util.NoSuchElementException;
+import java.util.Scanner;
-public final class AnalyzeUtil
-{
- /** Result of AnalyzeUtil.parseParameterLine(). */
- public static final class Result
- {
- public ParameterType m_type;
+public final class AnalyzeUtil {
+ /** Result of AnalyzeUtil.parseParameterLine(). */
+ public static final class Result {
+ public ParameterType m_type;
- /** Complete type metainformation. */
- public String m_typeInfo;
+ /** Complete type metainformation. */
+ public String m_typeInfo;
- public String m_key;
+ public String m_key;
- public String m_value;
- }
+ public String m_value;
+ }
- /** Get command for setting a parameter.
- See chapter "Analyze Commands" of the GoGui documentation. */
- public static String getParameterCommand(String command, String key,
- String value)
- {
- return command + " " + key + " " + value + "\n";
- }
+ /**
+ * Get command for setting a parameter. See chapter "Analyze Commands" of the GoGui documentation.
+ */
+ public static String getParameterCommand(String command, String key, String value) {
+ return command + " " + key + " " + value + "\n";
+ }
- /** Parse a line in the response of an analyze command of type "param".
- See chapter "Analyze Commands" of the GoGui documentation.
- @return The result or null, if line could not be parsed. */
- public static Result parseParameterLine(String line)
- {
- line = line.trim();
- if (line.startsWith("[") && line.endsWith("]"))
- {
- // Might be used as label for grouping parameters on tabbing
- // panes in a later version of GoGui, so we silently accept it
- return null;
- }
- if (line.length() == 0)
- return null;
- Scanner scanner = new Scanner(line);
- Result result = new Result();
- try
- {
- result.m_typeInfo = scanner.next("^\\[[^\\]]*\\]");
- line = line.substring(result.m_typeInfo.length()).trim();
- result.m_typeInfo =
- result.m_typeInfo.substring(1, result.m_typeInfo.length() - 1);
- }
- catch (NoSuchElementException e)
- {
- // Treat unknown types as string for compatibility with future
- // types
- result.m_typeInfo = "string";
- }
- int pos = line.indexOf(' ');
- if (pos < 0)
- {
- result.m_key = line.trim();
- result.m_value = "";
- }
- else
- {
- result.m_key = line.substring(0, pos).trim();
- result.m_value = line.substring(pos + 1).trim();
- }
- if (result.m_typeInfo.equals("bool"))
- result.m_type = ParameterType.BOOL;
- else if (result.m_typeInfo.startsWith("list/"))
- result.m_type = ParameterType.LIST;
- else
- // Treat unknown types as string for compatibility with future
- // types
- result.m_type = ParameterType.STRING;
- return result;
+ /**
+ * Parse a line in the response of an analyze command of type "param". See chapter "Analyze
+ * Commands" of the GoGui documentation.
+ *
+ * @return The result or null, if line could not be parsed.
+ */
+ public static Result parseParameterLine(String line) {
+ line = line.trim();
+ if (line.startsWith("[") && line.endsWith("]")) {
+ // Might be used as label for grouping parameters on tabbing
+ // panes in a later version of GoGui, so we silently accept it
+ return null;
}
-
- /** Make constructor unavailable; class is for namespace only. */
- private AnalyzeUtil()
- {
+ if (line.length() == 0) return null;
+ Scanner scanner = new Scanner(line);
+ Result result = new Result();
+ try {
+ result.m_typeInfo = scanner.next("^\\[[^\\]]*\\]");
+ line = line.substring(result.m_typeInfo.length()).trim();
+ result.m_typeInfo = result.m_typeInfo.substring(1, result.m_typeInfo.length() - 1);
+ } catch (NoSuchElementException e) {
+ // Treat unknown types as string for compatibility with future
+ // types
+ result.m_typeInfo = "string";
+ }
+ int pos = line.indexOf(' ');
+ if (pos < 0) {
+ result.m_key = line.trim();
+ result.m_value = "";
+ } else {
+ result.m_key = line.substring(0, pos).trim();
+ result.m_value = line.substring(pos + 1).trim();
}
+ if (result.m_typeInfo.equals("bool")) result.m_type = ParameterType.BOOL;
+ else if (result.m_typeInfo.startsWith("list/")) result.m_type = ParameterType.LIST;
+ else
+ // Treat unknown types as string for compatibility with future
+ // types
+ result.m_type = ParameterType.STRING;
+ return result;
+ }
+
+ /** Make constructor unavailable; class is for namespace only. */
+ private AnalyzeUtil() {}
}
diff --git a/src/main/java/hexgui/htp/HtpController.java b/src/main/java/hexgui/htp/HtpController.java
index ff9e9c5..bd53676 100644
--- a/src/main/java/hexgui/htp/HtpController.java
+++ b/src/main/java/hexgui/htp/HtpController.java
@@ -1,212 +1,195 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.htp;
-import hexgui.hex.HexPoint;
-import hexgui.util.Pair;
import hexgui.util.StringUtils;
-
+import java.io.BufferedReader;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
-import java.io.BufferedReader;
import java.io.PrintStream;
-import java.io.IOException;
-import java.util.Vector;
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
/** Sends HTP commands and parses the response. */
-public class HtpController
-{
- public interface IOInterface
- {
- void sentCommand(String str);
- void receivedResponse(String str);
- void receivedError(String str);
- }
+public class HtpController {
+ public interface IOInterface {
+ void sentCommand(String str);
+
+ void receivedResponse(String str);
+
+ void receivedError(String str);
+ }
+
+ // ------------------------------------------------------------
+
+ public interface GuiFxCallback {
+ void guifx(String cmd);
+ }
+
+ // ------------------------------------------------------------
+
+ /** Constructor */
+ public HtpController(InputStream in, OutputStream out, IOInterface io, GuiFxCallback guifx) {
+ System.out.println("controller: in constructor.");
+ m_in = new BufferedReader(new InputStreamReader(in));
+ m_out = new PrintStream(out);
+ m_io = io;
+ m_guifx = guifx;
+ m_connected = true;
+ m_waiting = false;
+ }
+
+ public void interrupt() {
+ System.out.println("Sending interrupt");
+ m_out.print("# interrupt\n");
+ m_out.flush();
+ m_io.sentCommand("# interrupt");
+ }
+
+ /**
+ * Sends command over the htp channel.
+ *
+ * Note this method is synchronized, and so HtpController will process only a single command at
+ * a time.
+ */
+ public synchronized void sendCommand(String cmd) throws HtpError {
+ if (!m_connected) return;
+
+ System.out.println("controller: sending '" + cmd.trim() + "'");
+ m_out.print(cmd);
+ m_out.flush();
+ m_io.sentCommand(cmd);
+ handleResponse();
+ }
+
+ public boolean cmdInProgress() {
+ return m_waiting;
+ }
+
+ public boolean wasSuccess() {
+ return m_success;
+ }
+
+ public String getResponse() {
+ return m_response;
+ }
+
+ private void handleResponse() throws HtpError {
+ m_waiting = true;
+
+ while (m_waiting) {
+
+ String response;
+ try {
+ response = waitResponse();
+ } catch (IOException e) {
+ m_waiting = false;
+ throw new HtpError("IOException waiting for response!");
+ }
- //------------------------------------------------------------
+ // Since the response must, by definition of the GTP
+ // protocol, always end with two newline characters,
+ // remove them.
+ response = response.replaceAll("[\n\r]$", "");
- public interface GuiFxCallback
- {
- void guifx(String cmd);
- }
+ // System.out.println("got: '" + response + "'");
- //------------------------------------------------------------
-
- /** Constructor */
- public HtpController(InputStream in, OutputStream out,
- IOInterface io, GuiFxCallback guifx)
- {
- System.out.println("controller: in constructor.");
- m_in = new BufferedReader(new InputStreamReader(in));
- m_out = new PrintStream(out);
- m_io = io;
- m_guifx = guifx;
- m_connected = true;
+ if (!m_connected) {
+ m_success = false;
+ m_response = "";
m_waiting = false;
- }
-
- public void interrupt()
- {
- System.out.println("Sending interrupt");
- m_out.print("# interrupt\n");
- m_out.flush();
- m_io.sentCommand("# interrupt");
- }
+ throw new HtpError("Program Disconnected.");
+ } else if (response == null) {
+ m_success = false;
+ m_response = "";
+ m_waiting = false;
+ throw new HtpError("Null response received!");
+ } else if (response.length() < 2) {
+ m_success = false;
+ m_response = response;
+ m_waiting = false;
+ throw new HtpError("Response length too short! '" + response + "'");
+ } else if (response.length() > 10 && response.substring(0, 10).equals("gogui-gfx:")) {
- /** Sends command over the htp channel.
-
- Note this method is synchronized, and so HtpController will
- process only a single command at a time.
- */
- public synchronized void sendCommand(String cmd)
- throws HtpError
- {
- if (!m_connected)
- return;
-
- System.out.println("controller: sending '" + cmd.trim() + "'");
- m_out.print(cmd);
- m_out.flush();
- m_io.sentCommand(cmd);
- handleResponse();
- }
+ String fx = StringUtils.cleanWhiteSpace(response.substring(10).trim());
- public boolean cmdInProgress() { return m_waiting; }
-
- public boolean wasSuccess() { return m_success; }
-
- public String getResponse() { return m_response; }
-
- private void handleResponse() throws HtpError
- {
- m_waiting = true;
-
- while (m_waiting) {
-
- String response;
- try {
- response = waitResponse();
- }
- catch (IOException e) {
- m_waiting = false;
- throw new HtpError("IOException waiting for response!");
- }
-
- // Since the response must, by definition of the GTP
- // protocol, always end with two newline characters,
- // remove them.
- response = response.replaceAll("[\n\r]$", "");
-
- //System.out.println("got: '" + response + "'");
-
- if (!m_connected) {
- m_success = false;
- m_response = "";
- m_waiting = false;
- throw new HtpError("Program Disconnected.");
- }
- else if (response == null) {
- m_success = false;
- m_response = "";
- m_waiting = false;
- throw new HtpError("Null response received!");
- } else if (response.length() < 2) {
- m_success = false;
- m_response = response;
- m_waiting = false;
- throw new HtpError("Response length too short! '"+response+"'");
- } else if (response.length() > 10 &&
- response.substring(0, 10).equals("gogui-gfx:"))
- {
-
- String fx
- = StringUtils.cleanWhiteSpace(response.substring(10).trim());
-
- m_guifx.guifx(fx);
-
- } else if (response.substring(0,2).equals("= ")) {
- m_success = true;
- m_response = response.substring(2);
- System.out.print("controller: success: ");
- m_io.receivedResponse(response);
- m_waiting = false;
- } else if (response.substring(0,2).equals("? ")) {
- m_success = false;
- m_response = response.substring(2);
- System.out.print("controller: error: ");
- m_io.receivedError(response);
- m_waiting = false;
- } else {
- m_response = response;
- m_success = false;
- System.out.print("controller: invalid: ");
- m_waiting = false;
- throw new HtpError("Invalid HTP response:'" + response + "'.");
- }
- }
-
- System.out.println("'" + m_response.trim() + "'");
- }
+ m_guifx.guifx(fx);
- private String waitResponse() throws IOException
- {
- StringBuilder ret = new StringBuilder();
- while (true) {
- //System.out.println("blocking on response");
- String line = m_in.readLine();
- //System.out.println("readline: '" + line + "'");
- if (line == null) {
- System.out.println("controller: Disconnected!");
- m_connected = false;
- break;
- }
- String clean = cleanInput(line);
- ret.append(clean);
- ret.append('\n');
-
- if (clean.equals(""))
- break;
- }
- System.out.println("controller: done waiting on response.");
- return ret.toString();
+ } else if (response.substring(0, 2).equals("= ")) {
+ m_success = true;
+ m_response = response.substring(2);
+ System.out.print("controller: success: ");
+ m_io.receivedResponse(response);
+ m_waiting = false;
+ } else if (response.substring(0, 2).equals("? ")) {
+ m_success = false;
+ m_response = response.substring(2);
+ System.out.print("controller: error: ");
+ m_io.receivedError(response);
+ m_waiting = false;
+ } else {
+ m_response = response;
+ m_success = false;
+ System.out.print("controller: invalid: ");
+ m_waiting = false;
+ throw new HtpError("Invalid HTP response:'" + response + "'.");
+ }
}
- /** Cleans the input. Removes all occurrences of '\r'.
- Converts all '\t' to ' '.
- */
- private String cleanInput(String in)
- {
- StringBuilder out = new StringBuilder();
- for (int i=0; i();
- m_swap_bug = false;
- try {
- findGameTree();
- m_gametree = parseGameTree(null, true);
- m_reader.close();
- }
- catch (IOException e) {
- throw sgfError("IO error occurred while parsing file.");
- }
+ }
+
+ private static final int GM_HEXGAME = 11;
+
+ /** Constructor. Parse the input stream in sgf format. */
+ public SgfReader(InputStream in) throws SgfError {
+ InputStreamReader reader = new InputStreamReader(in);
+ m_reader = new LineNumberReader(reader);
+ m_tokenizer = new StreamTokenizer(m_reader);
+ m_gameinfo = new GameInfo();
+ m_warnings = new Vector();
+ m_swap_bug = false;
+ try {
+ findGameTree();
+ m_gametree = parseGameTree(null, true);
+ m_reader.close();
+ } catch (IOException e) {
+ throw sgfError("IO error occurred while parsing file.");
}
+ }
- public Node getGameTree()
- {
- return m_gametree;
- }
+ public Node getGameTree() {
+ return m_gametree;
+ }
- public GameInfo getGameInfo()
- {
- return m_gameinfo;
- }
+ public GameInfo getGameInfo() {
+ return m_gameinfo;
+ }
- public Vector getWarnings()
- {
- if (m_warnings.size() == 0)
- return null;
- return m_warnings;
- }
+ public Vector getWarnings() {
+ if (m_warnings.size() == 0) return null;
+ return m_warnings;
+ }
- //------------------------------------------------------------
-
- /** Fast forward to the first "(". */
- private void findGameTree() throws SgfError, IOException
- {
- while (true) {
- int ttype = m_tokenizer.nextToken();
- if (ttype == StreamTokenizer.TT_EOF)
- throw sgfError("No game tree found!");
-
- if (ttype == '(') {
- m_tokenizer.pushBack();
- break;
- }
- }
- }
+ // ------------------------------------------------------------
- private Node parseGameTree(Node parent, boolean isroot)
- throws SgfError, IOException
- {
- int ttype = m_tokenizer.nextToken();
- if (ttype != '(')
- throw sgfError("Missing '(' at head of game tree.");
+ /** Fast forward to the first "(". */
+ private void findGameTree() throws SgfError, IOException {
+ while (true) {
+ int ttype = m_tokenizer.nextToken();
+ if (ttype == StreamTokenizer.TT_EOF) throw sgfError("No game tree found!");
- Node node = parseNode(parent, isroot);
-
- ttype = m_tokenizer.nextToken();
- if (ttype != ')')
- throw sgfError("Game tree not closed!");
-
- return node;
+ if (ttype == '(') {
+ m_tokenizer.pushBack();
+ break;
+ }
}
-
- private Node parseNode(Node parent, boolean isroot)
- throws SgfError, IOException
- {
- int ttype = m_tokenizer.nextToken();
- if (ttype != ';')
- throw sgfError("Error at head of node!");
-
- Node node = new Node();
- node.setParent(parent);
- if (parent != null)
- parent.addChild(node);
-
- boolean done = false;
- while (!done) {
- ttype = m_tokenizer.nextToken();
- switch(ttype) {
- case '(':
- m_tokenizer.pushBack();
- parseGameTree(node, false);
- break;
-
- case ';':
- m_tokenizer.pushBack();
- parseNode(node, false);
- done = true;
- break;
-
- case ')':
- m_tokenizer.pushBack();
- done = true;
- break;
-
- case StreamTokenizer.TT_WORD:
- parseProperty(node, isroot);
- break;
-
- case StreamTokenizer.TT_EOF:
- throw sgfError("Unexpected EOF in node!");
-
- default:
- throw sgfError("Error in SGF file.");
- }
- }
-
- return node;
+ }
+
+ private Node parseGameTree(Node parent, boolean isroot) throws SgfError, IOException {
+ int ttype = m_tokenizer.nextToken();
+ if (ttype != '(') throw sgfError("Missing '(' at head of game tree.");
+
+ Node node = parseNode(parent, isroot);
+
+ ttype = m_tokenizer.nextToken();
+ if (ttype != ')') throw sgfError("Game tree not closed!");
+
+ return node;
+ }
+
+ private Node parseNode(Node parent, boolean isroot) throws SgfError, IOException {
+ int ttype = m_tokenizer.nextToken();
+ if (ttype != ';') throw sgfError("Error at head of node!");
+
+ Node node = new Node();
+ node.setParent(parent);
+ if (parent != null) parent.addChild(node);
+
+ boolean done = false;
+ while (!done) {
+ ttype = m_tokenizer.nextToken();
+ switch (ttype) {
+ case '(':
+ m_tokenizer.pushBack();
+ parseGameTree(node, false);
+ break;
+
+ case ';':
+ m_tokenizer.pushBack();
+ parseNode(node, false);
+ done = true;
+ break;
+
+ case ')':
+ m_tokenizer.pushBack();
+ done = true;
+ break;
+
+ case StreamTokenizer.TT_WORD:
+ parseProperty(node, isroot);
+ break;
+
+ case StreamTokenizer.TT_EOF:
+ throw sgfError("Unexpected EOF in node!");
+
+ default:
+ throw sgfError("Error in SGF file.");
+ }
}
- /** Parse a point or move value.
- Supports both standard SGF notation for Hex (a1, ...) and Go-like
- notation used by Little Golem (aa, ...) */
- private HexPoint parsePoint(String s) throws SgfError
- {
- s = s.trim().toLowerCase(Locale.ENGLISH);
- HexPoint result = null;
- if (s.length() >= 2)
- {
- if (s.length() == 2 && s.charAt(1) >= 'a' && s.charAt(1) <= 'z')
- {
- // Go-like SGF notation
- int x = s.charAt(0) - 'a';
- int y = s.charAt(1) - 'a';
- if (x < HexPoint.MAX_WIDTH && y < HexPoint.MAX_HEIGHT)
- result = HexPoint.get(x, y);
- }
- else
- {
- // Standard SGF notation for Hex
- try
- {
- int x = s.charAt(0) - 'a';
- int y = Integer.parseInt(s.substring(1)) - 1;
- if (y >= 0 && y < HexPoint.MAX_HEIGHT)
- result = HexPoint.get(x, y);
- }
- catch (NumberFormatException e)
- {
- }
- }
+ return node;
+ }
+
+ /**
+ * Parse a point or move value. Supports both standard SGF notation for Hex (a1, ...) and Go-like
+ * notation used by Little Golem (aa, ...)
+ */
+ private HexPoint parsePoint(String s) throws SgfError {
+ s = s.trim().toLowerCase(Locale.ENGLISH);
+ HexPoint result = null;
+ if (s.length() >= 2) {
+ if (s.length() == 2 && s.charAt(1) >= 'a' && s.charAt(1) <= 'z') {
+ // Go-like SGF notation
+ int x = s.charAt(0) - 'a';
+ int y = s.charAt(1) - 'a';
+ if (x < HexPoint.MAX_WIDTH && y < HexPoint.MAX_HEIGHT) result = HexPoint.get(x, y);
+ } else {
+ // Standard SGF notation for Hex
+ try {
+ int x = s.charAt(0) - 'a';
+ int y = Integer.parseInt(s.substring(1)) - 1;
+ if (y >= 0 && y < HexPoint.MAX_HEIGHT) result = HexPoint.get(x, y);
+ } catch (NumberFormatException e) {
}
- if (result == null)
- throw sgfError(format("Invalid point {0}", s));
- return result;
+ }
}
-
- private HexPoint parseMove(String s) throws SgfError
- {
- s = s.trim().toLowerCase(Locale.ENGLISH);
-
- // Special case: some or all versions of HexGui up to 0.9.GIT
- // incorrectly used "swap-pieces" instead of "swap-sides".
- // The SGF specification states:
- //
- // * swap-sides - the player elects to swap sides with his
- // opponent; if he was playing Black he now plays White, and
- // vice versa.
- //
- // * swap-pieces - the player elects to swap pieces with his
- // opponent - all of Black's pieces are colored White, and
- // White's pieces are colored Black. Then the entire board
- // is reflected in the long diagonal axis.
- //
- // For backward compatibility, we must compensate for the
- // incorrect use of "swap-pieces" when reading SGF files
- // written by HexGui 0.9.GIT or earlier.
-
- if (m_swap_bug && s.equals("swap-pieces")) {
- s = "swap-sides";
- }
-
- // HexPoint.get() handles special move values like "swap"
- HexPoint result = HexPoint.get(s);
- if (result == null)
- // Handles Go-style point notation (aa, ...)
- result = parsePoint(s);
- return result;
+ if (result == null) throw sgfError(format("Invalid point {0}", s));
+ return result;
+ }
+
+ private HexPoint parseMove(String s) throws SgfError {
+ s = s.trim().toLowerCase(Locale.ENGLISH);
+
+ // Special case: some or all versions of HexGui up to 0.9.GIT
+ // incorrectly used "swap-pieces" instead of "swap-sides".
+ // The SGF specification states:
+ //
+ // * swap-sides - the player elects to swap sides with his
+ // opponent; if he was playing Black he now plays White, and
+ // vice versa.
+ //
+ // * swap-pieces - the player elects to swap pieces with his
+ // opponent - all of Black's pieces are colored White, and
+ // White's pieces are colored Black. Then the entire board
+ // is reflected in the long diagonal axis.
+ //
+ // For backward compatibility, we must compensate for the
+ // incorrect use of "swap-pieces" when reading SGF files
+ // written by HexGui 0.9.GIT or earlier.
+
+ if (m_swap_bug && s.equals("swap-pieces")) {
+ s = "swap-sides";
}
- private void parseProperty(Node node, boolean isroot)
- throws SgfError, IOException
- {
- int x,y;
- String name = m_tokenizer.sval;
-
- boolean done = false;
- while(!done) {
-
- int ttype = m_tokenizer.nextToken();
- if (ttype != '[') {
- done = true;
- }
- m_tokenizer.pushBack();
- if (done) {
- break;
- }
-
- String val;
- if (name.equals("C")) {
- val = parseComment();
- } else {
- val = parseValue();
- }
- //System.out.println(name + "[" + val + "]");
-
- if (name.equals("W")) {
- HexPoint point = parseMove(val);
- node.setMove(new Move(point, HexColor.WHITE));
- }
- else if (name.equals("B")) {
- HexPoint point = parseMove(val);
- node.setMove(new Move(point, HexColor.BLACK));
- }
- else if (name.equals("AB")) {
- node.addSetup(HexColor.BLACK, parsePoint(val));
- }
- else if (name.equals("AW")) {
- node.addSetup(HexColor.WHITE, parsePoint(val));
- }
- else if (name.equals("AE")) {
- node.addSetup(HexColor.EMPTY, parsePoint(val));
- }
- else if (name.equals("LB")) {
- node.addLabel(val);
- }
- else if (name.equals("FF")) {
- node.setSgfProperty(name, val);
- x = parseInt(val);
- if (x < 1 || x > 4)
- throw sgfError("Invalid SGF Version! (" + x + ")");
- }
- else if (name.equals("GM")) {
- node.setSgfProperty(name, val);
- if (!isroot) sgfWarning("GM property in non-root node!");
- if (parseInt(val) != GM_HEXGAME) throw sgfError("Not a Hex game!");
- }
- else if (name.equals("SZ")) {
- node.setSgfProperty(name, val);
- if (!isroot) sgfWarning("GM property in non-root node!");
- Dimension dim = new Dimension();
- String sp[] = val.split(":");
- if (sp.length == 1) {
- x = parseInt(sp[0]);
- dim.setSize(x,x);
- } else if (sp.length == 2) {
- x = parseInt(sp[0]);
- y = parseInt(sp[1]);
- dim.setSize(x,y);
- } else {
- throw sgfError("Malformed boardsize!");
- }
- m_gameinfo.setBoardSize(dim);
- }
- else if (name.equals("AP")) {
- node.setSgfProperty(name, val);
- String regex = "HexGui:0\\.[0-9](\\z|[^0-9].*)";
- if (val.matches(regex)) {
- // version HexGui:0.9 or earlier
- m_swap_bug = true;
- }
- }
- else {
- node.setSgfProperty(name, val);
- }
+ // HexPoint.get() handles special move values like "swap"
+ HexPoint result = HexPoint.get(s);
+ if (result == null)
+ // Handles Go-style point notation (aa, ...)
+ result = parsePoint(s);
+ return result;
+ }
+
+ private void parseProperty(Node node, boolean isroot) throws SgfError, IOException {
+ int x, y;
+ String name = m_tokenizer.sval;
+
+ boolean done = false;
+ while (!done) {
+
+ int ttype = m_tokenizer.nextToken();
+ if (ttype != '[') {
+ done = true;
+ }
+ m_tokenizer.pushBack();
+ if (done) {
+ break;
+ }
+
+ String val;
+ if (name.equals("C")) {
+ val = parseComment();
+ } else {
+ val = parseValue();
+ }
+ // System.out.println(name + "[" + val + "]");
+
+ if (name.equals("W")) {
+ HexPoint point = parseMove(val);
+ node.setMove(new Move(point, HexColor.WHITE));
+ } else if (name.equals("B")) {
+ HexPoint point = parseMove(val);
+ node.setMove(new Move(point, HexColor.BLACK));
+ } else if (name.equals("AB")) {
+ node.addSetup(HexColor.BLACK, parsePoint(val));
+ } else if (name.equals("AW")) {
+ node.addSetup(HexColor.WHITE, parsePoint(val));
+ } else if (name.equals("AE")) {
+ node.addSetup(HexColor.EMPTY, parsePoint(val));
+ } else if (name.equals("LB")) {
+ node.addLabel(val);
+ } else if (name.equals("FF")) {
+ node.setSgfProperty(name, val);
+ x = parseInt(val);
+ if (x < 1 || x > 4) throw sgfError("Invalid SGF Version! (" + x + ")");
+ } else if (name.equals("GM")) {
+ node.setSgfProperty(name, val);
+ if (!isroot) sgfWarning("GM property in non-root node!");
+ if (parseInt(val) != GM_HEXGAME) throw sgfError("Not a Hex game!");
+ } else if (name.equals("SZ")) {
+ node.setSgfProperty(name, val);
+ if (!isroot) sgfWarning("GM property in non-root node!");
+ Dimension dim = new Dimension();
+ String sp[] = val.split(":");
+ if (sp.length == 1) {
+ x = parseInt(sp[0]);
+ dim.setSize(x, x);
+ } else if (sp.length == 2) {
+ x = parseInt(sp[0]);
+ y = parseInt(sp[1]);
+ dim.setSize(x, y);
+ } else {
+ throw sgfError("Malformed boardsize!");
}
- }
-
- // Parse an SGF "SimpleText" property value.
- private String parseValue() throws SgfError, IOException
- {
- int ttype = m_tokenizer.nextToken();
- if (ttype != '[') {
- throw sgfError("Property missing opening '['.");
+ m_gameinfo.setBoardSize(dim);
+ } else if (name.equals("AP")) {
+ node.setSgfProperty(name, val);
+ String regex = "HexGui:0\\.[0-9](\\z|[^0-9].*)";
+ if (val.matches(regex)) {
+ // version HexGui:0.9 or earlier
+ m_swap_bug = true;
}
+ } else {
+ node.setSgfProperty(name, val);
+ }
+ }
+ }
- StringBuilder sb = new StringBuilder(256);
- boolean quoted = false;
- while (true) {
- int ch = m_reader.read();
- if (ch < 0) {
- throw sgfError("Property runs to EOF.");
- }
- // Don't rely on the default conversion, because
- // sb.append(ch) would convert the integer to a string
- // rather than a character.
- char c = (char)ch;
-
- if (!quoted) {
- if (c == ']') {
- break;
- }
- if (c == '\\') {
- quoted = true;
- } else {
- if (Character.isWhitespace(c)) {
- // The spec says "Whitespaces other than space
- // must be converted to space".
- sb.append(' ');
- } else {
- sb.append(c);
- }
- }
- } else {
- quoted = false;
- if (Character.isWhitespace(c)) {
- // The spec says "Any char following "\" is
- // inserted verbatim (exception: whitespaces still
- // have to be converted to space!)."
- sb.append(' ');
- } else {
- sb.append(c);
- }
- }
- }
-
- return sb.toString();
+ // Parse an SGF "SimpleText" property value.
+ private String parseValue() throws SgfError, IOException {
+ int ttype = m_tokenizer.nextToken();
+ if (ttype != '[') {
+ throw sgfError("Property missing opening '['.");
}
- // Parse an SGF "Text" property value.
- private String parseComment() throws SgfError, IOException
- {
- int ttype = m_tokenizer.nextToken();
- if (ttype != '[') {
- throw sgfError("Comment missing opening '['.");
+ StringBuilder sb = new StringBuilder(256);
+ boolean quoted = false;
+ while (true) {
+ int ch = m_reader.read();
+ if (ch < 0) {
+ throw sgfError("Property runs to EOF.");
+ }
+ // Don't rely on the default conversion, because
+ // sb.append(ch) would convert the integer to a string
+ // rather than a character.
+ char c = (char) ch;
+
+ if (!quoted) {
+ if (c == ']') {
+ break;
}
-
- StringBuilder sb = new StringBuilder(4096);
- boolean quoted = false;
- while (true) {
- int ch = m_reader.read();
- if (ch < 0) {
- throw sgfError("Comment runs to EOF.");
- }
- char c = (char)ch;
-
- if (!quoted) {
- if (c == ']') {
- break;
- }
-
- if (c == '\\') {
- quoted = true;
- } else {
- if (Character.isWhitespace(c) && c != '\n') {
- // The spec says "White spaces other than
- // linebreaks are converted to space (e.g. no
- // tab, vertical tab, ..)."
-
- // Also note that the LineNumberReader class
- // already takes care of newline conversion,
- // i.e., "\n", "\r", and "\r\n" are all
- // converted to '\n'.
- sb.append(' ');
- } else {
- sb.append(c);
- }
- }
- } else {
- quoted = false;
- if (c == '\n') {
- // Append nothing. The spec says: "Soft line
- // break: linebreaks preceded by a "\" (soft
- // linebreaks are converted to "", i.e. they are
- // removed)".
- } else if (Character.isWhitespace(c)) {
- // The spec says: "Any char following "\" is
- // inserted verbatim (exception: whitespaces still
- // have to be converted to space!).
- sb.append(' ');
- } else {
- sb.append(c);
- }
- }
- }
-
- return sb.toString();
+ if (c == '\\') {
+ quoted = true;
+ } else {
+ if (Character.isWhitespace(c)) {
+ // The spec says "Whitespaces other than space
+ // must be converted to space".
+ sb.append(' ');
+ } else {
+ sb.append(c);
+ }
+ }
+ } else {
+ quoted = false;
+ if (Character.isWhitespace(c)) {
+ // The spec says "Any char following "\" is
+ // inserted verbatim (exception: whitespaces still
+ // have to be converted to space!)."
+ sb.append(' ');
+ } else {
+ sb.append(c);
+ }
+ }
}
- private int parseInt(String str) throws SgfError
- {
- int ret;
- try {
- ret = Integer.parseInt(str);
- }
- catch (NumberFormatException e) {
- throw sgfError("Error parsing integer.");
- }
- return ret;
+ return sb.toString();
+ }
+
+ // Parse an SGF "Text" property value.
+ private String parseComment() throws SgfError, IOException {
+ int ttype = m_tokenizer.nextToken();
+ if (ttype != '[') {
+ throw sgfError("Comment missing opening '['.");
}
- //----------------------------------------------------------------------
+ StringBuilder sb = new StringBuilder(4096);
+ boolean quoted = false;
+ while (true) {
+ int ch = m_reader.read();
+ if (ch < 0) {
+ throw sgfError("Comment runs to EOF.");
+ }
+ char c = (char) ch;
+
+ if (!quoted) {
+ if (c == ']') {
+ break;
+ }
- private void verifyGame(Node root) throws SgfError
- {
- if (m_gameinfo.getBoardSize()==null) {
- throw sgfError("Missing SZ property.");
+ if (c == '\\') {
+ quoted = true;
+ } else {
+ if (Character.isWhitespace(c) && c != '\n') {
+ // The spec says "White spaces other than
+ // linebreaks are converted to space (e.g. no
+ // tab, vertical tab, ..)."
+
+ // Also note that the LineNumberReader class
+ // already takes care of newline conversion,
+ // i.e., "\n", "\r", and "\r\n" are all
+ // converted to '\n'.
+ sb.append(' ');
+ } else {
+ sb.append(c);
+ }
}
+ } else {
+ quoted = false;
+ if (c == '\n') {
+ // Append nothing. The spec says: "Soft line
+ // break: linebreaks preceded by a "\" (soft
+ // linebreaks are converted to "", i.e. they are
+ // removed)".
+ } else if (Character.isWhitespace(c)) {
+ // The spec says: "Any char following "\" is
+ // inserted verbatim (exception: whitespaces still
+ // have to be converted to space!).
+ sb.append(' ');
+ } else {
+ sb.append(c);
+ }
+ }
}
- private SgfError sgfError(String msg)
- {
- return new SgfError("Line " + m_reader.getLineNumber() + ": " + msg);
+ return sb.toString();
+ }
+
+ private int parseInt(String str) throws SgfError {
+ int ret;
+ try {
+ ret = Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ throw sgfError("Error parsing integer.");
}
+ return ret;
+ }
+
+ // ----------------------------------------------------------------------
- private void sgfWarning(String msg)
- {
- m_warnings.add("Line " + m_reader.getLineNumber() + ": " + msg);
+ private void verifyGame(Node root) throws SgfError {
+ if (m_gameinfo.getBoardSize() == null) {
+ throw sgfError("Missing SZ property.");
}
-
- private StreamTokenizer m_tokenizer;
- private LineNumberReader m_reader;
- private Node m_gametree;
- private GameInfo m_gameinfo;
- private Vector m_warnings;
- private boolean m_swap_bug;
+ }
+
+ private SgfError sgfError(String msg) {
+ return new SgfError("Line " + m_reader.getLineNumber() + ": " + msg);
+ }
+
+ private void sgfWarning(String msg) {
+ m_warnings.add("Line " + m_reader.getLineNumber() + ": " + msg);
+ }
+
+ private StreamTokenizer m_tokenizer;
+ private LineNumberReader m_reader;
+ private Node m_gametree;
+ private GameInfo m_gameinfo;
+ private Vector m_warnings;
+ private boolean m_swap_bug;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/sgf/SgfWriter.java b/src/main/java/hexgui/sgf/SgfWriter.java
index 05135f3..974ae71 100644
--- a/src/main/java/hexgui/sgf/SgfWriter.java
+++ b/src/main/java/hexgui/sgf/SgfWriter.java
@@ -1,177 +1,161 @@
-//----------------------------------------------------------------------------
-// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+// $Id$
+// ----------------------------------------------------------------------------
package hexgui.sgf;
-import hexgui.version.Version;
+import hexgui.game.GameInfo;
+import hexgui.game.Node;
import hexgui.hex.HexColor;
import hexgui.hex.HexPoint;
import hexgui.hex.Move;
-import hexgui.game.Node;
-import hexgui.game.GameInfo;
-
-import java.io.*;
+import hexgui.version.Version;
import java.awt.Dimension;
-import java.util.Map;
+import java.io.*;
import java.util.Iterator;
+import java.util.Map;
import java.util.Vector;
-//----------------------------------------------------------------------------
-
-/** SGF Writer.
- See https://www.red-bean.com/sgf/ for the SGF definition.
-*/
-public final class SgfWriter
-{
-
- /** Write a game tree. */
- public SgfWriter(OutputStream out, Node root, GameInfo game)
- {
- m_out = new PrintStream(out);
- m_buffer = new StringBuffer(128);
- m_gameinfo = game;
-
- writeTree(root, true);
- print("\n");
- flushBuffer();
- m_out.flush();
- m_out.close();
- }
+// ----------------------------------------------------------------------------
- private void writeTree(Node root, boolean isroot)
- {
- print("(");
- writeNode(root, isroot);
- print(")");
- }
+/** SGF Writer. See https://www.red-bean.com/sgf/ for the SGF definition. */
+public final class SgfWriter {
- private void writeNode(Node node, boolean isroot)
- {
- print(";");
+ /** Write a game tree. */
+ public SgfWriter(OutputStream out, Node root, GameInfo game) {
+ m_out = new PrintStream(out);
+ m_buffer = new StringBuffer(128);
+ m_gameinfo = game;
- if (isroot) {
- String value;
+ writeTree(root, true);
+ print("\n");
+ flushBuffer();
+ m_out.flush();
+ m_out.close();
+ }
- node.setSgfProperty("FF", "4");
- node.setSgfProperty("AP", "HexGui:"+Version.id);
- node.setSgfProperty("GM", "11");
-
- Dimension dim = m_gameinfo.getBoardSize();
- value = Integer.toString(dim.width);
- if (dim.width != dim.height)
- value += ":" + Integer.toString(dim.height);
- node.setSgfProperty("SZ", value);
+ private void writeTree(Node root, boolean isroot) {
+ print("(");
+ writeNode(root, isroot);
+ print(")");
+ }
- }
+ private void writeNode(Node node, boolean isroot) {
+ print(";");
- if (node.getMove() != null) {
- printMove(node.getMove());
- }
+ if (isroot) {
+ String value;
- Map map = node.getProperties();
- Iterator > it = map.entrySet().iterator();
- while(it.hasNext()) {
- Map.Entry e = it.next();
- if (!(e.getKey().equals("C") && e.getValue().equals(""))) {
- String val = e.getValue();
- if (e.getKey().equals("C")) {
- // For now we only escape comments, although there
- // may be other text values that should be escaped
- // too. Avoids escaping the ":" in AP field.
- val = escapeString(val);
- }
- print(e.getKey() + "[" + val + "]");
- }
- }
-
- if (node.hasSetup()) {
- Vector list;
- list = node.getSetup(HexColor.BLACK);
- if (!list.isEmpty()) {
- print("AB");
- printPointList(list);
- }
- list = node.getSetup(HexColor.WHITE);
- if (!list.isEmpty()) {
- print("AW");
- printPointList(list);
- }
- list = node.getSetup(HexColor.EMPTY);
- if (!list.isEmpty()) {
- print("AE");
- printPointList(list);
- }
- }
+ node.setSgfProperty("FF", "4");
+ node.setSgfProperty("AP", "HexGui:" + Version.id);
+ node.setSgfProperty("GM", "11");
- int num = node.numChildren();
- if (num == 0) return;
+ Dimension dim = m_gameinfo.getBoardSize();
+ value = Integer.toString(dim.width);
+ if (dim.width != dim.height) value += ":" + Integer.toString(dim.height);
+ node.setSgfProperty("SZ", value);
+ }
- if (num == 1) {
- writeNode(node.getChild(), false);
- return;
- }
-
- for (int i=0; i map = node.getProperties();
+ Iterator> it = map.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry e = it.next();
+ if (!(e.getKey().equals("C") && e.getValue().equals(""))) {
+ String val = e.getValue();
+ if (e.getKey().equals("C")) {
+ // For now we only escape comments, although there
+ // may be other text values that should be escaped
+ // too. Avoids escaping the ":" in AP field.
+ val = escapeString(val);
}
- return out.toString();
+ print(e.getKey() + "[" + val + "]");
+ }
}
-
- private void printMove(Move move)
- {
- String color = "B";
- if (move.getColor() == HexColor.WHITE)
- color = "W";
- print(color + "[" + move.getPoint().toString() + "]");
+
+ if (node.hasSetup()) {
+ Vector list;
+ list = node.getSetup(HexColor.BLACK);
+ if (!list.isEmpty()) {
+ print("AB");
+ printPointList(list);
+ }
+ list = node.getSetup(HexColor.WHITE);
+ if (!list.isEmpty()) {
+ print("AW");
+ printPointList(list);
+ }
+ list = node.getSetup(HexColor.EMPTY);
+ if (!list.isEmpty()) {
+ print("AE");
+ printPointList(list);
+ }
}
- private void printPointList(Vector list)
- {
- for (int i=0; i 72) {
- m_out.append(m_buffer.toString());
- m_out.append("\n");
- m_buffer.setLength(0);
- }
- m_buffer.append(str);
+ for (int i = 0; i < num; i++) {
+ writeTree(node.getChild(i), false);
+ }
+ }
+
+ private String escapeString(String s) {
+ StringBuilder out = new StringBuilder(256);
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ switch (c) {
+ case '\\':
+ case '[':
+ case ']':
+ case ':':
+ out.append('\\');
+ out.append(c);
+ break;
+ default:
+ out.append(c);
+ }
}
+ return out.toString();
+ }
+
+ private void printMove(Move move) {
+ String color = "B";
+ if (move.getColor() == HexColor.WHITE) color = "W";
+ print(color + "[" + move.getPoint().toString() + "]");
+ }
+
+ private void printPointList(Vector list) {
+ for (int i = 0; i < list.size(); ++i) {
+ print("[" + list.get(i).toString() + "]");
+ }
+ }
- private void flushBuffer()
- {
- m_out.append(m_buffer.toString());
- m_buffer.setLength(0);
+ private void print(String str) {
+ if (m_buffer.length() + str.length() > 72) {
+ m_out.append(m_buffer.toString());
+ m_out.append("\n");
+ m_buffer.setLength(0);
}
+ m_buffer.append(str);
+ }
+
+ private void flushBuffer() {
+ m_out.append(m_buffer.toString());
+ m_buffer.setLength(0);
+ }
- private PrintStream m_out;
- private StringBuffer m_buffer;
- private GameInfo m_gameinfo;
+ private PrintStream m_out;
+ private StringBuffer m_buffer;
+ private GameInfo m_gameinfo;
}
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/main/java/hexgui/util/BoardLayout.java b/src/main/java/hexgui/util/BoardLayout.java
index d3d8995..2f83437 100644
--- a/src/main/java/hexgui/util/BoardLayout.java
+++ b/src/main/java/hexgui/util/BoardLayout.java
@@ -1,52 +1,41 @@
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// $Id$
-//----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
package hexgui.util;
-import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
+import javax.swing.*;
-public class BoardLayout
- implements LayoutManager
-{
- public void addLayoutComponent(String name, Component comp)
- {
+public class BoardLayout implements LayoutManager {
+ public void addLayoutComponent(String name, Component comp) {}
+ public void layoutContainer(Container parent) {
+ if (parent.getComponentCount() != 1) {
+ System.err.println("BoardLayout: needs exactly one component!");
}
-
- public void layoutContainer(Container parent)
- {
- if (parent.getComponentCount() != 1) {
- System.err.println("BoardLayout: needs exactly one component!");
- }
- Dimension size = parent.getSize();
- Insets insets = parent.getInsets();
- size.width -= insets.left + insets.right;
- size.height -= insets.top + insets.bottom;
- int w = size.width;
- int h = size.height;
- //if (h*3/2 > w) h = 2*w/3;
- //if (h*3/2 < w) w = h*3/2;
-
- int x = (size.width - w) / 2;
- int y = (size.height - h) / 2;
- parent.getComponent(0).setBounds(x + insets.left, y + insets.top, w, h);
- }
-
- public Dimension minimumLayoutSize(Container parent)
- {
- return parent.getComponent(0).getMinimumSize();
- }
- public Dimension preferredLayoutSize(Container parent)
- {
- return parent.getComponent(0).getPreferredSize();
- }
-
- public void removeLayoutComponent(Component comp)
- {
-
- }
-
+ Dimension size = parent.getSize();
+ Insets insets = parent.getInsets();
+ size.width -= insets.left + insets.right;
+ size.height -= insets.top + insets.bottom;
+ int w = size.width;
+ int h = size.height;
+ // if (h*3/2 > w) h = 2*w/3;
+ // if (h*3/2 < w) w = h*3/2;
+
+ int x = (size.width - w) / 2;
+ int y = (size.height - h) / 2;
+ parent.getComponent(0).setBounds(x + insets.left, y + insets.top, w, h);
+ }
+
+ public Dimension minimumLayoutSize(Container parent) {
+ return parent.getComponent(0).getMinimumSize();
+ }
+
+ public Dimension preferredLayoutSize(Container parent) {
+ return parent.getComponent(0).getPreferredSize();
+ }
+
+ public void removeLayoutComponent(Component comp) {}
}
diff --git a/src/main/java/hexgui/util/ErrorMessage.java b/src/main/java/hexgui/util/ErrorMessage.java
index ef2200f..2c3d2fe 100644
--- a/src/main/java/hexgui/util/ErrorMessage.java
+++ b/src/main/java/hexgui/util/ErrorMessage.java
@@ -2,16 +2,17 @@
package hexgui.util;
-/** Error with error message.
- ErrorMessage are exceptions with a message meaningful for presentation
- to the user. */
-public class ErrorMessage
- extends Exception
-{
- /** Constructor.
- @param message The error message text. */
- public ErrorMessage(String message)
- {
- super(message);
- }
+/**
+ * Error with error message. ErrorMessage are exceptions with a message meaningful for presentation
+ * to the user.
+ */
+public class ErrorMessage extends Exception {
+ /**
+ * Constructor.
+ *
+ * @param message The error message text.
+ */
+ public ErrorMessage(String message) {
+ super(message);
+ }
}
diff --git a/src/main/java/hexgui/util/FileUtil.java b/src/main/java/hexgui/util/FileUtil.java
index 5b8dc5d..a11c497 100644
--- a/src/main/java/hexgui/util/FileUtil.java
+++ b/src/main/java/hexgui/util/FileUtil.java
@@ -11,165 +11,134 @@
import java.util.ArrayList;
/** Static file utility functions. */
-public final class FileUtil
-{
- /** Return the file extension of a file name.
- @param file The file.
- @return File extension or null if file name has no extension. */
- public static String getExtension(File file)
- {
- String ext = null;
- String s = file.getName();
- int i = s.lastIndexOf('.');
- if (i > 0 && i < s.length() - 1)
- ext = s.substring(i + 1);
- return ext;
- }
+public final class FileUtil {
+ /**
+ * Return the file extension of a file name.
+ *
+ * @param file The file.
+ * @return File extension or null if file name has no extension.
+ */
+ public static String getExtension(File file) {
+ String ext = null;
+ String s = file.getName();
+ int i = s.lastIndexOf('.');
+ if (i > 0 && i < s.length() - 1) ext = s.substring(i + 1);
+ return ext;
+ }
- /** Returns relative URI between to files.
- Can be used instead of URI.relativize(), which does not compute
- relative URI's correctly, if toFile is not a subdirectory of fromFile
- (Sun's Java 1.5.0).
- @todo Handle special characters and file names containing slashes.
- @param fromFile File to compute the URI relative to.
- @param toFile Target file or directory.
- @return Relative URI. */
- public static String getRelativeURI(File fromFile, File toFile)
- {
- assert ! fromFile.exists() || ! fromFile.isDirectory();
- fromFile = fromFile.getAbsoluteFile().getParentFile();
- assert fromFile != null;
- ArrayList fromList = splitFile(fromFile);
- ArrayList toList = splitFile(toFile);
- int fromSize = fromList.size();
- int toSize = toList.size();
- int i = 0;
- while (i < fromSize && i < toSize
- && fromList.get(i).equals(toList.get(i)))
- ++i;
- StringBuilder result = new StringBuilder();
- for (int j = i; j < fromSize; ++j)
- result.append("../");
- for (int j = i; j < toSize; ++j)
- {
- result.append(toList.get(j));
- if (j < toSize - 1)
- result.append('/');
- }
- return result.toString();
+ /**
+ * Returns relative URI between to files. Can be used instead of URI.relativize(), which does not
+ * compute relative URI's correctly, if toFile is not a subdirectory of fromFile (Sun's Java
+ * 1.5.0).
+ *
+ * @todo Handle special characters and file names containing slashes.
+ * @param fromFile File to compute the URI relative to.
+ * @param toFile Target file or directory.
+ * @return Relative URI.
+ */
+ public static String getRelativeURI(File fromFile, File toFile) {
+ assert !fromFile.exists() || !fromFile.isDirectory();
+ fromFile = fromFile.getAbsoluteFile().getParentFile();
+ assert fromFile != null;
+ ArrayList fromList = splitFile(fromFile);
+ ArrayList toList = splitFile(toFile);
+ int fromSize = fromList.size();
+ int toSize = toList.size();
+ int i = 0;
+ while (i < fromSize && i < toSize && fromList.get(i).equals(toList.get(i))) ++i;
+ StringBuilder result = new StringBuilder();
+ for (int j = i; j < fromSize; ++j) result.append("../");
+ for (int j = i; j < toSize; ++j) {
+ result.append(toList.get(j));
+ if (j < toSize - 1) result.append('/');
}
+ return result.toString();
+ }
- /** Return URI for file.
- Replacement for File.toURI() with defined (empty) authority. */
- public static URI getURI(File file)
- {
- try
- {
- return new URI("file", "", file.toURI().getPath(), null, null);
- }
- catch (URISyntaxException e)
- {
- return null;
- }
+ /** Return URI for file. Replacement for File.toURI() with defined (empty) authority. */
+ public static URI getURI(File file) {
+ try {
+ return new URI("file", "", file.toURI().getPath(), null, null);
+ } catch (URISyntaxException e) {
+ return null;
}
+ }
- /** Check for extension (case-insensitive). */
- public static boolean hasExtension(File f, String extension)
- {
- String ext = getExtension(f);
- if (ext == null)
- return false;
- return ext.equalsIgnoreCase(extension);
- }
+ /** Check for extension (case-insensitive). */
+ public static boolean hasExtension(File f, String extension) {
+ String ext = getExtension(f);
+ if (ext == null) return false;
+ return ext.equalsIgnoreCase(extension);
+ }
- /** Read a list of strings from a file.
- The file is expected to contain one string per line; leading and
- trailing whitespaces are removed. Empty lines or lines beginning
- with the comment character '#' are ignored. */
- public static ArrayList readStringListFromFile(File file)
- throws IOException
- {
- ArrayList result = new ArrayList();
- FileReader reader = new FileReader(file);
- BufferedReader in = new BufferedReader(reader);
- try
- {
- while (true)
- {
- String line = in.readLine();
- if (line == null)
- break;
- line = line.trim();
- if (! line.equals("") && ! line.startsWith("#"))
- result.add(line);
- }
- return result;
- }
- finally
- {
- in.close();
- }
+ /**
+ * Read a list of strings from a file. The file is expected to contain one string per line;
+ * leading and trailing whitespaces are removed. Empty lines or lines beginning with the comment
+ * character '#' are ignored.
+ */
+ public static ArrayList readStringListFromFile(File file) throws IOException {
+ ArrayList result = new ArrayList();
+ FileReader reader = new FileReader(file);
+ BufferedReader in = new BufferedReader(reader);
+ try {
+ while (true) {
+ String line = in.readLine();
+ if (line == null) break;
+ line = line.trim();
+ if (!line.equals("") && !line.startsWith("#")) result.add(line);
+ }
+ return result;
+ } finally {
+ in.close();
}
+ }
- /** Remove extension in file name.
- If the file does not have the extension oldExtension,
- the extension will not be removed. */
- public static String removeExtension(File file, String oldExtension)
- {
- String name = file.toString();
- if (hasExtension(file, oldExtension))
- {
- int index = name.lastIndexOf('.');
- assert index >= 0;
- return name.substring(0, index);
- }
- return name;
+ /**
+ * Remove extension in file name. If the file does not have the extension oldExtension, the
+ * extension will not be removed.
+ */
+ public static String removeExtension(File file, String oldExtension) {
+ String name = file.toString();
+ if (hasExtension(file, oldExtension)) {
+ int index = name.lastIndexOf('.');
+ assert index >= 0;
+ return name.substring(0, index);
}
+ return name;
+ }
- /** Replace extension in file name.
- If the file does not have the extension oldExtension,
- the extension will not be replaced but the new extension will be
- appended. */
- public static String replaceExtension(File file, String oldExtension,
- String newExtension)
- {
- String name = file.toString();
- if (hasExtension(file, oldExtension))
- {
- int index = name.lastIndexOf('.');
- assert index >= 0;
- return name.substring(0, index) + "." + newExtension;
- }
- return name + "." + newExtension;
+ /**
+ * Replace extension in file name. If the file does not have the extension oldExtension, the
+ * extension will not be replaced but the new extension will be appended.
+ */
+ public static String replaceExtension(File file, String oldExtension, String newExtension) {
+ String name = file.toString();
+ if (hasExtension(file, oldExtension)) {
+ int index = name.lastIndexOf('.');
+ assert index >= 0;
+ return name.substring(0, index) + "." + newExtension;
}
+ return name + "." + newExtension;
+ }
- public static String replaceExtension(String file, String oldExtension,
- String newExtension)
- {
- return replaceExtension(new File(file), oldExtension, newExtension);
- }
+ public static String replaceExtension(String file, String oldExtension, String newExtension) {
+ return replaceExtension(new File(file), oldExtension, newExtension);
+ }
- /** Make constructor unavailable; class is for namespace only. */
- private FileUtil()
- {
- }
+ /** Make constructor unavailable; class is for namespace only. */
+ private FileUtil() {}
- private static ArrayList splitFile(File file)
- {
- ArrayList