Holy Graphical User Interface, Batman!

This commit is contained in:
Doublestrike
2011-11-26 00:19:24 +00:00
parent af56838cbe
commit c03cdc3c1e
63 changed files with 5379 additions and 117 deletions

42
.gitattributes vendored
View File

@@ -9805,6 +9805,7 @@ res/images/deckeditor/filter_sorcery_n.png -text svneol=unset#image/png
res/images/deckeditor/filter_sorcery_y.png -text svneol=unset#image/png
res/images/deckeditor/filter_white_n.png -text svneol=unset#image/png
res/images/deckeditor/filter_white_y.png -text svneol=unset#image/png
res/images/skins/default/bg_match.jpg -text
res/images/skins/default/bg_splash.jpg -text
res/images/skins/default/btnLdown.png -text
res/images/skins/default/btnLover.png -text
@@ -9818,9 +9819,9 @@ res/images/skins/default/btnRup.png -text
res/images/skins/default/font1.ttf -text
res/images/skins/default/font2.ttf -text
res/images/skins/default/palette.png -text
res/images/skins/default/sprite.png -text
res/images/skins/default/texture1.jpg -text
res/images/skins/default/texture2.jpg -text
res/images/skins/default/texture3.jpg -text
res/images/skins/rebel/bg_match.jpg -text
res/images/skins/rebel/bg_splash.jpg -text
res/images/skins/rebel/btnLdown.png -text
res/images/skins/rebel/btnLover.png -text
@@ -9834,9 +9835,8 @@ res/images/skins/rebel/btnRup.png -text
res/images/skins/rebel/font1.ttf -text
res/images/skins/rebel/font2.ttf -text
res/images/skins/rebel/palette.png -text
res/images/skins/rebel/sprite.png -text
res/images/skins/rebel/texture1.jpg -text
res/images/skins/rebel/texture2.jpg -text
res/images/skins/rebel/texture3.jpg -text
res/images/symbols-13/0.png -text svneol=unset#image/png
res/images/symbols-13/1.png -text svneol=unset#image/png
res/images/symbols-13/10.png -text svneol=unset#image/png
@@ -9891,6 +9891,12 @@ res/images/symbols-13/counters2.png -text
res/images/symbols-13/counters3.png -text
res/images/symbols-13/countersMulti.png -text
res/images/symbols-13/defend.png -text svneol=unset#image/png
res/images/symbols-13/detail_exile.png -text
res/images/symbols-13/detail_flashback.png -text
res/images/symbols-13/detail_grave.png -text
res/images/symbols-13/detail_hand.png -text
res/images/symbols-13/detail_library.png -text
res/images/symbols-13/detail_poison.png -text
res/images/symbols-13/foil01.png -text svneol=unset#image/png
res/images/symbols-13/foil02.png -text svneol=unset#image/png
res/images/symbols-13/foil03.png -text svneol=unset#image/png
@@ -10692,6 +10698,18 @@ src/main/java/forge/card/trigger/TriggerTurnFaceUp.java svneol=native#text/plain
src/main/java/forge/card/trigger/TriggerUnequip.java svneol=native#text/plain
src/main/java/forge/card/trigger/TriggerUntaps.java svneol=native#text/plain
src/main/java/forge/card/trigger/package-info.java svneol=native#text/plain
src/main/java/forge/control/ControlAllUI.java -text
src/main/java/forge/control/ControlEditorUI.java -text
src/main/java/forge/control/ControlHomeUI.java -text
src/main/java/forge/control/ControlMatchUI.java -text
src/main/java/forge/control/match/ControlCardviewer.java -text
src/main/java/forge/control/match/ControlDock.java -text
src/main/java/forge/control/match/ControlField.java -text
src/main/java/forge/control/match/ControlHand.java -text
src/main/java/forge/control/match/ControlInput.java -text
src/main/java/forge/control/match/ControlTabber.java -text
src/main/java/forge/control/match/package-info.java -text
src/main/java/forge/control/package-info.java -text
src/main/java/forge/deck/Deck.java svneol=native#text/plain
src/main/java/forge/deck/DeckGeneration.java -text
src/main/java/forge/deck/DeckManager.java svneol=native#text/plain
@@ -10848,6 +10866,18 @@ src/main/java/forge/quest/gui/main/package-info.java svneol=native#text/plain
src/main/java/forge/quest/gui/package-info.java svneol=native#text/plain
src/main/java/forge/quest/package-info.java svneol=native#text/plain
src/main/java/forge/view/FView.java svneol=native#text/plain
src/main/java/forge/view/GuiTopLevel.java -text
src/main/java/forge/view/home/HomeTopLevel.java -text
src/main/java/forge/view/match/ViewAreaBattlefield.java -text
src/main/java/forge/view/match/ViewAreaSidebar.java -text
src/main/java/forge/view/match/ViewAreaUser.java -text
src/main/java/forge/view/match/ViewCardviewer.java -text
src/main/java/forge/view/match/ViewDock.java -text
src/main/java/forge/view/match/ViewField.java -text
src/main/java/forge/view/match/ViewHand.java -text
src/main/java/forge/view/match/ViewInput.java -text
src/main/java/forge/view/match/ViewTabber.java -text
src/main/java/forge/view/match/ViewTopLevel.java -text
src/main/java/forge/view/package-info.java svneol=native#text/plain
src/main/java/forge/view/swing/ApplicationView.java svneol=native#text/plain
src/main/java/forge/view/swing/GuiHomeScreen.java svneol=native#text/plain
@@ -10859,6 +10889,10 @@ src/main/java/forge/view/swing/SplashProgressModel.java -text
src/main/java/forge/view/swing/WinLoseFrame.java -text
src/main/java/forge/view/swing/WinLoseModeHandler.java -text
src/main/java/forge/view/swing/package-info.java svneol=native#text/plain
src/main/java/forge/view/toolbox/CardDetailPanel.java -text
src/main/java/forge/view/toolbox/CardViewer.java -text
src/main/java/forge/view/toolbox/FOverlay.java -text
src/main/java/forge/view/toolbox/FVerticalTabPanel.java -text
src/main/java/net/slightlymagic/braids/LICENSE.txt svneol=native#text/plain
src/main/java/net/slightlymagic/braids/util/ClumsyRunnable.java svneol=native#text/plain
src/main/java/net/slightlymagic/braids/util/ImmutableIterableFrom.java svneol=native#text/plain

14
.gitignore vendored
View File

@@ -17,8 +17,22 @@ res/quest/questData.dat
res/quest/questData.dat.xml
res/reprintSetInfo.log
res/setInfoScript.log
src/main/java/forge/control
src/main/java/forge/gui/control
src/main/java/forge/gui/ds
src/main/java/forge/gui/editor
src/main/java/forge/gui/home
src/main/java/forge/gui/match
src/main/java/forge/gui/matchOLD
src/main/java/forge/gui/toolbox
src/main/java/forge/gui/unfinished
src/main/java/forge/interfaces
src/main/java/forge/view/components
src/main/java/forge/view/controllers
src/main/java/forge/view/editor
src/main/java/forge/view/home
src/main/java/forge/view/interfaces
src/main/java/forge/view/match
src/main/java/forge/view/toolbox
/target
/test-output

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -134,7 +134,7 @@ NewGame/booster_text=Booster Draft (Schwierig) - W
NewGame/yourdeck=Dein Deck
NewGame/opponent=Gegner
NewGame/deckeditor=Deck Editor
NewGame/newgui=New Gui
NewGame/oldgui=Old Gui
NewGame/ailand=Stack AI Land
NewGame/devmode=Developer Mode
NewGame/questmode=Quest Mode

View File

@@ -172,7 +172,7 @@ NewGame/booster_text=Booster Draft (Hard) - Pick cards 1 at a time to create you
NewGame/yourdeck=Your Deck
NewGame/opponent=Opponent
NewGame/deckeditor=Deck Editor
NewGame/newgui=New Gui
NewGame/oldgui=Old Gui
NewGame/ailand=Stack AI Land
NewGame/devmode=Developer Mode
NewGame/questmode=Quest Mode

View File

