package freecell;
import freecell.model.Game;
import freecell.util.ImageReader;
import freecell.view.FeltPanel;
import freecell.view.GamePanel;
import freecell.view.LabelPanel;
import freecell.view.NewGamePanel;
import freecell.view.pile.PilePanel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
/**
* A graphical application for playing FreeCell.
*/
public class GraphicalApplication extends JFrame {
public static final Dimension DIMENSION = new Dimension(750, 600);
private final Game game;
private final GamePanel gamePanel;
private final NewGamePanel newGamePanel;
private PilePanel fromPanel;
private boolean winMessageShown;
public GraphicalApplication(Game game) {
this.game = game;
this.gamePanel = new GamePanel(game);
this.newGamePanel = new NewGamePanel();
super.setTitle("FreeCell");
super.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
super.setSize(DIMENSION);
super.setResizable(false);
super.setVisible(true);
super.setIconImage(ImageReader.readImage("/icons/DIAMOND.jpg"));
addComponents();
attachListeners();
}
public static void main(String[] args) throws IOException {
new GraphicalApplication(new Game());
}
private void addComponents() {
final Container contentPane = new FeltPanel();
contentPane.add(new LabelPanel(), BorderLayout.NORTH);
contentPane.add(gamePanel);
contentPane.add(newGamePanel, BorderLayout.SOUTH);
super.setContentPane(contentPane);
}
private void attachListeners() {
gamePanel.addMouseListener(new MouseClickListener());
newGamePanel.getButton().addActionListener(new NewGameAction());
// Add key bindings for 'undo' and 'redo' actions
InputMap inputMap = gamePanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK), "undoAction");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK), "redoAction");
ActionMap actionMap = gamePanel.getActionMap();
actionMap.put("undoAction", new UndoAction());
actionMap.put("redoAction", new RedoAction());
}
private void showDialogs() {
if (winMessageShown) {
return;
}
if (game.isWon()) {
Icon won = new ImageIcon(getClass().getResource("/icons/WON.png"));
JOptionPane.showMessageDialog(gamePanel, "You won!!!",
"Message", JOptionPane.INFORMATION_MESSAGE, won);
winMessageShown = true;
} else if (game.isLost()) {
Icon lost = new ImageIcon(getClass().getResource("/icons/LOST.png"));
JOptionPane.showMessageDialog(gamePanel, "You lost!",
"Message", JOptionPane.INFORMATION_MESSAGE, lost);
}
}
private class MouseClickListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
final PilePanel panelPressed = gamePanel.determinePanelPressed(e);
// Determine: fromPanel or toPanel?
if (fromPanel == null) {
fromPanel = panelPressed;
fromPanel.toggleSelected();
} else {
if (fromPanel == panelPressed) {
// Double click: try moving to a foundation.
fromPanel.toggleSelected();
for (PilePanel foundationPanel : gamePanel.getFoundationPanels()) {
if (game.move(fromPanel.getPile(), foundationPanel.getPile())) {
fromPanel.repaint();
foundationPanel.repaint();
showDialogs();
break;
}
}
} else {
// Try moving to other cell.
if (game.move(fromPanel.getPile(), panelPressed.getPile())) {
fromPanel.toggleSelected();
fromPanel.repaint();
panelPressed.repaint();
showDialogs();
} else
fromPanel.toggleSelected();
}
fromPanel = null;
}
}
}
private class NewGameAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
game.newGame();
winMessageShown = false;
if (fromPanel != null && fromPanel.isSelected()) {
fromPanel.toggleSelected();
}
fromPanel = null;
repaint();
}
}
private class UndoAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
game.undo();
repaint();
}
}
private class RedoAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
game.redo();
repaint();
}
}
}