package games.strategy.engine.framework.ui; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.SwingUtilities; import games.strategy.engine.data.GameData; import games.strategy.util.LocalizeHTML; public class NewGameChooser extends JDialog { private static final long serialVersionUID = -3223711652118741132L; private JButton okButton; private JButton cancelButton; private JList<NewGameChooserEntry> gameList; private JPanel infoPanel; private JEditorPane notesPanel; private NewGameChooserModel gameListModel; private NewGameChooserEntry chosen; private NewGameChooser(final Frame owner) { super(owner, "Select a Game", true); createComponents(); layoutCoponents(); setupListeners(); setWidgetActivation(); updateInfoPanel(); } private void createComponents() { okButton = new JButton("OK"); cancelButton = new JButton("Cancel"); gameListModel = getNewGameChooserModel(); gameList = new JList<>(gameListModel); infoPanel = new JPanel(); infoPanel.setLayout(new BorderLayout()); notesPanel = new JEditorPane(); notesPanel.setEditable(false); notesPanel.setContentType("text/html"); notesPanel.setBackground(new JLabel().getBackground()); } private void layoutCoponents() { setLayout(new BorderLayout()); final JSplitPane mainSplit = new JSplitPane(); add(mainSplit, BorderLayout.CENTER); final JScrollPane listScroll = new JScrollPane(); listScroll.setBorder(null); listScroll.getViewport().setBorder(null); listScroll.setViewportView(gameList); final JPanel leftPanel = new JPanel(); leftPanel.setLayout(new GridBagLayout()); final JLabel gamesLabel = new JLabel("Games"); gamesLabel.setFont(gamesLabel.getFont().deriveFont(Font.BOLD, gamesLabel.getFont().getSize() + 2)); leftPanel.add(gamesLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); leftPanel.add(listScroll, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.EAST, GridBagConstraints.BOTH, new Insets(0, 10, 0, 0), 0, 0)); mainSplit.setLeftComponent(leftPanel); mainSplit.setRightComponent(infoPanel); mainSplit.setBorder(null); listScroll.setMinimumSize(new Dimension(200, 0)); final JPanel buttonsPanel = new JPanel(); add(buttonsPanel, BorderLayout.SOUTH); buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS)); buttonsPanel.add(Box.createHorizontalStrut(30)); buttonsPanel.add(Box.createGlue()); buttonsPanel.add(okButton); buttonsPanel.add(cancelButton); buttonsPanel.add(Box.createGlue()); final JScrollPane notesScroll = new JScrollPane(); notesScroll.setViewportView(notesPanel); notesScroll.setBorder(null); notesScroll.getViewport().setBorder(null); infoPanel.add(Box.createVerticalStrut(10), BorderLayout.NORTH); infoPanel.add(Box.createHorizontalStrut(10), BorderLayout.WEST); infoPanel.add(notesScroll, BorderLayout.CENTER); } public static NewGameChooserEntry chooseGame(final Frame parent, final String defaultGameName) { final NewGameChooser chooser = new NewGameChooser(parent); chooser.setSize(800, 600); chooser.setLocationRelativeTo(parent); chooser.selectGame(defaultGameName); chooser.setVisible(true); // chooser is now visible and waits for user action final NewGameChooserEntry chosen = chooser.chosen; chooser.setVisible(false); chooser.removeAll(); chooser.dispose(); return chosen; } private void selectGame(final String gameName) { if (gameName == null || gameName.equals("-")) { gameList.setSelectedIndex(0); return; } final NewGameChooserEntry entry = gameListModel.findByName(gameName); if (entry != null) { gameList.setSelectedValue(entry, true); } } private void updateInfoPanel() { if (getSelected() != null) { final GameData data = getSelected().getGameData(); final StringBuilder notes = new StringBuilder(); notes.append("<h1>").append(data.getGameName()).append("</h1>"); final String mapNameDir = data.getProperties().get("mapName", ""); appendListItem("Map Name", mapNameDir, notes); appendListItem("Number Of Players", data.getPlayerList().size() + "", notes); appendListItem("Location", getSelected().getLocation() + "", notes); appendListItem("Version", data.getGameVersion() + "", notes); notes.append("<p></p>"); final String notesProperty = data.getProperties().get("notes", ""); if (notesProperty != null && notesProperty.trim().length() != 0) { // UIContext resource loader should be null (or potentially is still the last game we played's loader), // so we send the map dir name so that our localizing of image links can get a new resource loader if needed notes.append(LocalizeHTML.localizeImgLinksInHTML(notesProperty.trim(), null, mapNameDir)); } notesPanel.setText(notes.toString()); } else { if (notesPanel != null) { notesPanel.setText(""); } } // scroll to the top of the notes screen SwingUtilities.invokeLater(() -> { if (notesPanel != null) { notesPanel.scrollRectToVisible(new Rectangle(0, 0, 0, 0)); } }); } private static void appendListItem(final String title, final String value, final StringBuilder builder) { builder.append("<b>").append(title).append("</b>").append(": ").append(value).append("<br>"); } private NewGameChooserEntry getSelected() { final int selected = gameList.getSelectedIndex(); if (selected == -1) { return null; } return gameListModel.get(selected); } private void setWidgetActivation() {} private void setupListeners() { okButton.addActionListener(e -> selectAndReturn()); cancelButton.addActionListener(e -> cancelAndReturn()); gameList.addListSelectionListener(e -> updateInfoPanel()); gameList.addMouseListener(new MouseListener() { @Override public void mouseClicked(final MouseEvent event) { if (event.getClickCount() == 2) { selectAndReturn(); } } @Override public void mousePressed(final MouseEvent e) {} @Override public void mouseReleased(final MouseEvent e) {} @Override public void mouseEntered(final MouseEvent e) {} @Override public void mouseExited(final MouseEvent e) {} }); } /** Populates the NewGameChooserModel cache if empty, then returns the cached instance. */ public static synchronized NewGameChooserModel getNewGameChooserModel() { return new NewGameChooserModel(); } private void selectAndReturn() { chosen = getSelected(); setVisible(false); } private void cancelAndReturn() { chosen = null; setVisible(false); } }