@@ -11,6 +11,7 @@ import forge.card.trigger.TriggerHandler;
import forge.deck.DeckManager;
import forge.game.GameSummary;
import forge.gui.input.InputControl;
import forge.view.toolbox.FOverlay;
import forge.gui.skin.FSkin;
import forge.model.FGameState;
import forge.properties.ForgeProps;
@@ -78,6 +79,9 @@ public final class AllZone {
/** Global <code>display</code>. */
private static Display display;
/** Global <code>overlay</code>. */
private static FOverlay overlay;
/** Constant <code>DECK_MGR</code>. */
private static DeckManager deckManager;
@@ -629,4 +633,18 @@ public final class AllZone {
public static void setSkin(final FSkin fs) {
skin = fs;
}
/**
* @return overlay
*/
public static FOverlay getOverlay() {
return overlay;
}
/**
* @param overlay0 &emsp; Overlay panel
*/
public static void setOverlay(FOverlay overlay0) {
overlay = overlay0;
}
} // AllZone

View File

@@ -40,10 +40,17 @@ public final class Constant {
public static final boolean[] MILL = new boolean[1];
/** The Constant DevMode. */
public static final boolean[] DEV_MODE = new boolean[1]; // one for
// normal mode
// one for quest
// mode
// one for normal mode, one for quest mode
public static final boolean[] DEV_MODE = new boolean[1];
/** The Constant HANDVIEW. */
public static final boolean[] HANDVIEW = new boolean[1];
/** The Constant LIBRARYVIEW. */
public static final boolean[] LIBRARYVIEW = new boolean[1];
/** The Constant OLDGUI. */
public static final boolean[] OLDGUI = new boolean[1];
/** The Constant NetConn. */
public static final boolean[] NET_CONN = new boolean[1];

View File

@@ -42,6 +42,7 @@ import forge.properties.ForgeProps;
import forge.properties.NewConstants.Lang.GameAction.GameActionText;
import forge.quest.gui.QuestWinLoseHandler;
import forge.quest.gui.main.QuestEvent;
import forge.view.match.ViewTopLevel;
import forge.view.swing.WinLoseFrame;
/**
@@ -776,14 +777,22 @@ public class GameAction {
final boolean refreeze = AllZone.getStack().isFrozen();
AllZone.getStack().setFrozen(true);
if (Constant.Runtime.OLDGUI[0]) {
final JFrame frame = (JFrame) AllZone.getDisplay();
if (!frame.isDisplayable()) {
return;
}
}
else {
final ViewTopLevel frame = (ViewTopLevel) AllZone.getDisplay();
if (!frame.isDisplayable()) {
return;
}
}
if (this.canShowWinLose && this.checkEndGameSate()) {
AllZone.getDisplay().savePrefs();
frame.setEnabled(false);
//frame.setEnabled(false);
// frame.dispose();
// Gui_WinLose gwl = new Gui_WinLose(AllZone.getMatchState(),

View File

@@ -516,6 +516,9 @@ public class Phase extends MyObservable implements java.io.Serializable {
this.turn++;
}
// Visual indicators
PhaseUtil.visuallyActivatePhase(this.getPhase());
// When consecutively skipping phases (like in combat) this section
// pushes through that block
this.updateObservers();

View File

@@ -6,6 +6,8 @@ import java.util.HashMap;
import forge.Constant.Zone;
import forge.card.cardfactory.CardFactoryUtil;
import forge.gui.input.Input;
import forge.view.match.ViewField.PhaseLabel;
import forge.view.match.ViewTopLevel;
/**
* <p>
@@ -423,6 +425,7 @@ public class PhaseUtil {
*/
public static void handleUpkeep() {
Player turn = AllZone.getPhase().getPlayerTurn();
if (skipUpkeep()) {
// Slowtrips all say "on the next turn's upkeep" if there is no
// upkeep next turn, the trigger will never occur.
@@ -623,4 +626,46 @@ public class PhaseUtil {
|| phase.equals(Constant.Phase.DRAW) || phase.equals(Constant.Phase.MAIN1)
|| phase.equals(Constant.Phase.COMBAT_BEGIN);
}
/**
* Retrieves and visually activates phase label for appropriate
* phase and player.
*
* @param s &emsp; Phase state
*/
public static void visuallyActivatePhase(String s) {
PhaseLabel lbl = null;
Player p = AllZone.getPhase().getPlayerTurn();
ViewTopLevel t = (ViewTopLevel) AllZone.getDisplay();
int i; // Index of field; computer is 0, human is 1
if (p.isComputer()) {
i = 0;
}
else {
i = 1;
}
if (s.equals(Constant.Phase.UPKEEP)) {
lbl = t.getFieldControllers().get(i).getView().getLblUpkeep();
}
else if (s.equals(Constant.Phase.DRAW)) {
lbl = t.getFieldControllers().get(i).getView().getLblDraw();
}
else if (s.equals(Constant.Phase.COMBAT_BEGIN)) {
lbl = t.getFieldControllers().get(i).getView().getLblBeginCombat();
}
else if (s.equals(Constant.Phase.COMBAT_END)) {
lbl = t.getFieldControllers().get(i).getView().getLblEndCombat();
}
else if (s.equals(Constant.Phase.END_OF_TURN)) {
lbl = t.getFieldControllers().get(i).getView().getLblEndTurn();
}
else {
return;
}
t.getController().resetAllPhaseButtons();
lbl.setActive(true);
}
}

View File

@@ -0,0 +1,98 @@
package forge.control;
import java.awt.Component;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JLayeredPane;
import forge.view.GuiTopLevel;
import forge.view.editor.EditorTopLevel;
import forge.view.home.HomeTopLevel;
import forge.view.match.ViewTopLevel;
/**
* <p>ControlAllUI.</p>
* 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 class ControlAllUI {
private JLayeredPane display;
private GuiTopLevel view;
private HomeTopLevel home = null;
private ViewTopLevel match = null;
private EditorTopLevel editor = null;
/**
* <p>ControlAllUI.</p>
* 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 ControlAllUI() {
view = new GuiTopLevel();
view.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
Component[] children;
children = display.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER);
children[0].setSize(display.getSize());
children = display.getComponentsInLayer(JLayeredPane.MODAL_LAYER);
children[0].setSize(display.getSize());
}
});
display = (JLayeredPane) view.getContentPane();
changeState(1);
}
/**
* <p>changeState.</p>
* Switches between display states in top level JFrame.
*
* @param i &emsp; State index: 0 for home, 1 for match, etc.
*/
public void changeState(int i) {
home = null;
match = null;
editor = null;
display.removeAll();
view.addOverlay();
// Fire up new state
switch (i) {
case 0: // Home screen
home = new HomeTopLevel();
display.add(home);
break;
case 1: // Match screen
match = new ViewTopLevel();
display.add(match, JLayeredPane.DEFAULT_LAYER);
break;
case 2: // Deck editor screen
editor = new EditorTopLevel();
display.add(editor);
break;
default: break;
}
}
/** @return ViewTopLevel */
public ViewTopLevel getMatchView() {
return match;
}
/** @return ControlMatchUI */
public ControlMatchUI getMatchController() {
return match.getController();
}
}

View File

@@ -0,0 +1,19 @@
package forge.control;
import javax.swing.JPanel;
/**
* <p>ControlEditorUI</p>
* Top-level controller for deck editor.
*
*/
@SuppressWarnings("serial")
public class ControlEditorUI extends JPanel {
/**
* <p>ControlEditorUI</p>
* Top-level controller for deck editor.
*
*/
public ControlEditorUI() {
}
}

View File

@@ -0,0 +1,9 @@
package forge.control;
/**
* TODO: Write javadoc for this type.
*
*/
public class ControlHomeUI {
}

View File

@@ -0,0 +1,240 @@
package forge.control;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.InputMap;
import javax.swing.JComponent;
import forge.AllZone;
import forge.Singletons;
import forge.Constant.Zone;
import forge.control.match.ControlField;
import javax.swing.KeyStroke;
import org.apache.commons.lang3.StringUtils;
import forge.properties.ForgePreferences;
import forge.view.match.ViewTopLevel;
/**
* <p>ControlMatchUI</p>
* Top-level controller for matches. Implements Display.
*
*/
public class ControlMatchUI {
private ViewTopLevel view;
/**
* <p>ControlMatchUI</p>
* Constructs instance of match UI controller, used as a single
* point of top-level control for child UIs - in other words, this class
* controls the controllers. Tasks targeting the view of individual
* components are found in a separate controller for that component
* and should not be included here.
*
* This constructor is called after child components have been instantiated.
* When children are instantiated, they also instantiate their controller.
* So, this class must be called after everything is already in place.
*
* @param v &emsp; A ViewTopLevel object
*/
public ControlMatchUI(ViewTopLevel v) {
view = v;
}
/**
* Fires up controllers for each component of UI.
*
*/
public void initMatch() {
// All child components have been assembled; observers and listeners can
// be added safely.
view.getAreaSidebar().getTabber().getController().addObservers();
view.getAreaSidebar().getTabber().getController().addListeners();
view.getAreaUser().getPnlInput().getController().addListeners();
view.getAreaUser().getPnlHand().getController().addObservers();
view.getAreaUser().getPnlHand().getController().addListeners();
// Update all observers with values for start of match.
List<ControlField> fieldControllers = view.getFieldControllers();
for (ControlField f : fieldControllers) {
f.addObservers();
f.addListeners();
f.getPlayer().updateObservers();
}
AllZone.getHumanPlayer().getZone(Zone.Hand).updateObservers();
AllZone.getComputerPlayer().getZone(Zone.Hand).updateObservers();
AllZone.getStack().updateObservers();
AllZone.getHumanPlayer().getZone(Zone.Battlefield).updateObservers();
AllZone.getInputControl().updateObservers();
view.getAreaSidebar().getTabber().getController().updateObservers();
this.mapKeyboardShortcuts();
}
/**
* Resets all phase buttons in all fields to "inactive", so highlight won't be
* drawn on them. "Enabled" state remains the same.
*/
// This method is in the top-level controller because it affects ALL fields (not just one).
public void resetAllPhaseButtons() {
List<ControlField> fieldControllers = view.getFieldControllers();
for (ControlField c : fieldControllers) {
c.resetPhaseButtons();
}
}
/**
* Maps actions to shortcuts, and attaches each shortcut to the
* InputMap of the top level view.
*
*/
@SuppressWarnings("serial")
private void mapKeyboardShortcuts() {
InputMap im = ((ViewTopLevel) AllZone.getDisplay()).getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
ForgePreferences fp = Singletons.getModel().getPreferences();
String str;
KeyStroke key;
// Actions which correspond to key presses
Action actShowStack = new AbstractAction() {
public void actionPerformed(ActionEvent e) { view.getTabberController().showPnlStack(); }
};
Action actShowCombat = new AbstractAction() {
public void actionPerformed(ActionEvent e) { view.getTabberController().showPnlCombat(); }
};
Action actShowConsole = new AbstractAction() {
public void actionPerformed(ActionEvent e) { view.getTabberController().showPnlConsole(); }
};
Action actShowPlayers = new AbstractAction() {
public void actionPerformed(ActionEvent e) { view.getTabberController().showPnlPlayers(); }
};
Action actShowDev = new AbstractAction() {
public void actionPerformed(ActionEvent e) { view.getTabberController().showPnlDev(); }
};
Action actConcede = new AbstractAction() {
public void actionPerformed(ActionEvent e) { view.getDockController().concede(); }
};
Action actShowPicture = new AbstractAction() {
public void actionPerformed(ActionEvent e) { view.getCardviewerController().showPnlCardPic(); }
};
Action actShowDetail = new AbstractAction() {
public void actionPerformed(ActionEvent e) { view.getCardviewerController().showPnlCardDetail(); }
};
// Show stack
// (Get keycode string, convert to char, convert to keystroke, put on input map.)
str = fp.getShowStackShortcut();
key = KeyStroke.getKeyStroke(codes2Chars(str));
im.put(key, str);
((ViewTopLevel) AllZone.getDisplay()).getActionMap().put(im.get(key), actShowStack);
// Show combat
str = fp.getShowCombatShortcut();
key = KeyStroke.getKeyStroke(codes2Chars(str));
im.put(key, str);
((ViewTopLevel) AllZone.getDisplay()).getActionMap().put(im.get(key), actShowCombat);
// Show console
str = fp.getShowConsoleShortcut();
key = KeyStroke.getKeyStroke(codes2Chars(str));
im.put(key, str);
((ViewTopLevel) AllZone.getDisplay()).getActionMap().put(im.get(key), actShowConsole);
// Show players
str = fp.getShowPlayersShortcut();
key = KeyStroke.getKeyStroke(codes2Chars(str));
im.put(key, str);
((ViewTopLevel) AllZone.getDisplay()).getActionMap().put(im.get(key), actShowPlayers);
// Show devmode
str = fp.getShowDevShortcut();
key = KeyStroke.getKeyStroke(codes2Chars(str));
im.put(key, str);
((ViewTopLevel) AllZone.getDisplay()).getActionMap().put(im.get(key), actShowDev);
// Concede game
str = fp.getConcedeShortcut();
key = KeyStroke.getKeyStroke(codes2Chars(str));
im.put(key, str);
((ViewTopLevel) AllZone.getDisplay()).getActionMap().put(im.get(key), actConcede);
// Show card picture
str = fp.getShowPictureShortcut();
key = KeyStroke.getKeyStroke(codes2Chars(str));
im.put(key, str);
((ViewTopLevel) AllZone.getDisplay()).getActionMap().put(im.get(key), actShowPicture);
// Show card detail
str = fp.getShowDetailShortcut();
key = KeyStroke.getKeyStroke(codes2Chars(str));
im.put(key, str);
((ViewTopLevel) AllZone.getDisplay()).getActionMap().put(im.get(key), actShowDetail);
}
/**
* Converts a string of key codes (space delimited) into their respective
* key texts. This helps juggling between input maps, display text, save
* values, and input data.
*
* @param s0 &emsp; A string of keycodes
* @return String
*/
private String codes2Chars(String s0) {
List<String> codes = new ArrayList<String>(Arrays.asList(s0.split(" ")));
List<String> displayText = new ArrayList<String>();
String temp;
for (String s : codes) {
temp = KeyEvent.getKeyText(Integer.valueOf(s));
if (!s.isEmpty()) {
// Probably a better way to do this; but I couldn't find it
// after a decent look around. The main problem is that
// KeyEvent.getKeyText() will return "Ctrl", but the input
// map expects "control". Similar case problems with Shift and Alt.
// Doublestrike 21-11-11
if (temp.equalsIgnoreCase("ctrl")) {
temp = "control";
}
else if (temp.equalsIgnoreCase("shift")) {
temp = "shift";
}
else if (temp.equalsIgnoreCase("alt")) {
temp = "alt";
}
else if (temp.equalsIgnoreCase("escape")) {
temp = "escape";
}
displayText.add(temp);
}
}
return StringUtils.join(displayText, ' ');
}
}

View File

@@ -0,0 +1,64 @@
package forge.control.match;
import java.awt.Image;
import forge.Card;
import forge.ImageCache;
import forge.view.match.ViewCardviewer;
/**
*
* Controls the vertical tabber in sidebar used for
* viewing card details and picture.
*
*/
public class ControlCardviewer {
private ViewCardviewer view;
private Card currentCard = null;
/**
* Controls the vertical tabber in sidebar used for
* viewing card details and picture.
* @param v &emsp; The CardViewer Swing component.
*/
public ControlCardviewer(ViewCardviewer v) {
view = v;
}
/**
* Shows card details and/or picture in sidebar cardview tabber.
* @param c &emsp; Card object
*/
public void showCard(Card c) {
Image img = ImageCache.getImage(c);
this.currentCard = c;
view.getPnlCardPic().setCard(c);
view.getPnlCardDetail().setCard(c);
if (img != null) {
showPnlCardPic();
}
else {
showPnlCardDetail();
}
}
/** @return Card */
public Card getCurrentCard() {
return currentCard;
}
/**
* Programatically forces card layout of sidebar tabber to show "CardDetail" panel.
*/
public void showPnlCardDetail() {
view.getVtpCardviewer().showTab(1);
}
/**
* Programatically forces card layout of sidebar tabber to show card picture panel.
*/
public void showPnlCardPic() {
view.getVtpCardviewer().showTab(0);
}
}

View File

@@ -0,0 +1,106 @@
package forge.control.match;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import forge.AllZone;
import forge.Singletons;
import forge.properties.ForgePreferences;
import forge.view.match.ViewDock;
import forge.view.match.ViewDock.KeyboardShortcutField;
/**
* Child controller, handles dock button operations.
*
*/
public class ControlDock {
private ViewDock view;
/**
* Child controller, handles dock button operations.
* @param v &emsp; ViewDock obj
*/
public ControlDock(ViewDock v) {
view = v;
}
/** Concede game, bring up WinLose UI. */
public void concede() {
AllZone.getHumanPlayer().concede();
AllZone.getGameAction().checkStateEffects();
}
/** @return ViewDock */
public ViewDock getView() {
return view;
}
/** Updates and saves ForgePreferences with current shortcuts. */
public void saveKeyboardShortcuts() {
ForgePreferences fp = Singletons.getModel().getPreferences();
Map<String, KeyboardShortcutField> shortcuts = view.getKeyboardShortcutFields();
fp.setShowStackShortcut(shortcuts.get("showstack").getCodeString());
fp.setShowCombatShortcut(shortcuts.get("showcombat").getCodeString());
fp.setShowPlayersShortcut(shortcuts.get("showplayers").getCodeString());
fp.setShowConsoleShortcut(shortcuts.get("showconsole").getCodeString());
fp.setShowDevShortcut(shortcuts.get("showdev").getCodeString());
fp.setConcedeShortcut(shortcuts.get("concede").getCodeString());
fp.setShowPictureShortcut(shortcuts.get("showpicture").getCodeString());
fp.setShowDetailShortcut(shortcuts.get("showdetail").getCodeString());
try {
fp.save();
} catch (Exception e) {
e.printStackTrace();
}
AllZone.getOverlay().hideOverlay();
}
/**
* - Adds keycode to list stored in name of a text field.
* - Code is not added if already in list.
* - Backspace removes last code in list.
* - Sets text of text field with character equivalent of keycodes.
*
* @param e &emsp; KeyEvent
*/
public void addKeyCode(KeyEvent e) {
KeyboardShortcutField ksf = (KeyboardShortcutField) e.getSource();
String newCode = Integer.toString(e.getKeyCode());
String codestring = ksf.getCodeString();
List<String> existingCodes;
if (codestring != null) {
existingCodes = new ArrayList<String>(Arrays.asList(codestring.split(" ")));
}
else {
existingCodes = new ArrayList<String>();
}
// Backspace (8) will remove last code from list.
if (e.getKeyCode() == 8) {
existingCodes.remove(existingCodes.size() - 1);
}
else if (!existingCodes.contains(newCode)) {
existingCodes.add(newCode);
}
ksf.setCodeString(StringUtils.join(existingCodes, ' '));
}
/** */
public void endTurn() {
// Big thanks to you, Gameplay Guru, since I was too lazy to figure this out
// before release. Doublestrike 24-11-11
System.err.println("forge.control.match > ControlDock > endTurn()");
System.out.println("Should skip to the end of turn, or entire turn.");
System.err.println("If some gameplay guru could implement this, that would be great...");
}
}

View File

@@ -0,0 +1,459 @@
package forge.control.match;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JOptionPane;
import net.slightlymagic.braids.util.ImmutableIterableFrom;
import com.google.code.jyield.Generator;
import com.google.code.jyield.YieldUtils;
import forge.AllZone;
import forge.Card;
import forge.CardList;
import forge.Constant;
import forge.Constant.Zone;
import forge.GuiDisplayUtil;
import forge.Player;
import forge.PlayerZone;
import forge.card.cardfactory.CardFactoryUtil;
import forge.deck.Deck;
import forge.gui.ForgeAction;
import forge.gui.GuiUtils;
import forge.gui.input.Input;
import forge.gui.input.InputAttack;
import forge.gui.input.InputBlock;
import forge.gui.input.InputPayManaCost;
import forge.gui.input.InputPayManaCostAbility;
import forge.item.CardPrinted;
import forge.properties.ForgeProps;
import forge.properties.NewConstants;
import forge.properties.NewConstants.Lang.GuiDisplay.ComputerHand;
import forge.properties.NewConstants.Lang.GuiDisplay.ComputerLibrary;
import forge.view.match.ViewField;
import forge.view.match.ViewTopLevel;
/**
* Child controller, applied to single field in battlefield.
* Manages player view functions such as card observers,
* life total changes, graveyard button click, etc.
*
*/
public class ControlField {
private Player player;
private ViewField view;
/**
* Child controller, applied to single field in battlefield.
* Manages player view functions such as card observers,
* life total changes, graveyard button click, etc.
*
* @param p &emsp; The Player this field applies to
* @param v &emsp; The Swing component for this field
*/
public ControlField(Player p, ViewField v) {
player = p;
view = v;
}
/** @return Player */
public Player getPlayer() {
return player;
}
/** @return ViewField */
public ViewField getView() {
return view;
}
/**
* Adds observers to field components where required: card stats, player stats, etc.
*/
public void addObservers() {
// Hand, Graveyard, Library, Flashback, Exile totals, attached to respective Zones.
Observer o1 = new Observer() {
@Override
public void update(final Observable a, final Object b) {
view.updateZones(player);
}
};
player.getZone(Zone.Hand).addObserver(o1);
// Life total, poison total, and keywords, attached directly to Player.
Observer o2 = new Observer() {
@Override
public void update(final Observable a, final Object b) {
view.updateDetails(player);
}
};
player.addObserver(o2);
// Card play area, attached to battlefield zone.
Observer o3 = new Observer() {
public void update(final Observable a, final Object b) {
PlayerZone pZone = (PlayerZone) a;
Card[] c = pZone.getCards(false);
GuiDisplayUtil.setupPlayZone(view.getTabletop(), c);
}
};
player.getZone(Zone.Battlefield).addObserver(o3);
}
/**
* Listeners for user actions on the battlefield.
*
*/
public void addListeners() {
// When/if zone action properties become less specific, the conditional
// tests for computer/human players can be removed. If that's not ever
// going to happen, this comment can be removed. :) Doublestrike 29-10-11.
this.addZoneListeners();
// Battlefield card clicks
view.getTabletop().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(final MouseEvent e) {
ViewTopLevel t = (ViewTopLevel) AllZone.getDisplay();
Card c = t.getCardviewerController().getCurrentCard();
Input input = t.getInputController().getInputControl().getInput();
if (c != null) {
if (c.isTapped()
&& (input instanceof InputPayManaCost
|| input instanceof InputPayManaCostAbility)) {
arcane.ui.CardPanel cardPanel = view.getTabletop().getCardPanel(c.getUniqueNumber());
for (arcane.ui.CardPanel cp : cardPanel.getAttachedPanels()) {
if (cp.getCard().isUntapped()) {
break;
}
}
}
CardList att = new CardList(AllZone.getCombat().getAttackers());
if ((c.isTapped() || c.hasSickness() || ((c.hasKeyword("Vigilance")) && att.contains(c)))
&& (input instanceof InputAttack)) {
arcane.ui.CardPanel cardPanel = view.getTabletop().getCardPanel(c.getUniqueNumber());
for (arcane.ui.CardPanel cp : cardPanel.getAttachedPanels()) {
if (cp.getCard().isUntapped() && !cp.getCard().hasSickness()) {
break;
}
}
}
if (e.isMetaDown()) {
if (att.contains(c) && (input instanceof InputAttack)
&& !c.hasKeyword("CARDNAME attacks each turn if able.")) {
c.untap();
AllZone.getCombat().removeFromCombat(c);
} else if (input instanceof InputBlock) {
if (c.getController().isHuman()) {
AllZone.getCombat().removeFromCombat(c);
}
((InputBlock) input).removeFromAllBlocking(c);
}
}
else {
t.getInputController().getInputControl().selectCard(c, AllZone.getHumanPlayer().getZone(Zone.Battlefield));
}
}
}
});
// Battlefield card mouseover
view.getTabletop().addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(final MouseEvent me) {
ViewTopLevel t = (ViewTopLevel) AllZone.getDisplay();
Card c = view.getTabletop().getCardFromMouseOverPanel();
if (c != null) {
t.getCardviewerController().showCard(c);
}
}
});
// Player select
view.getLblLife().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(final MouseEvent e) {
ViewTopLevel t = (ViewTopLevel) AllZone.getDisplay();
if (player.isComputer()) {
t.getInputController().getInputControl().selectPlayer(AllZone.getComputerPlayer());
}
else {
t.getInputController().getInputControl().selectPlayer(AllZone.getHumanPlayer());
}
}
});
} // End addListeners()
/** Adds listeners to "zone" labels: flashback, graveyard, etc.
* This method only exists to avoid the 150-line limit in the checkstyle rules.
*/
private void addZoneListeners() {
// Graveyard card list button
view.getLblGraveyard().enableHover();
view.getLblGraveyard().addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (player.isComputer()) {
new ZoneAction(player.getZone(Zone.Graveyard),
NewConstants.Lang.GuiDisplay.COMPUTER_GRAVEYARD).actionPerformed(null);
}
else {
new ZoneAction(player.getZone(Zone.Graveyard),
NewConstants.Lang.GuiDisplay.HUMAN_GRAVEYARD).actionPerformed(null);
}
}
});
// Exile card list button
view.getLblExile().enableHover();
view.getLblExile().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (player.isComputer()) {
new ZoneAction(player.getZone(Zone.Exile),
NewConstants.Lang.GuiDisplay.COMPUTER_REMOVED).actionPerformed(null);
}
else {
new ZoneAction(player.getZone(Zone.Exile),
NewConstants.Lang.GuiDisplay.HUMAN_REMOVED).actionPerformed(null);
}
}
});
// Library card list button
view.getLblLibrary().enableHover();
view.getLblLibrary().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (!player.isComputer()) {
new DeckListAction(NewConstants.Lang.GuiDisplay.HUMAN_DECKLIST).actionPerformed(null);
}
else {
// TODO DeckListAction has been rewritten to accept either human or computer
// decklists. However, NewConstants.Lang.GuiDisplay does not have a computer
// decklist available. That needs to be added for the below line to work
// properly. The current solution will work in the meantime. Doublestrike 15-11-11.
//new DeckListAction(NewConstants.Lang.GuiDisplay).actionPerformed(null);
new ZoneAction(player.getZone(Zone.Library), ComputerLibrary.BASE).actionPerformed(null);
}
}
});
// Flashback card list button
view.getLblFlashback().enableHover();
view.getLblFlashback().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (!player.isComputer()) {
new ZoneAction(player.getZone(Zone.Graveyard), NewConstants.Lang.GuiDisplay.HUMAN_FLASHBACK) {
private static final long serialVersionUID = 8120331222693706164L;
@Override
protected Iterable<Card> getCardsAsIterable() {
return new ImmutableIterableFrom<Card>(CardFactoryUtil.getExternalZoneActivationCards(AllZone
.getHumanPlayer()));
}
@Override
protected void doAction(final Card c) {
AllZone.getGameAction().playCard(c);
}
};
}
}
});
// Hand button
if (player.isComputer()) {
view.getLblHand().enableHover();
view.getLblHand().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
new ZoneAction(player.getZone(Zone.Hand), ComputerHand.BASE).actionPerformed(null);
}
});
}
}
/**
* Resets all phase buttons to "inactive", so highlight won't be
* drawn on them. "Enabled" state remains the same.
*/
public void resetPhaseButtons() {
view.getLblUpkeep().setActive(false);
view.getLblDraw().setActive(false);
view.getLblBeginCombat().setActive(false);
view.getLblEndCombat().setActive(false);
view.getLblEndTurn().setActive(false);
}
/**
* Receives click and programmatic requests for viewing data stacks
* in the "zones" of a player field: hand, library, etc.
*
*/
private class ZoneAction extends ForgeAction {
private static final long serialVersionUID = -5822976087772388839L;
private PlayerZone zone;
private String title;
/**
* Receives click and programmatic requests for viewing data stacks
* in the "zones" of a player field: hand, graveyard, etc. The library
* "zone" is an exception to the rule; it's handled in DeckListAction.
*
* @param zone &emsp; PlayerZone obj
* @param property &emsp; String obj
*/
public ZoneAction(final PlayerZone zone, final String property) {
super(property);
title = ForgeProps.getLocalized(property + "/title");
this.zone = zone;
}
/** @param e &emsp; ActionEvent obj */
public void actionPerformed(final ActionEvent e) {
Generator<Card> c = YieldUtils.toGenerator(getCardsAsIterable());
if (AllZone.getNameChanger().shouldChangeCardName()) {
c = AllZone.getNameChanger().changeCard(c);
}
Iterable<Card> myIterable = YieldUtils.toIterable(c);
ArrayList<Card> choices = YieldUtils.toArrayList(myIterable);
//System.out.println("immediately after: "+choices);
//Iterator<Card> iter = myIterable.iterator();
ArrayList<Card> choices2 = new ArrayList<Card>();
if (choices.isEmpty()) {
GuiUtils.getChoiceOptional(title, new String[]{"no cards"});
}
else {
for (int i = 0; i < choices.size(); i++) {
Card crd = choices.get(i);
//System.out.println(crd+": "+crd.isFaceDown());
if (crd.isFaceDown()) {
Card faceDown = new Card();
faceDown.setName("Face Down");
choices2.add(faceDown);
//System.out.println("Added: "+faceDown);
}
else {
choices2.add(crd);
}
}
//System.out.println("Face down cards replaced: "+choices2);
Card choice = (Card) GuiUtils.getChoiceOptional(title, choices2.toArray());
if (choice != null) {
doAction(choice);
/*
Card choice = GuiUtils.getChoiceOptional(title, iter);
if (choice != null) doAction(choice);
*/
}
}
}
protected Iterable<Card> getCardsAsIterable() {
return new ImmutableIterableFrom<Card>(Arrays.asList(zone.getCards()));
}
protected void doAction(final Card c) {
}
} // End ZoneAction
/**
* Receives click and programmatic requests for viewing a player's
* library (typically used in dev mode). Allows copy of the
* cardlist to clipboard.
*
*/
private class DeckListAction extends ForgeAction {
public DeckListAction(final String property) {
super(property);
}
private static final long serialVersionUID = 9874492387239847L;
public void actionPerformed(final ActionEvent e) {
Deck targetDeck;
if (Constant.Runtime.HUMAN_DECK[0].countMain() > 1) {
targetDeck = Constant.Runtime.HUMAN_DECK[0];
}
else if (Constant.Runtime.COMPUTER_DECK[0].countMain() > 1) {
targetDeck = Constant.Runtime.COMPUTER_DECK[0];
}
else {
return;
}
HashMap<String, Integer> deckMap = new HashMap<String, Integer>();
for (Entry<CardPrinted, Integer> s : targetDeck.getMain()) {
deckMap.put(s.getKey().getName(), s.getValue());
}
String nl = System.getProperty("line.separator");
StringBuilder deckList = new StringBuilder();
String dName = targetDeck.getName();
if (dName == null) {
dName = "";
} else {
deckList.append(dName + nl);
}
ArrayList<String> dmKeys = new ArrayList<String>();
for (String s : deckMap.keySet()) {
dmKeys.add(s);
}
Collections.sort(dmKeys);
for (String s : dmKeys) {
deckList.append(deckMap.get(s) + " x " + s + nl);
}
int rcMsg = -1138;
String ttl = "Human's Decklist";
if (!dName.equals("")) {
ttl += " - " + dName;
}
StringBuilder msg = new StringBuilder();
if (deckMap.keySet().size() <= 32) {
msg.append(deckList.toString() + nl);
} else {
msg.append("Decklist too long for dialog." + nl + nl);
}
msg.append("Copy Decklist to Clipboard?");
rcMsg = JOptionPane.showConfirmDialog(null, msg, ttl, JOptionPane.OK_CANCEL_OPTION);
if (rcMsg == JOptionPane.OK_OPTION) {
StringSelection ss = new StringSelection(deckList.toString());
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);
}
}
} // End DeckListAction
}

View File

@@ -0,0 +1,128 @@
package forge.control.match;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import forge.AllZone;
import forge.Card;
import forge.Constant.Zone;
import forge.PlayerZone;
import forge.view.match.ViewHand;
import forge.view.match.ViewHand.CardPanel;
import forge.view.match.ViewTopLevel;
/**
* Child controller - handles operations related to cards in user's hand
* and their Swing components, which are assembled in ViewHand.
*
*/
public class ControlHand {
private List<Card> cardsInPanel;
private ViewHand view;
/**
* Child controller - handles operations related to cards in user's hand
* and their Swing components, which are assembled in ViewHand.
* @param v &emsp; The Swing component for user hand
*/
public ControlHand(ViewHand v) {
view = v;
cardsInPanel = new ArrayList<Card>();
}
/** Adds observers to hand panel. */
public void addObservers() {
Observer o1 = new Observer() {
public void update(final Observable a, final Object b) {
resetCards(Arrays.asList(((PlayerZone) a).getCards()));
}
};
AllZone.getHumanPlayer().getZone(Zone.Hand).addObserver(o1);
}
/** Adds listeners to hand panel: window resize, etc. */
public void addListeners() {
view.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
// Ensures cards in hand scale properly with parent.
view.refreshLayout();
}
});
}
/**
* Adds various listeners for cards in hand. Uses CardPanel
* instance from ViewHand.
*
* @param c &emsp; CardPanel object
*/
public void addCardPanelListeners(final CardPanel c) {
// Grab top level controller to facilitate interaction between children
final ViewTopLevel display = (ViewTopLevel) (AllZone.getDisplay());
final Card cardobj = c.getCard();
// Sidebar pic/detail on card hover
c.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(final MouseEvent e) {
display.getCardviewerController().showCard(cardobj);
}
});
// Mouse press
c.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(final MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
display.getInputController().getInputControl().selectCard(
cardobj, AllZone.getHumanPlayer().getZone(Zone.Hand));
}
});
}
/** @param c &emsp; Card object */
public void addCard(Card c) {
cardsInPanel.add(c);
view.refreshLayout();
}
/** @param c &emsp; List of Card objects */
public void addCards(List<Card> c) {
cardsInPanel.addAll(c);
view.refreshLayout();
}
/** @return List<Card> */
public List<Card> getCards() {
return cardsInPanel;
}
/** @param c &emsp; Card object */
public void removeCard(Card c) {
cardsInPanel.remove(c);
view.refreshLayout();
}
/** @param c &emsp; List of Card objects */
public void removeCards(List<Card> c) {
cardsInPanel.removeAll(c);
view.refreshLayout();
}
/** @param c &emsp; List of Card objects */
public void resetCards(List<Card> c) {
cardsInPanel.clear();
addCards(c);
}
}

View File

