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.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 Event sortByGroupsEvent = new Event();
private Event sortByRunsEvent = new Event();
private Event endTurnEvent = new Event();
private Event redealEvent = new Event();
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 setTimeLeft(int time) {
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;
}
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);
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(new 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(new 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();
}
});
}
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;
}
private 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.getWidth();
int handButtonWidth = (int) (width * HAND_ROW_BUTTON_RATIO);
int meanPanelWidth = (width - boardWidth) / 2;
int 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();
}
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);
ComponentListener rescaleListener = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
rescale();
}
};
addComponentListener(rescaleListener);
hand.addComponentListener(rescaleListener);
setEndTurnMode(true, true);
}
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;
}
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));
timeBar.setBounds(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));
}
}
@Override
public void setEndTurnMode(boolean inspectOnly, boolean mayRedeal) {
if (!inspectOnly) {
endTurnButton.setText("Zug beenden");
} else if (!mayRedeal) {
endTurnButton.setText("N\u00e4chster Spieler");
}
boolean smallButtons = mayRedeal && inspectOnly;
endTurnButton.setVisible(!smallButtons);
keepStonesButton.setVisible(smallButtons);
redealButton.setVisible(smallButtons);
}
void showButtons(boolean show) {
currentPlayerNameLabel.setVisible(show);
hasLaidOutLabel.setVisible(show);
sortByGroupsButton.setVisible(show);
sortByRunsButton.setVisible(show);
timeBar.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(false, false);
endTurnButton.setText("Computer 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);
}
}