package jrummikub.view.impl; import java.awt.Color; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.text.DecimalFormat; import java.util.Collections; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.UIManager; import javax.swing.border.EmptyBorder; import jrummikub.control.turn.TurnMode; import jrummikub.model.Position; import jrummikub.model.Stone; import jrummikub.util.Event; import jrummikub.util.IEvent; import jrummikub.util.Pair; import jrummikub.view.IPlayerPanel; /** * Implementation of the player panel */ @SuppressWarnings("serial") class PlayerPanel extends JPanel implements IPlayerPanel { private final static int SIDE_PANEL_INSET = 10; private final static int SIDE_PANEL_SEPARATOR = 5; private final static float SIDE_PANEL_FIRST_LINE_HEIGHT = 0.375f; private final static int SIDE_PANEL_MAX_WIDTH = 180; private final static float HAND_ROW_BUTTON_RATIO = 0.03f; private final static float MAX_BUTTON_FONT_SIZE = 12; private final static DecimalFormat secondFormat = new DecimalFormat("00"); private HandPanel hand; private JPanel leftPanel, rightPanel; private JLabel currentPlayerNameLabel; private JLabel hasLaidOutLabel; private JButton sortByGroupsButton; private JButton sortByRunsButton; private JButton handRowUpButton; private JButton handRowDownButton; private JProgressBar timeBar; private JButton endTurnButton; private JButton keepStonesButton; private JButton redealButton; private JButton pauseButton; private Event sortByGroupsEvent = new Event(); private Event sortByRunsEvent = new Event(); private Event endTurnEvent = new Event(); private Event redealEvent = new Event(); private Event pauseEvent = new Event(); private int leftPanelWidth; private boolean mayPause = true; private ComponentListener leftPanelResizeListener = new LeftPanelResizeListener(); private ComponentListener rightPanelResizeListener = new RightPanelResizeListener(); HandPanel getHandPanel() { return hand; } /** * Sets the current player name * * @param playerName * the player name */ void setCurrentPlayerName(String playerName) { currentPlayerNameLabel.setText(playerName); } void setCurrentPlayerColor(Color color) { currentPlayerNameLabel.setIcon(ImageUtil.createColorIcon(color, 12, 1)); } void setHasLaidOut(boolean hasLaidOut) { if (hasLaidOut) { hasLaidOutLabel.setText("ist rausgekommen"); } else { hasLaidOutLabel.setText("ist nicht rausgekommen"); } } @Override public void setTime(int time, int totalTime) { timeBar.setMaximum(totalTime); timeBar.setValue(time); timeBar.setString(Integer.toString(time / 60) + ":" + secondFormat.format(time % 60)); if (time <= 10) timeBar.setForeground(Color.RED); else timeBar.setForeground(UIManager.getColor("ProgressBar.foreground")); } @Override public IEvent getSortByGroupsEvent() { return sortByGroupsEvent; } @Override public IEvent getSortByRunsEvent() { return sortByRunsEvent; } @Override public IEvent getEndTurnEvent() { return endTurnEvent; } @Override public IEvent getRedealEvent() { return redealEvent; } IEvent getPauseEvent() { return pauseEvent; } private void createLeftPanel() { leftPanel = new JPanel(); leftPanel.setLayout(null); leftPanel.setBorder(new EmptyBorder(SIDE_PANEL_INSET, SIDE_PANEL_INSET, SIDE_PANEL_INSET, SIDE_PANEL_INSET)); currentPlayerNameLabel = new JLabel(); currentPlayerNameLabel.setHorizontalAlignment(JLabel.CENTER); currentPlayerNameLabel.setVerticalAlignment(JLabel.CENTER); currentPlayerNameLabel.putClientProperty("html.disable", Boolean.TRUE); leftPanel.add(currentPlayerNameLabel); hasLaidOutLabel = new JLabel(); hasLaidOutLabel.setHorizontalAlignment(JLabel.CENTER); hasLaidOutLabel.setVerticalAlignment(JLabel.CENTER); leftPanel.add(hasLaidOutLabel); sortByGroupsButton = createButton(leftPanel, "
Nach Sammlungen sortieren", new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { sortByGroupsEvent.emit(); } }); sortByRunsButton = createButton(leftPanel, "
Nach Reihen sortieren", new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { sortByRunsEvent.emit(); } }); leftPanel.addComponentListener(leftPanelResizeListener); } private void createRightPanel() { rightPanel = new JPanel(); rightPanel.setLayout(null); rightPanel.setBorder(new EmptyBorder(SIDE_PANEL_INSET, SIDE_PANEL_INSET, SIDE_PANEL_INSET, SIDE_PANEL_INSET)); handRowUpButton = createButton(rightPanel, "
\u25B2", new ActionListener() { @Override public void actionPerformed(ActionEvent e) { hand.rowUp(); } }); handRowDownButton = createButton(rightPanel, "
\u25BC", new ActionListener() { @Override public void actionPerformed(ActionEvent e) { hand.rowDown(); } }); timeBar = new JProgressBar(0, 60); timeBar.setStringPainted(true); rightPanel.add(timeBar); createRightPanelButtons(); rightPanel.addComponentListener(rightPanelResizeListener); } private void createRightPanelButtons() { endTurnButton = createButton(rightPanel, "---", new ActionListener() { @Override public void actionPerformed(ActionEvent e) { endTurnEvent.emit(); } }); keepStonesButton = createButton(rightPanel, "
Steine
behalten", new ActionListener() { @Override public void actionPerformed(ActionEvent e) { endTurnEvent.emit(); } }); redealButton = createButton(rightPanel, "
Neu
geben", new ActionListener() { @Override public void actionPerformed(ActionEvent e) { redealEvent.emit(); } }); pauseButton = createButton(rightPanel, null, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { pauseEvent.emit(); } }); } private JButton createButton(JPanel panel, String caption, ActionListener listener) { JButton button = new JButton(caption); button.setFont(button.getFont().deriveFont(0)); button.setMargin(new Insets(0, 0, 0, 0)); button.addActionListener(listener); panel.add(button); return button; } void rescale() { Insets insets = getInsets(); int x = insets.left, y = insets.top, width = getWidth() - insets.left - insets.right, height = getHeight() - insets.top - insets.bottom; int boardWidth = hand.rescale(height); int handButtonWidth = (int) (width * HAND_ROW_BUTTON_RATIO); int meanPanelWidth = (width - boardWidth) / 2; leftPanelWidth = meanPanelWidth - handButtonWidth / 2; int rightPanelWidth = meanPanelWidth + handButtonWidth / 2; leftPanel.setBounds(x, y, leftPanelWidth, height); hand.setBounds(x + leftPanelWidth, y, boardWidth, height); rightPanel.setBounds(x + leftPanelWidth + boardWidth, y, rightPanelWidth, height); leftPanel.validate(); rightPanel.validate(); } int getLeftPanelWidth() { return leftPanelWidth; } void updateButtons() { handRowUpButton.setEnabled(hand.canRowUp()); handRowUpButton.setForeground(hand.canRowUp() ? Color.BLACK : Color.GRAY); handRowDownButton.setEnabled(hand.canRowDown()); handRowDownButton.setForeground(hand.canRowDown() ? Color.BLACK : Color.GRAY); } /** * Creates a new PlayerPanel instance */ PlayerPanel() { setLayout(null); createLeftPanel(); add(leftPanel); hand = new HandPanel(this); add(hand); createRightPanel(); add(rightPanel); } @Override public void setEndTurnMode(TurnMode turnMode) { switch (turnMode) { case MAY_REDEAL: endTurnButton.setVisible(false); keepStonesButton.setVisible(true); redealButton.setVisible(true); break; case INSPECT_ONLY: endTurnButton.setText("N\u00e4chster Spieler"); endTurnButton.setVisible(true); keepStonesButton.setVisible(false); redealButton.setVisible(false); break; case NORMAL_TURN: endTurnButton.setText("Zug beenden"); endTurnButton.setVisible(true); keepStonesButton.setVisible(false); redealButton.setVisible(false); break; } } void showButtons(boolean show) { currentPlayerNameLabel.setVisible(show); hasLaidOutLabel.setVisible(show); sortByGroupsButton.setVisible(show); sortByRunsButton.setVisible(show); timeBar.setVisible(show); pauseButton.setVisible(show); if (!show) { handRowDownButton.setForeground(Color.GRAY); handRowDownButton.setEnabled(false); handRowUpButton.setForeground(Color.GRAY); handRowUpButton.setEnabled(false); endTurnButton.setVisible(false); redealButton.setVisible(false); keepStonesButton.setVisible(false); } } void enableButtons(boolean enable) { sortByGroupsButton.setEnabled(enable); sortByRunsButton.setEnabled(enable); if (!enable) { setEndTurnMode(TurnMode.NORMAL_TURN); endTurnButton.setText("
Spieler denkt nach"); hand.setStones(Collections.> emptyList()); handRowDownButton.setForeground(Color.GRAY); handRowDownButton.setEnabled(false); handRowUpButton.setForeground(Color.GRAY); handRowUpButton.setEnabled(false); } endTurnButton.setEnabled(enable); redealButton.setEnabled(enable); keepStonesButton.setEnabled(enable); hand.setEnabled(enable); } void setMayPause(boolean mayPause) { this.mayPause = mayPause; rightPanelResizeListener.componentResized(null); } private class LeftPanelResizeListener extends ComponentAdapter { @Override public void componentResized(ComponentEvent e) { Insets insets = leftPanel.getInsets(); int x = insets.left, y = insets.top, width = leftPanel.getWidth() - insets.left - insets.right, height = leftPanel.getHeight() - insets.top - insets.bottom; if (width > SIDE_PANEL_MAX_WIDTH) { x += (width - SIDE_PANEL_MAX_WIDTH) / 4; width = width / 2 + SIDE_PANEL_MAX_WIDTH / 2; } int labelHeight = (int) ((height - SIDE_PANEL_SEPARATOR) * SIDE_PANEL_FIRST_LINE_HEIGHT); int oneLabelHeight = labelHeight / 2; int buttonWidth = (width - SIDE_PANEL_SEPARATOR) / 2; int buttonHeight = height - SIDE_PANEL_SEPARATOR - labelHeight; float fontSize = (float) Math.sqrt(buttonWidth * buttonHeight) / 6; if (fontSize > MAX_BUTTON_FONT_SIZE) fontSize = MAX_BUTTON_FONT_SIZE; currentPlayerNameLabel.setBounds(x, y, width, oneLabelHeight); hasLaidOutLabel.setBounds(x, y + oneLabelHeight, width, oneLabelHeight); sortByGroupsButton.setBounds(x, y + labelHeight + SIDE_PANEL_SEPARATOR, buttonWidth, buttonHeight); sortByRunsButton.setBounds(x + buttonWidth + SIDE_PANEL_SEPARATOR, y + labelHeight + SIDE_PANEL_SEPARATOR, buttonWidth, buttonHeight); currentPlayerNameLabel.setFont(currentPlayerNameLabel.getFont() .deriveFont(fontSize)); hasLaidOutLabel.setFont(hasLaidOutLabel.getFont().deriveFont(fontSize)); sortByGroupsButton.setFont(sortByGroupsButton.getFont().deriveFont( fontSize)); sortByRunsButton.setFont(sortByRunsButton.getFont().deriveFont(fontSize)); } } private class RightPanelResizeListener extends ComponentAdapter { @Override public void componentResized(ComponentEvent e) { int handButtonWidth = (int) (getWidth() * HAND_ROW_BUTTON_RATIO); Insets insets = rightPanel.getInsets(); int x = insets.left + handButtonWidth, y = insets.top, width = rightPanel .getWidth() - insets.left - insets.right - handButtonWidth, height = rightPanel .getHeight() - insets.top - insets.bottom; if (width > SIDE_PANEL_MAX_WIDTH) { x += (width - SIDE_PANEL_MAX_WIDTH) / 4; width = width / 2 + SIDE_PANEL_MAX_WIDTH / 2; } int firstLineHeight = (int) ((height - SIDE_PANEL_SEPARATOR) * SIDE_PANEL_FIRST_LINE_HEIGHT); int buttonWidth = width; int smallButtonWidth = (width - SIDE_PANEL_SEPARATOR) / 2; int buttonHeight = height - SIDE_PANEL_SEPARATOR - firstLineHeight; float fontSize = (float) Math.sqrt(buttonWidth * buttonHeight) / 5; float smallFontSize = (float) Math.sqrt(smallButtonWidth * buttonHeight) / 5; if (fontSize > MAX_BUTTON_FONT_SIZE) { fontSize = MAX_BUTTON_FONT_SIZE; } if (smallFontSize > MAX_BUTTON_FONT_SIZE) { smallFontSize = MAX_BUTTON_FONT_SIZE; } rescaleUpDownButtons(handButtonWidth, fontSize); rescaleTimeBar(x, y, width, firstLineHeight); endTurnButton.setBounds(x, y + firstLineHeight + SIDE_PANEL_SEPARATOR, buttonWidth, buttonHeight); endTurnButton.setFont(endTurnButton.getFont().deriveFont(fontSize)); redealButton.setBounds(x, y + firstLineHeight + SIDE_PANEL_SEPARATOR, smallButtonWidth, buttonHeight); redealButton.setFont(redealButton.getFont().deriveFont(smallFontSize)); keepStonesButton.setBounds(x + smallButtonWidth + SIDE_PANEL_SEPARATOR, y + firstLineHeight + SIDE_PANEL_SEPARATOR, smallButtonWidth, buttonHeight); keepStonesButton.setFont(keepStonesButton.getFont().deriveFont( smallFontSize)); } private void rescaleTimeBar(int x, int y, int width, int firstLineHeight) { if (mayPause) { timeBar.setBounds(x, y, width - firstLineHeight - SIDE_PANEL_SEPARATOR, firstLineHeight); pauseButton.setBounds(x + width - firstLineHeight, y, firstLineHeight, firstLineHeight); pauseButton.setIcon(ImageUtil .createPauseIcon((int) (firstLineHeight * 0.5f))); } else { timeBar.setBounds(x, y, width, firstLineHeight); pauseButton.setBounds(0, 0, 0, 0); } } private void rescaleUpDownButtons(int handButtonWidth, float fontSize) { handRowUpButton.setBounds(0, 0, handButtonWidth, getHeight() / 2); handRowUpButton.setFont(handRowUpButton.getFont().deriveFont( fontSize * 1.5f)); handRowDownButton.setBounds(0, getHeight() / 2, handButtonWidth, getHeight() / 2); handRowDownButton.setFont(handRowDownButton.getFont().deriveFont( fontSize * 1.5f)); } } }