@@ -0,0 +1,88 @@
package forge.control.match;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import forge.AllZone;
import forge.GuiInput;
import forge.view.match.ViewInput;
/**
* Child controller - handles operations related to input panel.
*
*/
public class ControlInput {
private ViewInput view;
private GuiInput inputControl;
/**
* Child controller - handles operations related to input panel.
* @param v &emsp; The Swing component for the input area
*/
public ControlInput(ViewInput v) {
view = v;
inputControl = new GuiInput();
}
/** Adds listeners to input area. */
public void addListeners() {
view.getBtnCancel().addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent evt) {
btnCancelActionPerformed(evt);
view.getBtnOK().requestFocusInWindow();
}
});
//
view.getBtnOK().addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent evt) {
btnOKActionPerformed(evt);
if (AllZone.getPhase().isNeedToNextPhase()) {
// moves to next turn
AllZone.getPhase().setNeedToNextPhase(false);
AllZone.getPhase().nextPhase();
}
view.getBtnOK().requestFocusInWindow();
}
});
//
view.getBtnOK().addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent arg0) {
// TODO make triggers on escape
int code = arg0.getKeyCode();
if (code == KeyEvent.VK_ESCAPE) {
view.getBtnOK().doClick();
}
}
});
}
/**
* <p>btnCancelActionPerformed.</p>
* Triggers current cancel action from whichever input controller is being used.
*
* @param evt a {@link java.awt.event.ActionEvent} object.
*/
private void btnCancelActionPerformed(final ActionEvent evt) {
inputControl.selectButtonCancel();
}
/**
* <p>btnOKActionPerformed.</p>
* Triggers current OK action from whichever input controller is being used.
*
* @param evt a {@link java.awt.event.ActionEvent} object.
*/
private void btnOKActionPerformed(final ActionEvent evt) {
inputControl.selectButtonOK();
}
/** @return GuiInput */
public GuiInput getInputControl() {
return inputControl;
}
}

View File

@@ -0,0 +1,198 @@
package forge.control.match;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Observable;
import java.util.Observer;
import forge.AllZone;
import forge.GuiDisplayUtil;
import forge.MyObservable;
import forge.Singletons;
import forge.view.match.ViewTabber;
/**
* Controls the vertical tabber in sidebar used for
* viewing gameplay data: stack, combat, etc.
*
*/
public class ControlTabber extends MyObservable {
private ViewTabber view;
/**
* Controls the vertical tabber in sidebar used for
* viewing gameplay data: stack, combat, etc.
*
* @param v &emsp; The tabber Swing component
*/
public ControlTabber(ViewTabber v) {
view = v;
if (Singletons.getModel().getPreferences().isMillingLossCondition()) {
view.getLblMilling().setEnabled(true);
}
else {
view.getLblMilling().setEnabled(false);
}
if (Singletons.getModel().getPreferences().getHandView()) {
view.getLblHandView().setEnabled(true);
}
else {
view.getLblHandView().setEnabled(false);
}
if (Singletons.getModel().getPreferences().getLibraryView()) {
view.getLblLibraryView().setEnabled(true);
}
else {
view.getLblLibraryView().setEnabled(false);
}
}
/** Adds observers to tabber. */
public void addObservers() {
// Stack
Observer o1 = new Observer() {
public void update(final Observable a, final Object b) {
view.updateStack();
}
};
AllZone.getStack().addObserver(o1);
}
/** Adds listeners to various components in tabber. */
public void addListeners() {
// Milling enable toggle
view.getLblMilling().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
view.getLblMilling().toggleEnabled();
}
});
// View any hand toggle
view.getLblHandView().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
view.getLblHandView().toggleEnabled();
}
});
// DevMode: View any library toggle
view.getLblLibraryView().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
view.getLblLibraryView().toggleEnabled();
}
});
// DevMode: Play unlimited land this turn toggle
view.getLblUnlimitedLands().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
GuiDisplayUtil.devModeUnlimitedLand();
// TODO: Enable toggle for this (e.g. Unlimited land each turn: enabled)
// Also must change enabled/disabled text in ViewTabber to reflect this.
//view.getLblUnlimitedLands().toggleEnabled();
}
});
// DevMode: Generate mana
view.getLblGenerateMana().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
GuiDisplayUtil.devModeGenerateMana();
}
});
// DevMode: Battlefield setup
view.getLblSetupGame().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
GuiDisplayUtil.devSetupGameState();
}
});
// DevMode: Tutor for card
view.getLblTutor().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
GuiDisplayUtil.devModeTutor();
}
});
// DevMode: Add counter to permanent
view.getLblCounterPermanent().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
GuiDisplayUtil.devModeAddCounter();
}
});
// DevMode: Tap permanent
view.getLblTapPermanent().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
GuiDisplayUtil.devModeTapPerm();
}
});
// DevMode: Untap permanent
view.getLblUntapPermanent().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
GuiDisplayUtil.devModeUntapPerm();
}
});
// DevMode: Set human life
view.getLblHumanLife().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
GuiDisplayUtil.devModeSetLife();
}
});
}
/** @return ViewTabber */
public ViewTabber getView() {
return view;
}
/**
* Programatically forces card layout of sidebar tabber to show "Dev" panel.
*/
public void showPnlDev() {
view.getVtpTabber().showTab(4);
}
/**
* Programatically forces card layout of sidebar tabber to show "Players" panel.
*/
public void showPnlPlayers() {
view.getVtpTabber().showTab(3);
}
/**
* Programatically forces card layout of sidebar tabber to show "Console" panel.
*/
public void showPnlConsole() {
view.getVtpTabber().showTab(2);
}
/**
* Programatically forces card layout of sidebar tabber to show "Combat" panel.
*/
public void showPnlCombat() {
view.getVtpTabber().showTab(1);
}
/**
* Programatically forces card layout of sidebar tabber to show "Stack" panel.
*/
public void showPnlStack() {
view.getVtpTabber().showTab(0);
}
}

View File

@@ -0,0 +1,3 @@
/** Child controllers used in match UI. */
package forge.control.match;

View File

@@ -0,0 +1,3 @@
/** Controller (as in model-view-controller) for Forge. */
package forge.control;

View File

