diff --git a/.gitattributes b/.gitattributes index f7ee48cfbb4..995e9861d63 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14989,6 +14989,7 @@ src/main/java/forge/gui/match/controllers/CPlayers.java -text src/main/java/forge/gui/match/controllers/CStack.java -text src/main/java/forge/gui/match/controllers/package-info.java svneol=native#text/plain src/main/java/forge/gui/match/menus/CMatchUIMenus.java -text +src/main/java/forge/gui/match/menus/CardOverlaysMenu.java -text src/main/java/forge/gui/match/menus/DevModeMenu.java -text src/main/java/forge/gui/match/menus/GameMenu.java -text src/main/java/forge/gui/match/nonsingleton/CCommand.java -text diff --git a/src/main/java/forge/gui/match/CMatchUI.java b/src/main/java/forge/gui/match/CMatchUI.java index a0d22d84f56..ba551ba95aa 100644 --- a/src/main/java/forge/gui/match/CMatchUI.java +++ b/src/main/java/forge/gui/match/CMatchUI.java @@ -66,6 +66,7 @@ import forge.gui.toolbox.FSkin; import forge.gui.toolbox.special.PhaseLabel; import forge.item.InventoryItem; import forge.properties.ForgePreferences.FPref; +import forge.view.arcane.CardPanel; import forge.view.arcane.PlayArea; /** @@ -430,4 +431,23 @@ public enum CMatchUI implements ICDoc, IMenuProvider { @Override public void update() { } + public void repaintCardOverlays() { + List panels = getVisibleCardPanels(); + for (CardPanel panel : panels) { + panel.repaintOverlays(); + } + } + private List getVisibleCardPanels() { + List panels = new ArrayList(); + for (VHand h : view.getHands()) { + panels.addAll(h.getHandArea().getCardPanels()); + } + for (VField f : view.getFieldViews()) { + panels.addAll(f.getTabletop().getCardPanels()); + } + for (VCommand c : view.getCommandViews()) { + panels.addAll(c.getTabletop().getCardPanels()); + } + return panels; + } } diff --git a/src/main/java/forge/gui/match/menus/CardOverlaysMenu.java b/src/main/java/forge/gui/match/menus/CardOverlaysMenu.java new file mode 100644 index 00000000000..39aa1c8a1a6 --- /dev/null +++ b/src/main/java/forge/gui/match/menus/CardOverlaysMenu.java @@ -0,0 +1,107 @@ +package forge.gui.match.menus; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; + +import forge.Singletons; +import forge.gui.match.CMatchUI; +import forge.gui.menubar.MenuUtil; +import forge.properties.ForgePreferences; +import forge.properties.ForgePreferences.FPref; + +public final class CardOverlaysMenu { + private CardOverlaysMenu() { } + + private static ForgePreferences prefs = Singletons.getModel().getPreferences(); + private static boolean showOverlays = prefs.getPrefBoolean(FPref.UI_SHOW_CARD_OVERLAYS); + + public static JMenu getMenu(boolean showMenuIcons) { + JMenu menu = new JMenu("Card Overlays"); + menu.add(getMenuItem_ShowOverlays()); + menu.addSeparator(); + menu.add(getMenuItem_CardOverlay("Card Name", FPref.UI_OVERLAY_CARD_NAME)); + menu.add(getMenuItem_CardOverlay("Mana Cost", FPref.UI_OVERLAY_CARD_MANA_COST)); + menu.add(getMenuItem_CardOverlay("Power/Toughness", FPref.UI_OVERLAY_CARD_POWER)); + menu.add(getMenuItem_CardOverlay("Card Id", FPref.UI_OVERLAY_CARD_ID)); + return menu; + } + + private static JMenuItem getMenuItem_CardOverlay(String menuCaption, FPref pref) { + JCheckBoxMenuItem menu = new JCheckBoxMenuItem(menuCaption); + menu.setState(prefs.getPrefBoolean(pref)); + menu.setEnabled(showOverlays); + menu.addActionListener(getCardOverlaysAction(pref)); + return menu; + } + + private static JMenuItem getMenuItem_ShowOverlays() { + JCheckBoxMenuItem menu = new JCheckBoxMenuItem("Show"); + menu.setAccelerator(MenuUtil.getAcceleratorKey(KeyEvent.VK_O)); + menu.setState(prefs.getPrefBoolean(FPref.UI_SHOW_CARD_OVERLAYS)); + menu.addActionListener(getShowOverlaysAction()); + return menu; + } + + private static ActionListener getShowOverlaysAction() { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + toggleCardOverlayDisplay((JMenuItem)e.getSource()); + } + }; + } + + private static void toggleCardOverlayDisplay(JMenuItem showMenu) { + toggleShowOverlaySetting(); + repaintCardOverlays(); + // Enable/disable overlay menu items based on state of "Show" menu. + for (Component c : ((JPopupMenu)showMenu.getParent()).getComponents()) { + if (c instanceof JMenuItem) { + JMenuItem m = (JMenuItem)c; + if (m != showMenu) { + m.setEnabled(prefs.getPrefBoolean(FPref.UI_SHOW_CARD_OVERLAYS)); + } + } + } + } + + private static void toggleShowOverlaySetting() { + boolean isOverlayEnabled = !prefs.getPrefBoolean(FPref.UI_SHOW_CARD_OVERLAYS); + prefs.setPref(FPref.UI_SHOW_CARD_OVERLAYS, isOverlayEnabled); + prefs.save(); + } + + private static ActionListener getCardOverlaysAction(final FPref overlaySetting) { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + toggleOverlaySetting(overlaySetting); + repaintCardOverlays(); + } + + }; + } + + private static void toggleOverlaySetting(FPref overlaySetting) { + boolean isOverlayEnabled = !prefs.getPrefBoolean(overlaySetting); + prefs.setPref(overlaySetting, isOverlayEnabled); + prefs.save(); + } + + private static void repaintCardOverlays() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + CMatchUI.SINGLETON_INSTANCE.repaintCardOverlays(); + } + }); + } +} diff --git a/src/main/java/forge/gui/match/menus/GameMenu.java b/src/main/java/forge/gui/match/menus/GameMenu.java index f1903826df0..638075a8ba1 100644 --- a/src/main/java/forge/gui/match/menus/GameMenu.java +++ b/src/main/java/forge/gui/match/menus/GameMenu.java @@ -40,6 +40,8 @@ public final class GameMenu { menu.add(getMenuItem_AlphaStrike()); menu.addSeparator(); menu.add(getMenuItem_TargetingArcs()); + menu.add(CardOverlaysMenu.getMenu(showMenuIcons)); + menu.addSeparator(); menu.add(getMenuItem_GameSoundEffects()); menu.addSeparator(); menu.add(getMenuItem_ViewDeckList()); diff --git a/src/main/java/forge/properties/ForgePreferences.java b/src/main/java/forge/properties/ForgePreferences.java index 42e80a385c5..b3176ff61c9 100644 --- a/src/main/java/forge/properties/ForgePreferences.java +++ b/src/main/java/forge/properties/ForgePreferences.java @@ -30,7 +30,7 @@ import forge.gui.match.views.VDev; import forge.gui.toolbox.special.PhaseIndicator; public class ForgePreferences extends PreferencesStore { - /** + /** * Preference identifiers, and their default values. */ public static enum FPref { @@ -39,9 +39,11 @@ public class ForgePreferences extends PreferencesStore { UI_RANDOM_FOIL ("false"), UI_SMOOTH_LAND ("false"), UI_AVATARS ("0,1"), + UI_SHOW_CARD_OVERLAYS ("true"), UI_OVERLAY_CARD_NAME ("true"), UI_OVERLAY_CARD_POWER ("true"), - UI_OVERLAY_CARD_MANA_COST ("true"), + UI_OVERLAY_CARD_MANA_COST ("true"), + UI_OVERLAY_CARD_ID ("true"), UI_UPLOAD_DRAFT ("false"), UI_SCALE_LARGER ("true"), UI_MAX_STACK ("3"), @@ -63,7 +65,7 @@ public class ForgePreferences extends PreferencesStore { UI_THEMED_COMBOBOX ("true"), UI_HIDE_MENUBAR ("false"), // Dev setting only - cannot be set from GUI. UI_HIDE_GAME_TABS ("false"), // Visibility of tabs in match screen. - + UI_FOR_TOUCHSCREN("false"), MATCHPREF_PROMPT_FREE_BLOCKS("false"), @@ -140,12 +142,12 @@ public class ForgePreferences extends PreferencesStore { tiny, smaller, small, medium, large, huge } - + public static enum StackOffsetType { tiny, small, medium, large } - + public static enum HomeMenus { constructed, draft, sealed, quest, settings, utilities } @@ -244,7 +246,7 @@ public class ForgePreferences extends PreferencesStore { protected FPref[] getEnumValues() { return FPref.values(); } - + protected FPref valueOf(String name) { try { return FPref.valueOf(name); diff --git a/src/main/java/forge/view/arcane/CardPanel.java b/src/main/java/forge/view/arcane/CardPanel.java index c8e64be51bf..4b3458bfa98 100644 --- a/src/main/java/forge/view/arcane/CardPanel.java +++ b/src/main/java/forge/view/arcane/CardPanel.java @@ -115,11 +115,12 @@ public class CardPanel extends JPanel implements CardContainer { /** * */ - private final ScaledImagePanel imagePanel; + private ScaledImagePanel imagePanel; - private final OutlinedLabel titleText; - private final OutlinedLabel ptText; - private final OutlinedLabel damageText; + private OutlinedLabel titleText; + private OutlinedLabel ptText; + private OutlinedLabel damageText; + private OutlinedLabel cardIdText; private final List imageLoadListeners = new ArrayList(2); private boolean displayEnabled = true; private boolean isAnimationPanel; @@ -135,31 +136,20 @@ public class CardPanel extends JPanel implements CardContainer { * a {@link forge.Card} object. */ public CardPanel(final Card newGameCard) { - this.setGameCard(newGameCard); + this.gameCard = newGameCard; this.setBackground(Color.black); this.setOpaque(false); - this.titleText = new OutlinedLabel(); - this.titleText.setFont(this.getFont().deriveFont(Font.BOLD, 13f)); - this.titleText.setForeground(Color.white); - this.titleText.setGlow(Color.black); - this.titleText.setWrap(true); - this.add(this.titleText); + createCardNameOverlay(); + createPTOverlay(); + createCardIdOverlay(); + createScaleImagePanel(); - this.ptText = new OutlinedLabel(); - this.ptText.setFont(this.getFont().deriveFont(Font.BOLD, 13f)); - this.ptText.setForeground(Color.white); - this.ptText.setGlow(Color.black); - this.add(this.ptText); + this.setCard(newGameCard); + } - this.damageText = new OutlinedLabel(); - this.damageText.setFont(this.getFont().deriveFont(Font.BOLD, 15f)); - this.damageText.setForeground(new Color(160,0,0)); - this.damageText.setGlow(Color.white); - this.add(this.damageText); - - + private void createScaleImagePanel() { this.imagePanel = new ScaledImagePanel(); this.add(this.imagePanel); this.addComponentListener(new ComponentAdapter() { @@ -167,14 +157,43 @@ public class CardPanel extends JPanel implements CardContainer { public void componentShown(final ComponentEvent e) { CardPanel.this.setCard(CardPanel.this.getGameCard()); } - @Override public void componentResized(final ComponentEvent e) { CardPanel.this.setCard(CardPanel.this.getGameCard()); } }); + } - this.setCard(newGameCard); + private void createCardNameOverlay() { + this.titleText = new OutlinedLabel(); + this.titleText.setFont(this.getFont().deriveFont(Font.BOLD, 13f)); + this.titleText.setForeground(Color.white); + this.titleText.setGlow(Color.black); + this.titleText.setWrap(true); + this.add(this.titleText); + } + + private void createPTOverlay() { + // Power + this.ptText = new OutlinedLabel(); + this.ptText.setFont(this.getFont().deriveFont(Font.BOLD, 13f)); + this.ptText.setForeground(Color.white); + this.ptText.setGlow(Color.black); + this.add(this.ptText); + // Toughness + this.damageText = new OutlinedLabel(); + this.damageText.setFont(this.getFont().deriveFont(Font.BOLD, 15f)); + this.damageText.setForeground(new Color(160,0,0)); + this.damageText.setGlow(Color.white); + this.add(this.damageText); + } + + private void createCardIdOverlay() { + this.cardIdText = new OutlinedLabel(); + this.cardIdText.setFont(this.getFont().deriveFont(Font.BOLD, 11f)); + this.cardIdText.setForeground(Color.LIGHT_GRAY); + this.cardIdText.setGlow(Color.black); + this.add(this.cardIdText); } /** @@ -321,12 +340,12 @@ public class CardPanel extends JPanel implements CardContainer { final int n = Math.max(1, Math.round(this.cardWidth * CardPanel.SELECTED_BORDER_SIZE)); g2d.fillRoundRect(this.cardXOffset - n, (this.cardYOffset - n) + offset, this.cardWidth + (n * 2), this.cardHeight + (n * 2), cornerSize + n , cornerSize + n); } - - // Black fill - (will become outline for white bordered cards) + + // Black fill - (will become outline for white bordered cards) final int n = 0; g2d.setColor(Color.black); g2d.fillRoundRect(this.cardXOffset - n, (this.cardYOffset - n) + offset, this.cardWidth + (n * 2), this.cardHeight + (n * 2), cornerSize + n , cornerSize + n); - + // White border if card is known to have it. if (this.getGameCard() != null && !this.getGameCard().isFaceDown()) { CardEdition ed = Singletons.getModel().getEditions().get(this.getGameCard().getCurSetCode()); @@ -341,14 +360,14 @@ public class CardPanel extends JPanel implements CardContainer { /** * TODO: Write javadoc for this method. * @param g - * @param manaCost + * @param manaCost */ private void drawManaCost(final Graphics g, ManaCost cost, int deltaY ) { int width = CardFaceSymbols.getWidth(cost); int height = CardFaceSymbols.getHeight(); CardFaceSymbols.draw(g, cost, (this.cardXOffset + (this.cardWidth / 2)) - (width / 2), deltaY + this.cardYOffset + (this.cardHeight / 2) - height/2); } - + /** {@inheritDoc} */ @Override protected final void paintChildren(final Graphics g) { @@ -394,11 +413,11 @@ public class CardPanel extends JPanel implements CardContainer { final int combatXSymbols = (this.cardXOffset + (this.cardWidth / 4)) - 16; final int stateXSymbols = (this.cardXOffset + (this.cardWidth / 2)) - 16; - final int ySymbols = (this.cardYOffset + this.cardHeight) - (this.cardHeight / 8) - 16; + final int ySymbols = (this.cardYOffset + this.cardHeight) - (this.cardHeight / 8) - 16; // int yOff = (cardHeight/4) + 2; Combat combat = card.getGame().getCombat(); if( combat != null ) { - if ( combat.isAttacking(card)) + if ( combat.isAttacking(card)) CardFaceSymbols.drawSymbol("attack", g, combatXSymbols, ySymbols); if ( combat.isBlocking(card)) CardFaceSymbols.drawSymbol("defend", g, combatXSymbols, ySymbols); @@ -436,31 +455,53 @@ public class CardPanel extends JPanel implements CardContainer { this.imagePanel.setSize(imgSize); final int fontHeight = Math.round(this.cardHeight * (27f / 680)); - final boolean showText = !this.imagePanel.hasImage() || (!this.isAnimationPanel && (fontHeight < 12)); - this.titleText.setVisible(showText); - this.ptText.setVisible(showText); - this.damageText.setVisible(showText); + boolean showText = !this.imagePanel.hasImage() || (!this.isAnimationPanel && (fontHeight < 12)); - final int titleX = Math.round(imgSize.width * (24f / 480)); - final int titleY = Math.round(imgSize.height * (54f / 640)) - 15; - final int titleH = Math.round(imgSize.height * (360f / 640)); - this.titleText.setBounds(imgPos.x + titleX, imgPos.y + titleY, imgSize.width - 2 * titleX, titleH - titleY); - - final int rightLine = Math.round(imgSize.width * (412f / 480)); - - final Dimension ptSize = this.ptText.getPreferredSize(); - this.ptText.setSize(ptSize.width, ptSize.height); - final int ptX = rightLine - ptSize.width/2; - final int ptY = Math.round(imgSize.height * (650f / 680)) - 13; - this.ptText.setLocation(imgPos.x + ptX, imgPos.y + ptY); - - final Dimension dmgSize = this.damageText.getPreferredSize(); - this.damageText.setSize(dmgSize.width, dmgSize.height); - final int dmgX = rightLine - dmgSize.width / 2; - final int dmgY = ptY - 16; - this.damageText.setLocation(imgPos.x + dmgX, imgPos.y + dmgY); + displayCardNameOverlay(showText && showCardNameOverlay(), imgSize, imgPos); + displayPTOverlay(showText && showCardPowerOverlay(), imgSize, imgPos); + displayCardIdOverlay(showText && showCardIdOverlay(), imgSize, imgPos); } + private void displayCardIdOverlay(boolean isVisible, Dimension imgSize, Point imgPos) { + if (isVisible) { + final Dimension idSize = this.cardIdText.getPreferredSize(); + this.cardIdText.setSize(idSize.width, idSize.height); + final int idX = Math.round(imgSize.width * (24f / 480)); + final int idY = Math.round(imgSize.height * (650f / 680)) - 8; + this.cardIdText.setLocation(imgPos.x + idX, imgPos.y + idY); + } + this.cardIdText.setVisible(isVisible); + } + + private void displayPTOverlay(boolean isVisible, Dimension imgSize, Point imgPos) { + if (isVisible) { + final int rightLine = Math.round(imgSize.width * (412f / 480)) + 3; + // Power + final Dimension ptSize = this.ptText.getPreferredSize(); + this.ptText.setSize(ptSize.width, ptSize.height); + final int ptX = rightLine - ptSize.width/2; + final int ptY = Math.round(imgSize.height * (650f / 680)) - 10; + this.ptText.setLocation(imgPos.x + ptX, imgPos.y + ptY); + // Toughness + final Dimension dmgSize = this.damageText.getPreferredSize(); + this.damageText.setSize(dmgSize.width, dmgSize.height); + final int dmgX = rightLine - dmgSize.width / 2; + final int dmgY = ptY - 16; + this.damageText.setLocation(imgPos.x + dmgX, imgPos.y + dmgY); + } + this.ptText.setVisible(isVisible); + this.damageText.setVisible(isVisible); + } + + private void displayCardNameOverlay(boolean isVisible, Dimension imgSize, Point imgPos) { + if (isVisible) { + final int titleX = Math.round(imgSize.width * (24f / 480)); + final int titleY = Math.round(imgSize.height * (54f / 640)) - 15; + final int titleH = Math.round(imgSize.height * (360f / 640)); + this.titleText.setBounds(imgPos.x + titleX, imgPos.y + titleY + 2, imgSize.width - 2 * titleX, titleH - titleY); + } + this.titleText.setVisible(isVisible); + } @Override public final String toString() { @@ -580,37 +621,38 @@ public class CardPanel extends JPanel implements CardContainer { * a {@link forge.Card} object. */ public final void setText(final Card card) { - + if ((card == null)) { return; } - + + // Card name overlay if (card.isFaceDown()) { this.titleText.setText(""); } else { - if (showCardNameOverlay()) { - this.titleText.setText(card.getName()); - } + this.titleText.setText(card.getName()); } - - if (showCardPowerOverlay()) { - String sPt = ""; - if (card.isCreature() && card.isPlaneswalker()) { - sPt = String.format("%d/%d (%d)", card.getNetAttack(), card.getNetDefense(), card.getCounters(CounterType.LOYALTY)); - } else if (card.isCreature()) { - sPt = String.format("%d/%d", card.getNetAttack(), card.getNetDefense()); - } else if (card.isPlaneswalker()) { - int loyalty = card.getCounters(CounterType.LOYALTY); - sPt = String.valueOf(loyalty == 0 ? card.getBaseLoyalty() : loyalty); - } - this.ptText.setText(sPt); + + // P/T overlay + String sPt = ""; + if (card.isCreature() && card.isPlaneswalker()) { + sPt = String.format("%d/%d (%d)", card.getNetAttack(), card.getNetDefense(), card.getCounters(CounterType.LOYALTY)); + } else if (card.isCreature()) { + sPt = String.format("%d/%d", card.getNetAttack(), card.getNetDefense()); + } else if (card.isPlaneswalker()) { + int loyalty = card.getCounters(CounterType.LOYALTY); + sPt = String.valueOf(loyalty == 0 ? card.getBaseLoyalty() : loyalty); } + this.ptText.setText(sPt); int damage = card.getDamage(); this.damageText.setText(damage > 0 ? "\u00BB " + String.valueOf(damage) + " \u00AB" : ""); + // Card Id overlay + this.cardIdText.setText(Integer.toString(card.getUniqueNumber())); + } - + /** *

