diff --git a/src/main/java/forge/control/FControl.java b/src/main/java/forge/control/FControl.java
index 0ef3d3c94c5..b10b49e850b 100644
--- a/src/main/java/forge/control/FControl.java
+++ b/src/main/java/forge/control/FControl.java
@@ -1,442 +1,453 @@
-/*
- * Forge: Play Magic: the Gathering.
- * Copyright (C) 2011 Forge Team
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package forge.control;
-
-import java.awt.Component;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowListener;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import javax.swing.ImageIcon;
-import javax.swing.JLayeredPane;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-import javax.swing.WindowConstants;
-
-import forge.Card;
-import forge.Constant.Preferences;
-import forge.Singletons;
-import forge.control.KeyboardShortcuts.Shortcut;
-import forge.game.Game;
-import forge.game.player.LobbyPlayer;
-import forge.game.player.Player;
-import forge.gui.GuiDialog;
-import forge.gui.SOverlayUtils;
-import forge.gui.deckeditor.CDeckEditorUI;
-import forge.gui.deckeditor.VDeckEditorUI;
-import forge.gui.framework.EDocID;
-import forge.gui.framework.InvalidLayoutFileException;
-import forge.gui.framework.SDisplayUtil;
-import forge.gui.framework.SLayoutIO;
-import forge.gui.framework.SOverflowUtil;
-import forge.gui.framework.SResizingUtil;
-import forge.gui.home.CHomeUI;
-import forge.gui.home.VHomeUI;
-import forge.gui.match.CMatchUI;
-import forge.gui.match.VMatchUI;
-import forge.gui.match.controllers.CDock;
-import forge.gui.match.controllers.CLog;
-import forge.gui.match.controllers.CMessage;
-import forge.gui.match.controllers.CStack;
-import forge.gui.match.nonsingleton.VField;
-import forge.gui.match.views.VAntes;
-import forge.gui.toolbox.FSkin;
-import forge.net.NetServer;
-import forge.properties.NewConstants;
-import forge.quest.data.QuestPreferences.QPref;
-import forge.quest.io.QuestDataIO;
-import forge.sound.SoundSystem;
-import forge.view.FView;
-
-/**
- *
- * FControl.
- *
- * Controls all Forge UI functionality inside one JFrame. This class switches
- * between various display states in that JFrame. Controllers are instantiated
- * separately by each state's top level view class.
- */
-public enum FControl {
- instance;
-
- private List shortcuts;
- private JLayeredPane display;
- private Screens state = Screens.UNKNOWN;
-
- private WindowListener waDefault, waConcede, waLeaveBazaar, waLeaveEditor;
-
- public static enum Screens {
- UNKNOWN,
- HOME_SCREEN,
- MATCH_SCREEN,
- DECK_EDITOR_CONSTRUCTED,
- QUEST_BAZAAR,
- DECK_EDITOR_LIMITED,
- DECK_EDITOR_QUEST,
- QUEST_CARD_SHOP,
- DRAFTING_PROCESS
- }
-
- private final SoundSystem soundSystem = new SoundSystem();
-
- /**
- *
- * FControl.
- *
- * Controls all Forge UI functionality inside one JFrame. This class
- * switches between various display states in that JFrame. Controllers are
- * instantiated separately by each state's top level view class.
- */
- private FControl() {
- this.waDefault = new WindowAdapter() {
- @Override
- public void windowClosing(final WindowEvent e) {
- Singletons.getView().getFrame().setDefaultCloseOperation(
- WindowConstants.EXIT_ON_CLOSE);
-
- System.exit(0);
- }
- };
-
-
-
- // "Close" button override during match
- this.waConcede = new WindowAdapter() {
- @Override
- public void windowClosing(final WindowEvent e) {
- Singletons.getView().getFrame().setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
-
- if (!FControl.this.game.isGameOver())
- stopGame();
- else {
- Singletons.getControl().changeState(FControl.Screens.HOME_SCREEN);
- SOverlayUtils.hideOverlay();
- }
- }
- };
-
- // "Close" button override while inside bazaar (will probably be used later for other things)
- this.waLeaveBazaar = new WindowAdapter() {
- @Override
- public void windowClosing(final WindowEvent e) {
- Singletons.getView().getFrame().setDefaultCloseOperation(
- WindowConstants.DO_NOTHING_ON_CLOSE);
-
- changeState(Screens.HOME_SCREEN);
- }
- };
-
- this.waLeaveEditor = new WindowAdapter() {
- @Override
- public void windowClosing(final WindowEvent ev) {
- Singletons.getView().getFrame().setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
-
- if (CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().exit()) {
- changeState(Screens.HOME_SCREEN);
- }
- }
- };
- }
-
- /** After view and model have been initialized, control can start.
- * @param isHeadlessMode */
- public void initialize() {
- // Preloads skin components (using progress bar).
- FSkin.loadFull();
-
- //This must be done here or at least between the skin being loaded and any FTabbedPanes being created.
- //Why,Swing? Why is this not a property of JTabbbedPane?
- UIManager.put("TabbedPane.selected", FSkin.getColor(FSkin.Colors.CLR_ACTIVE));
- UIManager.put("TabbedPane.contentOpaque", FSkin.getColor(FSkin.Colors.CLR_THEME));
- UIManager.put("TabbedPane.unselectedBackground", FSkin.getColor(FSkin.Colors.CLR_THEME2));
-
- this.shortcuts = KeyboardShortcuts.attachKeyboardShortcuts();
- this.display = FView.SINGLETON_INSTANCE.getLpnDocument();
-
- FSkin.setProgessBarMessage("About to load current quest.");
- // Preload quest data if present
- final File dirQuests = new File(NewConstants.QUEST_SAVE_DIR);
- final String questname = Singletons.getModel().getQuestPreferences().getPref(QPref.CURRENT_QUEST);
- final File data = new File(dirQuests.getPath(), questname);
- if (data.exists()) {
- Singletons.getModel().getQuest().load(QuestDataIO.loadData(data));
- }
-
- // Handles resizing in null layouts of layers in JLayeredPane.
- Singletons.getView().getFrame().addComponentListener(new ComponentAdapter() {
- @Override
- public void componentResized(final ComponentEvent e) {
- sizeChildren();
- }
- });
-
- FView.SINGLETON_INSTANCE.getLpnDocument().addMouseListener(SOverflowUtil.getHideOverflowListener());
- FView.SINGLETON_INSTANCE.getLpnDocument().addComponentListener(SResizingUtil.getWindowResizeListener());
-
- FSkin.setProgessBarMessage("Opening main window...");
- SwingUtilities.invokeLater(new Runnable() { @Override
- public void run() { Singletons.getView().initialize(); } });
- }
-
- /**
- * Switches between display states in top level JFrame.
- */
- public void changeState(Screens screen) {
- clearChildren(JLayeredPane.DEFAULT_LAYER);
- this.state = screen;
-
- Singletons.getView().getFrame().removeWindowListener(waDefault);
- Singletons.getView().getFrame().removeWindowListener(waConcede);
- Singletons.getView().getFrame().removeWindowListener(waLeaveBazaar);
- Singletons.getView().getFrame().removeWindowListener(waLeaveEditor);
-
- // Fire up new state
- switch (screen) {
- case HOME_SCREEN:
- SOverlayUtils.hideTargetingOverlay();
- VHomeUI.SINGLETON_INSTANCE.populate();
- CHomeUI.SINGLETON_INSTANCE.initialize();
- FView.SINGLETON_INSTANCE.getPnlInsets().setVisible(true);
- FView.SINGLETON_INSTANCE.getPnlInsets().setForegroundImage(new ImageIcon());
- Singletons.getView().getFrame().addWindowListener(waDefault);
- break;
-
- case MATCH_SCREEN:
- VMatchUI.SINGLETON_INSTANCE.populate();
- FView.SINGLETON_INSTANCE.getPnlInsets().setVisible(true);
- FView.SINGLETON_INSTANCE.getPnlInsets().setForegroundImage(FSkin.getIcon(FSkin.Backgrounds.BG_MATCH));
- Singletons.getView().getFrame().addWindowListener(waConcede);
- SOverlayUtils.showTargetingOverlay();
- break;
-
- case DECK_EDITOR_CONSTRUCTED:
- case DECK_EDITOR_LIMITED:
- case DECK_EDITOR_QUEST:
- case QUEST_CARD_SHOP:
- case DRAFTING_PROCESS:
- SOverlayUtils.hideTargetingOverlay();
- VDeckEditorUI.SINGLETON_INSTANCE.populate();
- FView.SINGLETON_INSTANCE.getPnlInsets().setVisible(true);
- FView.SINGLETON_INSTANCE.getPnlInsets().setForegroundImage(new ImageIcon());
- Singletons.getView().getFrame().addWindowListener(waLeaveEditor);
- break;
-
- case QUEST_BAZAAR:
- SOverlayUtils.hideTargetingOverlay();
- display.add(Singletons.getView().getViewBazaar(), JLayeredPane.DEFAULT_LAYER);
- FView.SINGLETON_INSTANCE.getPnlInsets().setVisible(false);
- sizeChildren();
- Singletons.getView().getFrame().addWindowListener(waLeaveBazaar);
- break;
-
- default:
- throw new RuntimeException("unhandled screen: " + screen);
- }
- }
-
- public void changeStateAutoFixLayout(Screens newState, String stateName) {
- try {
- changeState(newState);
- } catch (InvalidLayoutFileException ex) {
- GuiDialog.message("Your " + stateName + " layout file could not be read. It will be deleted after you press OK.\nThe game will proceed with default layout.");
- File fLayout = new File(SLayoutIO.getFilePreferred(newState));
- fLayout.delete();
- // try again
- changeState(newState);
- }
- }
-
- /**
- * Returns the int reflecting the current state of the top level frame
- * (see field definitions and class methods for details).
- *
- * @return {@link java.lang.Integer}
- * */
- public Screens getState() {
- return this.state;
- }
-
- /** @return List A list of attached keyboard shortcut descriptions and properties. */
- public List getShortcuts() {
- return this.shortcuts;
- }
-
- /** Remove all children from a specified layer. */
- private void clearChildren(final int layer0) {
- final Component[] children = FView.SINGLETON_INSTANCE.getLpnDocument()
- .getComponentsInLayer(layer0);
-
- for (final Component c : children) {
- display.remove(c);
- }
- }
-
- /** Sizes children of JLayeredPane to fully fit their layers. */
- private void sizeChildren() {
- Component[] children = display.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER);
- if (children.length != 0) { children[0].setSize(display.getSize()); }
-
- children = display.getComponentsInLayer(FView.TARGETING_LAYER);
- if (children.length != 0) { children[0].setSize(display.getSize()); }
-
- children = display.getComponentsInLayer(JLayeredPane.MODAL_LAYER);
- if (children.length != 0) { children[0].setSize(display.getSize()); }
- }
-
- /**
- * TODO: Write javadoc for this method.
- * @return
- */
- private Lobby lobby = null;
- public Lobby getLobby() {
- if (lobby == null) {
- lobby = new Lobby();
- }
- return lobby;
- }
-
- public Player getCurrentPlayer() {
- // try current priority
- Player currentPriority = game.getPhaseHandler().getPriorityPlayer();
- if( null != currentPriority && currentPriority.getLobbyPlayer() == getLobby().getGuiPlayer() )
- return currentPriority;
-
- // otherwise find just any player, belonging to this lobbyplayer
- for(Player p : game.getPlayers())
- if(p.getLobbyPlayer() == getLobby().getGuiPlayer() )
- return p;
-
- return null;
- }
-
- public boolean mayShowCard(Card c) {
- return game == null || !gameHasHumanPlayer || c.canBeShownTo(getCurrentPlayer());
- }
-
- /**
- * TODO: Write javadoc for this method.
- * @return
- */
- public SoundSystem getSoundSystem() {
- return soundSystem;
- }
-
- /**
- * TODO: Write javadoc for this method.
- * @return
- */
- private final NetServer server = new NetServer();
- public NetServer getServer() {
- // TODO Auto-generated method stub
- return server;
- }
-
- private Game game;
- private boolean gameHasHumanPlayer;
-
- public Game getObservedGame() {
- return game;
- }
-
- public final void stopGame() {
- List pp = new ArrayList();
- for(Player p : game.getPlayers()) {
- if ( p.getOriginalLobbyPlayer() == getLobby().getGuiPlayer() )
- pp.add(p);
- }
- boolean hasHuman = !pp.isEmpty();
-
- if ( pp.isEmpty() )
- pp.addAll(game.getPlayers()); // no human? then all players surrender!
-
- for(Player p: pp)
- p.concede();
-
- Player priorityPlayer = game.getPhaseHandler().getPriorityPlayer();
- boolean humanHasPriority = priorityPlayer == null || priorityPlayer.getLobbyPlayer() == getLobby().getGuiPlayer();
-
- if ( hasHuman && humanHasPriority )
- game.getAction().checkGameOverCondition();
- else
- game.isGameOver(); // this is synchronized method - it's used to make Game-0 thread see changes made here
-
- playbackControl.onGameStopRequested();
- }
-
- private InputQueue inputQueue;
- public InputQueue getInputQueue() {
- return inputQueue;
- }
-
-
- private final FControlGameEventHandler fcVisitor = new FControlGameEventHandler(this);
- private final FControlGamePlayback playbackControl = new FControlGamePlayback(this);
- public void attachToGame(Game game0) {
- // TODO: Detach from other game we might be looking at
-
- inputQueue = new InputQueue();
-
- this.game = game0;
- game.subscribeToEvents(Singletons.getControl().getSoundSystem());
-
- LobbyPlayer humanLobbyPlayer = getLobby().getGuiPlayer();
- // The UI controls should use these game data as models
- CMatchUI.SINGLETON_INSTANCE.initMatch(game.getRegisteredPlayers(), humanLobbyPlayer);
- CDock.SINGLETON_INSTANCE.setModel(game, humanLobbyPlayer);
- CStack.SINGLETON_INSTANCE.setModel(game.getStack(), humanLobbyPlayer);
- CLog.SINGLETON_INSTANCE.setModel(game.getGameLog());
-
-
- Singletons.getModel().getPreferences().actuateMatchPreferences();
-
- changeStateAutoFixLayout(Screens.MATCH_SCREEN, "match");
- SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc());
-
- CMessage.SINGLETON_INSTANCE.getInputControl().setGame(game);
-
- // Listen to DuelOutcome event to show ViewWinLose
- game.subscribeToEvents(fcVisitor);
-
- // Add playback controls to match if needed
- gameHasHumanPlayer = false;
- for(Player p : game.getPlayers()) {
- if ( p.getController().getLobbyPlayer() == getLobby().getGuiPlayer() )
- gameHasHumanPlayer = true;
- }
-
- if (!gameHasHumanPlayer) {
- game.subscribeToEvents(playbackControl);
- }
-
- VAntes.SINGLETON_INSTANCE.setModel(game.getRegisteredPlayers());
-
- for (final VField field : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) {
- field.getDetailsPanel().getLblLibrary().setHoverable(Preferences.DEV_MODE);
- }
-
- // per player observers were set in CMatchUI.SINGLETON_INSTANCE.initMatch
- //Set Field shown to current player.
- VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(game.getPlayers().get(0));
- SDisplayUtil.showTab(nextField);
- }
-}
-
+/*
+ * Forge: Play Magic: the Gathering.
+ * Copyright (C) 2011 Forge Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package forge.control;
+
+import java.awt.Component;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.ImageIcon;
+import javax.swing.JLayeredPane;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.WindowConstants;
+
+import forge.Card;
+import forge.Constant.Preferences;
+import forge.Singletons;
+import forge.control.KeyboardShortcuts.Shortcut;
+import forge.game.Game;
+import forge.game.player.LobbyPlayer;
+import forge.game.player.Player;
+import forge.gui.GuiDialog;
+import forge.gui.SOverlayUtils;
+import forge.gui.deckeditor.CDeckEditorUI;
+import forge.gui.deckeditor.VDeckEditorUI;
+import forge.gui.framework.EDocID;
+import forge.gui.framework.InvalidLayoutFileException;
+import forge.gui.framework.SDisplayUtil;
+import forge.gui.framework.SLayoutIO;
+import forge.gui.framework.SOverflowUtil;
+import forge.gui.framework.SResizingUtil;
+import forge.gui.home.CHomeUI;
+import forge.gui.home.VHomeUI;
+import forge.gui.match.CMatchUI;
+import forge.gui.match.VMatchUI;
+import forge.gui.match.controllers.CDock;
+import forge.gui.match.controllers.CLog;
+import forge.gui.match.controllers.CMessage;
+import forge.gui.match.controllers.CStack;
+import forge.gui.match.nonsingleton.VField;
+import forge.gui.match.views.VAntes;
+import forge.gui.toolbox.FSkin;
+import forge.net.NetServer;
+import forge.properties.ForgePreferences.FPref;
+import forge.properties.NewConstants;
+import forge.quest.data.QuestPreferences.QPref;
+import forge.quest.io.QuestDataIO;
+import forge.sound.SoundSystem;
+import forge.view.FView;
+
+/**
+ *
+ * FControl.
+ *
+ * Controls all Forge UI functionality inside one JFrame. This class switches
+ * between various display states in that JFrame. Controllers are instantiated
+ * separately by each state's top level view class.
+ */
+public enum FControl {
+ instance;
+
+ private List shortcuts;
+ private JLayeredPane display;
+ private Screens state = Screens.UNKNOWN;
+
+ private WindowListener waDefault, waConcede, waLeaveBazaar, waLeaveEditor;
+
+ public static enum Screens {
+ UNKNOWN,
+ HOME_SCREEN,
+ MATCH_SCREEN,
+ DECK_EDITOR_CONSTRUCTED,
+ QUEST_BAZAAR,
+ DECK_EDITOR_LIMITED,
+ DECK_EDITOR_QUEST,
+ QUEST_CARD_SHOP,
+ DRAFTING_PROCESS
+ }
+
+ private final SoundSystem soundSystem = new SoundSystem();
+
+ /**
+ *
+ * FControl.
+ *
+ * Controls all Forge UI functionality inside one JFrame. This class
+ * switches between various display states in that JFrame. Controllers are
+ * instantiated separately by each state's top level view class.
+ */
+ private FControl() {
+ this.waDefault = new WindowAdapter() {
+ @Override
+ public void windowClosing(final WindowEvent e) {
+ Singletons.getView().getFrame().setDefaultCloseOperation(
+ WindowConstants.EXIT_ON_CLOSE);
+
+ System.exit(0);
+ }
+ };
+
+
+
+ // "Close" button override during match
+ this.waConcede = new WindowAdapter() {
+ @Override
+ public void windowClosing(final WindowEvent e) {
+ Singletons.getView().getFrame().setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+
+ if (!FControl.this.game.isGameOver())
+ stopGame();
+ else {
+ Singletons.getControl().changeState(FControl.Screens.HOME_SCREEN);
+ SOverlayUtils.hideOverlay();
+ }
+ }
+ };
+
+ // "Close" button override while inside bazaar (will probably be used later for other things)
+ this.waLeaveBazaar = new WindowAdapter() {
+ @Override
+ public void windowClosing(final WindowEvent e) {
+ Singletons.getView().getFrame().setDefaultCloseOperation(
+ WindowConstants.DO_NOTHING_ON_CLOSE);
+
+ changeState(Screens.HOME_SCREEN);
+ }
+ };
+
+ this.waLeaveEditor = new WindowAdapter() {
+ @Override
+ public void windowClosing(final WindowEvent ev) {
+ Singletons.getView().getFrame().setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+
+ if (CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().exit()) {
+ changeState(Screens.HOME_SCREEN);
+ }
+ }
+ };
+ }
+
+ /** After view and model have been initialized, control can start.
+ * @param isHeadlessMode */
+ public void initialize() {
+ // Preloads skin components (using progress bar).
+ FSkin.loadFull();
+
+ //This must be done here or at least between the skin being loaded and any FTabbedPanes being created.
+ //Why,Swing? Why is this not a property of JTabbbedPane?
+ UIManager.put("TabbedPane.selected", FSkin.getColor(FSkin.Colors.CLR_ACTIVE));
+ UIManager.put("TabbedPane.contentOpaque", FSkin.getColor(FSkin.Colors.CLR_THEME));
+ UIManager.put("TabbedPane.unselectedBackground", FSkin.getColor(FSkin.Colors.CLR_THEME2));
+
+ this.shortcuts = KeyboardShortcuts.attachKeyboardShortcuts();
+ this.display = FView.SINGLETON_INSTANCE.getLpnDocument();
+
+ FSkin.setProgessBarMessage("About to load current quest.");
+ // Preload quest data if present
+ final File dirQuests = new File(NewConstants.QUEST_SAVE_DIR);
+ final String questname = Singletons.getModel().getQuestPreferences().getPref(QPref.CURRENT_QUEST);
+ final File data = new File(dirQuests.getPath(), questname);
+ if (data.exists()) {
+ Singletons.getModel().getQuest().load(QuestDataIO.loadData(data));
+ }
+
+ // Handles resizing in null layouts of layers in JLayeredPane.
+ Singletons.getView().getFrame().addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(final ComponentEvent e) {
+ sizeChildren();
+ }
+ });
+
+ FView.SINGLETON_INSTANCE.getLpnDocument().addMouseListener(SOverflowUtil.getHideOverflowListener());
+ FView.SINGLETON_INSTANCE.getLpnDocument().addComponentListener(SResizingUtil.getWindowResizeListener());
+
+ FSkin.setProgessBarMessage("Opening main window...");
+ SwingUtilities.invokeLater(new Runnable() { @Override
+ public void run() { Singletons.getView().initialize(); } });
+ }
+
+ /**
+ * Switches between display states in top level JFrame.
+ */
+ public void changeState(Screens screen) {
+ clearChildren(JLayeredPane.DEFAULT_LAYER);
+ this.state = screen;
+
+ Singletons.getView().getFrame().removeWindowListener(waDefault);
+ Singletons.getView().getFrame().removeWindowListener(waConcede);
+ Singletons.getView().getFrame().removeWindowListener(waLeaveBazaar);
+ Singletons.getView().getFrame().removeWindowListener(waLeaveEditor);
+
+ // Fire up new state
+ switch (screen) {
+ case HOME_SCREEN:
+ SOverlayUtils.hideTargetingOverlay();
+ VHomeUI.SINGLETON_INSTANCE.populate();
+ CHomeUI.SINGLETON_INSTANCE.initialize();
+ FView.SINGLETON_INSTANCE.getPnlInsets().setVisible(true);
+ FView.SINGLETON_INSTANCE.getPnlInsets().setForegroundImage(new ImageIcon());
+ Singletons.getView().getFrame().addWindowListener(waDefault);
+ break;
+
+ case MATCH_SCREEN:
+ VMatchUI.SINGLETON_INSTANCE.populate();
+ FView.SINGLETON_INSTANCE.getPnlInsets().setVisible(true);
+ showMatchBackgroundImage();
+ Singletons.getView().getFrame().addWindowListener(waConcede);
+ SOverlayUtils.showTargetingOverlay();
+ break;
+
+ case DECK_EDITOR_CONSTRUCTED:
+ case DECK_EDITOR_LIMITED:
+ case DECK_EDITOR_QUEST:
+ case QUEST_CARD_SHOP:
+ case DRAFTING_PROCESS:
+ SOverlayUtils.hideTargetingOverlay();
+ VDeckEditorUI.SINGLETON_INSTANCE.populate();
+ FView.SINGLETON_INSTANCE.getPnlInsets().setVisible(true);
+ FView.SINGLETON_INSTANCE.getPnlInsets().setForegroundImage(new ImageIcon());
+ Singletons.getView().getFrame().addWindowListener(waLeaveEditor);
+ break;
+
+ case QUEST_BAZAAR:
+ SOverlayUtils.hideTargetingOverlay();
+ display.add(Singletons.getView().getViewBazaar(), JLayeredPane.DEFAULT_LAYER);
+ FView.SINGLETON_INSTANCE.getPnlInsets().setVisible(false);
+ sizeChildren();
+ Singletons.getView().getFrame().addWindowListener(waLeaveBazaar);
+ break;
+
+ default:
+ throw new RuntimeException("unhandled screen: " + screen);
+ }
+ }
+
+ private void showMatchBackgroundImage() {
+ if (isMatchBackgroundImageVisible()) {
+ FView.SINGLETON_INSTANCE.getPnlInsets().setForegroundImage(FSkin.getIcon(FSkin.Backgrounds.BG_MATCH));
+ }
+ }
+
+ private boolean isMatchBackgroundImageVisible() {
+ return Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_MATCH_IMAGE_VISIBLE);
+ }
+
+ public void changeStateAutoFixLayout(Screens newState, String stateName) {
+ try {
+ changeState(newState);
+ } catch (InvalidLayoutFileException ex) {
+ GuiDialog.message("Your " + stateName + " layout file could not be read. It will be deleted after you press OK.\nThe game will proceed with default layout.");
+ File fLayout = new File(SLayoutIO.getFilePreferred(newState));
+ fLayout.delete();
+ // try again
+ changeState(newState);
+ }
+ }
+
+ /**
+ * Returns the int reflecting the current state of the top level frame
+ * (see field definitions and class methods for details).
+ *
+ * @return {@link java.lang.Integer}
+ * */
+ public Screens getState() {
+ return this.state;
+ }
+
+ /** @return List A list of attached keyboard shortcut descriptions and properties. */
+ public List getShortcuts() {
+ return this.shortcuts;
+ }
+
+ /** Remove all children from a specified layer. */
+ private void clearChildren(final int layer0) {
+ final Component[] children = FView.SINGLETON_INSTANCE.getLpnDocument()
+ .getComponentsInLayer(layer0);
+
+ for (final Component c : children) {
+ display.remove(c);
+ }
+ }
+
+ /** Sizes children of JLayeredPane to fully fit their layers. */
+ private void sizeChildren() {
+ Component[] children = display.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER);
+ if (children.length != 0) { children[0].setSize(display.getSize()); }
+
+ children = display.getComponentsInLayer(FView.TARGETING_LAYER);
+ if (children.length != 0) { children[0].setSize(display.getSize()); }
+
+ children = display.getComponentsInLayer(JLayeredPane.MODAL_LAYER);
+ if (children.length != 0) { children[0].setSize(display.getSize()); }
+ }
+
+ /**
+ * TODO: Write javadoc for this method.
+ * @return
+ */
+ private Lobby lobby = null;
+ public Lobby getLobby() {
+ if (lobby == null) {
+ lobby = new Lobby();
+ }
+ return lobby;
+ }
+
+ public Player getCurrentPlayer() {
+ // try current priority
+ Player currentPriority = game.getPhaseHandler().getPriorityPlayer();
+ if( null != currentPriority && currentPriority.getLobbyPlayer() == getLobby().getGuiPlayer() )
+ return currentPriority;
+
+ // otherwise find just any player, belonging to this lobbyplayer
+ for(Player p : game.getPlayers())
+ if(p.getLobbyPlayer() == getLobby().getGuiPlayer() )
+ return p;
+
+ return null;
+ }
+
+ public boolean mayShowCard(Card c) {
+ return game == null || !gameHasHumanPlayer || c.canBeShownTo(getCurrentPlayer());
+ }
+
+ /**
+ * TODO: Write javadoc for this method.
+ * @return
+ */
+ public SoundSystem getSoundSystem() {
+ return soundSystem;
+ }
+
+ /**
+ * TODO: Write javadoc for this method.
+ * @return
+ */
+ private final NetServer server = new NetServer();
+ public NetServer getServer() {
+ // TODO Auto-generated method stub
+ return server;
+ }
+
+ private Game game;
+ private boolean gameHasHumanPlayer;
+
+ public Game getObservedGame() {
+ return game;
+ }
+
+ public final void stopGame() {
+ List pp = new ArrayList();
+ for(Player p : game.getPlayers()) {
+ if ( p.getOriginalLobbyPlayer() == getLobby().getGuiPlayer() )
+ pp.add(p);
+ }
+ boolean hasHuman = !pp.isEmpty();
+
+ if ( pp.isEmpty() )
+ pp.addAll(game.getPlayers()); // no human? then all players surrender!
+
+ for(Player p: pp)
+ p.concede();
+
+ Player priorityPlayer = game.getPhaseHandler().getPriorityPlayer();
+ boolean humanHasPriority = priorityPlayer == null || priorityPlayer.getLobbyPlayer() == getLobby().getGuiPlayer();
+
+ if ( hasHuman && humanHasPriority )
+ game.getAction().checkGameOverCondition();
+ else
+ game.isGameOver(); // this is synchronized method - it's used to make Game-0 thread see changes made here
+
+ playbackControl.onGameStopRequested();
+ }
+
+ private InputQueue inputQueue;
+ public InputQueue getInputQueue() {
+ return inputQueue;
+ }
+
+
+ private final FControlGameEventHandler fcVisitor = new FControlGameEventHandler(this);
+ private final FControlGamePlayback playbackControl = new FControlGamePlayback(this);
+ public void attachToGame(Game game0) {
+ // TODO: Detach from other game we might be looking at
+
+ inputQueue = new InputQueue();
+
+ this.game = game0;
+ game.subscribeToEvents(Singletons.getControl().getSoundSystem());
+
+ LobbyPlayer humanLobbyPlayer = getLobby().getGuiPlayer();
+ // The UI controls should use these game data as models
+ CMatchUI.SINGLETON_INSTANCE.initMatch(game.getRegisteredPlayers(), humanLobbyPlayer);
+ CDock.SINGLETON_INSTANCE.setModel(game, humanLobbyPlayer);
+ CStack.SINGLETON_INSTANCE.setModel(game.getStack(), humanLobbyPlayer);
+ CLog.SINGLETON_INSTANCE.setModel(game.getGameLog());
+
+
+ Singletons.getModel().getPreferences().actuateMatchPreferences();
+
+ changeStateAutoFixLayout(Screens.MATCH_SCREEN, "match");
+ SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc());
+
+ CMessage.SINGLETON_INSTANCE.getInputControl().setGame(game);
+
+ // Listen to DuelOutcome event to show ViewWinLose
+ game.subscribeToEvents(fcVisitor);
+
+ // Add playback controls to match if needed
+ gameHasHumanPlayer = false;
+ for(Player p : game.getPlayers()) {
+ if ( p.getController().getLobbyPlayer() == getLobby().getGuiPlayer() )
+ gameHasHumanPlayer = true;
+ }
+
+ if (!gameHasHumanPlayer) {
+ game.subscribeToEvents(playbackControl);
+ }
+
+ VAntes.SINGLETON_INSTANCE.setModel(game.getRegisteredPlayers());
+
+ for (final VField field : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) {
+ field.getDetailsPanel().getLblLibrary().setHoverable(Preferences.DEV_MODE);
+ }
+
+ // per player observers were set in CMatchUI.SINGLETON_INSTANCE.initMatch
+ //Set Field shown to current player.
+ VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(game.getPlayers().get(0));
+ SDisplayUtil.showTab(nextField);
+ }
+}
+
diff --git a/src/main/java/forge/gui/home/settings/CSubmenuPreferences.java b/src/main/java/forge/gui/home/settings/CSubmenuPreferences.java
index be694131861..4f24d225328 100644
--- a/src/main/java/forge/gui/home/settings/CSubmenuPreferences.java
+++ b/src/main/java/forge/gui/home/settings/CSubmenuPreferences.java
@@ -51,7 +51,7 @@ public enum CSubmenuPreferences implements ICDoc {
this.view = VSubmenuPreferences.SINGLETON_INSTANCE;
this.prefs = Singletons.getModel().getPreferences();
-
+
// This updates variable right now and is not standard
view.getCbDevMode().addItemListener(new ItemListener() {
@Override
@@ -83,6 +83,7 @@ public enum CSubmenuPreferences implements ICDoc {
lstControls.add(Pair.of(view.getCbOverlayCardName(), FPref.UI_OVERLAY_CARD_NAME));
lstControls.add(Pair.of(view.getCbOverlayCardPower(), FPref.UI_OVERLAY_CARD_POWER));
lstControls.add(Pair.of(view.getCbOverlayCardManaCost(), FPref.UI_OVERLAY_CARD_MANA_COST));
+ lstControls.add(Pair.of(view.getCbShowMatchBackgroundImage(), FPref.UI_MATCH_IMAGE_VISIBLE));
for(final Pair kv : lstControls) {
kv.getKey().addItemListener(new ItemListener() {
@@ -113,19 +114,21 @@ public enum CSubmenuPreferences implements ICDoc {
public void run() {
CSubmenuPreferences.this.resetMatchScreenLayout();
}
- });
-
+ });
+
initializeGameLogVerbosityComboBox();
initializeAiProfilesComboBox();
initializeSkinsComboBox();
}
-
+
+
/* (non-Javadoc)
* @see forge.control.home.IControlSubmenu#update()
*/
@Override
public void update() {
+
this.view = VSubmenuPreferences.SINGLETON_INSTANCE;
this.prefs = Singletons.getModel().getPreferences();
diff --git a/src/main/java/forge/gui/home/settings/VSubmenuPreferences.java b/src/main/java/forge/gui/home/settings/VSubmenuPreferences.java
index 37fc22f9cb6..c3f8474e6ec 100644
--- a/src/main/java/forge/gui/home/settings/VSubmenuPreferences.java
+++ b/src/main/java/forge/gui/home/settings/VSubmenuPreferences.java
@@ -22,7 +22,6 @@ import javax.swing.border.MatteBorder;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.lang3.StringUtils;
-
import forge.GameLogEntryType;
import forge.Singletons;
import forge.control.KeyboardShortcuts;
@@ -82,6 +81,7 @@ public enum VSubmenuPreferences implements IVSubmenu {
private final JCheckBox cbOverlayCardPower = new OptionsCheckBox("Power/Toughness");
private final JCheckBox cbOverlayCardManaCost = new OptionsCheckBox("Mana Cost");
private final JCheckBox cbCompactMainMenu = new OptionsCheckBox("Use Compact Main Sidebar Menu");
+ private final JCheckBox cbShowMatchBackgroundImage = new OptionsCheckBox("Show Background Image on Match Screen");
private final Map shortcutFields = new HashMap();
@@ -166,6 +166,7 @@ public enum VSubmenuPreferences implements IVSubmenu {
pnlPrefs.add(cbpGameLogEntryType, "w 80%!, gap 10% 0 0 10px, span 2 1");
pnlPrefs.add(new NoteLabel("Changes how much information is displayed in the game log. Sorted by least to most verbose."), regularConstraints);
+
// Themes
pnlPrefs.add(new SectionLabel("Visual Themes"), sectionConstraints + ", gaptop 2%");
@@ -173,6 +174,10 @@ public enum VSubmenuPreferences implements IVSubmenu {
pnlPrefs.add(cbpSkin, "w 80%!, gap 10% 0 0 10px, span 2 1");
pnlPrefs.add(new NoteLabel("Change the overall look and feel of Forge (RESTART REQUIRED)."), regularConstraints);
+ pnlPrefs.add(cbShowMatchBackgroundImage, regularConstraints);
+ pnlPrefs.add(new NoteLabel("Toggle the visibility of the background image on the match screen."), regularConstraints);
+
+
// Graphic Options
pnlPrefs.add(new SectionLabel("Graphic Options"), sectionConstraints + ", gaptop 2%");
@@ -188,13 +193,14 @@ public enum VSubmenuPreferences implements IVSubmenu {
pnlPrefs.add(cbUiForTouchScreen, regularConstraints);
pnlPrefs.add(new NoteLabel("Increases some UI elements to provide a better experience on touchscreen devices. (Needs restart)"), regularConstraints);
- // Overlay options
+ // Card Overlay options
pnlPrefs.add(new SectionLabel("Card Overlay Options"), sectionConstraints);
pnlPrefs.add(new NoteLabel("Show text overlays which are easier to read when cards are reduced in size to fit the play area."), regularConstraints);
pnlPrefs.add(cbOverlayCardName, regularConstraints);
pnlPrefs.add(cbOverlayCardPower, regularConstraints);
pnlPrefs.add(cbOverlayCardManaCost, regularConstraints);
+
// Sound options
pnlPrefs.add(new SectionLabel("Sound Options"), sectionConstraints + ", gaptop 2%");
@@ -204,6 +210,7 @@ public enum VSubmenuPreferences implements IVSubmenu {
pnlPrefs.add(cbAltSoundSystem, regularConstraints);
pnlPrefs.add(new NoteLabel("Use the alternate sound system (only use in case your have issues with sound not playing or disappearing)"), regularConstraints);
+
// Keyboard shortcuts
final JLabel lblShortcuts = new SectionLabel("Keyboard Shortcuts");
pnlPrefs.add(lblShortcuts, sectionConstraints + ", gaptop 2%");
@@ -467,6 +474,7 @@ public enum VSubmenuPreferences implements IVSubmenu {
public FComboBoxPanel getSkinsComboBoxPanel() {
return cbpSkin;
}
+
/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getCbEnforceDeckLegality() {
return cbEnforceDeckLegality;
@@ -496,9 +504,11 @@ public enum VSubmenuPreferences implements IVSubmenu {
return btnReset;
}
+ /** @return {@link javax.swing.JCheckBox} */
+ public JCheckBox getCbShowMatchBackgroundImage() {
+ return cbShowMatchBackgroundImage;
+ }
-
-
//========== Overridden from IVDoc
public final FLabel getBtnDeleteMatchUI() {
diff --git a/src/main/java/forge/properties/ForgePreferences.java b/src/main/java/forge/properties/ForgePreferences.java
index 19deefeb9b6..9d91f2f885e 100644
--- a/src/main/java/forge/properties/ForgePreferences.java
+++ b/src/main/java/forge/properties/ForgePreferences.java
@@ -59,6 +59,7 @@ public class ForgePreferences extends PreferencesStore {
UI_RANDOM_CARD_ART ("false"),
UI_CURRENT_AI_PROFILE (AiProfileUtil.AI_PROFILE_RANDOM_MATCH),
UI_CLONE_MODE_SOURCE ("false"), /** */
+ UI_MATCH_IMAGE_VISIBLE ("true"),
UI_FOR_TOUCHSCREN("false"),