@@ -31,7 +31,14 @@ public class FButton extends JButton {
private final AlphaComposite disabledComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25f);
/**
* Instantiates a new f button.
* Instantiates a new FButton.
*/
public FButton() {
this("");
}
/**
* Instantiates a new FButton.
*
* @param msg
* the msg

View File

@@ -2,6 +2,7 @@ package forge.gui.skin;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.LayoutManager;
import javax.swing.ImageIcon;
@@ -11,14 +12,15 @@ import javax.swing.JPanel;
* <p>
* FPanel.
* </p>
* The core JPanel used throughout the Forge project. Allows tiled images and
* ...
* The core JPanel used throughout the Forge project. Allows tiled texture images
* and single background images, using setBGTexture() and setBGImage() respectively.
*
*/
@SuppressWarnings("serial")
public class FPanel extends JPanel {
private ImageIcon bgImg = null;
private int w, h, iw, ih, x, y = 0;
private Image bgTexture, bgImg = null;
// Panel Width, panel Height, Image Width, Image Height, Image Aspect Ratio
private double w, h, iw, ih, iar, x, y = 0;
/**
* Instantiates a new f panel.
@@ -45,40 +47,84 @@ public class FPanel extends JPanel {
*/
@Override
protected void paintComponent(final Graphics g) {
// System.out.print("\nRepainting. ");
if (this.bgImg != null) {
this.w = this.getWidth();
this.h = this.getHeight();
this.iw = this.bgImg.getIconWidth();
this.ih = this.bgImg.getIconHeight();
w = this.getWidth();
h = this.getHeight();
while (this.x < this.w) {
while (this.y < this.h) {
g.drawImage(this.bgImg.getImage(), this.x, this.y, null);
this.y += this.ih;
// Draw background texture
if (bgTexture != null) {
iw = bgTexture.getWidth(null);
ih = bgTexture.getHeight(null);
x = 0;
y = 0;
while (x < w) {
while (y < h) {
g.drawImage(bgTexture, (int) x, (int) y, null);
y += ih;
}
this.x += this.iw;
this.y = 0;
x += iw;
y = 0;
}
x = 0;
}
// Draw background image
if (bgImg != null) {
iw = bgImg.getWidth(null); // Image Width
ih = bgImg.getHeight(null); // Image Height
iar = iw / ih; // Image Aspect Ratio
// Image is smaller than panel:
if (w > iw && h > ih) {
g.drawImage(bgImg, (int) (w - iw) / 2, (int) (h - ih) / 2, (int) iw, (int) ih, null);
}
// Image is larger than panel, and tall:
else if (iar < 1) {
g.drawImage(bgImg,
(int) ((w - h * iar) / 2), 0,
(int) ((w + h * iar) / 2), (int) h,
0, 0, (int) iw, (int) ih, null);
}
// Image is larger than panel, and wide:
else if (iar > 1) {
g.drawImage(bgImg,
0, (int) ((h - w / iar) / 2),
(int) w, (int) ((h + w / iar) / 2),
0, 0, (int) iw, (int) ih, null);
}
this.x = 0;
}
super.paintComponent(g);
}
/**
* Sets the bG img.
* An FPanel can have a tiled texture and an image. The texture will be drawn
* first. If a background image has been set, it will be drawn on top of the
* texture, centered and scaled proportional to its aspect ratio.
*
* @param icon
* the new bG img
* @param i0 &emsp; ImageIcon
*/
public void setBGImg(final ImageIcon icon) {
this.bgImg = icon;
public void setBGImg(final ImageIcon i0) {
this.bgImg = i0.getImage();
if (this.bgImg != null) {
this.setOpaque(false);
}
}
/**
* An FPanel can have a tiled texture and an image. The texture will be drawn
* first. If a background image has been set, it will be drawn on top of the
* texture, centered and scaled proportional to its aspect ratio.
*
* @param i0 &emsp; ImageIcon
*/
public void setBGTexture(final ImageIcon i0) {
this.bgTexture = i0.getImage();
if (this.bgTexture != null) {
this.setOpaque(false);
}
}
/**
* Sets the preferred size.
*

View File

@@ -22,6 +22,7 @@ import forge.AllZone;
*/
@SuppressWarnings("serial")
public class FRoundedPanel extends JPanel {
private boolean[] borders = { true, true, true, true };
private boolean[] corners = { true, true, true, true }; // NW, SW, SE, NE
private Color shadowColor = new Color(150, 150, 150, 150);
private Color borderColor = AllZone.getSkin().getClrBorders();
@@ -146,41 +147,58 @@ public class FRoundedPanel extends JPanel {
// Mid, left, right rectangles: border
g2d.setColor(this.borderColor);
g2d.drawLine(r, 0, w - r - so, 0);
g2d.drawLine(r, h - so - 1, w - r - so, h - so - 1);
g2d.drawLine(0, r, 0, h - r - so);
g2d.drawLine(w - so - 1, r, w - so - 1, h - r - so);
if (this.borders[0]) { g2d.drawLine(r, 0, w - r - so, 0); }
if (this.borders[1]) { g2d.drawLine(0, r, 0, h - r - so); }
if (this.borders[2]) { g2d.drawLine(r, h - so - 1, w - r - so, h - so - 1); }
if (this.borders[3]) { g2d.drawLine(w - so - 1, r, w - so - 1, h - r - so); }
// Corners: border
// NW
if (this.corners[0]) {
g2d.drawArc(0, 0, 2 * r, 2 * r, 90, 90);
} else {
if (this.borders[0]) {
g2d.drawLine(0, 0, r, 0);
}
if (this.borders[1]) {
g2d.drawLine(0, 0, 0, r);
}
}
// SW
if (this.corners[1]) {
g2d.drawArc(0, h - (2 * r) - so, 2 * r, (2 * r) - 1, 180, 90);
} else {
if (this.borders[1]) {
g2d.drawLine(0, h - so - 1, 0, h - r - so - 1);
}
if (this.borders[2]) {
g2d.drawLine(0, h - so - 1, r, h - so - 1);
}
}
// SE
if (this.corners[2]) {
g2d.drawArc(w - (2 * r) - so, h - (2 * r) - so, (2 * r) - 1, (2 * r) - 1, 270, 90);
} else {
g2d.drawLine(w - so - 1, h - so - 1, w - so - 1, h - r - so);
if (this.borders[2]) {
g2d.drawLine(w - so - 1, h - so - 1, w - r - so, h - so - 1);
}
if (this.borders[3]) {
g2d.drawLine(w - so - 1, h - so - 1, w - so - 1, h - r - so);
}
}
// NE
if (this.corners[3]) {
g2d.drawArc(w - (2 * r) - so, 0, (2 * r) - 1, (2 * r) - 1, 0, 90);
} else {
if (this.borders[0]) {
g2d.drawLine(w - so - 1, 0, w - so - r, 0);
}
if (this.borders[3]) {
g2d.drawLine(w - so - 1, 0, w - so - 1, r);
}
}
}
/**
* <p>
@@ -230,15 +248,14 @@ public class FRoundedPanel extends JPanel {
* </p>
* Sets radius of each corner on rounded panel.
*
* @param r
* the new corner radius
* @param r0 &emsp; int
*/
public void setCornerRadius(int r) {
if (r < 0) {
r = 0;
public void setCornerRadius(int r0) {
if (r0 < 0) {
r0 = 0;
}
this.cornerRadius = r;
this.cornerRadius = r0;
}
/**
@@ -248,8 +265,7 @@ public class FRoundedPanel extends JPanel {
* Sets if corners should be rounded or not in the following order: NW, SW,
* SE, NE
*
* @param vals
* the new corners
* @param vals &emsp; boolean[4]
*/
public void setCorners(final boolean[] vals) {
if (vals.length != 4) {
@@ -259,6 +275,23 @@ public class FRoundedPanel extends JPanel {
this.corners = vals;
}
/**
* <p>
* setBorders.
* </p>
* Sets if borders should be displayed or not following order: N, W, S, E.
* Only works for square corners, rounded corners will be shown with borders.
*
* @param vals &emsp; boolean[4]
*/
public void setBorders(final boolean[] vals) {
if (vals.length != 4) {
throw new IllegalArgumentException("FRoundedPanel > setBorders requires an array of booleans of length 4.");
}
this.borders = vals;
}
/**
* Sets the show shadow.
*

View File

@@ -28,6 +28,9 @@ public class FSkin {
/** Primary texture used in skin. */
private ImageIcon texture1 = null;
/** Primary background image used during match play. */
private ImageIcon matchBG = null;
/** Left side of button, up state. */
private ImageIcon btnLup = null;
@@ -58,6 +61,17 @@ public class FSkin {
/** Splash screen image. */
private ImageIcon splash = null;
/** Splash screen image. */
private ImageIcon icoEnabled = null;
private ImageIcon icoDisabled = null;
private ImageIcon icoTap = null;
private ImageIcon icoUntap = null;
private ImageIcon icoPlus = null;
private ImageIcon icoShortcuts = null;
private ImageIcon icoSettings = null;
private ImageIcon icoConcede = null;
private ImageIcon icoEndTurn = null;
/** Base color used in skin. */
private Color clrTheme = Color.red;
@@ -95,7 +109,7 @@ public class FSkin {
private String name = "default";
// ===== Private fields
private final String paletteFile = "palette.png";
private final String spriteFile = "sprite.png";
private final String font1file = "font1.ttf";
private final String font2file = "font2.ttf";
private final String texture1file = "texture1.jpg";
@@ -109,11 +123,11 @@ public class FSkin {
private final String btnMdownfile = "btnMdown.png";
private final String btnRdownfile = "btnRdown.png";
private final String splashfile = "bg_splash.jpg";
private final String matchfile = "bg_match.jpg";
private ImageIcon tempImg;
private Font tempFont;
private String skin;
private final String notfound = "FSkin.java: \"" + this.skin + "\" skin can't find ";
private final String notfound = "FSkin.java: Can't find ";
/**
* FSkin constructor. No arguments, will generate default skin settings,
@@ -153,6 +167,7 @@ public class FSkin {
// Images
this.setTexture1(this.retrieveImage(dirName + this.texture1file));
this.setMatchBG(this.retrieveImage(dirName + this.matchfile));
this.setBtnLup(this.retrieveImage(dirName + this.btnLupfile));
this.setBtnMup(this.retrieveImage(dirName + this.btnMupfile));
this.setBtnRup(this.retrieveImage(dirName + this.btnRupfile));
@@ -162,26 +177,35 @@ public class FSkin {
this.setBtnLdown(this.retrieveImage(dirName + this.btnLdownfile));
this.setBtnMdown(this.retrieveImage(dirName + this.btnMdownfile));
this.setBtnRdown(this.retrieveImage(dirName + this.btnRdownfile));
this.setSplash(this.retrieveImage(dirName + this.splashfile));
this.setSplashBG(this.retrieveImage(dirName + this.splashfile));
// Color palette
final File file = new File(dirName + this.paletteFile);
final File file = new File(dirName + this.spriteFile);
BufferedImage image;
try {
image = ImageIO.read(file);
this.setClrTheme(this.getColorFromPixel(image.getRGB(60, 10)));
this.setClrBorders(this.getColorFromPixel(image.getRGB(60, 30)));
this.setClrZebra(this.getColorFromPixel(image.getRGB(60, 50)));
this.setClrHover(this.getColorFromPixel(image.getRGB(60, 70)));
this.setClrActive(this.getColorFromPixel(image.getRGB(60, 90)));
this.setClrInactive(this.getColorFromPixel(image.getRGB(60, 110)));
this.setClrText(this.getColorFromPixel(image.getRGB(60, 130)));
this.setClrProgress1(this.getColorFromPixel(image.getRGB(55, 145)));
this.setClrProgress2(this.getColorFromPixel(image.getRGB(65, 145)));
this.setClrProgress3(this.getColorFromPixel(image.getRGB(55, 155)));
this.setClrProgress4(this.getColorFromPixel(image.getRGB(65, 155)));
this.setClrTheme(this.getColorFromPixel(image.getRGB(70, 10)));
this.setClrBorders(this.getColorFromPixel(image.getRGB(70, 30)));
this.setClrZebra(this.getColorFromPixel(image.getRGB(70, 50)));
this.setClrHover(this.getColorFromPixel(image.getRGB(70, 70)));
this.setClrActive(this.getColorFromPixel(image.getRGB(70, 90)));
this.setClrInactive(this.getColorFromPixel(image.getRGB(70, 110)));
this.setClrText(this.getColorFromPixel(image.getRGB(70, 130)));
this.setClrProgress1(this.getColorFromPixel(image.getRGB(65, 145)));
this.setClrProgress2(this.getColorFromPixel(image.getRGB(75, 145)));
this.setClrProgress3(this.getColorFromPixel(image.getRGB(65, 155)));
this.setClrProgress4(this.getColorFromPixel(image.getRGB(75, 155)));
this.setIconEnabled(image.getSubimage(80, 0, 40, 40));
this.setIconDisabled(image.getSubimage(120, 0, 40, 40));
this.setIconTap(image.getSubimage(80, 40, 40, 40));
this.setIconUntap(image.getSubimage(120, 40, 40, 40));
this.setIconPlus(image.getSubimage(80, 80, 40, 40));
this.setIconShortcuts(image.getSubimage(160, 0, 80, 80));
this.setIconEndTurn(image.getSubimage(160, 80, 80, 80));
this.setIconSettings(image.getSubimage(80, 0, 80, 80));
this.setIconConcede(image.getSubimage(80, 80, 80, 80));
} catch (final IOException e) {
System.err.println(this.notfound + this.paletteFile);
System.err.println(this.notfound + this.spriteFile);
}
}
@@ -273,7 +297,7 @@ public class FSkin {
* Splash screen image.
* @return {@link javax.swing.ImageIcon} splash
*/
public ImageIcon getSplash() {
public ImageIcon getSplashBG() {
return splash;
}
@@ -281,7 +305,7 @@ public class FSkin {
* Splash screen image.
* @param splash0 &emsp; an image icon
*/
public void setSplash(ImageIcon splash0) {
public void setSplashBG(ImageIcon splash0) {
this.splash = splash0;
}
@@ -333,6 +357,22 @@ public class FSkin {
this.texture1 = texture10;
}
/**
* Primary background image used during match play.
* @return ImageIcon
*/
public ImageIcon getMatchBG() {
return matchBG;
}
/**
* Primary background image used during match play.
* @param img0 &emsp; an image icon
*/
public void setMatchBG(ImageIcon img0) {
this.matchBG = img0;
}
/**
* Color of zebra striping in grid displays.
* @return {@link java.awt.Color} clrZebra
@@ -626,4 +666,94 @@ public class FSkin {
public String getName() {
return name;
}
/** @param bi0 &emsp; BufferedImage */
public void setIconEnabled(BufferedImage bi0) {
this.icoEnabled = new ImageIcon(bi0);
}
/** @return ImageIcon */
public ImageIcon getIconEnabled() {
return icoEnabled;
}
/** @param bi0 &emsp; BufferedImage */
public void setIconDisabled(BufferedImage bi0) {
this.icoDisabled = new ImageIcon(bi0);
}
/** @return ImageIcon */
public ImageIcon getIconDisabled() {
return icoDisabled;
}
/** @param bi0 &emsp; BufferedImage */
public void setIconTap(BufferedImage bi0) {
this.icoTap = new ImageIcon(bi0);
}
/** @return ImageIcon */
public ImageIcon getIconTap() {
return icoTap;
}
/** @param bi0 &emsp; BufferedImage */
public void setIconUntap(BufferedImage bi0) {
this.icoUntap = new ImageIcon(bi0);
}
/** @return ImageIcon */
public ImageIcon getIconUntap() {
return icoUntap;
}
/** @param bi0 &emsp; BufferedImage */
public void setIconPlus(BufferedImage bi0) {
this.icoPlus = new ImageIcon(bi0);
}
/** @return ImageIcon */
public ImageIcon getIconPlus() {
return icoPlus;
}
/** @param bi0 &emsp; BufferedImage */
public void setIconShortcuts(BufferedImage bi0) {
this.icoShortcuts = new ImageIcon(bi0);
}
/** @return ImageIcon */
public ImageIcon getIconShortcuts() {
return icoShortcuts;
}
/** @param bi0 &emsp; BufferedImage */
public void setIconSettings(BufferedImage bi0) {
this.icoSettings = new ImageIcon(bi0);
}
/** @return ImageIcon */
public ImageIcon getIconSettings() {
return icoSettings;
}
/** @param bi0 &emsp; BufferedImage */
public void setIconConcede(BufferedImage bi0) {
this.icoConcede = new ImageIcon(bi0);
}
/** @return ImageIcon */
public ImageIcon getIconConcede() {
return icoConcede;
}
/** @param bi0 &emsp; BufferedImage */
public void setIconEndTurn(BufferedImage bi0) {
this.icoEndTurn = new ImageIcon(bi0);
}
/** @return ImageIcon */
public ImageIcon getIconEndTurn() {
return icoEndTurn;
}
}

View File

@@ -172,6 +172,7 @@ public class FGameState {
* the phase to set
*/
protected final void setPhase(final Phase phase0) {
System.out.println("asdf:"+phase0);
this.phase = phase0;
}

View File

@@ -18,8 +18,8 @@ import java.util.List;
*/
public class ForgePreferences extends Preferences {
/** The new gui. */
private final boolean newGui;
/** Old gui checkbox toggle. */
private boolean oldGui;
/** The stack ai land. */
private boolean stackAiLand;
@@ -27,7 +27,13 @@ public class ForgePreferences extends Preferences {
/** The milling loss condition. */
private boolean millingLossCondition;
/** The developer mode. */
/** Hand view toggle. */
private boolean handView;
/** Library view toggle. */
private boolean libraryView;
/** Developer mode. */
private boolean developerMode;
/** The upload draft ai. */
@@ -106,6 +112,17 @@ public class ForgePreferences extends Preferences {
/** The b human end combat. */
private boolean bHumanEndCombat;
// Keyboard shortcuts
private String showStackShortcut;
private String showCombatShortcut;
private String showConsoleShortcut;
private String showPlayersShortcut;
private String showDevShortcut;
private String concedeShortcut;
private String showPictureShortcut;
private String showDetailShortcut;
//
private final List<SavePreferencesListener> saveListeners = new ArrayList<SavePreferencesListener>();
private final String fileName;
@@ -135,9 +152,11 @@ public class ForgePreferences extends Preferences {
throw new Exception("Error reading \"" + fileName + "\".", ex);
}
this.newGui = this.getBoolean("gui.new", true);
this.oldGui = this.getBoolean("gui.old", true);
this.setStackAiLand(this.getBoolean("AI.stack.land", false));
this.setMillingLossCondition(this.getBoolean("loss.condition.milling", true));
this.setHandView(this.getBoolean("developer.handview", true));
this.setLibraryView(this.getBoolean("developer.libraryview", true));
this.setDeveloperMode(this.getBoolean("developer.mode", false));
this.setUploadDraftAI(this.getBoolean("upload.Draft.AI", true));
@@ -172,6 +191,16 @@ public class ForgePreferences extends Preferences {
this.setbHumanEOT(this.getBoolean("phase.human.eot", true));
this.setbHumanBeginCombat(this.getBoolean("phase.human.beginCombat", true));
this.setbHumanEndCombat(this.getBoolean("phase.human.endCombat", true));
// Keyboard shortcuts
this.setShowStackShortcut(this.get("shortcut.showstack", "83"));
this.setShowCombatShortcut(this.get("shortcut.showcombat", "67"));
this.setShowConsoleShortcut(this.get("shortcut.showconsole", "76"));
this.setShowPlayersShortcut(this.get("shortcut.showplayers", "80"));
this.setShowDevShortcut(this.get("shortcut.showdev", "68"));
this.setConcedeShortcut(this.get("shortcut.concede", "27"));
this.setShowPictureShortcut(this.get("shortcut.showpicture", "17 80"));
this.setShowDetailShortcut(this.get("shortcut.showdetail", "17 68"));
}
/**
@@ -184,10 +213,12 @@ public class ForgePreferences extends Preferences {
*/
public final void save() throws Exception {
this.set("gui.new", this.newGui);
this.set("gui.old", this.oldGui);
this.set("AI.stack.land", this.isStackAiLand());
this.set("loss.condition.milling", this.isMillingLossCondition());
this.set("developer.handview", this.getHandView());
this.set("developer.libraryview", this.getLibraryView());
this.set("developer.mode", this.isDeveloperMode());
this.set("upload.Draft.AI", this.isUploadDraftAI());
@@ -224,6 +255,16 @@ public class ForgePreferences extends Preferences {
this.set("phase.human.beginCombat", this.isbHumanBeginCombat());
this.set("phase.human.endCombat", this.isbHumanEndCombat());
// Keyboard shortcuts
this.set("shortcut.showstack", this.getShowStackShortcut());
this.set("shortcut.showcombat", this.getShowCombatShortcut());
this.set("shortcut.showconsole", this.getShowConsoleShortcut());
this.set("shortcut.showplayers", this.getShowPlayersShortcut());
this.set("shortcut.showdev", this.getShowDevShortcut());
this.set("shortcut.concede", this.getConcedeShortcut());
this.set("shortcut.showpicture", this.getShowPictureShortcut());
this.set("shortcut.showdetail", this.getShowDetailShortcut());
try {
final FileOutputStream stream = new FileOutputStream(this.fileName);
this.store(stream, "Forge");
@@ -248,7 +289,7 @@ public class ForgePreferences extends Preferences {
/**
* Checks if is stack ai land.
*
* @return the stackAiLand
* @return boolean
*/
public boolean isStackAiLand() {
return this.stackAiLand;
@@ -257,29 +298,78 @@ public class ForgePreferences extends Preferences {
/**
* Sets the stack ai land.
*
* @param stackAiLand the stackAiLand to set
* @param b0 &emsp; boolean
*/
public void setStackAiLand(final boolean stackAiLand) {
this.stackAiLand = stackAiLand; // TODO: Add 0 to parameter's name.
public void setStackAiLand(final boolean b0) {
this.stackAiLand = b0;
}
/**
* Checks if is milling loss condition.
* Checks if old gui is to be used.
*
* @return the millingLossCondition
* @return boolean
*/
public boolean isOldGui() {
return this.oldGui;
}
/**
* Sets if old gui is to be used.
*
* @param b0 &emsp; boolean
*/
public void setOldGui(final boolean b0) {
this.oldGui = b0;
}
/**
* Checks if loss by milling is enabled.
*
* @return boolean
*/
public boolean isMillingLossCondition() {
return this.millingLossCondition;
}
/**
* Sets the milling loss condition.
* Sets if loss by milling is enabled.
*
* @param millingLossCondition the millingLossCondition to set
* @param millingLossCondition0 the millingLossCondition to set
*/
public void setMillingLossCondition(final boolean millingLossCondition) {
this.millingLossCondition = millingLossCondition; // TODO: Add 0 to
// parameter's name.
public void setMillingLossCondition(final boolean millingLossCondition0) {
this.millingLossCondition = millingLossCondition0;
}
/**
* Determines if "view any hand" option in dev mode is enabled or not.
* @return boolean
*/
public boolean getHandView() {
return this.handView;
}
/**
* Determines if "view any hand" option in dev mode is enabled or not.
* @param b0 &emsp; boolean
*/
public void setHandView(final boolean b0) {
this.handView = b0;
}
/**
* Determines if "view any library" option in dev mode is enabled or not.
* @return boolean
*/
public boolean getLibraryView() {
return this.libraryView;
}
/**
* Determines if "view any library" option in dev mode is enabled or not.
* @param b0 &emsp; boolean
*/
public void setLibraryView(final boolean b0) {
this.libraryView = b0;
}
/**
@@ -791,4 +881,85 @@ public class ForgePreferences extends Preferences {
/** The large. */
large
}
// Keyboard shortcuts
/** @return String &emsp; String of keycodes set for this shortcut, delimited with spaces. */
public String getShowStackShortcut() {
return this.showStackShortcut;
}
/** @param keycodes &emsp; String of keycodes to set for this shortcut, delimited with spaces. */
public void setShowStackShortcut(String keycodes) {
this.showStackShortcut = keycodes;
}
/** @return String &emsp; String of keycodes set for this shortcut, delimited with spaces. */
public String getShowCombatShortcut() {
return this.showCombatShortcut;
}
/** @param keycodes &emsp; String of keycodes to set for this shortcut, delimited with spaces. */
public void setShowCombatShortcut(String keycodes) {
this.showCombatShortcut = keycodes;
}
/** @return String &emsp; String of keycodes set for this shortcut, delimited with spaces. */
public String getShowConsoleShortcut() {
return this.showConsoleShortcut;
}
/** @param keycodes &emsp; String of keycodes to set for this shortcut, delimited with spaces. */
public void setShowConsoleShortcut(String keycodes) {
this.showConsoleShortcut = keycodes;
}
/** @return String &emsp; String of keycodes set for this shortcut, delimited with spaces. */
public String getShowPlayersShortcut() {
return this.showPlayersShortcut;
}
/** @param keycodes &emsp; String of keycodes to set for this shortcut, delimited with spaces. */
public void setShowPlayersShortcut(String keycodes) {
this.showPlayersShortcut = keycodes;
}
/** @return String &emsp; String of keycodes set for this shortcut, delimited with spaces. */
public String getShowDevShortcut() {
return this.showDevShortcut;
}
/** @param keycodes &emsp; String of keycodes to set for this shortcut, delimited with spaces. */
public void setShowDevShortcut(String keycodes) {
this.showDevShortcut = keycodes;
}
/** @return String &emsp; String of keycodes set for this shortcut, delimited with spaces. */
public String getConcedeShortcut() {
return this.concedeShortcut;
}
/** @param keycodes &emsp; String of keycodes to set for this shortcut, delimited with spaces. */
public void setConcedeShortcut(String keycodes) {
this.concedeShortcut = keycodes;
}
/** @return String &emsp; String of keycodes set for this shortcut, delimited with spaces. */
public String getShowPictureShortcut() {
return this.showPictureShortcut;
}
/** @param keycodes &emsp; String of keycodes to set for this shortcut, delimited with spaces. */
public void setShowPictureShortcut(String keycodes) {
this.showPictureShortcut = keycodes;
}
/** @return String &emsp; String of keycodes set for this shortcut, delimited with spaces. */
public String getShowDetailShortcut() {
return this.showDetailShortcut;
}
/** @param keycodes &emsp; String of keycodes to set for this shortcut, delimited with spaces. */
public void setShowDetailShortcut(String keycodes) {
this.showDetailShortcut = keycodes;
}
}

View File

@@ -760,7 +760,7 @@ public final class NewConstants {
public static final String DECK_EDITOR = "%s/NewGame/deckeditor";
/** The NE w_ gui. */
public static final String NEW_GUI = "%s/NewGame/newgui";
public static final String OLD_GUI = "%s/NewGame/oldgui";
/** The A i_ land. */
public static final String AI_LAND = "%s/NewGame/ailand";

View File

@@ -31,6 +31,7 @@ import forge.Command;
import forge.Constant;
import forge.GuiDisplay;
import forge.ImageCache;
import forge.control.ControlAllUI;
import forge.deck.Deck;
import forge.gui.GuiUtils;
import forge.gui.deckeditor.DeckEditorQuest;
@@ -755,13 +756,14 @@ public class QuestMainPanel extends QuestAbstractPanel {
// Dev Mode occurs before Display
Constant.Runtime.DEV_MODE[0] = this.devModeCheckBox.isSelected();
// DO NOT CHANGE THIS ORDER, GuiDisplay needs to be created before cards
// are added
// if (newGUICheckbox.isSelected()) {
if (Constant.Runtime.OLDGUI[0]) {
AllZone.setDisplay(new GuiDisplay());
// } else {
// AllZone.setDisplay(new GuiDisplay3());
// }
}
else {
ControlAllUI ui = new ControlAllUI();
AllZone.setDisplay(ui.getMatchView());
ui.getMatchController().initMatch();
}
Constant.Runtime.SMOOTH[0] = this.smoothLandCheckBox.isSelected();

View File

@@ -0,0 +1,49 @@
package forge.view;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import forge.AllZone;
import forge.view.toolbox.FOverlay;
/**
* Parent JFrame for Forge UI.
*
*/
@SuppressWarnings("serial")
public class GuiTopLevel extends JFrame {
private JLayeredPane lpnContent;
/**
* Parent JFrame for Forge UI.
*/
public GuiTopLevel() {
super();
setMinimumSize(new Dimension(800, 600));
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
lpnContent = new JLayeredPane();
lpnContent.setOpaque(true);
setContentPane(lpnContent);
addOverlay();
setVisible(true);
}
/**
* Adds overlay panel to modal layer. Used when removeAll()
* has been called on the JLayeredPane parent.
*/
public void addOverlay() {
final FOverlay pnlOverlay = new FOverlay();
AllZone.setOverlay(pnlOverlay);
pnlOverlay.setOpaque(false);
pnlOverlay.setVisible(false);
pnlOverlay.setBounds(0, 0, getWidth(), getHeight());
lpnContent.add(pnlOverlay, JLayeredPane.MODAL_LAYER);
}
}

View File

@@ -0,0 +1,16 @@
package forge.view.home;
import forge.gui.skin.FPanel;
/**
* Lays out battle, sidebar, user areas in locked % vals and repaints
* as necessary.
*
*/
@SuppressWarnings("serial")
public class HomeTopLevel extends FPanel {
public HomeTopLevel() {
super();
}
}

View File

@@ -0,0 +1,52 @@
package forge.view.match;
import java.util.ArrayList;
import java.util.List;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.gui.skin.FPanel;
/**
* Battlefield, assembles and contains instances of MatchPlayer.
* SHOULD PROBABLY COLLAPSE INTO TOP LEVEL.
*
*/
@SuppressWarnings("serial")
public class ViewAreaBattlefield extends FPanel {
private List<ViewField> fields;
/**
* An FPanel that adds instances of ViewField fields
* from player name list.
*
*/
public ViewAreaBattlefield() {
super();
setOpaque(false);
setLayout(new MigLayout("wrap, insets 1% 0.5% 0 0, gap 1%, nocache"));
// When future codebase upgrades allow, as many fields as
// necessary can be instantiated here. Doublestrike 29-10-11
fields = new ArrayList<ViewField>();
ViewField temp;
temp = new ViewField(AllZone.getComputerPlayer());
this.add(temp, "h 48.5%!, w 99.5%!");
fields.add(temp);
temp = new ViewField(AllZone.getHumanPlayer());
this.add(temp, "h 48.5%!, w 99.5%!");
fields.add(temp);
}
/**
* Returns a list of field components in battlefield.
* @return List<ViewFields>
*/
public List<ViewField> getFields() {
return fields;
}
}

View File

@@ -0,0 +1,62 @@
package forge.view.match;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.gui.skin.FPanel;
import forge.gui.skin.FRoundedPanel;
/**
* Handles display of child components of sidebar area in match UI.
* SHOULD PROBABLY COLLAPSE INTO TOP LEVEL.
*
*/
@SuppressWarnings("serial")
public class ViewAreaSidebar extends FPanel {
private ViewCardviewer cardviewer;
private ViewTabber tabber;
private FRoundedPanel sidebar;
/**
* Handles display of all components of sidebar area in match UI.
*
*/
public ViewAreaSidebar() {
super();
setOpaque(false);
setLayout(new MigLayout("insets 0"));
sidebar = new FRoundedPanel();
sidebar.setLayout(new MigLayout("wrap, gap 0, insets 0"));
sidebar.setBackground(AllZone.getSkin().getClrTheme());
sidebar.setCorners(new boolean[] {true, true, false, false});
// Add tabber, cardview, and finally sidebar. Unfortunately,
// tabber and cardviewer cannot extend FVerticalTabPanel, since that
// requires child panels to be prepared before it's instantiated.
// Therefore, their vertical tab panels must be accessed indirectly via
// an instance of this class.
cardviewer = new ViewCardviewer();
tabber = new ViewTabber();
sidebar.add(cardviewer.getVtpCardviewer(), "w 97%!, h 40%!, gapleft 1%, gapright 2%");
sidebar.add(tabber.getVtpTabber(), "w 97%!, h 60%!, gapright 2%");
add(sidebar, "h 98%!, w 98%!, gapleft 2%, gaptop 1%");
}
/**
* Retrieves vertical tab panel used for card picture and detail.
*
* @return ViewCardviewer vertical tab panel
*/
public ViewCardviewer getCardviewer() {
return cardviewer;
}
/**
* Retrieves vertical tab panel used for data presentation.
*
* @return ViewTabber vertical tab panel
*/
public ViewTabber getTabber() {
return tabber;
}
}

View File

@@ -0,0 +1,63 @@
package forge.view.match;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import forge.gui.skin.FPanel;
/**
* Parent panel for display of input, hand, and dock.
* SHOULD PROBABLY COLLAPSE INTO TOP LEVEL.
*
*/
@SuppressWarnings("serial")
public class ViewAreaUser extends FPanel {
private ViewDock pnlDock;
private ViewHand pnlHand;
private JPanel pnlMessage;
private ViewInput pnlInput;
/**
* Assembles user area of match UI.
*/
public ViewAreaUser() {
super();
setOpaque(false);
setLayout(new MigLayout("fill, insets 0, gap 0"));
// Input panel
pnlInput = new ViewInput();
// Hand panel
pnlHand = new ViewHand();
// Dock panel
pnlDock = new ViewDock();
// A.D.D.
add(pnlInput, "h 100%!, west, w 200px!");
add(pnlHand, "grow, gapleft 5");
add(pnlDock, "growx, h 50px!, south, gaptop 5, gapleft 5");
}
/** @return ViewDock */
public ViewDock getPnlDock() {
return pnlDock;
}
/** @return ViewHand */
public ViewHand getPnlHand() {
return pnlHand;
}
/** @return JPanel */
public JPanel getPnlMessage() {
return pnlMessage;
}
/** @return ViewInput */
public ViewInput getPnlInput() {
return pnlInput;
}
}

View File

@@ -0,0 +1,107 @@
package forge.view.match;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import forge.Card;
import forge.ImageCache;
import forge.control.match.ControlCardviewer;
import forge.gui.skin.FPanel;
import forge.view.toolbox.CardDetailPanel;
import forge.view.toolbox.FVerticalTabPanel;
/**
* Vertical tab panel for viewing card picture and/or details.
*
*/
public class ViewCardviewer {
private List<JPanel> panelList;
private ControlCardviewer control;
private CardPicPanel pnlCardPic;
private CardDetailPanel pnlCardDetail;
private FVerticalTabPanel vtpCardviewer;
private int w, h;
/**
*
*/
public ViewCardviewer() {
// Assemble card pic viewer
panelList = new ArrayList<JPanel>();
pnlCardPic = new CardPicPanel();
pnlCardPic.setOpaque(false);
pnlCardPic.setName("Picture");
pnlCardPic.setToolTipText("Card Picture");
panelList.add(pnlCardPic);
pnlCardDetail = new CardDetailPanel();
pnlCardDetail.setOpaque(false);
pnlCardDetail.setName("Detail");
pnlCardDetail.setToolTipText("Card Text");
panelList.add(pnlCardDetail);
vtpCardviewer = new FVerticalTabPanel(panelList);
// After all components are in place, instantiate controller.
control = new ControlCardviewer(this);
}
/** @return ControlCardviewer */
public ControlCardviewer getController() {
return control;
}
/**
* Card picture handling in side panel of match.
*
*/
@SuppressWarnings("serial")
public class CardPicPanel extends FPanel {
private Card card = null;
/** @param c &emsp; Card object */
public void setCard(Card c) {
this.card = c;
repaint();
}
/** @return Card */
public Card getCard() {
return this.card;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (card != null) {
w = getWidth();
h = (int) (w / 0.7);
BufferedImage img = ImageCache.getImage(card, w, h);
g.drawImage(img, 0, (int) ((getHeight() - h) / 2), null);
}
}
}
/** @return CardPicPanel */
public CardPicPanel getPnlCardPic() {
return pnlCardPic;
}
/** @return CardDetailPanel */
public CardDetailPanel getPnlCardDetail() {
return pnlCardDetail;
}
/** @return FVerticalTabPanel */
public FVerticalTabPanel getVtpCardviewer() {
return vtpCardviewer;
}
}

View File

@@ -0,0 +1,388 @@
package forge.view.match;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
import org.apache.commons.lang3.StringUtils;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.Singletons;
import forge.control.match.ControlDock;
import forge.gui.skin.FButton;
import forge.gui.skin.FPanel;
import forge.gui.skin.FRoundedPanel;
import forge.gui.skin.FSkin;
import forge.properties.ForgePreferences;
import forge.view.toolbox.FOverlay;
/**
* Swing component for button dock.
*
*/
@SuppressWarnings("serial")
public class ViewDock extends FRoundedPanel {
private FSkin skin;
private ControlDock control;
private Map<String, KeyboardShortcutField> keyboardShortcutFields;
private Action actClose, actSaveKeyboardShortcuts;
/**
* Swing component for button dock.
*
*/
public ViewDock() {
super();
setCorners(new boolean[] {false, false, false, false});
setBorders(new boolean[] {true, true, false, true});
setToolTipText("Shortcut Button Dock");
setBackground(AllZone.getSkin().getClrTheme());
setLayout(new MigLayout("insets 0, gap 0, ay center, ax center"));
String constraints = "w 30px!, h 30px!, gap 0 10px";
skin = AllZone.getSkin();
keyboardShortcutFields = new HashMap<String, KeyboardShortcutField>();
actClose = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
AllZone.getOverlay().hideOverlay();
}
};
actSaveKeyboardShortcuts = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
control.saveKeyboardShortcuts();
}
};
JLabel btnConcede = new DockButton(skin.getIconConcede(), "Concede Game");
btnConcede.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
control.concede();
}
});
JLabel btnShortcuts = new DockButton(skin.getIconShortcuts(), "Keyboard Shortcuts");
btnShortcuts.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
overlayKeyboard();
}
});
JLabel btnSettings = new DockButton(skin.getIconSettings(), "Game Settings");
btnSettings.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
overlaySettings();
}
});
JLabel btnEndTurn = new DockButton(skin.getIconEndTurn(), "Game Settings");
btnEndTurn.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
control.endTurn();
}
});
add(btnConcede, constraints);
add(btnShortcuts, constraints);
add(btnSettings, constraints);
add(btnEndTurn, constraints);
// After all components are in place, instantiate controller.
control = new ControlDock(this);
}
/** @return ControlDock */
public ControlDock getController() {
return control;
}
/**
* Buttons in Dock. JLabels are used to allow hover effects.
*/
public class DockButton extends JLabel {
private Image img;
private Color hoverBG = skin.getClrHover();
private Color defaultBG = new Color(0, 0, 0, 0);
private Color clrBorders = new Color(0, 0, 0, 0);
private int w, h;
/**
* Buttons in Dock. JLabels are used to allow hover effects.
*
* @param i0 &emsp; ImageIcon to show in button
* @param s0 &emsp; Tooltip string
*/
public DockButton(ImageIcon i0, String s0) {
super();
setToolTipText(s0);
setOpaque(false);
setBackground(defaultBG);
img = i0.getImage();
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
clrBorders = skin.getClrBorders();
setBackground(hoverBG);
}
@Override
public void mouseExited(MouseEvent e) {
clrBorders = new Color(0, 0, 0, 0);
setBackground(defaultBG);
}
});
}
@Override
public void paintComponent(Graphics g) {
w = getWidth();
h = getHeight();
g.setColor(getBackground());
g.fillRect(0, 0, w, h);
g.setColor(clrBorders);
g.drawRect(0, 0, w - 1, h - 1);
g.drawImage(img, 0, 0, w, h, null);
super.paintComponent(g);
}
}
/** */
private void overlayKeyboard() {
FOverlay overlay = AllZone.getOverlay();
overlay.removeAll();
overlay.setLayout(new MigLayout("insets 0"));
overlay.showOverlay();
FPanel parent = new FPanel();
parent.setBGImg(skin.getTexture1());
parent.setBorder(new LineBorder(skin.getClrBorders(), 1));
parent.setLayout(new MigLayout("insets 0, wrap 2, ax center, ay center"));
overlay.add(parent, "w 80%!, h 80%!, gaptop 10%, gapleft 10%, span 2 1");
FButton btnOK = new FButton();
FButton btnCancel = new FButton();
overlay.add(btnOK, "width 30%, newline, gapright 10%, gapleft 15%, gaptop 10px");
overlay.add(btnCancel, "width 30%!");
btnOK.setAction(actSaveKeyboardShortcuts);
btnOK.setText("Save and Exit");
btnCancel.setAction(actClose);
btnCancel.setText("Exit Without Save");
KeyboardShortcutLabel lblBlurb = new KeyboardShortcutLabel();
lblBlurb.setText("<html><center>Focus in a box and press a key.<br>"
+ "Backspace will remove the last keypress.<br>"
+ "Restart Forge to map any new changes.</center></html>");
parent.add(lblBlurb, "span 2 1, gapbottom 30px");
ForgePreferences fp = Singletons.getModel().getPreferences();
// Keyboard shortcuts are a bit tricky to make, since they involve three
// different parts of the codebase: Preferences, main match control, and
// the customize button in the dock. To make a keyboard shortcut:
//
// 1. Go to ForgePreferences and set a variable, default value, setter, and getter
// 2. Go to ControlMatchUI and map an action using mapKeyboardShortcuts
// 3. (Optional) Come back to this file and add a new KeyboardShortcutField so
// the user can customize this shortcut. Update ControlDock to ensure any
// changes will be saved.
// Keyboard shortcuts must be created, then added to the HashMap to help saving.
// Their actions must also be declared, using mapKeyboardShortcuts in ControlMatchUI.
final KeyboardShortcutField showStack = new KeyboardShortcutField(fp.getShowStackShortcut());
this.keyboardShortcutFields.put("showstack", showStack);
final KeyboardShortcutField showCombat = new KeyboardShortcutField(fp.getShowCombatShortcut());
this.keyboardShortcutFields.put("showcombat", showCombat);
final KeyboardShortcutField showConsole = new KeyboardShortcutField(fp.getShowConsoleShortcut());
this.keyboardShortcutFields.put("showconsole", showConsole);
final KeyboardShortcutField showPlayers = new KeyboardShortcutField(fp.getShowPlayersShortcut());
this.keyboardShortcutFields.put("showplayers", showPlayers);
final KeyboardShortcutField showDev = new KeyboardShortcutField(fp.getShowDevShortcut());
this.keyboardShortcutFields.put("showdev", showDev);
final KeyboardShortcutField concedeGame = new KeyboardShortcutField(fp.getConcedeShortcut());
this.keyboardShortcutFields.put("concede", concedeGame);
final KeyboardShortcutField showPicture = new KeyboardShortcutField(fp.getShowPictureShortcut());
this.keyboardShortcutFields.put("showpicture", showPicture);
final KeyboardShortcutField showDetail = new KeyboardShortcutField(fp.getShowDetailShortcut());
this.keyboardShortcutFields.put("showdetail", showDetail);
//
parent.add(new KeyboardShortcutLabel("Show stack tab: "), "w 200px!");
parent.add(showStack, "w 100px!");
parent.add(new KeyboardShortcutLabel("Show combat tab: "), "w 200px!");
parent.add(showCombat, "w 100px!");
parent.add(new KeyboardShortcutLabel("Show console tab: "), "w 200px!");
parent.add(showConsole, "w 100px!");
parent.add(new KeyboardShortcutLabel("Show players tab: "), "w 200px!");
parent.add(showPlayers, "w 100px!");
parent.add(new KeyboardShortcutLabel("Show devmode tab: "), "w 200px!");
parent.add(showDev, "w 100px!");
parent.add(new KeyboardShortcutLabel("Concede game: "), "w 200px!");
parent.add(concedeGame, "w 100px!");
parent.add(new KeyboardShortcutLabel("Show card picture: "), "w 200px!");
parent.add(showPicture, "w 100px!");
parent.add(new KeyboardShortcutLabel("Show card detail: "), "w 200px!");
parent.add(showDetail, "w 100px!");
}
/** */
private void overlaySettings() {
FOverlay overlay = AllZone.getOverlay();
overlay.setLayout(new MigLayout("insets 0"));
overlay.showOverlay();
JPanel parent = new JPanel();
parent.setBackground(Color.red.darker());
overlay.add(parent, "w 80%!, h 80%!, gaptop 10%, gapleft 10%, span 2 1");
FButton btnOK = new FButton("Save and Exit");
FButton btnCancel = new FButton("Exit Without Save");
overlay.add(btnOK, "width 30%, newline, gapright 10%, gapleft 15%, gaptop 10px");
overlay.add(btnCancel, "width 30%!");
btnOK.setAction(actClose);
btnOK.setText("Save and Exit");
btnCancel.setAction(actClose);
btnCancel.setText("Exit Without Save");
JLabel test = new JLabel();
test.setForeground(Color.white);
test.setText("<html><center>'Settings' does not do anything yet.<br>"
+ "This button is just here to demonstrate the dock feature.<br>"
+ "'Settings' can be removed or developed further.</center></html>");
parent.add(test);
}
/** Small private class to centralize label styling. */
private class KeyboardShortcutLabel extends JLabel {
public KeyboardShortcutLabel() {
this("");
}
public KeyboardShortcutLabel(String s0) {
super(s0);
this.setForeground(skin.getClrText());
this.setFont(skin.getFont1().deriveFont(Font.PLAIN, 16));
}
}
/** A JTextField plus a "codeString" property, that stores keycodes for the shortcut.
* Also, an action listener that handles translation of keycodes into characters and
* (dis)assembly of keycode stack.
*/
public class KeyboardShortcutField extends JTextField {
private String codeString;
/** A JTextField plus a "codeString" property, that stores keycodes for the shortcut.
* Also, an action listener that handles translation of keycodes into characters and
* (dis)assembly of keycode stack.
*
* This constructor sets the keycode string for this shortcut.
* Important: this parameter is keyCODEs not keyCHARs.
*
* @param s0 &emsp; The string of keycodes for this shortcut
*/
public KeyboardShortcutField(String s0) {
this();
this.setCodeString(s0);
}
/** A JTextField plus a "codeString" property, that stores keycodes for the shortcut.
* Also, an action listener that handles translation of keycodes into characters and
* (dis)assembly of keycode stack.
*/
public KeyboardShortcutField() {
super();
this.setEditable(false);
this.setFont(skin.getFont1().deriveFont(Font.PLAIN, 14));
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
control.addKeyCode(e);
}
});
this.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
setBackground(skin.getClrActive());
}
@Override
public void focusLost(FocusEvent e) {
setBackground(Color.white);
}
});
}
/** @return String */
public String getCodeString() {
return codeString;
}
/** @param s0 &emsp; The new code string (space delimited) */
public void setCodeString(String s0) {
if (s0.equals("null")) {
return;
}
codeString = s0.trim();
List<String> codes = new ArrayList<String>(Arrays.asList(codeString.split(" ")));
List<String> displayText = new ArrayList<String>();
for (String s : codes) {
if (!s.isEmpty()) {
displayText.add(KeyEvent.getKeyText(Integer.valueOf(s)));
}
}
this.setText(StringUtils.join(displayText, ' '));
}
}
/** @return Map<String, JTextField> */
public Map<String, KeyboardShortcutField> getKeyboardShortcutFields() {
return keyboardShortcutFields;
}
}

View File

@@ -0,0 +1,628 @@
package forge.view.match;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;
import arcane.ui.PlayArea;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.Player;
import forge.Constant.Zone;
import forge.card.cardfactory.CardFactoryUtil;
import forge.control.match.ControlField;
import forge.gui.skin.FPanel;
import forge.gui.skin.FRoundedPanel;
import forge.gui.skin.FSkin;
/**
* Assembles Swing components of player field instance.
*
*/
@SuppressWarnings("serial")
public class ViewField extends FRoundedPanel {
private FSkin skin;
private int counter;
private ControlField control;
private PlayArea tabletop;
private Border hoverBorder, inactiveBorder;
private DetailLabel
lblHand, lblGraveyard, lblLibrary,
lblExile, lblFlashback, lblPoison,
lblBlack, lblBlue, lblGreen,
lblRed, lblWhite, lblColorless;
private PhaseLabel
lblUpkeep, lblDraw, lblBeginCombat, lblEndCombat, lblEndTurn;
private JLabel lblLife;
private Map<String, JLabel> keywordLabels;
private Color transparent = new Color(0, 0, 0, 0);
/**
* Assembles Swing components of player field instance.
*
* @param player &emsp; a Player object.
*/
public ViewField(Player player) {
super();
setOpaque(false);
setLayout(new MigLayout("insets 1% 0.5%, gap 0.5%"));
setCornerRadius(5);
setToolTipText(player.getName() + " Gameboard");
setBackground(AllZone.getSkin().getClrTheme());
skin = AllZone.getSkin();
inactiveBorder = new LineBorder(new Color(0, 0, 0, 0), 1);
hoverBorder = new LineBorder(skin.getClrBorders(), 1);
counter = -1;
JScrollPane scroller = new JScrollPane();
tabletop = new PlayArea(scroller, true);
scroller.setViewportView(tabletop);
scroller.setOpaque(false);
scroller.getViewport().setOpaque(false);
scroller.setBorder(null);
tabletop.setBorder(new MatteBorder(0, 1, 0, 0, skin.getClrBorders()));
tabletop.setOpaque(false);
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
//
Avatar pic = new Avatar("res/pics/icons/unknown.jpg");
Details pool = new Details();
add(pic, "h 98%!, w 10%!");
add(pool, "h 98%!, w 11%!");
add(scroller, "h 98%!, w 77%!");
// After all components are in place, instantiate controller.
control = new ControlField(player, this);
}
/** @return ControlField */
public ControlField getController() {
return control;
}
/** Handles observer update of player Zones - hand, graveyard, etc.
*
* @param p0 &emsp; Player obj
*/
public void updateZones(Player p0) {
getLblHand().setText(""
+ p0.getZone(Zone.Hand).size());
getLblGraveyard().setText(""
+ p0.getZone(Zone.Graveyard).size());
getLblLibrary().setText(""
+ p0.getZone(Zone.Library).size());
getLblFlashback().setText(""
+ CardFactoryUtil.getExternalZoneActivationCards(p0).size());
getLblExile().setText(""
+ p0.getZone(Zone.Exile).size());
}
/** Handles observer update of non-Zone details - life, poison, etc.
* Also updates "players" panel in tabber for this player.
*
* @param p0 &emsp; Player obj
*/
public void updateDetails(Player p0) {
// "Players" panel update
ViewTopLevel t = (ViewTopLevel) AllZone.getDisplay();
t.getTabberController().getView().updatePlayerLabels(p0);
// Poison/life
getLblLife().setText("" + p0.getLife());
getLblPoison().setText("" + p0.getPoisonCounters());
// Hide all keyword labels, then show the appropriate ones.
for (JLabel lbl : keywordLabels.values()) {
lbl.setVisible(false);
}
for (String s : p0.getKeywords()) {
keywordLabels.get(s).setVisible(true);
}
}
//========= Retrieval methods
/** @return PlayArea where cards for this field are in play */
public PlayArea getTabletop() {
return tabletop;
}
/** @return DetailLabel */
public JLabel getLblLife() {
return lblLife;
}
/** @return DetailLabel for hand cards */
public DetailLabel getLblHand() {
return lblHand;
}
/** @return DetailLabel for library cards */
public DetailLabel getLblLibrary() {
return lblLibrary;
}
/** @return DetailLabel for graveyard cards */
public DetailLabel getLblGraveyard() {
return lblGraveyard;
}
/** @return DetailLabel for exiled cards */
public DetailLabel getLblExile() {
return lblExile;
}
/** @return DetailLabel for flashback cards */
public DetailLabel getLblFlashback() {
return lblFlashback;
}
/** @return DetailLabel for poison counters */
public DetailLabel getLblPoison() {
return lblPoison;
}
/** @return DetailLabel for colorless mana count */
public DetailLabel getLblColorless() {
return lblColorless;
}
/** @return DetailLabel for black mana count */
public DetailLabel getLblBlack() {
return lblBlack;
}
/** @return DetailLabel for blue mana count */
public DetailLabel getLblBlue() {
return lblBlue;
}
/** @return DetailLabel for green mana count */
public DetailLabel getLblGreen() {
return lblGreen;
}
/** @return DetailLabel for red mana count */
public DetailLabel getLblRed() {
return lblRed;
}
/** @return DetailLabel for white mana count */
public DetailLabel getLblWhite() {
return lblWhite;
}
// Phases
/** @return PhaseLabel for upkeep */
public PhaseLabel getLblUpkeep() {
return lblUpkeep;
}
/** @return PhaseLabel for draw */
public PhaseLabel getLblDraw() {
return lblDraw;
}
/** @return PhaseLabel for beginning of combat*/
public PhaseLabel getLblBeginCombat() {
return lblBeginCombat;
}
/** @return PhaseLabel for end of combat */
public PhaseLabel getLblEndCombat() {
return lblEndCombat;
}
/** @return PhaseLabel for end of turn */
public PhaseLabel getLblEndTurn() {
return lblEndTurn;
}
/** @return Map<String,JLabel> */
public Map<String, JLabel> getKeywordLabels() {
return keywordLabels;
}
//========== Custom classes
/**
* Shows user icon, keywords, and phase for this field.
*/
private class Avatar extends FPanel {
private ImageIcon icon;
private Color transparent = new Color(0, 0, 0, 0);
public Avatar(String filename) {
// Panel and background image icon init
super();
setOpaque(false);
setLayout(new MigLayout("fill, wrap, insets 0, gap 0"));
icon = new ImageIcon(filename);
// Life label
lblLife = new JLabel("--");
lblLife.setBorder(inactiveBorder);
lblLife.setToolTipText("<html>Player life.<br>Click to select player.</html>");
lblLife.setFont(skin.getFont1().deriveFont(Font.BOLD, 18));
lblLife.setForeground(skin.getClrText());
lblLife.setBackground(skin.getClrTheme().darker());
lblLife.setOpaque(true);
lblLife.setHorizontalAlignment(JLabel.CENTER);
lblLife.setAlignmentX(Component.CENTER_ALIGNMENT);
lblLife.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
lblLife.setBackground(AllZone.getSkin().getClrHover());
lblLife.setBorder(hoverBorder);
}
@Override
public void mouseExited(MouseEvent e) {
lblLife.setBackground(skin.getClrTheme());
lblLife.setBorder(inactiveBorder);
}
});
add(lblLife, "w 100%!, dock north");
keywordLabels = new HashMap<String, JLabel>();
// TODO link these map keys to correct keyword constant
keywordLabels.put("shroud", new KeywordLabel("Shroud"));
keywordLabels.put("extraturn", new KeywordLabel("+1 turn"));
keywordLabels.put("skipturn", new KeywordLabel("Skip turn"));
keywordLabels.put("problack", new KeywordLabel("Pro: Black"));
keywordLabels.put("problue", new KeywordLabel("Pro: Blue"));
keywordLabels.put("progreen", new KeywordLabel("Pro: Green"));
keywordLabels.put("prored", new KeywordLabel("Pro: Red"));
keywordLabels.put("prowhite", new KeywordLabel("Pro: White"));
JPanel pnlKeywords = new JPanel(new MigLayout("insets 0, wrap, hidemode 2"));
pnlKeywords.setOpaque(false);
for (JLabel lbl : keywordLabels.values()) {
pnlKeywords.add(lbl);
}
JScrollPane scrKeywords = new JScrollPane(pnlKeywords,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrKeywords.setBorder(new EmptyBorder(0, 0, 0, 0));
scrKeywords.setOpaque(false);
scrKeywords.getViewport().setOpaque(false);
scrKeywords.setViewportView(pnlKeywords);
add(scrKeywords, "w 100%!, growy");
JPanel phase = new JPanel();
phase.setOpaque(false);
phase.setLayout(new MigLayout("fillx, insets 0, gap 0"));
add(phase, "w 100%!, h 20px!");
// Constraints string must be set once, for ease and also
// since dynamic sizing is buggy.
String constraints = "w 20%!, h 100%!";
lblUpkeep = new PhaseLabel("UP");
lblUpkeep.setToolTipText("<html>Phase: Upkeep<br>Click to toggle.</html>");
phase.add(lblUpkeep, constraints);
lblDraw = new PhaseLabel("DR");
lblDraw.setToolTipText("<html>Phase: Draw<br>Click to toggle.</html>");
phase.add(lblDraw, constraints);
lblBeginCombat = new PhaseLabel("BC");
lblBeginCombat.setToolTipText("<html>Phase: Begin Combat<br>Click to toggle.</html>");
phase.add(lblBeginCombat, constraints);
lblEndCombat = new PhaseLabel("EC");
lblEndCombat.setToolTipText("<html>Phase: End Combat<br>Click to toggle.</html>");
phase.add(lblEndCombat, constraints);
lblEndTurn = new PhaseLabel("ET");
lblEndTurn.setToolTipText("<html>Phase: End Turn<br>Click to toggle.</html>");
phase.add(lblEndTurn, constraints);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBorder(new MatteBorder(getWidth(), 0, 0, 0, transparent));
g.drawImage(icon.getImage(), 0, 0, getWidth(), getWidth(),
0, 0, icon.getIconWidth(), icon.getIconHeight(), null);
lblLife.setFont(skin.getFont1().deriveFont(Font.PLAIN, (int) (getWidth() / 4)));
}
}
/**
* The "details" section of player info:
* Hand, library, graveyard, exiled, flashback, poison,
* and mana pool (BBGRW and colorless).
*
*/
// Design note: Labels are used here since buttons have various
// difficulties in displaying the desired "flat" background and
// also strange icon/action behavior.
private class Details extends JPanel {
public Details() {
super();
setLayout(new MigLayout("insets 0, gap 0, wrap 2, filly"));
setOpaque(false);
final String constraints = "w 50%!, h 12.5%!, growy";
// Hand, library, graveyard, exile, flashback, poison labels
lblGraveyard = new DetailLabel(new ImageIcon("res/images/symbols-13/detail_grave.png"), "99");
lblGraveyard.setToolTipText("Cards in graveyard");
add(lblGraveyard, constraints);
lblLibrary = new DetailLabel(new ImageIcon("res/images/symbols-13/detail_library.png"), "99");
lblLibrary.setToolTipText("Cards in library");
add(lblLibrary, constraints);
lblExile = new DetailLabel(new ImageIcon("res/images/symbols-13/detail_exile.png"), "99");
lblExile.setToolTipText("Exiled cards");
add(lblExile, constraints);
lblFlashback = new DetailLabel(new ImageIcon("res/images/symbols-13/detail_flashback.png"), "99");
lblFlashback.setToolTipText("Flashback cards");
add(lblFlashback, constraints);
lblHand = new DetailLabel(new ImageIcon("res/images/symbols-13/detail_hand.png"), "99");
lblHand.setToolTipText("Cards in hand");
add(lblHand, constraints);
lblPoison = new DetailLabel(new ImageIcon("res/images/symbols-13/detail_poison.png"), "99");
lblPoison.setToolTipText("Poison counters");
add(lblPoison, constraints);
// Black, Blue, Colorless, Green, Red, White mana labels
lblBlack = new DetailLabel(new ImageIcon("res/images/symbols-13/B.png"), "99");
lblBlack.setToolTipText("Black mana");
add(lblBlack, constraints);
lblBlue = new DetailLabel(new ImageIcon("res/images/symbols-13/U.png"), "99");
lblBlue.setToolTipText("Blue mana");
add(lblBlue, constraints);
lblGreen = new DetailLabel(new ImageIcon("res/images/symbols-13/G.png"), "99");
lblGreen.setToolTipText("Green mana");
add(lblGreen, constraints);
lblRed = new DetailLabel(new ImageIcon("res/images/symbols-13/R.png"), "99");
lblRed.setToolTipText("Red mana");
add(lblRed, constraints);
lblWhite = new DetailLabel(new ImageIcon("res/images/symbols-13/W.png"), "99");
lblWhite.setToolTipText("White mana");
add(lblWhite, constraints);
lblColorless = new DetailLabel(new ImageIcon("res/images/symbols-13/X.png"), "99");
lblColorless.setToolTipText("Colorless mana");
add(lblColorless, constraints);
}
}
/**
* Used to show various values in "details" panel. Also increments
* grid bag constraints object as it goes, and zebra-stripes the labels.
*/
public class DetailLabel extends JLabel {
private final Dimension labelSize = new Dimension(40, 25);
private Color defaultBG;
private Color hoverBG;
private Color clrBorders;
private MouseAdapter madHover;
private int w, h;
/**
* Instance of JLabel detailing info about field:
* has icon and optional hover effect.
*
* @param icon &emsp; Label's icon
* @param txt &emsp; Label's text
*/
public DetailLabel(ImageIcon icon, String txt) {
super();
setIcon(icon);
setText(txt);
setOpaque(false);
setForeground(skin.getClrText());
setPreferredSize(labelSize);
setMaximumSize(labelSize);
setMinimumSize(labelSize);
setBorder(new LineBorder(new Color(0, 0, 0, 0), 1));
setHorizontalAlignment(CENTER);
// Increment counter and check for zebra. Set default BG
// so hover effects return to the same color.
counter++;
if (counter % 4 == 2 || counter % 4 == 3) {
defaultBG = skin.getClrZebra();
}
else {
defaultBG = skin.getClrTheme();
}
setBackground(defaultBG);
madHover = new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
setBackground(hoverBG);
clrBorders = skin.getClrBorders();
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(defaultBG);
clrBorders = transparent;
}
};
hoverBG = skin.getClrHover();
clrBorders = transparent;
}
/** Enable hover effects for this label. */
public void enableHover() {
addMouseListener(madHover);
}
/** Disable hover effects for this label. */
public void disableHover() {
removeMouseListener(madHover);
}
@Override
protected void paintComponent(Graphics g) {
w = getWidth();
h = getHeight();
g.setColor(getBackground());
g.fillRect(0, 0, w, h);
g.setColor(clrBorders);
g.drawRect(0, 0, w - 1, h - 1);
this.setFont(skin.getFont1().deriveFont(Font.PLAIN, (int) (h / 2)));
super.paintComponent(g);
}
}
private class KeywordLabel extends JLabel {
public KeywordLabel(String s) {
super(s);
setToolTipText(s);
}
}
/**
* Shows phase labels, handles repainting and on/off states. A PhaseLabel
* has "skip" and "active" states, meaning "this phase is (not) skipped"
* and "this is the current phase".
*/
public class PhaseLabel extends JLabel {
private boolean enabled = true;
private boolean active = false;
private boolean hover = false;
private Color hoverBG = AllZone.getSkin().getClrHover();
/**
* Shows phase labels, handles repainting and on/off states. A PhaseLabel
* has "skip" and "active" states, meaning "this phase is (not) skipped"
* and "this is the current phase".
*
* @param txt &emsp; Label text
*/
public PhaseLabel(String txt) {
super(txt);
this.setHorizontalTextPosition(CENTER);
this.setHorizontalAlignment(CENTER);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (enabled) { enabled = false; }
else { enabled = true; }
}
@Override
public void mouseEntered(MouseEvent e) {
hover = true;
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
hover = false;
repaint();
}
});
}
/**
* Determines whether play pauses at this phase or not.
*
* @param b &emsp; boolean, true if play pauses
*/
public void setEnabled(boolean b) {
enabled = b;
}
/**
* Determines whether play pauses at this phase or not.
*
* @return boolean
*/
public boolean getEnabled() {
return enabled;
}
/**
* Determines if this phase is the current phase (or not).
*
* @param b &emsp; boolean, true if phase is current
*/
public void setActive(boolean b) {
active = b;
}
/**
* Determines if this phase is the current phase (or not).
*
* @return boolean
*/
public boolean getActive() {
return active;
}
@Override
public void paintComponent(Graphics g) {
int w = getWidth();
int h = getHeight();
Color c;
// Set color according to skip or active or hover state of label
if (hover) {
c = hoverBG;
}
else if (enabled) {
c = Color.green;
}
else {
c = Color.red;
}
if (active && !hover) {
c = c.darker().darker();
}
// Center vertically and horizontally. Show border if active.
g.setColor(c);
g.fillRoundRect(1, 1, w - 2, h - 2, 5, 5);
setFont(new Font("TAHOMA", Font.PLAIN, (int) (w / 2)));
g.setColor(Color.black);
super.paintComponent(g);
}
}
}

