package jrummikub.view.impl; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import jrummikub.model.GameSettings; import jrummikub.model.PlayerSettings; import jrummikub.util.Event; import jrummikub.util.Event1; import jrummikub.util.Event2; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; import jrummikub.util.IEvent2; import jrummikub.view.ISettingsPanel; @SuppressWarnings("serial") class SettingsPanel extends JPanel implements ISettingsPanel { private JPanel playerSetupPanel; private JPanel playerSettingsViewport; private JPanel optionsPanel; private JButton addPlayerButton; private JLabel errorMessageLabel; private JButton startButton; private boolean removeButtonsEnabled = true; private List playerSettingsPanels = new ArrayList(); private JSpinner initialMeldThresholdSpinner; private Event startGameEvent = new Event(); private Event addPlayerEvent = new Event(); private Event1 removePlayerEvent = new Event1(); private Event2 changePlayerColorEvent = new Event2(); private Event2 changePlayerNameEvent = new Event2(); private Event1 changeInitialMeldThresholdEvent = new Event1(); @Override public IEvent getStartGameEvent() { return startGameEvent; } @Override public IEvent getAddPlayerEvent() { return addPlayerEvent; } @Override public IEvent1 getRemovePlayerEvent() { return removePlayerEvent; } @Override public IEvent2 getChangePlayerColorEvent() { return changePlayerColorEvent; } @Override public IEvent2 getChangePlayerNameEvent() { return changePlayerNameEvent; } @Override public IEvent1 getChangeInitialMeldThresholdEvent() { return changeInitialMeldThresholdEvent; } @Override public void setError(SettingsError error) { switch (error) { case NO_ERROR: errorMessageLabel.setText(" "); break; case DUPLICATE_PLAYER_NAME: errorMessageLabel .setText("Jeder Spielername darf nur einmal verwendet werden."); break; case NO_PLAYER_NAME: errorMessageLabel.setText("Jeder Spieler muss einen Namen haben."); break; } } @Override public void enableStartGameButton(boolean enable) { startButton.setEnabled(enable); } @Override public void enableAddPlayerButton(boolean enable) { addPlayerButton.setVisible(enable); } @Override public void enableRemovePlayerButtons(boolean enable) { removeButtonsEnabled = enable; for (PlayerSettingsPanel psp : playerSettingsPanels) { psp.enableRemoveButton(enable); } } @Override public void setGameSettings(GameSettings gameSettings) { while (playerSettingsPanels.size() > gameSettings.getPlayerList().size()) { removePlayerSettingsPanel(); } for (int i = 0; i < gameSettings.getPlayerList().size(); ++i) { updatePlayerSettingsPanel(i, gameSettings.getPlayerList().get(i)); } playerSettingsViewport.revalidate(); } private void updatePlayerSettingsPanel(int i, PlayerSettings settings) { if (i < playerSettingsPanels.size()) { playerSettingsPanels.get(i).setSettings(settings); } else { addPlayerSettingsPanel(i, settings); } } private void addPlayerSettingsPanel(int i, PlayerSettings settings) { PlayerSettingsPanel panel = new PlayerSettingsPanel(i, settings); playerSettingsPanels.add(panel); playerSettingsViewport.add(panel, playerSettingsViewport.getComponentCount() - 1); } private void removePlayerSettingsPanel() { PlayerSettingsPanel p = playerSettingsPanels.remove(playerSettingsPanels .size() - 1); playerSettingsViewport.remove(p); } private void createPlayerSetupPanel() { playerSetupPanel = new JPanel(); playerSetupPanel.setLayout(new BorderLayout()); playerSettingsViewport = new JPanel(); playerSettingsViewport.setLayout(new BoxLayout(playerSettingsViewport, BoxLayout.Y_AXIS)); JScrollPane scrollPane = new JScrollPane(playerSettingsViewport, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); playerSetupPanel.add(scrollPane); JPanel addPlayerPanel = new JPanel(); addPlayerPanel.setLayout(new FlowLayout(FlowLayout.TRAILING, 0, 2)); playerSettingsViewport.add(addPlayerPanel); addPlayerButton = new JButton("+"); addPlayerButton.setFont(addPlayerButton.getFont().deriveFont(Font.BOLD)); addPlayerButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { addPlayerEvent.emit(); } }); addPlayerPanel.add(addPlayerButton); } private JComponent makeFiller() { return new Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)); } private void createOptionsPanel() { optionsPanel = new JPanel(); GridBagLayout layout = new GridBagLayout(); optionsPanel.setLayout(layout); GridBagConstraints labelC = new GridBagConstraints(); GridBagConstraints optionC = new GridBagConstraints(); labelC.anchor = GridBagConstraints.EAST; labelC.gridx = 0; labelC.insets = new Insets(5,5,5,5); optionC.anchor = GridBagConstraints.WEST; optionC.gridx = 1; optionC.insets = new Insets(5,5,5,5); JLabel label = new JLabel("Auslegeschranke:"); labelC.gridy = 0; optionsPanel.add(label, labelC); initialMeldThresholdSpinner = new JSpinner(); initialMeldThresholdSpinner.setModel(new SpinnerNumberModel(1, 1, 999, 1)); initialMeldThresholdSpinner.setPreferredSize(new Dimension(60, initialMeldThresholdSpinner.getMinimumSize().height)); initialMeldThresholdSpinner.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { changeInitialMeldThresholdEvent.emit((Integer)initialMeldThresholdSpinner.getValue()); } }); optionC.gridy = 0; optionsPanel.add(initialMeldThresholdSpinner, optionC); label = new JLabel("Dinge:"); labelC.gridx = 0; labelC.gridy = 1; optionsPanel.add(label, labelC); labelC.gridx = 1; labelC.gridy = 2; labelC.fill = GridBagConstraints.BOTH; labelC.weightx = 1; labelC.weighty = 1; optionsPanel.add(makeFiller(), labelC); // TODO Knöpfe für Dinge } SettingsPanel() { setLayout(new GridBagLayout()); final JTabbedPane tabbedPane = new JTabbedPane(); createPlayerSetupPanel(); tabbedPane.addTab("Spieler", playerSetupPanel); createOptionsPanel(); tabbedPane.addTab("Optionen", optionsPanel); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.gridwidth = GridBagConstraints.REMAINDER; c.weightx = 1; c.weighty = 1; add(tabbedPane, c); errorMessageLabel = new JLabel(" "); errorMessageLabel.setForeground(Color.RED); c.weighty = 0; add(errorMessageLabel, c); startButton = new JButton("Spiel starten"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { startGameEvent.emit(); } }); add(startButton, c); setBorder(new CompoundBorder(new LineBorder(Color.BLACK), new EmptyBorder( 10, 10, 10, 10))); } private class PlayerSettingsPanel extends JPanel { private int playerNumber; private JButton colorButton; private JTextField nameField; private JButton removeButton; public void setSettings(PlayerSettings settings) { if (!nameField.getText().equals(settings.getName())) { nameField.setText(settings.getName()); } colorButton .setIcon(ImageUtil.createColorIcon(settings.getColor(), 16, 2)); } public void enableRemoveButton(boolean enable) { removeButton.setEnabled(enable); } public PlayerSettingsPanel(int playerNumber, PlayerSettings settings) { setLayout(new BorderLayout()); this.playerNumber = playerNumber; colorButton = new JButton(); nameField = new JTextField(settings.getName()); setSettings(settings); colorButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { new ColorMenu(); } }); add(colorButton, BorderLayout.WEST); nameField.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { changeName(); } @Override public void removeUpdate(DocumentEvent e) { changeName(); } @Override public void changedUpdate(DocumentEvent e) { changeName(); } }); add(nameField); removeButton = new JButton("\u00d7"); removeButton.setFont(removeButton.getFont().deriveFont(Font.BOLD)); removeButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { remove(); } }); removeButton.setEnabled(removeButtonsEnabled); add(removeButton, BorderLayout.EAST); } @Override public Dimension getPreferredSize() { return getComponent(1).getPreferredSize(); } @Override public Dimension getMaximumSize() { return new Dimension(Integer.MAX_VALUE, getPreferredSize().height); } private void changeName() { changePlayerNameEvent.emit(playerNumber, nameField.getText()); } private void changeColor(Color c) { changePlayerColorEvent.emit(playerNumber, c); } private void remove() { removePlayerEvent.emit(playerNumber); } private class ColorMenu extends JPanel { ColorMenu() { setLayout(new GridLayout(4, 4, 1, 1)); JPopupMenu menu = new JPopupMenu(); for (Color c : PLAYER_COLORS) { add(new ColorButton(c, menu)); } menu.setLayout(new BorderLayout()); menu.add(this); menu.show(colorButton, 0, colorButton.getHeight()); } private class ColorButton extends JLabel { ColorButton(final Color c, final JPopupMenu menu) { final Icon normalIcon = ImageUtil.createColorIcon(c, 16, 1); final Icon hoverIcon = ImageUtil.createColorIcon(c, 16, 2); setIcon(normalIcon); addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { setIcon(hoverIcon); } @Override public void mouseExited(MouseEvent e) { setIcon(normalIcon); } @Override public void mouseClicked(MouseEvent e) { menu.setVisible(false); changeColor(c); } }); } } } } @Override public void setInitialMeldThreshold(int value) { initialMeldThresholdSpinner.setValue(value); } }