// GameInfoDialog.java package net.sf.gogui.gui; import java.awt.Component; import java.awt.FlowLayout; import java.awt.GridLayout; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import net.sf.gogui.go.GoColor; import static net.sf.gogui.go.GoColor.BLACK; import static net.sf.gogui.go.GoColor.WHITE; import net.sf.gogui.go.InvalidKomiException; import net.sf.gogui.go.Komi; import static net.sf.gogui.gui.I18n.i18n; import net.sf.gogui.game.GameInfo; import net.sf.gogui.game.StringInfo; import net.sf.gogui.game.StringInfoColor; import net.sf.gogui.game.TimeSettings; /** Dialog for editing game settings and other information. */ public final class GameInfoDialog extends JOptionPane { public static void show(Component parent, GameInfo info, MessageDialogs messageDialogs) { GameInfoDialog gameInfo = new GameInfoDialog(info); JDialog dialog = gameInfo.createDialog(parent, i18n("TIT_GAMEINFO")); boolean done = false; while (! done) { dialog.setVisible(true); Object value = gameInfo.getValue(); if (! (value instanceof Integer) || ((Integer)value).intValue() != JOptionPane.OK_OPTION) return; done = gameInfo.validate(parent, messageDialogs); } dialog.dispose(); gameInfo.updateGameInfo(info); } private static class PlayerInfo { public Box m_box; public JTextField m_name; public JTextField m_rank; } private TimeField m_byoyomi; private JTextField m_byoyomiMoves; private final JTextField m_date; private final JTextField m_komi; private final PlayerInfo m_black; private final PlayerInfo m_white; private TimeField m_preByoyomi; private final JTextField m_result; private final JTextField m_rules; private GameInfoDialog(GameInfo info) { Box outerBox = Box.createVerticalBox(); m_white = createPlayerInfo(WHITE, info); m_white.m_box.setAlignmentX(Component.LEFT_ALIGNMENT); outerBox.add(m_white.m_box); outerBox.add(GuiUtil.createFiller()); m_black = createPlayerInfo(BLACK, info); m_black.m_box.setAlignmentX(Component.LEFT_ALIGNMENT); outerBox.add(m_black.m_box); outerBox.add(GuiUtil.createFiller()); outerBox.add(GuiUtil.createFiller()); Box box = Box.createHorizontalBox(); box.setAlignmentX(Component.LEFT_ALIGNMENT); outerBox.add(box); JPanel labels = new JPanel(new GridLayout(0, 1, 0, GuiUtil.PAD)); box.add(labels); box.add(GuiUtil.createSmallFiller()); JPanel values = new JPanel(new GridLayout(0, 1, 0, GuiUtil.PAD)); box.add(values); m_result = createEntry("LB_GAMEINFO_RESULT", 12, info.get(StringInfo.RESULT), "TT_GAMEINFO_RESULT", labels, values); m_date = createEntry("LB_GAMEINFO_DATE", 12, info.get(StringInfo.DATE), "TT_GAMEINFO_DATE", labels, values); m_rules = createEntry("LB_GAMEINFO_RULES", 12, info.get(StringInfo.RULES), "TT_GAMEINFO_RULES", labels, values); String komi = ""; if (info.getKomi() != null) komi = info.getKomi().toString(); m_komi = createEntry("LB_GAMEINFO_KOMI", 12, komi, "TT_GAMEINFO_KOMI", labels, values); createTime(info.getTimeSettings(), labels, values); setMessage(outerBox); setOptionType(OK_CANCEL_OPTION); } private JTextField createEntry(String labelText, int cols, String text, String toolTipText, JComponent labels, JComponent values) { Box boxLabel = Box.createHorizontalBox(); boxLabel.add(Box.createHorizontalGlue()); JLabel label = new JLabel(i18n(labelText)); label.setAlignmentY(Component.CENTER_ALIGNMENT); boxLabel.add(label); labels.add(boxLabel); JPanel fieldPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); JTextField field = new JTextField(cols); field.setHorizontalAlignment(JTextField.CENTER); field.setToolTipText(i18n(toolTipText)); field.setText(text); fieldPanel.add(field); values.add(fieldPanel); return field; } private void createTime(TimeSettings timeSettings, JComponent labels, JComponent values) { Box boxLabel = Box.createHorizontalBox(); boxLabel.add(Box.createHorizontalGlue()); JLabel label = new JLabel(i18n("LB_GAMEINFO_TIME")); label.setAlignmentY(Component.CENTER_ALIGNMENT); boxLabel.add(label); labels.add(boxLabel); Box boxValue = Box.createVerticalBox(); JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); boxValue.add(Box.createVerticalGlue()); boxValue.add(panel); boxValue.add(Box.createVerticalGlue()); m_preByoyomi = new TimeField(3, "TT_GAMEINFO_TIME_MAIN"); if (timeSettings != null) m_preByoyomi.setTime(timeSettings.getPreByoyomi()); panel.add(m_preByoyomi); panel.add(new JLabel(" + ")); m_byoyomi = new TimeField(2, "TT_GAMEINFO_TIME_BYOYOMI"); if (timeSettings != null && timeSettings.getUseByoyomi()) m_byoyomi.setTime(timeSettings.getByoyomi()); panel.add(m_byoyomi); panel.add(new JLabel(" / ")); m_byoyomiMoves = new JTextField(2); m_byoyomiMoves.setToolTipText(i18n("TT_GAMEINFO_TIME_BYOYOMI_MOVES")); m_byoyomiMoves.setHorizontalAlignment(JTextField.RIGHT); if (timeSettings != null && timeSettings.getUseByoyomi()) { int byoyomiMoves = timeSettings.getByoyomiMoves(); m_byoyomiMoves.setText(Integer.toString(byoyomiMoves)); } panel.add(m_byoyomiMoves); panel.add(new JLabel(" " + i18n("LB_GAMEINFO_TIME_MOVES"))); values.add(boxValue); } private PlayerInfo createPlayerInfo(GoColor c, GameInfo info) { assert c.isBlackWhite(); PlayerInfo playerInfo = new PlayerInfo(); Box box = Box.createHorizontalBox(); JLabel label; if (c == BLACK) label = new JLabel(GuiUtil.getIcon("gogui-black-16x16", i18n("LB_BLACK"))); else label = new JLabel(GuiUtil.getIcon("gogui-white-16x16", i18n("LB_WHITE"))); label.setAlignmentY(Component.CENTER_ALIGNMENT); box.add(label); box.add(GuiUtil.createFiller()); playerInfo.m_box = box; playerInfo.m_name = new JTextField(18); playerInfo.m_name.setText(info.get(StringInfoColor.NAME, c)); box.add(playerInfo.m_name); playerInfo.m_name.setHorizontalAlignment(JTextField.CENTER); if (c == BLACK) playerInfo.m_name.setToolTipText(i18n("TT_GAMEINFO_NAME_BLACK")); else playerInfo.m_name.setToolTipText(i18n("TT_GAMEINFO_NAME_WHITE")); box.add(GuiUtil.createFiller()); playerInfo.m_rank = new JTextField(5); playerInfo.m_rank.setHorizontalAlignment(JTextField.CENTER); if (c == BLACK) playerInfo.m_rank.setToolTipText(i18n("TT_GAMEINFO_RANK_BLACK")); else playerInfo.m_rank.setToolTipText(i18n("TT_GAMEINFO_RANK_WHITE")); box.add(playerInfo.m_rank); playerInfo.m_rank.setText(info.get(StringInfoColor.RANK, c)); box.setAlignmentY(Component.CENTER_ALIGNMENT); return playerInfo; } private static String getTextFieldContent(JTextField textField) { return textField.getText().trim(); } private boolean isEmpty(JTextField textField) { return getTextFieldContent(textField).equals(""); } private void updateGameInfo(GameInfo info) { info.set(StringInfoColor.NAME, BLACK, getTextFieldContent(m_black.m_name)); info.set(StringInfoColor.NAME, WHITE, getTextFieldContent(m_white.m_name)); info.set(StringInfoColor.RANK, BLACK, getTextFieldContent(m_black.m_rank)); info.set(StringInfoColor.RANK, WHITE, getTextFieldContent(m_white.m_rank)); info.set(StringInfo.RULES, getTextFieldContent(m_rules)); info.set(StringInfo.RESULT, getTextFieldContent(m_result)); info.set(StringInfo.DATE, getTextFieldContent(m_date)); String komiText = getTextFieldContent(m_komi); Komi komi = null; try { komi = Komi.parseKomi(komiText); } catch (InvalidKomiException e) { assert false; // already validated } info.setKomi(komi); if (m_preByoyomi.isEmpty() && m_byoyomi.isEmpty() && isEmpty(m_byoyomiMoves)) info.setTimeSettings(null); else { long preByoyomi = m_preByoyomi.getTime(); long byoyomi = -1; int byoyomiMoves = -1; if (! m_byoyomi.isEmpty()) byoyomi = m_byoyomi.getTime(); if (! isEmpty(m_byoyomiMoves)) byoyomiMoves = Integer.parseInt(getTextFieldContent(m_byoyomiMoves)); if (byoyomi > 0 && byoyomiMoves > 0) { TimeSettings settings = new TimeSettings(preByoyomi, byoyomi, byoyomiMoves); info.setTimeSettings(settings); } else { TimeSettings settings = new TimeSettings(preByoyomi); info.setTimeSettings(settings); } } } private boolean validate(Component parent, MessageDialogs messageDialogs) { if (! validateKomi(parent, m_komi, messageDialogs)) return false; if (! m_preByoyomi.validateTime(parent, messageDialogs)) return false; if (! m_byoyomi.validateTime(parent, messageDialogs)) return false; if (! validatePosIntOrEmpty(parent, m_byoyomiMoves, "MSG_GAMEINFO_INVALID_TIME", messageDialogs)) return false; if (m_byoyomi.isEmpty() != isEmpty(m_byoyomiMoves)) { messageDialogs.showError(parent, i18n("MSG_GAMEINFO_INVALID_BYOYOMI"), i18n("MSG_GAMEINFO_INVALID_BYOYOMI_2"), false); return false; } return true; } private boolean validateKomi(Component parent, JTextField textField, MessageDialogs messageDialogs) { String text = getTextFieldContent(textField); try { Komi.parseKomi(text); } catch (InvalidKomiException e) { messageDialogs.showError(parent, i18n("MSG_GAMEINFO_INVALID_KOMI"), i18n("MSG_GAMEINFO_INVALID_KOMI_2"), false); return false; } return true; } private boolean validatePosIntOrEmpty(Component parent, JTextField textField, String errorMessage, MessageDialogs messageDialogs) { try { String content = getTextFieldContent(textField); if (content.trim().equals("")) return true; int value = Integer.parseInt(content); if (value <= 0) { messageDialogs.showError(parent, i18n(errorMessage), i18n("MSG_GAMEINFO_NO_POSITIVE_NUMBER"), false); return false; } } catch (NumberFormatException e) { messageDialogs.showError(parent, i18n(errorMessage), i18n("MSG_GAMEINFO_NO_NUMBER"), false); return false; } return true; } } class TimeField extends Box { public TimeField(int cols, String toolTipText) { super(BoxLayout.Y_AXIS); JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); add(Box.createVerticalGlue()); add(panel); add(Box.createVerticalGlue()); m_textField = new JTextField(cols); m_textField.setHorizontalAlignment(JTextField.RIGHT); m_textField.setToolTipText(i18n(toolTipText)); panel.add(m_textField); panel.add(GuiUtil.createSmallFiller()); String[] units = { i18n("LB_GAMEINFO_MIN"), i18n("LB_GAMEINFO_SEC") }; m_comboBox = new JComboBox(units); panel.add(m_comboBox); } public boolean isEmpty() { return m_textField.getText().trim().equals(""); } public long getTime() { try { long units; if (m_comboBox.getSelectedIndex() == 0) units = 60000; else units = 1000; return units * Long.parseLong(m_textField.getText().trim()); } catch (NumberFormatException e) { return 0; } } public void setTime(long millis) { long seconds = millis / 1000L; if (seconds % 60 == 0) { m_textField.setText(Long.toString(seconds / 60L)); m_comboBox.setSelectedIndex(0); } else { m_textField.setText(Long.toString(seconds)); m_comboBox.setSelectedIndex(1); } } public boolean validateTime(Component parent, MessageDialogs messageDialogs) { try { if (isEmpty()) return true; int value = Integer.parseInt(m_textField.getText().trim()); if (value < 0) { messageDialogs.showError(parent, i18n("MSG_GAMEINFO_INVALID_TIME"), i18n("MSG_GAMEINFO_NO_POSITIVE_NUMBER"), false); return false; } } catch (NumberFormatException e) { messageDialogs.showError(parent, i18n("MSG_GAMEINFO_INVALID_TIME"), i18n("MSG_GAMEINFO_NO_NUMBER"), false); return false; } return true; } private final JTextField m_textField; private final JComboBox m_comboBox; }