View File

@@ -0,0 +1,171 @@
package forge.view.match;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.Card;
import forge.GuiDisplayUtil;
import forge.ImageCache;
import forge.control.match.ControlHand;
import forge.gui.skin.FRoundedPanel;
/**
* VIEW - Swing components for user hand.
*
*/
@SuppressWarnings("serial")
public class ViewHand extends JScrollPane {
private FRoundedPanel pnlContent;
private ControlHand control;
private List<CardPanel> cardPanels = new ArrayList<CardPanel>();
/**
* VIEW - Swing components for user hand.
*/
public ViewHand() {
super(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
setOpaque(false);
getViewport().setOpaque(false);
getHorizontalScrollBar().setUnitIncrement(16);
setBorder(null);
// After all components are in place, instantiate controller.
control = new ControlHand(this);
}
/** @return ControlHand */
public ControlHand getController() {
return control;
}
/**
* Rebuilds layout of the hand panel. Card panels are removed,
* the height and card aspect ratio are used to set layout column width,
* then card panels are added to the fresh layout.
*
*/
// This design choice was made to allow the functionality of a JPanel
// while maintaining a scale-able view. Overridden paint methods could
// do this, but require heavy coding.
public void refreshLayout() {
// Remove all panels and recalculate layout scaling based on aspect ratio.
pnlContent = new FRoundedPanel();
pnlContent.setBackground(AllZone.getSkin().getClrTheme());
pnlContent.setCorners(new boolean[] {true, false, false, true});
pnlContent.setLayout(new MigLayout("insets 3 10 3 10"));
pnlContent.setSize(getViewport().getSize());
pnlContent.validate();
this.setViewportView(pnlContent);
int h = getViewport().getHeight() - 6;
pnlContent.setLayout(new MigLayout("align center"));
// Re-insert panel instances. Possible memory management problem
// from re-adding pre-existing panels. Doublestrike 22-11-11
cardPanels = new ArrayList<CardPanel>();
for (Card c : control.getCards()) {
CardPanel temp = new CardPanel(c);
cardPanels.add(temp);
pnlContent.add(temp, "h " + h + "px!, w " + (int) (h * 0.7) + "px!");
control.addCardPanelListeners(temp);
}
// Notify system of change.
}
/**
*
*/
public class CardPanel extends JPanel {
private static final long serialVersionUID = 509877513760665415L;
private Card card = null;
private Image img;
private int w, h = 0;
/**
* <p>Constructor for CardPanel.</p>
*
* @param c &emsp; Card object.
*/
public CardPanel(Card c) {
super();
this.card = c;
this.img = ImageCache.getImage(card);
setToolTipText("<html>" + c.getName() + "<br>" + GuiDisplayUtil.formatCardType(c) + "</html>");
// No image?
if (img == null) {
setBorder(new LineBorder(new Color(240, 240, 240), 1));
setLayout(new MigLayout("wrap, insets 2, gap 0"));
setOpaque(true);
setBackground(new Color(200, 200, 200));
JLabel lblManaCost = new JLabel(c.getManaCost());
lblManaCost.setHorizontalAlignment(SwingConstants.RIGHT);
JLabel lblCardName = new JLabel(c.getName());
lblCardName.setHorizontalAlignment(SwingConstants.CENTER);
JLabel lblPowerToughness = new JLabel("");
lblPowerToughness.setHorizontalAlignment(SwingConstants.RIGHT);
if (c.isFaceDown()) {
lblCardName.setText("Morph");
lblManaCost.setText("");
}
if (c.isCreature()) {
lblPowerToughness.setText(c.getNetAttack() + " / " + c.getNetDefense());
}
add(lblManaCost, "w 90%!");
add(lblCardName, "w 90%!");
add(lblPowerToughness, "w 90%!, gaptop 25");
}
else {
setBorder(new LineBorder(Color.black, 1));
w = img.getWidth(null);
h = img.getHeight(null);
}
}
/** @return Card */
public Card getCard() {
return this.card;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, 0, 0, getWidth(), getHeight(), 0, 0, w, h, null);
}
else {
g.setColor(new Color(200, 200, 200));
g.drawRect(1, 1, getWidth(), getHeight());
}
}
}
/** @return List<CardPanel> */
public List<CardPanel> getCardPanels() {
return cardPanels;
}
}

