This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
JRummikub/src/jrummikub/view/impl/View.java
Matthias Schiffer ada8c1869c Add proper handling for lost server connections
git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@581 72836036-5685-4462-b002-a69064685172
2011-06-22 07:04:15 +02:00

701 lines
18 KiB
Java

package jrummikub.view.impl;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.CompoundBorder;
import javax.swing.border.MatteBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import jrummikub.model.Position;
import jrummikub.model.Stone;
import jrummikub.model.StoneColor;
import jrummikub.model.StoneSet;
import jrummikub.util.Event;
import jrummikub.util.Event1;
import jrummikub.util.IEvent;
import jrummikub.util.IEvent1;
import jrummikub.util.IListener;
import jrummikub.util.Pair;
import jrummikub.view.IConnectPanel;
import jrummikub.view.IGameListPanel;
import jrummikub.view.IHandPanel;
import jrummikub.view.ILoginPanel;
import jrummikub.view.IPlayerPanel;
import jrummikub.view.IQuitWarningPanel;
import jrummikub.view.IScorePanel;
import jrummikub.view.ISettingsPanel;
import jrummikub.view.ISidePanel;
import jrummikub.view.ITablePanel;
import jrummikub.view.IView;
/**
* Implementation of the top-level view interface
*/
@SuppressWarnings("serial")
public class View extends JFrame implements IView {
private final static float PLAYER_PANEL_RATIO = 0.14f;
private final static int PLAYER_PANEL_MAX_HEIGHT = 180;
private final static int TABLE_BORDER_WIDTH = 1;
private JLayeredPane layeredPane;
private JPanel mainLayer;
private JMenuBar menuBar;
private JMenuItem saveItem;
private TablePanel table;
private PlayerPanel playerPanel;
private StartTurnPanel startTurnPanel;
private PausePanel pausePanel;
private RoundEndPanel roundEndPanel;
private SettingsPanel settingsPanel;
private LoginPanel loginPanel;
private ScorePanel scorePanel;
private GameListPanel gameListPanel;
private SidePanel sidePanel;
private QuitWarningPanel quitWarningPanel;
private ConnectPanel connectPanel;
private BottomPanelType bottomPanelType;
private JFileChooser chooser;
private Event menuNewGameEvent = new Event();
private Event networkGameEvent = new Event();
private Event loadEvent = new Event();
private Event1<File> loadFileEvent = new Event1<File>();
private Event1<File> saveEvent = new Event1<File>();
private Event quitEvent = new Event();
private JFrame quitWarningFrame;
private static int even(double d) {
return 2 * (int) (d / 2);
}
@Override
public ISettingsPanel getSettingsPanel() {
return settingsPanel;
}
@Override
public ILoginPanel getLoginPanel() {
return loginPanel;
}
@Override
public IScorePanel getScorePanel() {
return scorePanel;
}
@Override
public ITablePanel getTablePanel() {
return table;
}
@Override
public ISidePanel getSidePanel() {
return sidePanel;
}
@Override
public IHandPanel getHandPanel() {
return playerPanel.getHandPanel();
}
@Override
public IPlayerPanel getPlayerPanel() {
return playerPanel;
}
@Override
public IQuitWarningPanel getQuitWarningPanel() {
return quitWarningPanel;
}
@Override
public IConnectPanel getConnectPanel() {
return connectPanel;
}
@Override
public IGameListPanel getGameListPanel() {
return gameListPanel;
}
@Override
public IEvent getMenuNewGameEvent() {
return menuNewGameEvent;
}
@Override
public IEvent1<File> getLoadFileEvent() {
return loadFileEvent;
}
@Override
public IEvent getLoadEvent() {
return loadEvent;
}
@Override
public IEvent1<File> getSaveEvent() {
return saveEvent;
}
@Override
public IEvent getPauseEvent() {
return playerPanel.getPauseEvent();
}
@Override
public IEvent getEndPauseEvent() {
return pausePanel.getEndPauseEvent();
}
@Override
public IEvent getNetworkGameEvent() {
return networkGameEvent;
}
@Override
public IEvent getQuitEvent() {
return quitEvent;
}
@Override
public void clearView() {
showScorePanel(false);
showSettingsPanel(false);
showLoginPanel(false);
showGameListPanel(false);
getHandPanel().setStones(Collections.<Pair<Stone, Position>> emptyList());
getTablePanel().setStoneSets(
Collections.<Pair<StoneSet, Position>> emptyList());
setSelectedStones(Collections.<Stone> emptyList());
}
@Override
public void showLoadingError() {
JOptionPane.showMessageDialog(this, "Kein g\u00fcltiger Spielstand",
"Fehler", JOptionPane.ERROR_MESSAGE);
}
@Override
public void showServerStartupError(boolean alreadyRunning) {
JOptionPane
.showMessageDialog(
this,
alreadyRunning ? "Ein XMPP-Server l\u00e4ft bereits auf diesem Computer"
: "Der Server konnte nicht gestartet werden", "Fehler",
JOptionPane.ERROR_MESSAGE);
}
private void createFileChooser() {
chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"JRummikub-Spiele", "rum");
chooser.setFileFilter(filter);
String defaultFile = "spiel.rum";
chooser.setSelectedFile(new File(defaultFile));
}
private void createMenuBar() {
menuBar = new JMenuBar();
JMenu gameMenu = new JMenu("Spiel");
menuBar.add(gameMenu);
gameMenu.add(createMenuItem("Neu", menuNewGameEvent));
gameMenu.add(createMenuItem("Netzwerkspiel...", networkGameEvent));
gameMenu.addSeparator();
JMenuItem loadItem = new JMenuItem("Laden...");
loadItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
loadEvent.emit();
}
});
gameMenu.add(loadItem);
saveItem = new JMenuItem("Speichern...");
saveItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
save();
}
});
gameMenu.add(saveItem);
gameMenu.addSeparator();
gameMenu.add(createMenuItem("Beenden", quitEvent));
setJMenuBar(menuBar);
}
private JMenuItem createMenuItem(String text, final Event event) {
JMenuItem item = new JMenuItem(text);
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
event.emit();
}
});
return item;
}
@Override
public void enableSave(boolean enable) {
saveItem.setEnabled(enable);
}
@Override
public void load() {
int returnVal = chooser.showOpenDialog(View.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
loadFileEvent.emit(chooser.getSelectedFile());
}
}
private void save() {
int returnVal = chooser.showSaveDialog(View.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
saveEvent.emit(chooser.getSelectedFile());
}
}
/**
* Create a new instance of the view
*/
public View() {
super("JRummikub");
setLayout(null);
setSize(1000, 700);
setMinimumSize(new Dimension(750, 550));
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if (isEnabled()) {
quitEvent.emit();
}
}
});
createFileChooser();
createMenuBar();
layeredPane = new JLayeredPane();
layeredPane.setLayout(null);
add(layeredPane);
createMainLayer();
createSettingsPanel();
createLayeredPane();
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
rescale();
}
@Override
public void componentMoved(ComponentEvent e) {
quitWarningFrame.setLocationRelativeTo(View.this);
}
});
setVisible(true);
}
private void createLayeredPane() {
layeredPane.setLayer(settingsPanel, JLayeredPane.POPUP_LAYER);
layeredPane.add(settingsPanel);
loginPanel = new LoginPanel();
loginPanel.setVisible(false);
layeredPane.setLayer(loginPanel, JLayeredPane.POPUP_LAYER);
layeredPane.add(loginPanel);
gameListPanel = new GameListPanel();
gameListPanel.setVisible(false);
layeredPane.setLayer(gameListPanel, JLayeredPane.POPUP_LAYER);
layeredPane.add(gameListPanel);
connectPanel = new ConnectPanel();
connectPanel.setVisible(false);
layeredPane.setLayer(connectPanel, JLayeredPane.POPUP_LAYER);
layeredPane.add(connectPanel);
quitWarningPanel = new QuitWarningPanel();
quitWarningFrame = new JFrame();
quitWarningFrame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
quitWarningFrame.add(quitWarningPanel);
quitWarningFrame.setAlwaysOnTop(true);
quitWarningFrame.setUndecorated(true);
// layeredPane.setLayer(quitWarningPanel, JLayeredPane.POPUP_LAYER);
// layeredPane.add(quitWarningPanel);
// quitWarningPanel.setVisible(true);
scorePanel = new ScorePanel();
scorePanel.setVisible(false);
layeredPane.setLayer(scorePanel, JLayeredPane.POPUP_LAYER);
layeredPane.add(scorePanel);
}
private void createSettingsPanel() {
settingsPanel = new SettingsPanel();
settingsPanel.setVisible(false);
settingsPanel.getNetworkGameEvent().add(new IListener() {
@Override
public void handle() {
networkGameEvent.emit();
}
});
settingsPanel.getLoadGameEvent().add(new IListener() {
@Override
public void handle() {
load();
}
});
}
private void createMainLayer() {
mainLayer = new JPanel();
mainLayer.setLayout(null);
layeredPane.add(mainLayer);
table = new TablePanel();
mainLayer.add(table);
table.setBorder(new MatteBorder(0, 0, TABLE_BORDER_WIDTH, 0, Color.BLACK));
playerPanel = new PlayerPanel();
mainLayer.add(playerPanel);
startTurnPanel = new StartTurnPanel();
startTurnPanel.setVisible(false);
mainLayer.add(startTurnPanel);
pausePanel = new PausePanel();
pausePanel.setVisible(false);
mainLayer.add(pausePanel);
roundEndPanel = new RoundEndPanel();
roundEndPanel.setVisible(false);
mainLayer.add(roundEndPanel);
sidePanel = new SidePanel();
sidePanel.setVisible(false);
mainLayer.add(sidePanel);
sidePanel
.setBorder(new CompoundBorder(new MatteBorder(0, 0, 0, 1, Color.BLACK),
new MatteBorder(0, 0, TABLE_BORDER_WIDTH, 0, Color.GRAY)));
}
@Override
public void setMayPause(boolean mayPause) {
playerPanel.setMayPause(mayPause);
}
@Override
public void enablePauseMode(boolean enable) {
table.enablePauseMode(enable);
doSetBottomPanel(enable ? null : bottomPanelType);
pausePanel.setVisible(enable);
}
private void rescale() {
int width = getContentPane().getWidth(), height = getContentPane()
.getHeight();
layeredPane.setBounds(0, 0, width, height);
mainLayer.setBounds(0, 0, width, height);
int playerPanelHeight = even(Math.pow((double) width * width * height,
1 / 3.0) * PLAYER_PANEL_RATIO);
if (playerPanelHeight > PLAYER_PANEL_MAX_HEIGHT)
playerPanelHeight = PLAYER_PANEL_MAX_HEIGHT;
int tableHeight = height - playerPanelHeight;
playerPanel.setBounds(0, tableHeight, width, playerPanelHeight);
playerPanel.rescale();
int sideWidth = sidePanel.isVisible() ? playerPanel.getLeftPanelWidth() + 1
: 0;
table.setBounds(sideWidth, 0, width - sideWidth, tableHeight);
table.validate();
if (sidePanel.isVisible()) {
sidePanel.setBounds(0, 0, sideWidth, tableHeight);
}
startTurnPanel.setBounds(0, tableHeight, width, playerPanelHeight);
pausePanel.setBounds(0, tableHeight, width, playerPanelHeight);
roundEndPanel.setBounds(0, tableHeight, width, playerPanelHeight);
rescaleSubpanel(settingsPanel, 1 / 2.0, 1 / 2.0, 475, 300);
rescaleSubpanel(scorePanel, 3 / 4.0, 1 / 2.0, 450, 300);
rescaleSubpanel(loginPanel, 1 / 3.0, 1 / 3.0, 350, 200);
rescaleSubpanel(gameListPanel, 1 / 2.0, 1 / 2.0, 475, 300);
rescaleSubpanel(quitWarningPanel, 1 / 2.0, 1 / 6.0, 400, 150);
quitWarningPanel.setLocation(0, 0);
quitWarningFrame.setSize(quitWarningPanel.getSize());
quitWarningFrame.setLocationRelativeTo(this);
rescaleSubpanel(connectPanel, 1 / 2.0, 1 / 6.0, 400, 150);
}
private void rescaleSubpanel(JPanel sub, double widthFactor,
double heightFactor, int minWidth, int minHeight) {
int width = getContentPane().getWidth(), height = getContentPane()
.getHeight();
int panelWidth = Math.max(minWidth, (int) (width * widthFactor));
int panelHeight = Math.max(minHeight, (int) (height * heightFactor));
int x = (width - panelWidth) / 2;
int y = (height - panelHeight) / 2;
sub.setBounds(x, y, panelWidth, panelHeight);
}
@Override
public void setSelectedStones(Collection<Stone> stones) {
table.setSelectedStones(stones);
playerPanel.getHandPanel().setSelectedStones(stones);
}
@Override
public void setInvalidStoneSets(Collection<StoneSet> sets) {
table.setInvalidStoneSets(sets);
}
@Override
public void showSettingsPanel(boolean show) {
if (show) {
settingsPanel.resetTabbedPane();
}
settingsPanel.setVisible(show);
}
@Override
public void showLoginPanel(boolean show) {
loginPanel.setVisible(show);
}
@Override
public void resetLoginPanel() {
loginPanel.resetLoginPanel();
}
@Override
public void showGameListPanel(boolean show) {
if (show) {
gameListPanel.reset();
}
gameListPanel.setVisible(show);
}
@Override
public void showScorePanel(boolean show) {
scorePanel.setVisible(show);
}
@Override
public void showSidePanel(boolean show) {
sidePanel.setVisible(show);
rescale();
}
@Override
public void showQuitWarningPanel(boolean show) {
quitWarningFrame.setLocationRelativeTo(this);
quitWarningFrame.setVisible(show);
if (System.getProperty("os.name").startsWith("Windows")) {
// disabling is broken under windows
layeredPane.setVisible(!show);
menuBar.setVisible(!show);
} else {
setEnabled(!show);
}
}
@Override
public void showConnectPanel(boolean show) {
connectPanel.setVisible(show);
}
@Override
public void setCurrentPlayerName(String playerName) {
playerPanel.setCurrentPlayerName(playerName);
startTurnPanel.setCurrentPlayerName(playerName);
pausePanel.setCurrentPlayerName(playerName);
}
@Override
public void setInitialMeldError(int points) {
startTurnPanel.setInitialMeldError(points);
}
@Override
public void setInitialMeldFirstError() {
startTurnPanel.setInitialMeldFirstError();
}
@Override
public void setCurrentPlayerColor(Color color) {
playerPanel.setCurrentPlayerColor(color);
startTurnPanel.setCurrentPlayerColor(color);
pausePanel.setCurrentPlayerColor(color);
}
@Override
public void setRedealedPlayerName(String name) {
startTurnPanel.setRedealedPlayerName(name);
}
@Override
public void setLastStonePlayerName(String name) {
startTurnPanel.setLastStonePlayerName(name);
}
@Override
public void setCurrentPlayerHasLaidOut(boolean hasLaidOut) {
playerPanel.setHasLaidOut(hasLaidOut);
}
@Override
public IEvent getStartTurnEvent() {
return startTurnPanel.getStartTurnEvent();
}
@Override
public IEvent getAcknowledgeInvalidEvent() {
return startTurnPanel.getAcknowledgeInvalidEvent();
}
@Override
public IEvent getAcknowledgeConnectionLostEvent() {
return startTurnPanel.getAcknowledgeConnectionLostEvent();
}
@Override
public IEvent getNewRoundEvent() {
return roundEndPanel.getNewRoundEvent();
}
@Override
public IEvent getNewGameEvent() {
return roundEndPanel.getNewGameEvent();
}
@Override
public IEvent getEndProgramEvent() {
return roundEndPanel.getEndProgramEvent();
}
@SuppressWarnings("unchecked")
private List<Pair<Stone, Position>> createDecorationStones() {
Pair<Stone, Position> stoneJ = new Pair<Stone, Position>(new Stone(-'J',
StoneColor.BLACK), new Position(2.5f, 0));
Pair<Stone, Position> stoneR = new Pair<Stone, Position>(new Stone(-'R',
StoneColor.ORANGE), new Position(3.5f, 0));
Pair<Stone, Position> stoneu1 = new Pair<Stone, Position>(new Stone(-'u',
StoneColor.BLUE), new Position(4.5f, 0));
Pair<Stone, Position> stonem1 = new Pair<Stone, Position>(new Stone(-'m',
StoneColor.RED), new Position(5.5f, 0));
Pair<Stone, Position> stonem2 = new Pair<Stone, Position>(new Stone(-'m',
StoneColor.GREEN), new Position(6.5f, 0));
Pair<Stone, Position> stonei = new Pair<Stone, Position>(new Stone(-'i',
StoneColor.VIOLET), new Position(7.5f, 0));
Pair<Stone, Position> stonek = new Pair<Stone, Position>(new Stone(-'k',
StoneColor.AQUA), new Position(8.5f, 0));
Pair<Stone, Position> stoneu2 = new Pair<Stone, Position>(new Stone(-'u',
StoneColor.GRAY), new Position(9.5f, 0));
Pair<Stone, Position> stoneb = new Pair<Stone, Position>(new Stone(-'b',
StoneColor.BLACK), new Position(10.5f, 0));
Pair<Stone, Position> stone1 = new Pair<Stone, Position>(new Stone(
StoneColor.RED), new Position(2, 1));
Pair<Stone, Position> stone2 = new Pair<Stone, Position>(new Stone(13,
StoneColor.BLACK), new Position(5, 1));
Pair<Stone, Position> stone3 = new Pair<Stone, Position>(new Stone(13,
StoneColor.ORANGE), new Position(6, 1));
Pair<Stone, Position> stone4 = new Pair<Stone, Position>(new Stone(13,
StoneColor.BLUE), new Position(7, 1));
Pair<Stone, Position> stone5 = new Pair<Stone, Position>(new Stone(13,
StoneColor.RED), new Position(8, 1));
Pair<Stone, Position> stone6 = new Pair<Stone, Position>(new Stone(
StoneColor.BLACK), new Position(11, 1));
return Arrays
.asList(stoneJ, stoneR, stoneu1, stonem1, stonem2, stonei, stonek,
stoneu2, stoneb, stone1, stone2, stone3, stone4, stone5, stone6);
}
@Override
public void setBottomPanel(BottomPanelType type) {
bottomPanelType = type;
doSetBottomPanel(type);
}
private void doSetBottomPanel(BottomPanelType type) {
boolean showStartTurnPanel = (type == BottomPanelType.START_TURN_PANEL
|| type == BottomPanelType.START_REDEAL_TURN_PANEL
|| type == BottomPanelType.START_LAST_TURN_PANEL
|| type == BottomPanelType.INVALID_TURN_PANEL || type == BottomPanelType.NETWORK_SERVER_CONNECTION_LOST_PANEL);
startTurnPanel.setType(type);
startTurnPanel.setVisible(showStartTurnPanel);
boolean showWinPanel = (type == BottomPanelType.WIN_PANEL
|| type == BottomPanelType.NETWORK_WIN_PANEL || type == BottomPanelType.NETWORK_CONNECTION_LOST_PANEL);
roundEndPanel.setType(type);
roundEndPanel.setVisible(showWinPanel);
playerPanel.setVisible((!showStartTurnPanel) && (!showWinPanel)
&& type != null);
if (type == BottomPanelType.START_GAME_PANEL) {
table.setStoneSets(Collections.<Pair<StoneSet, Position>> emptyList());
playerPanel.getHandPanel().setStones(createDecorationStones());
}
playerPanel.showButtons(type != BottomPanelType.START_GAME_PANEL);
playerPanel.enableButtons(type != BottomPanelType.NONHUMAN_HAND_PANEL);
}
@Override
public void setStoneCollectionHidden(boolean enable) {
table.getStoneCollectionPanel().setHidden(enable);
}
}