diff --git a/docs/Credit-and-Thanks.md b/docs/Credit-and-Thanks.md index ccf3653ed48..0dafeb8930a 100644 --- a/docs/Credit-and-Thanks.md +++ b/docs/Credit-and-Thanks.md @@ -29,4 +29,7 @@ Some of the sprites and tiles that are used in Adventure mode come from external 1. Forest biome = Enchanted Forest - Logan Epic Canto // The Celtic King 1. Plains biome = Cobblestone Village - Brandon Fiechter // Camelot - Brandon Fiechter 1. Mountain biome = Goblin Tinker - Brandon Fiechter // Goblin King's Tavern - Brandon Fiechter -1. Castle = Horus - Brandon Fiechter & Derek Fiechter \ No newline at end of file +1. Castle = Horus - Brandon Fiechter & Derek Fiechter + +## Other sprites and icons +1. Clipboard icon by Dimitry Miroliubov at [Flaticon](https://www.flaticon.com/free-icon/clipboard_340068) \ No newline at end of file diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CCurrentDeck.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CCurrentDeck.java index cfdf67dd9f9..f92d87e35d4 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CCurrentDeck.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CCurrentDeck.java @@ -15,6 +15,7 @@ import forge.deck.DeckBase; import forge.deck.io.DeckSerializer; import forge.deck.io.DeckStorage; +import forge.gui.GuiBase; import forge.gui.UiCommand; import forge.gui.framework.ICDoc; import forge.localinstance.properties.ForgeConstants; @@ -23,6 +24,7 @@ import forge.screens.deckeditor.SEditorIO; import forge.screens.deckeditor.views.VCurrentDeck; import forge.toolbox.FOptionPane; +import forge.util.Localizer; /** * Controls the "current deck" panel in the deck editor UI. @@ -70,6 +72,7 @@ public void initialize() { VCurrentDeck.SINGLETON_INSTANCE.getBtnSave().setCommand((UiCommand) SEditorIO::saveDeck); VCurrentDeck.SINGLETON_INSTANCE.getBtnSaveAs().setCommand((UiCommand) this::exportDeck); VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies().setCommand((UiCommand) this::printProxies); + VCurrentDeck.SINGLETON_INSTANCE.getBtnCopyToClipboard().setCommand((UiCommand) this::copyDeckToClipboard); VCurrentDeck.SINGLETON_INSTANCE.getBtnOpen().setCommand((UiCommand) this::openDeck); VCurrentDeck.SINGLETON_INSTANCE.getBtnNew().setCommand((UiCommand) this::newDeck); @@ -183,6 +186,20 @@ private void exportDeck() { } } + private void copyDeckToClipboard() { + if (CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController() == null) { + return; + } + Object model = CDeckEditorUI.SINGLETON_INSTANCE + .getCurrentEditorController().getDeckController().getModel(); + if (!(model instanceof Deck deck)) { + return; + } + GuiBase.getInterface().copyToClipboard(deck.generateTextExport()); + FOptionPane.showMessageDialog( + Localizer.getInstance().getMessage("lblDeckListCopiedClipboard", deck.getName())); + } + /** */ @SuppressWarnings("unchecked") private void printProxies() { diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/menus/DeckFileMenu.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/menus/DeckFileMenu.java index 3617bc6d2b0..19475908a67 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/menus/DeckFileMenu.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/menus/DeckFileMenu.java @@ -1,13 +1,19 @@ package forge.screens.deckeditor.menus; +import java.awt.Toolkit; import java.awt.event.ActionListener; +import java.awt.event.InputEvent; import java.awt.event.KeyEvent; +import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JSeparator; +import javax.swing.KeyStroke; +import forge.localinstance.properties.ForgePreferences.FPref; import forge.localinstance.skin.FSkinProp; import forge.menus.MenuUtil; +import forge.model.FModel; import forge.screens.deckeditor.CDeckEditorUI; import forge.screens.deckeditor.views.VCurrentDeck; import forge.toolbox.FSkin.SkinnedMenuItem; @@ -36,6 +42,9 @@ public static JMenu getMenu(boolean showMenuIcons) { menu.add(getMenuItem_SaveAs()); menu.add(new JSeparator()); menu.add(getMenuItem_Print()); + menu.add(getMenuItem_CopyToClipboard()); + menu.add(new JSeparator()); + menu.add(getMenuItem_EnforceConformity()); updateSaveEnabled(); return menu; } @@ -129,4 +138,25 @@ private static SkinnedMenuItem getMenuItem_Print() { private static ActionListener getPrintAction() { return e -> VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies().getCommand().run(); } + + private static SkinnedMenuItem getMenuItem_CopyToClipboard() { + final Localizer localizer = Localizer.getInstance(); + SkinnedMenuItem menuItem = new SkinnedMenuItem(localizer.getMessage("btnCopyToClipboard")); + menuItem.setIcon(showIcons ? MenuUtil.getMenuIcon(FSkinProp.ICO_CLIPBOARD) : null); + menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx() | InputEvent.SHIFT_DOWN_MASK)); + menuItem.addActionListener(e -> VCurrentDeck.SINGLETON_INSTANCE.getBtnCopyToClipboard().getCommand().run()); + return menuItem; + } + + private static JCheckBoxMenuItem getMenuItem_EnforceConformity() { + final Localizer localizer = Localizer.getInstance(); + JCheckBoxMenuItem checkItem = new JCheckBoxMenuItem(localizer.getMessage("cbEnforceDeckLegality")); + checkItem.setSelected(FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)); + checkItem.addActionListener(e -> { + FModel.getPreferences().setPref(FPref.ENFORCE_DECK_LEGALITY, checkItem.isSelected()); + FModel.getPreferences().save(); + }); + return checkItem; + } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/views/VCurrentDeck.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/views/VCurrentDeck.java index 12cd0d0ccda..fc45e5c1dad 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/views/VCurrentDeck.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/views/VCurrentDeck.java @@ -73,6 +73,14 @@ public enum VCurrentDeck implements IVDoc { .icon(FSkin.getIcon(FSkinProp.ICO_PRINT)) .text(" ").hoverable(true).build(); + private final FLabel btnCopyToClipboard = new FLabel.Builder() + .fontSize(14) + .tooltip(localizer.getMessage("btnCopyToClipboard")) + .iconInBackground(true) + .iconAlignX(SwingConstants.CENTER) + .icon(FSkin.getIcon(FSkinProp.ICO_CLIPBOARD)) + .text(" ").hoverable(true).build(); + private final FLabel btnImport = new FLabel.Builder() .fontSize(14) .text(localizer.getMessage("lblImport")) @@ -102,7 +110,7 @@ public enum VCurrentDeck implements IVDoc { pnlHeader.add(btnLoad, "w 26px!, h 26px!"); pnlHeader.add(btnSaveAs, "w 26px!, h 26px!"); - pnlHeader.add(btnPrintProxies, "w 26px!, h 26px!"); + pnlHeader.add(btnCopyToClipboard, "w 26px!, h 26px!"); pnlHeader.add(btnImport, "w 61px!, h 26px!"); } @@ -187,6 +195,11 @@ public FLabel getBtnPrintProxies() { return btnPrintProxies; } + /** @return {@link javax.swing.JLabel} */ + public FLabel getBtnCopyToClipboard() { + return btnCopyToClipboard; + } + /** @return {@link javax.swing.JLabel} */ public FLabel getBtnOpen() { return btnLoad; diff --git a/forge-gui/res/skins/default/sprite_icons.png b/forge-gui/res/skins/default/sprite_icons.png index 1d689c69c8c..c6aacf247f6 100644 Binary files a/forge-gui/res/skins/default/sprite_icons.png and b/forge-gui/res/skins/default/sprite_icons.png differ diff --git a/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java b/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java index 95663eb9420..90ed6c0f10e 100644 --- a/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java +++ b/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java @@ -367,6 +367,7 @@ public enum FSkinProp { ICO_CLOSE (new int[] {640, 640, 20, 20}, PropType.ICON), ICO_LIST (new int[] {640, 660, 20, 20}, PropType.ICON), + ICO_CLIPBOARD (new int[] {640, 700, 20, 20}, PropType.ICON), ICO_CARD_IMAGE (new int[] {660, 660, 20, 20}, PropType.ICON), ICO_FOLDER (new int[] {640, 680, 20, 20}, PropType.ICON),