View File

@@ -0,0 +1,79 @@
package forge.view.match;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JTextArea;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.control.match.ControlInput;
import forge.gui.skin.FButton;
import forge.gui.skin.FRoundedPanel;
import forge.gui.skin.FSkin;
/**
* Assembles Swing components of input area.
*
*/
@SuppressWarnings("serial")
public class ViewInput extends FRoundedPanel {
private ControlInput control;
private JButton btnOK, btnCancel;
private JTextArea tarMessage;
private FSkin skin;
/**
* Assembles UI for input area (buttons and message panel).
*
*/
public ViewInput() {
super();
skin = AllZone.getSkin();
setToolTipText("Input Area");
setBackground(skin.getClrTheme());
setForeground(skin.getClrText());
setCorners(new boolean[] {false, false, false, true});
setBorders(new boolean[] {true, false, false, true});
setLayout(new MigLayout("wrap 2, fill, insets 0, gap 0"));
// Cancel button
btnCancel = new FButton("Cancel");
btnOK = new FButton("OK");
tarMessage = new JTextArea();
tarMessage.setOpaque(false);
tarMessage.setFocusable(false);
tarMessage.setEditable(false);
tarMessage.setLineWrap(true);
tarMessage.setForeground(skin.getClrText());
tarMessage.setFont(skin.getFont1().deriveFont(Font.PLAIN, 12));
add(tarMessage, "span 2 1, h 80%!, w 96%!, gapleft 2%, gaptop 1%");
add(btnOK, "w 47%!, gapright 2%, gapleft 1%");
add(btnCancel, "w 47%!, gapright 1%");
// After all components are in place, instantiate controller.
control = new ControlInput(this);
}
/** @return ControlInput */
public ControlInput getController() {
return control;
}
/** @return JButton */
public JButton getBtnOK() {
return btnOK;
}
/** @return JButton */
public JButton getBtnCancel() {
return btnCancel;
}
/** @return JTextArea */
public JTextArea getTarMessage() {
return tarMessage;
}
}

View File

@@ -0,0 +1,501 @@
package forge.view.match;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.Constant;
import forge.MagicStack;
import forge.Player;
import forge.card.spellability.SpellAbilityStackInstance;
import forge.control.match.ControlTabber;
import forge.gui.MultiLineLabelUI;
import forge.gui.skin.FPanel;
import forge.gui.skin.FSkin;
import forge.view.toolbox.FVerticalTabPanel;
/**
* Vertical tab panel for viewing stack, combat, etc.
* Unfortunately, cannot extend a Swing component, since
* vertical tabs are generated dynamically in the constructor.
*
*/
public class ViewTabber {
private List<JPanel> panelList;
private HashMap<Player, JLabel[]> detailLabels;
private ControlTabber control;
private FSkin skin;
private FPanel pnlStack, pnlCombat, pnlConsole, pnlPlayers, pnlDev;
private DevLabel lblMilling, lblHandView, lblLibraryView, lblGenerateMana,
lblSetupGame, lblTutor, lblCounterPermanent, lblTapPermanent, lblUntapPermanent,
lblUnlimitedLands, lblHumanLife;
private FVerticalTabPanel vtpTabber;
/**
* Assembles Swing components for tabber area in sidebar.
*/
public ViewTabber() {
skin = AllZone.getSkin();
// Assemble card pic viewer
panelList = new ArrayList<JPanel>();
String constraints = "wrap, insets 0, gap 0";
pnlStack = new FPanel();
pnlStack.setName("Stack");
pnlStack.setOpaque(false);
pnlStack.setLayout(new MigLayout(constraints));
pnlStack.setToolTipText("View Stack");
panelList.add(pnlStack);
pnlCombat = new FPanel();
pnlCombat.setName("Combat");
pnlCombat.setOpaque(false);
pnlCombat.setLayout(new MigLayout(constraints));
pnlCombat.setToolTipText("View Combat");
panelList.add(pnlCombat);
pnlConsole = new FPanel();
pnlConsole.setName("Log");
pnlConsole.setOpaque(false);
pnlConsole.setLayout(new MigLayout(constraints));
pnlConsole.setToolTipText("View Console");
panelList.add(pnlConsole);
pnlPlayers = new FPanel();
pnlPlayers.setName("Players");
pnlPlayers.setOpaque(false);
pnlPlayers.setLayout(new MigLayout(constraints));
pnlPlayers.setToolTipText("Player List");
panelList.add(pnlPlayers);
pnlDev = new FPanel();
pnlDev.setName("Dev");
pnlDev.setOpaque(false);
pnlDev.setLayout(new MigLayout(constraints));
pnlDev.setToolTipText("Developer Mode");
if (Constant.Runtime.DEV_MODE[0]) {
panelList.add(pnlDev);
}
// Populate the various panels in the tabber.
populatePnlDev();
populatePnlPlayers();
populatePnlConsole();
vtpTabber = new FVerticalTabPanel(panelList);
vtpTabber.getContentPanel().setBorder(new MatteBorder(1, 0, 0, 1, skin.getClrBorders()));
// After all components are in place, instantiate controller.
control = new ControlTabber(this);
}
/** @return ControlTabber */
public ControlTabber getController() {
return control;
}
/**
* Removes and adds JTextAreas to stack panel, which briefly summarize the
* spell and allow mouseover.
*
*/
public void updateStack() {
final MagicStack stack = AllZone.getStack();
final ViewTopLevel t = (ViewTopLevel) AllZone.getDisplay();
int count = 1;
JTextArea tar;
String txt, isOptional;
pnlStack.removeAll();
vtpTabber.showTab(0);
Font font = skin.getFont1().deriveFont(Font.PLAIN, 11);
Border border = new MatteBorder(0, 0, 1, 0, Color.black);
for (int i = stack.size() - 1; 0 <= i; i--) {
isOptional = stack.peekAbility(i).isOptionalTrigger() && stack.peekAbility(i).getSourceCard().getController().isHuman() ? "(OPTIONAL) " : "";
txt = (count++) + ". " + isOptional + stack.peekInstance(i).getStackDescription();
tar = new JTextArea(txt);
tar.setToolTipText(txt);
tar.setOpaque(false);
tar.setBorder(border);
tar.setFont(font);
tar.setFocusable(false);
tar.setEditable(false);
tar.setLineWrap(true);
tar.setWrapStyleWord(true);
final SpellAbilityStackInstance spell = stack.peekInstance(i);
tar.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
t.getCardviewerController().showCard(spell.getSpellAbility().getSourceCard());
System.out.println();
}
});
pnlStack.add(tar, "w 100%!");
}
}
/**
* Removes and adds JTextAreas to combat panel, which briefly summarize the
* current combat situation.
*
* @param s &emsp; String message
*/
// Note: Can (should?) be easily retrofitted to fit stack-style reporting:
// multiple text areas, with mouseovers highlighting combat cards. Doublestrike 06-11-11
public void updateCombat(String s) {
pnlCombat.removeAll();
vtpTabber.showTab(1);
Font font = skin.getFont1().deriveFont(Font.PLAIN, 11);
Border border = new MatteBorder(1, 0, 0, 0, Color.black);
JTextArea tar = new JTextArea(s);
tar.setOpaque(false);
tar.setBorder(border);
tar.setFont(font);
tar.setFocusable(false);
tar.setLineWrap(true);
pnlCombat.add(tar, "h 100%!, w 100%!");
}
/** Updates labels in the "player" panel, which display non-critical details about
* each player in the game.
*
* @param p0 &emsp; Player obj
*/
public void updatePlayerLabels(Player p0) {
JLabel[] temp = detailLabels.get(p0);
temp[0].setText("Life: " + String.valueOf(p0.getLife()));
temp[1].setText("Max hand: " + String.valueOf(p0.getMaxHandSize()));
temp[2].setText("Draw per turn: " + String.valueOf(p0.getNumDrawnThisTurn()));
}
/** @return FVerticalTabPanel */
public FVerticalTabPanel getVtpTabber() {
return vtpTabber;
}
/** @return FPanel */
public FPanel getPnlStack() {
return pnlStack;
}
/** @return FPanel */
public FPanel getPnlCombat() {
return pnlCombat;
}
/** @return FPanel */
public FPanel getPnlPlayers() {
return pnlPlayers;
}
/** @return FPanel */
public FPanel getPnlDev() {
return pnlDev;
}
/** @return DevLabel */
public DevLabel getLblMilling() {
return lblMilling;
}
/** @return DevLabel */
public DevLabel getLblHandView() {
return lblHandView;
}
/** @return DevLabel */
public DevLabel getLblLibraryView() {
return lblLibraryView;
}
/** @return DevLabel */
public DevLabel getLblGenerateMana() {
return lblGenerateMana;
}
/** @return DevLabel */
public DevLabel getLblSetupGame() {
return lblSetupGame;
}
/** @return DevLabel */
public DevLabel getLblTutor() {
return lblTutor;
}
/** @return DevLabel */
public DevLabel getLblCounterPermanent() {
return lblCounterPermanent;
}
/** @return DevLabel */
public DevLabel getLblTapPermanent() {
return lblTapPermanent;
}
/** @return DevLabel */
public DevLabel getLblUntapPermanent() {
return lblUntapPermanent;
}
/** @return DevLabel */
public DevLabel getLblUnlimitedLands() {
return lblUnlimitedLands;
}
/** @return DevLabel */
public DevLabel getLblHumanLife() {
return lblHumanLife;
}
/** @return HashMap<Player, JLabel[]> */
public HashMap<Player, JLabel[]> getDetailLabels() {
return detailLabels;
}
/** Assembles Swing components for "players" panel. */
private void populatePnlPlayers() {
List<Player> players = AllZone.getPlayersInGame();
detailLabels = new HashMap<Player, JLabel[]>();
for (Player p : players) {
// Create and store labels detailing various non-critical player info.
InfoLabel name = new InfoLabel();
InfoLabel life = new InfoLabel();
InfoLabel hand = new InfoLabel();
InfoLabel draw = new InfoLabel();
detailLabels.put(p, new JLabel[] {life, hand, draw});
// Set border on bottom label, and larger font on player name
draw.setBorder(new MatteBorder(0, 0, 1, 0, skin.getClrBorders()));
name.setText(p.getName());
name.setFont(skin.getFont1().deriveFont(Font.PLAIN, 14));
// Add to "players" tab panel
String constraints = "w 97%!, gapleft 2%, gapbottom 1%";
pnlPlayers.add(name, constraints);
pnlPlayers.add(life, constraints);
pnlPlayers.add(hand, constraints);
pnlPlayers.add(draw, constraints);
}
}
/** Assembles Swing components for "dev mode" panel. */
private void populatePnlDev() {
JPanel viewport = new JPanel();
viewport.setLayout(new MigLayout("wrap, insets 0"));
viewport.setOpaque(false);
JScrollPane jsp = new JScrollPane(viewport, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jsp.setOpaque(false);
jsp.getViewport().setOpaque(false);
pnlDev.add(jsp, "w 100%!, h 100%!");
lblMilling = new DevLabel("Loss by Milling: Enabled", "Loss by Milling: Disabled");
lblHandView = new DevLabel("View Any Hand: Enabled", "View Any Hand: Disabled");
lblLibraryView = new DevLabel("View Any Library: Enabled", "View Any Library: Disabled");
lblGenerateMana = new DevLabel("Generate Mana");
lblSetupGame = new DevLabel("Setup Game State");
lblTutor = new DevLabel("Tutor for card");
lblCounterPermanent = new DevLabel("Add Counter to Permanent");
lblTapPermanent = new DevLabel("Tap Permanent");
lblUntapPermanent = new DevLabel("Untap Permanent");
lblUnlimitedLands = new DevLabel("Play Unlimited Lands This Turn");
lblHumanLife = new DevLabel("Set Player Life");
String constraints = "w 100%!, gap 0 0 5px 0";
viewport.add(lblMilling, constraints);
viewport.add(lblHandView, constraints);
viewport.add(lblLibraryView, constraints);
viewport.add(lblGenerateMana, constraints);
viewport.add(lblSetupGame, constraints);
viewport.add(lblTutor, constraints);
viewport.add(lblCounterPermanent, constraints);
viewport.add(lblTapPermanent, constraints);
viewport.add(lblUntapPermanent, constraints);
viewport.add(lblUnlimitedLands, constraints);
viewport.add(lblHumanLife, constraints);
}
/** Assembles swing components for "console" panel. */
private void populatePnlConsole() {
JLabel prompt = new JLabel("IN > ");
JTextField input = new JTextField();
JTextArea log = new JTextArea();
log.setBackground(new Color(0, 0, 0, 20));
log.setWrapStyleWord(true);
log.setLineWrap(true);
log.setWrapStyleWord(true);
log.setEditable(false);
log.setFocusable(false);
log.setForeground(skin.getClrText());
log.setFont(skin.getFont1().deriveFont(Font.PLAIN, 12));
log.setBorder(new MatteBorder(1, 0, 0, 0, skin.getClrBorders()));
log.setText("Not implemented yet. Input codes entered above. "
+ "Output data recorded below.");
pnlConsole.setLayout(new MigLayout("insets 0, gap 0, wrap 2"));
pnlConsole.add(prompt, "w 28%!, h 10%!, gapleft 2%, gaptop 2%, gapbottom 2%");
pnlConsole.add(input, "w 68%!, gapright 2%, gaptop 2%, gapbottom 2%");
pnlConsole.add(log, "w 94%!, h 80%!, gapleft 4%, span 2 1");
}
/**
* Labels that act as buttons which control dev mode functions. Labels
* are used to support multiline text.
*
*/
public class DevLabel extends JLabel {
private static final long serialVersionUID = 7917311680519060700L;
private Color defaultBG = Color.green;
private Color hoverBG = skin.getClrHover();
private boolean enabled;
private String enabledText, disabledText;
private int w, h, r, i; // Width, height, radius, insets (for paintComponent)
/**
* Labels that act as buttons which control dev mode functions. Labels
* are used (instead of buttons) to support multiline text.
*
* Constructor for DevLabel which doesn't use enabled/disabled states;
* only single text string required.
*
* @param s0 &emsp; String text/tooltip of label
*/
public DevLabel(String s0) {
this(s0, s0);
}
/**
* Labels that act as buttons which control dev mode functions. Labels
* are used (instead of buttons) to support multiline text.
*
* This constructor for DevLabels empowers an "enable" state that
* displays them as green (enabled) or red (disabled).
*
* @param en0 &emsp; String text/tooltip of label, in "enabled" state
* @param dis0 &emsp; String text/tooltip of label, in "disabled" state
*/
public DevLabel(String en0, String dis0) {
super();
this.setUI(MultiLineLabelUI.getLabelUI());
this.setFont(skin.getFont1().deriveFont(Font.PLAIN, 11));
this.setBorder(new EmptyBorder(5, 5, 5, 5));
this.enabledText = en0;
this.disabledText = dis0;
this.r = 6; // Radius (for paintComponent)
this.i = 2; // Insets (for paintComponent)
setEnabled(true);
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
setBackground(hoverBG);
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(defaultBG);
}
});
}
/**
* Changes enabled state per boolean parameter, automatically updating
* text string and background color.
*
* @param b &emsp; boolean
*/
public void setEnabled(boolean b) {
String s;
if (b) {
defaultBG = Color.green;
s = enabledText;
}
else {
defaultBG = Color.red;
s = disabledText;
}
enabled = b;
this.setText(s);
this.setToolTipText(s);
this.setBackground(defaultBG);
}
/** @return boolean */
public boolean getEnabled() {
return enabled;
}
/**
* In many cases, a DevLabel state will just be toggling a boolean.
* This method sets up and evaluates the condition and toggles as appropriate.
*
*/
public void toggleEnabled() {
if (enabled) {
setEnabled(false);
}
else {
setEnabled(true);
}
}
@Override
protected void paintComponent(Graphics g) {
w = getWidth();
h = getHeight();
g.setColor(this.getBackground());
g.fillRoundRect(i, i, w - 2 * i, h - i, r, r);
super.paintComponent(g);
}
}
/** A quick JLabel for info in "players" panel, to consolidate styling. */
@SuppressWarnings("serial")
private class InfoLabel extends JLabel {
public InfoLabel() {
super();
this.setFont(skin.getFont1().deriveFont(Font.PLAIN, 11));
this.setForeground(skin.getClrText());
}
}
}