* getCard. @@ -629,8 +671,8 @@ public class CardPanel extends JPanel implements CardContainer { && this.imagePanel.hasImage()) { return; } - - this.setGameCard(card); + + this.gameCard = card; if (!this.isShowing()) { return; } @@ -640,7 +682,7 @@ public class CardPanel extends JPanel implements CardContainer { this.setImage(image); } - + /** * Gets the game card. * @@ -650,16 +692,6 @@ public class CardPanel extends JPanel implements CardContainer { return this.gameCard; } - /** - * Sets the game card. - * - * @param gameCard0 - * the gameCard to set - */ - public final void setGameCard(final Card gameCard0) { - this.gameCard = gameCard0; - } - /** * Gets the drag animation panel. * @@ -763,22 +795,36 @@ public class CardPanel extends JPanel implements CardContainer { public static final float getBorderSize() { return BLACK_BORDER_SIZE; } - + private boolean isPreferenceEnabled(FPref preferenceName) { return Singletons.getModel().getPreferences().getPrefBoolean(preferenceName); - } + } + + private boolean isShowingOverlays() { + return isPreferenceEnabled(FPref.UI_SHOW_CARD_OVERLAYS); + } private boolean showCardNameOverlay() { - return isPreferenceEnabled(FPref.UI_OVERLAY_CARD_NAME); + return isShowingOverlays() && isPreferenceEnabled(FPref.UI_OVERLAY_CARD_NAME); } private boolean showCardPowerOverlay() { - return isPreferenceEnabled(FPref.UI_OVERLAY_CARD_POWER); + return isShowingOverlays() && isPreferenceEnabled(FPref.UI_OVERLAY_CARD_POWER); } private boolean showCardManaCostOverlay() { - return isPreferenceEnabled(FPref.UI_OVERLAY_CARD_MANA_COST) && !this.getCard().isFaceDown(); + return isShowingOverlays() && + isPreferenceEnabled(FPref.UI_OVERLAY_CARD_MANA_COST) && + !this.getCard().isFaceDown(); } - - + + private boolean showCardIdOverlay() { + return isShowingOverlays() && isPreferenceEnabled(FPref.UI_OVERLAY_CARD_ID); + } + + public void repaintOverlays() { + repaint(); + doLayout(); + } + }