View File

@@ -0,0 +1,453 @@
package forge.view.match;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextArea;
import forge.AllZone;
import forge.Card;
import forge.CardList;
import forge.Constant;
import forge.Display;
import forge.MyButton;
import forge.Player;
import forge.Singletons;
import forge.control.ControlMatchUI;
import forge.control.match.ControlCardviewer;
import forge.control.match.ControlDock;
import forge.control.match.ControlField;
import forge.control.match.ControlHand;
import forge.control.match.ControlInput;
import forge.control.match.ControlTabber;
import forge.gui.skin.FPanel;
import forge.properties.ForgePreferences;
/**
* - Lays out battle, sidebar, user areas in locked % vals and repaints
* as necessary.<br>
* - Instantiates top-level controller for match UI.<br>
* - Has access methods for all child controllers<br>
* - Implements Display interface used in singleton pattern
*
*/
@SuppressWarnings("serial")
public class ViewTopLevel extends FPanel implements Display {
private ViewAreaSidebar areaSidebar;
private ViewAreaBattlefield areaBattle;
private ViewAreaUser areaUser;
private int w, h;
private static final double SIDEBAR_W_PCT = 0.16;
private static final double USER_H_PCT = 0.27;
private ControlMatchUI control;
/**
* - Lays out battle, sidebar, user areas in locked % vals and repaints
* as necessary.<br>
* - Instantiates top-level controller for match UI.<br>
* - Has access methods for all child controllers<br>
* - Implements Display interface used in singleton pattern
*
*/
public ViewTopLevel() {
super();
// Set properties
setOpaque(false);
setBGTexture(AllZone.getSkin().getTexture1());
setBGImg(AllZone.getSkin().getMatchBG());
setLayout(null);
// areaBattle: holds fields for all players in match.
areaBattle = new ViewAreaBattlefield();
areaBattle.setBounds(0, 0, getWidth() / 2, getHeight() / 2);
add(areaBattle);
// areaSidebar: holds card detail, info tabber.
areaSidebar = new ViewAreaSidebar();
areaSidebar.setBounds(0, 0, getWidth() / 2, getHeight() / 2);
add(areaSidebar);
// areaUser: holds input, hand, dock.
areaUser = new ViewAreaUser();
areaUser.setBounds(0, 0, getWidth() / 2, getHeight() / 2);
add(areaUser);
// After all components are in place, instantiate controller.
control = new ControlMatchUI(this);
}
/**
* The null layout used in MatchFrame has zones split into percentage values
* to prevent child components pushing around the parent layout. A single
* instance of BodyPanel holds these zones, and handles the percentage resizing.
*
* @param g &emsp; Graphics object
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
w = getWidth();
h = getHeight();
// Set % boundaries of layout control layer
areaBattle.setBounds(0, 0, (int) (w * (1 - SIDEBAR_W_PCT)),
(int) (h * (1 - USER_H_PCT)));
areaSidebar.setBounds((int) (w * (1 - SIDEBAR_W_PCT)), 0,
(int) (w * SIDEBAR_W_PCT), h);
areaUser.setBounds(0, (int) (h * (1 - USER_H_PCT)),
(int) (w * (1 - SIDEBAR_W_PCT)), (int) (h * USER_H_PCT));
areaBattle.validate();
}
//========== Retrieval functions for easier interation with children panels.
/** @return ViewAreaSidebar */
public ViewAreaSidebar getAreaSidebar() {
return areaSidebar;
}
/** @return ViewAreaBattlefield */
public ViewAreaBattlefield getAreaBattlefield() {
return areaBattle;
}
/** @return ViewAreaUser */
public ViewAreaUser getAreaUser() {
return areaUser;
}
/**
* Retrieves top level controller (actions, observers, etc.)
* for this UI.
*
* @return {@link java.util.List<MatchPlayer>}
*/
public ControlMatchUI getController() {
return control;
}
/** @return ControlCardviewer */
public ControlCardviewer getCardviewerController() {
return areaSidebar.getCardviewer().getController();
}
/** @return ControlTabber */
public ControlTabber getTabberController() {
return areaSidebar.getTabber().getController();
}
/** @return ControlInput */
public ControlInput getInputController() {
return areaUser.getPnlInput().getController();
}
/** @return ControlHand */
public ControlHand getHandController() {
return areaUser.getPnlHand().getController();
}
/** @return ControlDock */
public ControlDock getDockController() {
return areaUser.getPnlDock().getController();
}
/** @return List<ControlField> */
public List<ControlField> getFieldControllers() {
List<ViewField> fields = areaBattle.getFields();
List<ControlField> controllers = new ArrayList<ControlField>();
for (ViewField f : fields) {
controllers.add(f.getController());
}
return controllers;
}
/** @return List<ViewField> */
public List<ViewField> getFieldViews() {
return areaBattle.getFields();
}
//========== Input panel and human hand retrieval functions
// Also due to be deprecated. Access should be handled by child component
// view and/or controller.
/** @return <b>JTextArea</b> Message area of input panel. */
public JTextArea getPnlMessage() {
return areaUser.getPnlInput().getTarMessage();
}
/** @return <b>ViewHand</b> Retrieves player hand panel. */
public ViewHand getPnlHand() {
return areaUser.getPnlHand();
}
//========== The following methods are required by the Display interface.
// To fit the UI MVC architecture with the previous "mixed nuts" architecture,
// these methods are temporarily required. However, since they are a mix of
// view and control functionalities, they are ALL on the "to-be-deprecated" list.
// The Display interface is to be reworked, eventually, with a better name
// and with interfaces for every screen in the entire UI.
// Doublestrike 23-10-11
/**
* Required by Display interface.
* Due to be deprecated in favor of more semantic getBtnCancel().
*
* @return MyButton
*/
public MyButton getButtonCancel() {
MyButton cancel = new MyButton() {
public void select() {
getInputController().getInputControl().selectButtonCancel();
}
public boolean isSelectable() {
return areaUser.getPnlInput().getBtnCancel().isEnabled();
}
public void setSelectable(final boolean b) {
areaUser.getPnlInput().getBtnCancel().setEnabled(b);
}
public String getText() {
return areaUser.getPnlInput().getBtnCancel().getText();
}
public void setText(final String text) {
areaUser.getPnlInput().getBtnCancel().setText(text);
}
public void reset() {
areaUser.getPnlInput().getBtnCancel().setText("Cancel");
}
};
return cancel;
}
/**
* Required by Display interface.
* Due to be deprecated in favor of more semantic getBtnOK().
*
* @return MyButton
*/
public MyButton getButtonOK() {
MyButton ok = new MyButton() {
public void select() {
getInputController().getInputControl().selectButtonOK();
}
public boolean isSelectable() {
return areaUser.getPnlInput().getBtnOK().isEnabled();
}
public void setSelectable(final boolean b) {
areaUser.getPnlInput().getBtnOK().setEnabled(b);
}
public String getText() {
return areaUser.getPnlInput().getBtnOK().getText();
}
public void setText(final String text) {
areaUser.getPnlInput().getBtnOK().setText(text);
}
public void reset() {
areaUser.getPnlInput().getBtnOK().setText("OK");
}
};
return ok;
}
/**
* Required by Display interface.
* Due to be deprecated: is now and should be handled by ControlMatchUI.
*
* @param s &emsp; Message string
*/
public void showMessage(String s) {
getPnlMessage().setText(s);
}
/**
* Required by Display interface.
* Due to be deprecated: should be handled by ControlMatchUI.
*
* @param s &emsp; Message string
*/
public void showCombat(String s) {
getTabberController().getView().updateCombat(s);
}
/**
* Required by Display interface.
* Due to be deprecated: should be handled by a control class, and
* poorly named; "decking" == "milling" in preferences, same terminology
* should be used throughout project for obvious reasons. Unless "decking"
* is already the correct terminology, in which case, everything else is
* poorly named.
*
* @return boolean
*/
public boolean canLoseByDecking() {
return Constant.Runtime.MILL[0];
}
/**
* <p>loadPrefs.</p>
* Required by Display interface.
* Due to be deprecated: will be handled by ControlMatchUI.
*
*
* @return boolean.
*/
public final boolean loadPrefs() {
ForgePreferences fp = Singletons.getModel().getPreferences();
List<ViewField> fieldViews = getFieldViews();
// AI field is at index [0]
fieldViews.get(0).getLblUpkeep().setEnabled(fp.isbAIUpkeep());
fieldViews.get(0).getLblDraw().setEnabled(fp.isbAIDraw());
fieldViews.get(0).getLblEndTurn().setEnabled(fp.isbAIEOT());
fieldViews.get(0).getLblBeginCombat().setEnabled(fp.isbAIBeginCombat());
fieldViews.get(0).getLblEndCombat().setEnabled(fp.isbAIEndCombat());
// Human field is at index [1]
fieldViews.get(1).getLblUpkeep().setEnabled(fp.isbHumanUpkeep());
fieldViews.get(1).getLblDraw().setEnabled(fp.isbHumanDraw());
fieldViews.get(1).getLblEndTurn().setEnabled(fp.isbHumanEOT());
fieldViews.get(1).getLblBeginCombat().setEnabled(fp.isbHumanBeginCombat());
fieldViews.get(1).getLblEndCombat().setEnabled(fp.isbHumanEndCombat());
return true;
}
/**
* <p>savePrefs.</p>
* Required by Display interface.
* Due to be deprecated: will be handled by ControlMatchUI.
* Also, this functionality is already performed elsewhere in the code base.
* Furthermore, there's a strong possibility this will need bo be broken
* down and can't be in one place - e.g. keyboard shortcuts are
* saved after they're edited.
*
* @return a boolean.
*/
public final boolean savePrefs() {
ForgePreferences fp = Singletons.getModel().getPreferences();
List<ViewField> fieldViews = getFieldViews();
// AI field is at index [0]
fp.setbAIUpkeep(fieldViews.get(0).getLblUpkeep().getEnabled());
fp.setbAIDraw(fieldViews.get(0).getLblDraw().getEnabled());
fp.setbAIEOT(fieldViews.get(0).getLblEndTurn().getEnabled());
fp.setbAIBeginCombat(fieldViews.get(0).getLblBeginCombat().getEnabled());
fp.setbAIEndCombat(fieldViews.get(0).getLblEndCombat().getEnabled());
// Human field is at index [1]
fp.setbHumanUpkeep(fieldViews.get(1).getLblUpkeep().getEnabled());
fp.setbHumanDraw(fieldViews.get(1).getLblDraw().getEnabled());
fp.setbHumanEOT(fieldViews.get(1).getLblEndTurn().getEnabled());
fp.setbHumanBeginCombat(fieldViews.get(1).getLblBeginCombat().getEnabled());
fp.setbHumanEndCombat(fieldViews.get(1).getLblEndCombat().getEnabled());
Constant.Runtime.MILL[0] = this.getTabberController().getView().getLblMilling().getEnabled();
Constant.Runtime.HANDVIEW[0] = this.getTabberController().getView().getLblHandView().getEnabled();
Constant.Runtime.LIBRARYVIEW[0] = this.getTabberController().getView().getLblLibraryView().getEnabled();
fp.setMillingLossCondition(Constant.Runtime.MILL[0]);
fp.setHandView(Constant.Runtime.HANDVIEW[0]);
fp.setLibraryView(Constant.Runtime.LIBRARYVIEW[0]);
return true;
}
/**
* <p>stopAtPhase.</p>
* Required by Display interface.
* Due to be deprecated: should be handled by control class.
*
* @param turn &emsp; Player object...more info needed
* @param phase &emsp; A string...more info needed
* @return a boolean.
*/
public final boolean stopAtPhase(final Player turn, final String phase) {
List<ControlField> fieldControllers = getFieldControllers();
// AI field is at index [0]
if (turn.isComputer()) {
if (phase.equals(Constant.Phase.END_OF_TURN)) {
return fieldControllers.get(0).getView().getLblEndTurn().getEnabled();
} else if (phase.equals(Constant.Phase.UPKEEP)) {
return fieldControllers.get(0).getView().getLblUpkeep().getEnabled();
} else if (phase.equals(Constant.Phase.DRAW)) {
return fieldControllers.get(0).getView().getLblDraw().getEnabled();
} else if (phase.equals(Constant.Phase.COMBAT_BEGIN)) {
return fieldControllers.get(0).getView().getLblBeginCombat().getEnabled();
} else if (phase.equals(Constant.Phase.COMBAT_END)) {
return fieldControllers.get(0).getView().getLblEndCombat().getEnabled();
}
}
// Human field is at index [1]
else {
if (phase.equals(Constant.Phase.END_OF_TURN)) {
return fieldControllers.get(1).getView().getLblEndTurn().getEnabled();
} else if (phase.equals(Constant.Phase.UPKEEP)) {
return fieldControllers.get(1).getView().getLblUpkeep().getEnabled();
} else if (phase.equals(Constant.Phase.DRAW)) {
return fieldControllers.get(1).getView().getLblDraw().getEnabled();
} else if (phase.equals(Constant.Phase.COMBAT_BEGIN)) {
return fieldControllers.get(1).getView().getLblBeginCombat().getEnabled();
} else if (phase.equals(Constant.Phase.COMBAT_END)) {
return fieldControllers.get(1).getView().getLblEndCombat().getEnabled();
}
}
return true;
}
/**
* Required by display interface.
* Due to be deprecated: handled by control class.
*
* @return a {@link forge.Card} object.
*/
public final Card getCard() {
System.err.println("ViewTopLevel > getCard: Something should happen here!");
new Exception().printStackTrace();
return null; //new Card(); //detail.getCard();
}
/**
* Required by display interface.
* Due to be deprecated: already handled by controller class.
*
* @param card &emsp; a card
*/
public final void setCard(final Card card) {
System.err.println("ViewTopLevel > getCard: Something should happen here!");
new Exception().printStackTrace();
}
/**
* Required by Display interface.
* Assigns damage to multiple blockers.
* Due to be deprecated: Gui_MultipleBlockers4 says "very hacky"; needs
* rewriting.
*
* @param attacker &emsp; Card object
* @param blockers &emsp; Card objects in CardList form
* @param damage &emsp; int
*/
public final void assignDamage(final Card attacker, final CardList blockers, final int damage) {
if (damage <= 0) {
return;
}
//new Gui_MultipleBlockers4(attacker, blockers, damage, this);
}
}

View File

@@ -97,7 +97,7 @@ public class ApplicationView implements FView {
final ForgePreferences preferences = model.getPreferences();
OldGuiNewGame.getUseLAFFonts().setSelected(preferences.isLafFonts());
// newGuiCheckBox.setSelected(preferences.newGui);
OldGuiNewGame.getOldGuiCheckBox().setSelected(preferences.isOldGui());
OldGuiNewGame.getSmoothLandCheckBox().setSelected(preferences.isStackAiLand());
OldGuiNewGame.getDevModeCheckBox().setSelected(preferences.isDeveloperMode());
OldGuiNewGame.getCardOverlay().setSelected(preferences.isCardOverlay());

View File

@@ -59,6 +59,7 @@ import forge.ImageCache;
import forge.MyRandom;
import forge.PlayerType;
import forge.Singletons;
import forge.control.ControlAllUI;
import forge.deck.Deck;
import forge.deck.DeckGeneration;
import forge.deck.DeckManager;
@@ -124,8 +125,8 @@ public class OldGuiNewGame extends JFrame {
// @SuppressWarnings("unused")
// titledBorder2
/** Constant <code>newGuiCheckBox</code>. */
// private static JCheckBox newGuiCheckBox = new JCheckBox("", true);
/** Constant <code>oldGuiCheckBox</code>. */
private static JCheckBox oldGuiCheckBox = new JCheckBox("", false);
/** Constant <code>smoothLandCheckBox</code>. */
private static JCheckBox smoothLandCheckBox = new JCheckBox("", false);
/** Constant <code>devModeCheckBox</code>. */
@@ -556,7 +557,7 @@ public class OldGuiNewGame extends JFrame {
ForgeProps.getLocalized(NewConstants.Lang.OldGuiNewGame.NewGameText.SETTINGS));
this.jPanel3.setLayout(new MigLayout("align center"));
// newGuiCheckBox.setText(ForgeProps.getLocalized(NEW_GAME_TEXT.NEW_GUI));
oldGuiCheckBox.setText(ForgeProps.getLocalized(NewConstants.Lang.OldGuiNewGame.NewGameText.OLD_GUI));
OldGuiNewGame.getSmoothLandCheckBox().setText(
ForgeProps.getLocalized(NewConstants.Lang.OldGuiNewGame.NewGameText.AI_LAND));
@@ -639,7 +640,7 @@ public class OldGuiNewGame extends JFrame {
this.getContentPane().add(this.jPanel3, "span 2, grow");
// jPanel3.add(newGuiCheckBox, "wrap");
jPanel3.add(oldGuiCheckBox, "wrap");
this.jPanel3.add(OldGuiNewGame.getSmoothLandCheckBox(), "wrap");
this.jPanel3.add(OldGuiNewGame.getDevModeCheckBox(), "wrap");
this.jPanel3.add(OldGuiNewGame.getUpldDrftCheckBox(), "wrap");
@@ -865,15 +866,19 @@ public class OldGuiNewGame extends JFrame {
}
} // else
// DO NOT CHANGE THIS ORDER, GuiDisplay needs to be created before cards
// are added
// Constant.Runtime.DevMode[0] = devModeCheckBox.isSelected();
Constant.Runtime.OLDGUI[0] = oldGuiCheckBox.isSelected();
// if (newGuiCheckBox.isSelected())
if (Constant.Runtime.OLDGUI[0]) {
AllZone.setDisplay(new GuiDisplay());
// else AllZone.setDisplay(new GuiDisplay3());
}
else {
ControlAllUI ui = new ControlAllUI();
AllZone.setDisplay(ui.getMatchView());
ui.getMatchController().initMatch();
}
Constant.Runtime.SMOOTH[0] = OldGuiNewGame.getSmoothLandCheckBox().isSelected();
//Constant.Runtime.DEV_MODE[0] = OldGuiNewGame.devModeCheckBox.isSelected();
AllZone.getGameAction().newGame(Constant.Runtime.HUMAN_DECK[0], Constant.Runtime.COMPUTER_DECK[0]);
AllZone.getDisplay().setVisible(true);
@@ -1714,7 +1719,7 @@ public class OldGuiNewGame extends JFrame {
final ForgePreferences preferences = Singletons.getModel().getPreferences();
preferences.setLaf(UIManager.getLookAndFeel().getClass().getName());
preferences.setLafFonts(OldGuiNewGame.getUseLAFFonts().isSelected());
// preferences.newGui = newGuiCheckBox.isSelected();
preferences.setOldGui(oldGuiCheckBox.isSelected());
preferences.setStackAiLand(OldGuiNewGame.getSmoothLandCheckBox().isSelected());
preferences.setMillingLossCondition(Constant.Runtime.MILL[0]);
preferences.setDeveloperMode(Constant.Runtime.DEV_MODE[0]);
@@ -2000,4 +2005,8 @@ public class OldGuiNewGame extends JFrame {
// name.
}
/** @return JCheckBox */
public static JCheckBox getOldGuiCheckBox() {
return OldGuiNewGame.oldGuiCheckBox;
}
}

View File

@@ -69,7 +69,7 @@ public class SplashFrame extends JFrame {
this.setUndecorated(true);
// Set preferred JFrame properties.
final ImageIcon bgIcon = skin.getSplash();
final ImageIcon bgIcon = skin.getSplashBG();
final int splashWidthPx = bgIcon.getIconWidth();
final int splashHeightPx = bgIcon.getIconHeight();

View File

@@ -17,6 +17,7 @@ import javax.swing.border.AbstractBorder;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.Constant;
import forge.Phase;
import forge.Player;
import forge.gui.skin.FButton;
@@ -24,6 +25,7 @@ import forge.gui.skin.FPanel;
import forge.properties.ForgeProps;
import forge.properties.NewConstants.Lang.WinLoseFrame.WinLoseText;
import forge.quest.data.QuestMatchState;
import forge.view.match.ViewTopLevel;
/**
* <p>
@@ -88,7 +90,7 @@ public class WinLoseFrame extends JFrame {
// Place all content in FPanel
final FPanel contentPanel = new FPanel(new MigLayout("wrap, fill, insets 20 0 10 10"));
contentPanel.setBGImg(AllZone.getSkin().getTexture1());
contentPanel.setBGTexture(AllZone.getSkin().getTexture1());
contentPanel.setBorder(new WinLoseBorder());
this.getContentPane().add(contentPanel);
@@ -271,8 +273,17 @@ public class WinLoseFrame extends JFrame {
* @return {@link javax.swing.JFrame} display frame
*/
final JFrame closeWinLoseFrame() {
JFrame frame;
// Issue 147 - keep battlefield up following win/loss
final JFrame frame = (JFrame) AllZone.getDisplay();
if (Constant.Runtime.OLDGUI[0]) {
frame = (JFrame) AllZone.getDisplay();
}
else {
ViewTopLevel temp = (ViewTopLevel) AllZone.getDisplay();
frame = (JFrame) temp.getParent().getParent().getParent().getParent();
}
frame.dispose();
frame.setEnabled(true);
this.dispose();

View File

@@ -0,0 +1,382 @@
package forge.view.toolbox;
import java.awt.Color;
import java.awt.Font;
import java.util.Iterator;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.Card;
import forge.CardContainer;
import forge.Constant.Zone;
import forge.Counters;
import forge.GameEntity;
import forge.GuiDisplayUtil;
import forge.gui.skin.FSkin;
/** Shows details of card if moused over. */
@SuppressWarnings("serial")
public class CardDetailPanel extends JPanel implements CardContainer {
private Card card = null;
private JLabel lblCardName, lblCardCost, lblCardType,
lblCardID, lblCardPT, lblCardSet, lblCardDmg1, lblCardDmg2;
private JTextArea tarInfo;
private static final Color PURPLE = new Color(14381203);
private FSkin skin;
private Font f;
private Color foreground;
private Color zebra;
/** */
public CardDetailPanel() {
super();
setLayout(new MigLayout("wrap, insets 0, gap 0"));
// Styles used in DetailLabel class
skin = AllZone.getSkin();
f = skin.getFont1().deriveFont(Font.PLAIN, 11);
foreground = skin.getClrText();
zebra = skin.getClrZebra();
// DetailLabel instances (true = zebra stripe)
lblCardName = new DetailLabel();
lblCardCost = new DetailLabel();
lblCardType = new DetailLabel();
lblCardPT = new DetailLabel();
lblCardDmg1 = new DetailLabel();
lblCardDmg2 = new DetailLabel();
lblCardID = new DetailLabel();
lblCardSet = new DetailLabel();
// Info text area
tarInfo = new JTextArea();
tarInfo.setFont(f);
tarInfo.setLineWrap(true);
tarInfo.setWrapStyleWord(true);
tarInfo.setFocusable(false);
add(lblCardName, "w 100%!");
add(lblCardCost, "w 100%!");
add(lblCardType, "w 100%!");
add(lblCardPT, "w 100%!");
add(lblCardDmg1, "w 100%!");
add(lblCardDmg2, "w 100%!");
add(lblCardID, "w 100%!");
add(lblCardSet, "w 100%!");
add(new JScrollPane(tarInfo,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER), "w 100%!, h 45%!, south");
setCard(card);
}
/**
* A fairly long method testing conditions determining which details to show.
*
* @param c &emsp; Card obj
*/
public void setCard(Card c) {
lblCardName.setText(" ");
lblCardCost.setText(" ");
lblCardType.setText(" ");
lblCardPT.setText(" ");
lblCardDmg1.setText(" ");
lblCardDmg2.setText(" ");
lblCardID.setText(" ");
lblCardSet.setText(" ");
lblCardSet.setOpaque(true);
lblCardSet.setBorder(null);
tarInfo.setText(" ");
this.card = c;
if (card == null) {
return;
}
boolean faceDown = card.isFaceDown() && card.getController() != AllZone.getHumanPlayer();
if (!faceDown) {
lblCardName.setText(card.getName());
if (!card.getManaCost().equals("") && !card.isLand()) {
lblCardCost.setText(card.getManaCost());
}
}
else {
lblCardName.setText("Morph");
}
if (!faceDown) {
lblCardType.setText(GuiDisplayUtil.formatCardType(card));
}
else {
lblCardType.setText("Creature");
}
if (card.isCreature()) {
lblCardPT.setText(card.getNetAttack() + " / " + card.getNetDefense());
lblCardDmg1.setText("Damage: " + card.getDamage());
lblCardDmg2.setText("Assigned Damage: " + card.getTotalAssignedDamage());
}
if (card.isPlaneswalker()) {
lblCardDmg2.setText("Assigned Damage: " + card.getTotalAssignedDamage());
}
lblCardID.setText("Card ID " + card.getUniqueNumber());
// Rarity and set of a face down card should not be visible to the opponent
if (!card.isFaceDown() || card.getController().isHuman()) {
String s = card.getCurSetCode();
if (s.equals("")) {
lblCardSet.setText("---");
}
else {
lblCardSet.setText(s);
}
}
String csr = card.getCurSetRarity();
if (csr.equals("Common") || csr.equals("Land")) {
lblCardSet.setBackground(Color.BLACK);
lblCardSet.setForeground(Color.WHITE);
//lblCardSet.setBorder(BorderFactory.createLineBorder(Color.WHITE));
} else if (csr.equals("Uncommon")) {
lblCardSet.setBackground(Color.LIGHT_GRAY);
lblCardSet.setForeground(Color.BLACK);
//lblCardSet.setBorder(BorderFactory.createLineBorder(Color.BLACK));
} else if (csr.equals("Rare")) {
lblCardSet.setBackground(Color.YELLOW);
lblCardSet.setForeground(Color.BLACK);
//lblCardSet.setBorder(BorderFactory.createLineBorder(Color.BLACK));
} else if (csr.equals("Mythic")) {
lblCardSet.setBackground(Color.RED);
lblCardSet.setForeground(Color.BLACK);
//lblCardSet.setBorder(BorderFactory.createLineBorder(Color.BLACK));
} else if (csr.equals("Special")) {
// "Timeshifted" or other Special Rarity Cards
lblCardSet.setBackground(PURPLE);
lblCardSet.setForeground(Color.BLACK);
//lblCardSet.setBorder(BorderFactory.createLineBorder(Color.BLACK));
}
// Fill the card text
StringBuilder str = new StringBuilder();
// Token
if (card.isToken()) { str.append("Token"); }
if (!faceDown) {
if (str.length() != 0) { str.append("\n"); }
String text = card.getText();
//LEVEL [0-9]+-[0-9]+
//LEVEL [0-9]+\+
String regex = "LEVEL [0-9]+-[0-9]+ ";
text = text.replaceAll(regex, "$0\r\n");
regex = "LEVEL [0-9]+\\+ ";
text = text.replaceAll(regex, "\r\n$0\r\n");
// Displays keywords that have dots in them a little better:
regex = "\\., ";
text = text.replaceAll(regex, ".\r\n");
str.append(text);
}
// Phasing
if (card.isPhasedOut()) {
if (str.length() != 0) { str.append("\n"); }
str.append("Phased Out");
}
// Counter text
Counters[] counters = Counters.values();
for (Counters counter : counters) {
if (card.getCounters(counter) != 0) {
if (str.length() != 0) { str.append("\n"); }
str.append(counter.getName() + " counters: ");
str.append(card.getCounters(counter));
}
}
// Regeneration Shields
int regenShields = card.getShield();
if (regenShields > 0) {
if (str.length() != 0) { str.append("\n"); }
str.append("Regeneration Shield(s): ").append(regenShields);
}
// Damage Prevention
int preventNextDamage = card.getPreventNextDamage();
if (preventNextDamage > 0) {
str.append("\n");
str.append("Prevent the next ").append(preventNextDamage).append(" damage that would be dealt to ");
str.append(card.getName()).append(" it this turn.");
}
// Top revealed
if (card.hasKeyword("Play with the top card of your library revealed.") && card.getController() != null
&& !card.getController().getZone(Zone.Library).isEmpty()) {
str.append("\r\nTop card: ");
str.append(card.getController().getCardsIn(Zone.Library, 1));
}
// Chosen type
if (card.getChosenType() != "") {
if (str.length() != 0) { str.append("\n"); }
str.append("(chosen type: ");
str.append(card.getChosenType());
str.append(")");
}
// Chosen color
if (!card.getChosenColor().isEmpty()) {
if (str.length() != 0) { str.append("\n"); }
str.append("(chosen colors: ");
str.append(card.getChosenColor());
str.append(")");
}
// Named card
if (card.getNamedCard() != "") {
if (str.length() != 0) { str.append("\n"); }
str.append("(named card: ");
str.append(card.getNamedCard());
str.append(")");
}
// Equipping
if (card.getEquipping().size() > 0) {
if (str.length() != 0) { str.append("\n"); }
str.append("=Equipping ");
str.append(card.getEquipping().get(0));
str.append("=");
}
// Equipped by
if (card.getEquippedBy().size() > 0) {
if (str.length() != 0) { str.append("\n"); }
str.append("=Equipped by ");
for (Iterator<Card> it = card.getEquippedBy().iterator(); it.hasNext();) {
str.append(it.next());
if (it.hasNext()) { str.append(", "); }
}
str.append("=");
}
// Enchanting
GameEntity entity = card.getEnchanting();
if (entity != null) {
if (str.length() != 0) { str.append("\n"); }
str.append("*Enchanting ");
if (entity instanceof Card) {
Card temp = (Card) entity;
if (temp.isFaceDown() && temp.getController().isComputer()) {
str.append("Morph (");
str.append(card.getUniqueNumber());
str.append(")");
}
else {
str.append(entity);
}
}
else {
str.append(entity);
}
str.append("*");
}
// Enchanted by
if (card.getEnchantedBy().size() > 0) {
if (str.length() != 0) { str.append("\n"); }
str.append("*Enchanted by ");
for (Iterator<Card> it = card.getEnchantedBy().iterator(); it.hasNext();) {
str.append(it.next());
if (it.hasNext()) { str.append(", "); }
}
str.append("*");
}
// Controlling
if (card.getGainControlTargets().size() > 0) {
if (str.length() != 0) { str.append("\n"); }
str.append("+Controlling: ");
for (Iterator<Card> it = card.getGainControlTargets().iterator(); it.hasNext();) {
str.append(it.next());
if (it.hasNext()) { str.append(", "); }
}
str.append("+");
}
// Cloned via
if (card.getCloneOrigin() != null) {
if (str.length() != 0) { str.append("\n"); }
str.append("^Cloned via: ");
str.append(card.getCloneOrigin().getName());
str.append("^");
}
// Imprint
if (!card.getImprinted().isEmpty()) {
if (str.length() != 0) { str.append("\n"); }
str.append("^Imprinting: ");
for (Iterator<Card> it = card.getImprinted().iterator(); it.hasNext();) {
str.append(it.next());
if (it.hasNext()) { str.append(", "); }
}
str.append("^");
}
// Uncastable
/*if (card.isUnCastable()) {
if (str.length() != 0) str.append("\n");
str.append("This card can't be cast.");
}*/
if (card.hasAttachedCardsByMindsDesire()) {
if (str.length() != 0) { str.append("\n"); }
Card[] cards = card.getAttachedCardsByMindsDesire();
str.append("=Attached: ");
for (Card temp : cards) {
str.append(temp.getName());
str.append(" ");
}
str.append("=");
}
tarInfo.setText(str.toString());
}
/** @return Card */
public Card getCard() {
return this.card;
}
/** A brief JLabel to consolidate styling. */
private class DetailLabel extends JLabel {
public DetailLabel(boolean zebra0) {
super();
if (zebra0) {
this.setBackground(zebra);
this.setOpaque(true);
}
this.setFont(f);
this.setForeground(foreground);
this.setHorizontalAlignment(SwingConstants.CENTER);
}
public DetailLabel() {
this(false);
}
}
}

View File

@@ -0,0 +1,88 @@
package forge.view.toolbox;
import javax.swing.AbstractListModel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import forge.AllZone;
import forge.Card;
import forge.CardUtil;
import forge.gui.game.CardDetailPanel;
import forge.gui.game.CardPicturePanel;
import forge.item.CardPrinted;
import java.util.List;
import static java.util.Collections.unmodifiableList;
/**
* A simple JPanel that shows three columns: card list, pic, and description..
*
* @author Forge
* @version $Id: ListChooser.java 9708 2011-08-09 19:34:12Z jendave $
*/
@SuppressWarnings("serial")
public class CardViewer extends JPanel {
//Data and number of choices for the list
private List<CardPrinted> list;
//initialized before; listeners may be added to it
private JList jList;
private CardDetailPanel detail;
private CardPicturePanel picture;
public CardViewer(List<CardPrinted> list) {
this.list = unmodifiableList(list);
jList = new JList(new ChooserListModel());
detail = new CardDetailPanel(null);
picture = new CardPicturePanel(null);
this.add(new JScrollPane(jList));
this.add(picture);
this.add(detail);
this.setLayout( new java.awt.GridLayout(1, 3, 6, 0) );
// selection is here
jList.getSelectionModel().addListSelectionListener(new SelListener());
jList.setSelectedIndex(0);
}
private class ChooserListModel extends AbstractListModel {
private static final long serialVersionUID = 3871965346333840556L;
public int getSize() { return list.size(); }
public Object getElementAt(int index) { return list.get(index); }
}
private class SelListener implements ListSelectionListener {
private Card[] cache = null;
public void valueChanged(final ListSelectionEvent e) {
int row = jList.getSelectedIndex();
// (String) jList.getSelectedValue();
if (row >= 0 && row < list.size()) {
CardPrinted cp = list.get(row);
ensureCacheHas(row, cp);
detail.setCard(cache[row]);
picture.setCard(cp);
}
}
private void ensureCacheHas(int row, CardPrinted cp) {
if (cache == null) { cache = new Card[list.size()]; }
if (null == cache[row]) {
Card card = AllZone.getCardFactory().getCard(cp.getName(), null);
card.setCurSetCode(cp.getSet());
card.setImageFilename(CardUtil.buildFilename(card));
cache[row] = card;
}
}
}
}

View File

@@ -0,0 +1,78 @@
package forge.view.toolbox;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
/**
* Semi-transparent overlay panel. Should be used with layered panes.
*
*/
// Currently used only once, in top level UI, with layering already in place.
// Getter in AllZone: getOverlay()
@SuppressWarnings("serial")
public class FOverlay extends JPanel {
private JButton btnClose;
/**
* Semi-transparent overlay panel. Should be used with layered panes.
*/
public FOverlay() {
super();
btnClose = new JButton("X");
btnClose.setForeground(Color.white);
btnClose.setBorder(BorderFactory.createLineBorder(Color.white));
btnClose.setOpaque(false);
btnClose.setBackground(new Color(0, 0, 0));
btnClose.setFocusPainted(false);
btnClose.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
hideOverlay();
}
});
}
/** */
public void showOverlay() {
setVisible(true);
}
/** */
public void hideOverlay() {
setVisible(false);
}
/**
* Gets the close button, which must be added dynamically since
* different overlays have different layouts. The overlay does
* not have the close button by default, but a fully working
* instance is available if required.
*
* @return JButton
*/
public JButton getBtnClose() {
return btnClose;
}
/**
* For some reason, the alpha channel background doesn't work
* properly on Windows 7, so the paintComponent override is
* required for a semi-transparent overlay.
*
* @param g &emsp; Graphics object
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0, 0, 0, 200));
g.fillRect(0, 0, getWidth(), getHeight());
}
}

View File

@@ -0,0 +1,190 @@
package forge.view.toolbox;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
import net.miginfocom.swing.MigLayout;
import forge.AllZone;
import forge.gui.skin.FPanel;
import forge.gui.skin.FSkin;
/**
* TODO: Write javadoc for this type.
*
*/
@SuppressWarnings("serial")
public class FVerticalTabPanel extends FPanel {
private CardLayout cards;
private JPanel pnlContent;
private List<VTab> allVTabs;
private FSkin skin;
private int active;
private Color activeColor, inactiveColor, hoverColor;
private Border inactiveBorder, hoverBorder;
/**
* Assembles vertical tab panel from list of child panels. Tooltip
* on tab is same as tooltip on child panel. Title of tab is same
* as name of child panel.
*
* @param childPanels &emsp; JPanels to be placed in tabber
*/
public FVerticalTabPanel(List<JPanel> childPanels) {
// General inits and skin settings
super();
setLayout(new MigLayout("insets 0, gap 0, wrap 2"));
setOpaque(false);
int size = childPanels.size();
skin = AllZone.getSkin();
hoverColor = skin.getClrHover();
activeColor = skin.getClrActive();
inactiveColor = skin.getClrInactive();
hoverBorder = new MatteBorder(1, 0, 1, 1, skin.getClrBorders());
inactiveBorder = new MatteBorder(1, 0, 1, 1, new Color(0, 0, 0, 0));
final int pctTabH = (int) ((100 - 2 - 2) / size);
final int pctTabW = 11;
final int pctInsetH = 3;
final int pctSpacing = 1;
// Content panel and card layout inits
cards = new CardLayout();
pnlContent = new JPanel();
pnlContent.setOpaque(false);
pnlContent.setLayout(cards);
pnlContent.setBorder(new MatteBorder(0, 0, 0, 1, skin.getClrBorders()));
add(pnlContent, "span 1 " + (size + 2) + ", w " + (100 - pctTabW) + "%!, h 100%!");
JPanel topSpacer = new JPanel();
topSpacer.setOpaque(false);
add(topSpacer, "w " + pctTabW + "%!, h " + pctInsetH + "%!");
// Add all tabs
VTab tab;
allVTabs = new ArrayList<VTab>();
for (int i = 0; i < size; i++) {
tab = new VTab(childPanels.get(i).getName(), i);
tab.setToolTipText(childPanels.get(i).getToolTipText());
if (i == 0) {
tab.setBackground(activeColor);
active = 0;
}
else {
tab.setBackground(inactiveColor);
}
add(tab, "w " + pctTabW + "%!, h " + (pctTabH - pctSpacing) + "%!, gapbottom " + pctSpacing + "%!");
allVTabs.add(tab);
// Add card to content panel
pnlContent.add(childPanels.get(i), "CARD" + i);
}
JPanel bottomSpacer = new JPanel();
bottomSpacer.setOpaque(false);
add(bottomSpacer, "w 10%!, h " + (pctInsetH + pctSpacing) + "%!");
}
/**
* Programatically flips tab layout to specified number (without needing
* a mouse event).
*
* @param index &emsp; Tab number, starting from 0
*/
public void showTab(int index) {
if (index >= this.allVTabs.size()) {
return;
}
allVTabs.get(active).setBackground(inactiveColor);
active = index;
cards.show(pnlContent, "CARD" + index);
allVTabs.get(active).setBackground(activeColor);
}
/** @return JPanel */
public JPanel getContentPanel() {
return pnlContent;
}
/**
* A single instance of a vertical tab, with paintComponent overridden
* to provide vertical-ness. Also manages root level hover and click effects.
*
*/
private class VTab extends JPanel {
private String msg;
private int id, w;
// ID is used to retrieve this tab from the list of allVTabs.
VTab(String txt, int i) {
super();
setLayout(new MigLayout("insets 0, gap 0"));
setOpaque(true);
msg = txt;
id = i;
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
if (id != active) {
setBorder(hoverBorder);
setBackground(hoverColor);
}
}
@Override
public void mouseExited(MouseEvent e) {
if (id != active) {
setBorder(inactiveBorder);
setBackground(inactiveColor);
}
}
@Override
public void mousePressed(MouseEvent e) {
allVTabs.get(active).setBackground(inactiveColor);
active = id;
cards.show(pnlContent, "CARD" + id);
setBackground(activeColor);
}
});
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
w = getWidth();
// Careful with this font scale factor; the vertical tabs will be unreadable
// if small window, too big if large window.
g.setFont(skin.getFont1().deriveFont(Font.PLAIN, (int) (w * 0.68)));
// Rotate, draw string, rotate back (to allow hover border to be painted properly)
Graphics2D g2d = (Graphics2D) g;
AffineTransform at = g2d.getTransform();
at.rotate(Math.toRadians(90), 0, 0);
g2d.setTransform(at);
g2d.setColor(AllZone.getSkin().getClrText());
g2d.drawString(msg, 5, -4);
at.rotate(Math.toRadians(-90), 0, 0);
g2d.setTransform(at);
}
}
}