- fixed resize cursor not appearing when hovering between columns in table headers

- added forge-specific spinner widget (FSpinner)
- allowed labels to have their toggle state read externally and added configuration to set whether the onClick command is executed on mouse button down or mouse button up (FLabel)
- added builder pattern to FTextField and autoset properties to common values
- fixed header comments in WrapLayout
- renamed DialogCustomFormat to the more generic DialogChooseSets since I use it now from the filters too; extended its functionality to run a specified command on ok button click
- removed Filters dockable panel
- added old filters functionality to the stats buttons above the catalog table (stats can no longer be removed via a preference setting)
- combined scattered metadata about the filters (e.g. icon, label, filter predicate) into a single enum
- rewrote filter utility functions to not have any side effects (they now use no global data/singletons)
- added "Owned" column to spell shop catalog, indicating number of cards already owned by player (can remove column with preference)
- don't count the "click" as a sort command when resizing a column
- exposed top-level main world custom format in QuestController -- other format-retrieving methods would be masked by the current world selection
- added utility fn to TextUtils to create a (locale-independent) Title out of an ENUM
- added a templated Pair<T, V> utility class for ad-hoc two-value parameter returning
- prevented invalid enum values in editor_preferred.xml from causing errors
This commit is contained in:
myk
2013-01-30 22:04:21 +00:00
parent 09de9e2a91
commit b007e3943c
38 changed files with 1455 additions and 1657 deletions

3
.gitattributes vendored
View File

@@ -13984,7 +13984,6 @@ src/main/java/forge/gui/deckeditor/controllers/CEditorPreferences.java -text
src/main/java/forge/gui/deckeditor/controllers/CEditorQuest.java svneol=native#text/plain src/main/java/forge/gui/deckeditor/controllers/CEditorQuest.java svneol=native#text/plain
src/main/java/forge/gui/deckeditor/controllers/CEditorQuestCardShop.java -text src/main/java/forge/gui/deckeditor/controllers/CEditorQuestCardShop.java -text
src/main/java/forge/gui/deckeditor/controllers/CEditorVariant.java -text src/main/java/forge/gui/deckeditor/controllers/CEditorVariant.java -text
src/main/java/forge/gui/deckeditor/controllers/CFilters.java -text
src/main/java/forge/gui/deckeditor/controllers/CProbabilities.java -text src/main/java/forge/gui/deckeditor/controllers/CProbabilities.java -text
src/main/java/forge/gui/deckeditor/controllers/CStatistics.java -text src/main/java/forge/gui/deckeditor/controllers/CStatistics.java -text
src/main/java/forge/gui/deckeditor/package-info.java -text src/main/java/forge/gui/deckeditor/package-info.java -text
@@ -14004,7 +14003,6 @@ src/main/java/forge/gui/deckeditor/views/VCardCatalog.java -text
src/main/java/forge/gui/deckeditor/views/VCurrentDeck.java -text src/main/java/forge/gui/deckeditor/views/VCurrentDeck.java -text
src/main/java/forge/gui/deckeditor/views/VDeckgen.java -text src/main/java/forge/gui/deckeditor/views/VDeckgen.java -text
src/main/java/forge/gui/deckeditor/views/VEditorPreferences.java -text src/main/java/forge/gui/deckeditor/views/VEditorPreferences.java -text
src/main/java/forge/gui/deckeditor/views/VFilters.java -text
src/main/java/forge/gui/deckeditor/views/VProbabilities.java -text src/main/java/forge/gui/deckeditor/views/VProbabilities.java -text
src/main/java/forge/gui/deckeditor/views/VStatistics.java -text src/main/java/forge/gui/deckeditor/views/VStatistics.java -text
src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java svneol=native#text/plain src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java svneol=native#text/plain
@@ -14055,7 +14053,6 @@ src/main/java/forge/gui/home/quest/CSubmenuDuels.java -text
src/main/java/forge/gui/home/quest/CSubmenuQuestData.java -text src/main/java/forge/gui/home/quest/CSubmenuQuestData.java -text
src/main/java/forge/gui/home/quest/CSubmenuQuestDecks.java -text src/main/java/forge/gui/home/quest/CSubmenuQuestDecks.java -text
src/main/java/forge/gui/home/quest/CSubmenuQuestPrefs.java -text src/main/java/forge/gui/home/quest/CSubmenuQuestPrefs.java -text
src/main/java/forge/gui/home/quest/DialogCustomFormat.java -text
src/main/java/forge/gui/home/quest/IVQuestStats.java -text src/main/java/forge/gui/home/quest/IVQuestStats.java -text
src/main/java/forge/gui/home/quest/PnlEvent.java -text src/main/java/forge/gui/home/quest/PnlEvent.java -text
src/main/java/forge/gui/home/quest/QuestFileLister.java -text src/main/java/forge/gui/home/quest/QuestFileLister.java -text

View File

@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@@ -3,7 +3,6 @@
<cell x="0.77443" y="0.37698" w="0.22557" h="0.62302"> <cell x="0.77443" y="0.37698" w="0.22557" h="0.62302">
<doc>CARD_PICTURE</doc> <doc>CARD_PICTURE</doc>
<doc>EDITOR_PREFERENCES</doc> <doc>EDITOR_PREFERENCES</doc>
<doc>EDITOR_FILTERS</doc>
</cell> </cell>
<cell x="0.38722" y="0.0" w="0.38722" h="1.0"> <cell x="0.38722" y="0.0" w="0.38722" h="1.0">
<doc>EDITOR_CURRENTDECK</doc> <doc>EDITOR_CURRENTDECK</doc>

View File

@@ -2,13 +2,12 @@
<preferences type="editor"> <preferences type="editor">
<pref name="display_unique_only" value="true"></pref> <pref name="display_unique_only" value="true"></pref>
<pref name="elastic_columns" value="false"></pref> <pref name="elastic_columns" value="false"></pref>
<pref name="stats_catalog" value="true"></pref>
<pref name="stats_deck" value="true"></pref> <pref name="stats_deck" value="true"></pref>
<col enumval="CAT_QUANTITY" identifier="Quantity" show="true" sortpriority="3" sortstate="ASC" width="30"></col> <col enumval="CAT_QUANTITY" identifier="Quantity" show="true" sortpriority="3" sortstate="ASC" width="30"></col>
<col enumval="CAT_NAME" identifier="Name" show="true" sortpriority="0" sortstate="NONE" width="262"></col> <col enumval="CAT_NAME" identifier="Name" show="true" sortpriority="0" sortstate="NONE" width="262"></col>
<col enumval="CAT_COST" identifier="Cost" show="true" sortpriority="2" sortstate="DESC" width="82"></col> <col enumval="CAT_COST" identifier="Cost" show="true" sortpriority="2" sortstate="DESC" width="82"></col>
<col enumval="CAT_COLOR" identifier="Color" show="true" sortpriority="3" sortstate="DESC" width="54"></col> <col enumval="CAT_COLOR" identifier="Color" show="true" sortpriority="4" sortstate="DESC" width="54"></col>
<col enumval="CAT_TYPE" identifier="Type" show="true" sortpriority="1" sortstate="ASC" width="217"></col> <col enumval="CAT_TYPE" identifier="Type" show="true" sortpriority="3" sortstate="ASC" width="217"></col>
<col enumval="CAT_POWER" identifier="Power" show="true" sortpriority="0" sortstate="NONE" width="30"></col> <col enumval="CAT_POWER" identifier="Power" show="true" sortpriority="0" sortstate="NONE" width="30"></col>
<col enumval="CAT_TOUGHNESS" identifier="Toughness" show="true" sortpriority="0" sortstate="NONE" width="30"></col> <col enumval="CAT_TOUGHNESS" identifier="Toughness" show="true" sortpriority="0" sortstate="NONE" width="30"></col>
<col enumval="CAT_CMC" identifier="CMC" show="true" sortpriority="0" sortstate="NONE" width="30"></col> <col enumval="CAT_CMC" identifier="CMC" show="true" sortpriority="0" sortstate="NONE" width="30"></col>
@@ -17,6 +16,7 @@
<col enumval="CAT_AI" identifier="AI" show="false" sortpriority="0" sortstate="NONE" width="30"></col> <col enumval="CAT_AI" identifier="AI" show="false" sortpriority="0" sortstate="NONE" width="30"></col>
<col enumval="CAT_NEW" identifier="New" show="true" sortpriority="1" sortstate="ASC" width="34"></col> <col enumval="CAT_NEW" identifier="New" show="true" sortpriority="1" sortstate="ASC" width="34"></col>
<col enumval="CAT_PURCHASE_PRICE" identifier="Purchase Price" show="true" sortpriority="2" sortstate="ASC" width="40"></col> <col enumval="CAT_PURCHASE_PRICE" identifier="Purchase Price" show="true" sortpriority="2" sortstate="ASC" width="40"></col>
<col enumval="CAT_OWNED" identifier="Owned" show="true" sortpriority="1" sortstate="ASC" width="75"></col>
<col enumval="DECK_QUANTITY" identifier="Quantity" show="true" sortpriority="0" sortstate="NONE" width="30"></col> <col enumval="DECK_QUANTITY" identifier="Quantity" show="true" sortpriority="0" sortstate="NONE" width="30"></col>
<col enumval="DECK_NAME" identifier="Name" show="true" sortpriority="3" sortstate="ASC" width="262"></col> <col enumval="DECK_NAME" identifier="Name" show="true" sortpriority="3" sortstate="ASC" width="262"></col>
<col enumval="DECK_COST" identifier="Cost" show="true" sortpriority="1" sortstate="ASC" width="82"></col> <col enumval="DECK_COST" identifier="Cost" show="true" sortpriority="1" sortstate="ASC" width="82"></col>

View File

@@ -270,11 +270,9 @@ public enum FControl {
Component[] children = display.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER); Component[] children = display.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER);
if (children.length != 0) { children[0].setSize(display.getSize()); } if (children.length != 0) { children[0].setSize(display.getSize()); }
children = display.getComponentsInLayer(FView.TARGETING_LAYER); for (Component child : display.getComponentsInLayer(JLayeredPane.MODAL_LAYER)) {
if (children.length != 0) { children[0].setSize(display.getSize()); } child.setSize(display.getSize());
}
children = display.getComponentsInLayer(JLayeredPane.MODAL_LAYER);
if (children.length != 0) { children[0].setSize(display.getSize()); }
} }
/** @return {@link forge.game.player.Player} */ /** @return {@link forge.game.player.Player} */

View File

@@ -39,8 +39,8 @@ public class WrapLayout extends FlowLayout {
* and the indicated horizontal and vertical gaps. * and the indicated horizontal and vertical gaps.
* <p> * <p>
* The value of the alignment argument must be one of * The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>, * <code>FlowLayout.LEFT</code>, <code>FlowLayout.CENTER</code>,
* or <code>WrapLayout</code>. * or <code>FlowLayout.RIGHT</code>.
* @param align the alignment value * @param align the alignment value
* @param hgap the horizontal gap between components * @param hgap the horizontal gap between components
* @param vgap the vertical gap between components * @param vgap the vertical gap between components

View File

@@ -23,10 +23,11 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import forge.Card; import forge.Card;
import forge.deck.DeckBase;
import forge.gui.CardContainer; import forge.gui.CardContainer;
import forge.gui.deckeditor.SEditorIO.EditorPreference; import forge.gui.deckeditor.SEditorIO.EditorPreference;
import forge.gui.deckeditor.controllers.ACEditorBase; import forge.gui.deckeditor.controllers.ACEditorBase;
import forge.gui.deckeditor.views.VFilters; import forge.gui.deckeditor.controllers.CCardCatalog;
import forge.gui.match.controllers.CDetail; import forge.gui.match.controllers.CDetail;
import forge.gui.match.controllers.CPicture; import forge.gui.match.controllers.CPicture;
import forge.item.InventoryItem; import forge.item.InventoryItem;
@@ -74,7 +75,7 @@ public enum CDeckEditorUI implements CardContainer {
/** /**
* @return ACEditorBase<?, ?> * @return ACEditorBase<?, ?>
*/ */
public ACEditorBase<?, ?> getCurrentEditorController() { public ACEditorBase<? extends InventoryItem, ? extends DeckBase> getCurrentEditorController() {
return childController; return childController;
} }
@@ -93,7 +94,7 @@ public enum CDeckEditorUI implements CardContainer {
childController.getTableCatalog().setWantUnique(wantUnique); childController.getTableCatalog().setWantUnique(wantUnique);
childController.getTableDeck().setWantUnique(wantUnique); childController.getTableDeck().setWantUnique(wantUnique);
} }
VFilters.SINGLETON_INSTANCE.getLayoutControl().buildFilter(); CCardCatalog.SINGLETON_INSTANCE.applyCurrentFilter();
} }
//========== Other methods //========== Other methods

View File

@@ -47,9 +47,8 @@ public class SEditorIO {
} }
/** Preferences (must match with PREFS file). */ /** Preferences (must match with PREFS file). */
public enum EditorPreference { /** */ public enum EditorPreference {
stats_deck, /** */ stats_deck,
stats_catalog,
display_unique_only, display_unique_only,
elastic_columns elastic_columns
} }

View File

@@ -1,16 +1,14 @@
package forge.gui.deckeditor; package forge.gui.deckeditor;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JLabel;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import forge.Command; import forge.Command;
import forge.card.CardRulesPredicates;
import forge.card.CardRules; import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.gui.deckeditor.views.ITableContainer; import forge.gui.deckeditor.views.ITableContainer;
import forge.gui.deckeditor.views.VCardCatalog; import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.deckeditor.views.VCurrentDeck;
@@ -19,6 +17,7 @@ import forge.gui.toolbox.FSkin;
import forge.item.InventoryItem; import forge.item.InventoryItem;
import forge.item.ItemPoolView; import forge.item.ItemPoolView;
import forge.util.Aggregates; import forge.util.Aggregates;
import forge.util.TextUtil;
/** /**
@@ -31,52 +30,38 @@ import forge.util.Aggregates;
* *
*/ */
public final class SEditorUtil { public final class SEditorUtil {
/** Pre-cached resized version. */ /** An enum to encapsulate metadata for the stats/filter objects. */
public static final ImageIcon ICO_ARTIFACT = public static enum StatTypes {
new ImageIcon(FSkin.getImage(FSkin.EditorImages.IMG_ARTIFACT, 18, 18)); TOTAL (FSkin.ZoneImages.ICO_HAND, null),
/** Pre-cached resized version. */
public static final ImageIcon ICO_CREATURE =
new ImageIcon(FSkin.getImage(FSkin.EditorImages.IMG_CREATURE, 18, 18));
/** Pre-cached resized version. */
public static final ImageIcon ICO_ENCHANTMENT =
new ImageIcon(FSkin.getImage(FSkin.EditorImages.IMG_ENCHANTMENT, 18, 18));
/** Pre-cached resized version. */
public static final ImageIcon ICO_INSTANT =
new ImageIcon(FSkin.getImage(FSkin.EditorImages.IMG_INSTANT, 18, 18));
/** Pre-cached resized version. */
public static final ImageIcon ICO_LAND =
new ImageIcon(FSkin.getImage(FSkin.EditorImages.IMG_LAND, 18, 18));
/** Pre-cached resized version. */
public static final ImageIcon ICO_PLANESWALKER =
new ImageIcon(FSkin.getImage(FSkin.EditorImages.IMG_PLANESWALKER, 18, 18));
/** Pre-cached resized version. */
public static final ImageIcon ICO_SORCERY =
new ImageIcon(FSkin.getImage(FSkin.EditorImages.IMG_SORCERY, 18, 18));
/** Pre-cached resized version. */ WHITE (FSkin.ManaImages.IMG_WHITE, CardRulesPredicates.Presets.IS_WHITE),
public static final ImageIcon ICO_TOTAL = BLUE (FSkin.ManaImages.IMG_BLUE, CardRulesPredicates.Presets.IS_BLUE),
new ImageIcon(FSkin.getImage(FSkin.ZoneImages.ICO_HAND, 18, 18)); BLACK (FSkin.ManaImages.IMG_BLACK, CardRulesPredicates.Presets.IS_BLACK),
/** Pre-cached resized version. */ RED (FSkin.ManaImages.IMG_RED, CardRulesPredicates.Presets.IS_RED),
public static final ImageIcon ICO_MULTI = GREEN (FSkin.ManaImages.IMG_GREEN, CardRulesPredicates.Presets.IS_GREEN),
new ImageIcon(FSkin.getImage(FSkin.EditorImages.IMG_MULTI, 18, 18)); COLORLESS (FSkin.ManaImages.IMG_COLORLESS, CardRulesPredicates.Presets.IS_COLORLESS),
/** Pre-cached resized version. */ MULTICOLOR (FSkin.EditorImages.IMG_MULTI, CardRulesPredicates.Presets.IS_MULTICOLOR),
public static final ImageIcon ICO_BLACK =
new ImageIcon(FSkin.getImage(FSkin.ManaImages.IMG_BLACK, 18, 18)); LAND (FSkin.EditorImages.IMG_LAND, CardRulesPredicates.Presets.IS_LAND),
/** Pre-cached resized version. */ ARTIFACT (FSkin.EditorImages.IMG_ARTIFACT, CardRulesPredicates.Presets.IS_ARTIFACT),
public static final ImageIcon ICO_BLUE = CREATURE (FSkin.EditorImages.IMG_CREATURE, CardRulesPredicates.Presets.IS_CREATURE),
new ImageIcon(FSkin.getImage(FSkin.ManaImages.IMG_BLUE, 18, 18)); ENCHANTMENT (FSkin.EditorImages.IMG_ENCHANTMENT, CardRulesPredicates.Presets.IS_ENCHANTMENT),
/** Pre-cached resized version. */ PLANESWALKER (FSkin.EditorImages.IMG_PLANESWALKER, CardRulesPredicates.Presets.IS_PLANESWALKER),
public static final ImageIcon ICO_GREEN = INSTANT (FSkin.EditorImages.IMG_INSTANT, CardRulesPredicates.Presets.IS_INSTANT),
new ImageIcon(FSkin.getImage(FSkin.ManaImages.IMG_GREEN, 18, 18)); SORCERY (FSkin.EditorImages.IMG_SORCERY, CardRulesPredicates.Presets.IS_SORCERY);
/** Pre-cached resized version. */
public static final ImageIcon ICO_RED = public final ImageIcon img;
new ImageIcon(FSkin.getImage(FSkin.ManaImages.IMG_RED, 18, 18)); public final Predicate<CardRules> predicate;
/** Pre-cached resized version. */
public static final ImageIcon ICO_WHITE = StatTypes(FSkin.SkinProp prop, Predicate<CardRules> pred) {
new ImageIcon(FSkin.getImage(FSkin.ManaImages.IMG_WHITE, 18, 18)); img = new ImageIcon(FSkin.getImage(prop, 18, 18));
/** Pre-cached resized version. */ predicate = pred;
public static final ImageIcon ICO_COLORLESS = }
new ImageIcon(FSkin.getImage(FSkin.ColorlessManaImages.IMG_X, 18, 18));
public String toLabelString() {
return TextUtil.enumToLabel(this) + " cards";
}
}
/** /**
* Divides X by Y, multiplies by 100, rounds, returns. * Divides X by Y, multiplies by 100, rounds, returns.
@@ -86,12 +71,7 @@ public final class SEditorUtil {
* @return rounded result (int) * @return rounded result (int)
*/ */
public static int calculatePercentage(final int x0, final int y0) { public static int calculatePercentage(final int x0, final int y0) {
return (int) Math.round((double) x0 / (double) y0 * 100); return (int) Math.round((double) (x0 * 100) / (double) y0);
}
public static <T extends InventoryItem> void setLabelTextSum(JLabel label, final ItemPoolView<T> deck, Predicate<CardRules> predicate) {
int sum = Aggregates.sum(Iterables.filter(deck, Predicates.compose(predicate, deck.getFnToCard())), deck.getFnToCount());
label.setText(String.valueOf(sum));
} }
/** /**
@@ -102,27 +82,25 @@ public final class SEditorUtil {
* @param view &emsp; {@link forge.gui.deckeditor.views.ITableContainer} * @param view &emsp; {@link forge.gui.deckeditor.views.ITableContainer}
*/ */
public static <T extends InventoryItem> void setStats(final ItemPoolView<T> deck, final ITableContainer view) { public static <T extends InventoryItem> void setStats(final ItemPoolView<T> deck, final ITableContainer view) {
view.getLblTotal().setText(String.valueOf(deck.countAll())); for (StatTypes s : StatTypes.values()) {
switch (s) {
setLabelTextSum(view.getLblCreature(), deck, CardRulesPredicates.Presets.IS_CREATURE); case TOTAL:
setLabelTextSum(view.getLblLand(), deck, CardRulesPredicates.Presets.IS_LAND); view.getStatLabel(StatTypes.TOTAL).setText(String.valueOf(deck.countAll()));
setLabelTextSum(view.getLblEnchantment(), deck, CardRulesPredicates.Presets.IS_ENCHANTMENT); break;
setLabelTextSum(view.getLblArtifact(), deck, CardRulesPredicates.Presets.IS_ARTIFACT); case COLORLESS:
setLabelTextSum(view.getLblInstant(), deck, CardRulesPredicates.Presets.IS_INSTANT); break; // TODO: why?
setLabelTextSum(view.getLblSorcery(), deck, CardRulesPredicates.Presets.IS_SORCERY); default:
setLabelTextSum(view.getLblPlaneswalker(), deck, CardRulesPredicates.Presets.IS_PLANESWALKER); view.getStatLabel(s).setText(String.valueOf(
setLabelTextSum(view.getLblColorless(), deck, CardRulesPredicates.Presets.IS_COLORLESS); Aggregates.sum(Iterables.filter(deck, Predicates.compose(s.predicate, deck.getFnToCard())), deck.getFnToCount())));
setLabelTextSum(view.getLblBlack(), deck, CardRulesPredicates.Presets.IS_BLACK); }
setLabelTextSum(view.getLblBlue(), deck, CardRulesPredicates.Presets.IS_BLUE); }
setLabelTextSum(view.getLblGreen(), deck, CardRulesPredicates.Presets.IS_GREEN);
setLabelTextSum(view.getLblRed(), deck, CardRulesPredicates.Presets.IS_RED);
setLabelTextSum(view.getLblWhite(), deck, CardRulesPredicates.Presets.IS_WHITE);
} // getStats() } // getStats()
/** /**
* Resets components that may have been changed * Resets components that may have been changed
* by various configurations of the deck editor. * by various configurations of the deck editor.
*/ */
@SuppressWarnings("serial")
public static void resetUI() { public static void resetUI() {
VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setVisible(true); VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove4().setVisible(true); VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove4().setVisible(true);
@@ -142,16 +120,13 @@ public final class SEditorUtil {
VCurrentDeck.SINGLETON_INSTANCE.getTabLabel().setText("Current Deck"); VCurrentDeck.SINGLETON_INSTANCE.getTabLabel().setText("Current Deck");
VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies().setVisible(true); VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard().setVisible(false); VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard().setVisible(false);
VCurrentDeck.SINGLETON_INSTANCE.getTxfTitle().setVisible(true); VCurrentDeck.SINGLETON_INSTANCE.getTxfTitle().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getLblTitle().setText("Title:"); VCurrentDeck.SINGLETON_INSTANCE.getLblTitle().setText("Title:");
((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnSave()) ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnSave())
.setCommand(new Command() { private static final long serialVersionUID = -7995834050136126035L; .setCommand(new Command() {
@Override public void execute() { SEditorIO.saveDeck(); } });
@Override
public void execute() { SEditorIO.saveDeck(); } });
} }
} }

View File

@@ -1,33 +1,21 @@
package forge.gui.deckeditor; package forge.gui.deckeditor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import forge.card.CardEdition;
import forge.card.CardRulesPredicates;
import forge.card.CardRules; import forge.card.CardRules;
import forge.game.GameFormat; import forge.card.CardRulesPredicates;
import forge.gui.WrapLayout; import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VFilters; import forge.gui.deckeditor.views.VCardCatalog.RangeTypes;
import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSpinner;
import forge.item.CardPrinted; import forge.item.CardPrinted;
import forge.util.ComparableOp; import forge.util.ComparableOp;
import forge.util.Pair;
import forge.util.PredicateString.StringOp; import forge.util.PredicateString.StringOp;
/** /**
@@ -37,300 +25,96 @@ import forge.util.PredicateString.StringOp;
* <i>(S at beginning of class name denotes a static factory.)</i> * <i>(S at beginning of class name denotes a static factory.)</i>
*/ */
public class SFilterUtil { public class SFilterUtil {
/** An enum to encapsulate metadata for the checkbox objects in the color/type filter maps. */
private enum FilterProperty {
WHITE (SEditorUtil.ICO_WHITE.getImage(), "White Cards"),
BLUE (SEditorUtil.ICO_BLUE.getImage(), "Blue Cards"),
BLACK (SEditorUtil.ICO_BLACK.getImage(), "Black Cards"),
RED (SEditorUtil.ICO_RED.getImage(), "Red Cards"),
GREEN (SEditorUtil.ICO_GREEN.getImage(), "Green Cards"),
COLORLESS (SEditorUtil.ICO_COLORLESS.getImage(), "Colorless Cards"),
MULTICOLOR (SEditorUtil.ICO_MULTI.getImage(), "Multicolor Cards"),
LAND (SEditorUtil.ICO_LAND.getImage(), "Land Cards"),
ARTIFACT (SEditorUtil.ICO_ARTIFACT.getImage(), "Artifact Cards"),
CREATURE (SEditorUtil.ICO_CREATURE.getImage(), "Creature Cards"),
ENCHANTMENT (SEditorUtil.ICO_ENCHANTMENT.getImage(), "Enchantment Cards"),
PLANESWALKER (SEditorUtil.ICO_PLANESWALKER.getImage(), "Planeswalker Cards"),
INSTANT (SEditorUtil.ICO_INSTANT.getImage(), "Instant Cards"),
SORCERY (SEditorUtil.ICO_SORCERY.getImage(), "Sorcery Cards");
private final Image img;
private final String tooltip;
FilterProperty(final Image img0, final String tooltip0) {
img = img0;
tooltip = tooltip0;
}
public Image getImage() {
return img;
}
public String getTooltip() {
return tooltip;
}
}
private static final FilterProperty[] COLOR_FILTER_PROPERTIES = {
FilterProperty.WHITE,
FilterProperty.BLUE,
FilterProperty.BLACK,
FilterProperty.RED,
FilterProperty.GREEN,
FilterProperty.COLORLESS,
FilterProperty.MULTICOLOR
};
private static final FilterProperty[] TYPE_FILTER_PROPERTIES = {
FilterProperty.LAND,
FilterProperty.ARTIFACT,
FilterProperty.CREATURE,
FilterProperty.ENCHANTMENT,
FilterProperty.PLANESWALKER,
FilterProperty.INSTANT,
FilterProperty.SORCERY
};
private static final Map<FilterProperty, ChbPnl> MAP_COLOR_CHECKBOXES =
new HashMap<FilterProperty, ChbPnl>();
private static final Map<FilterProperty, ChbPnl> MAP_TYPE_CHECKBOXES =
new HashMap<FilterProperty, ChbPnl>();
/** /**
* queries color filters for state and returns a predicate.
*/
private static boolean preventFiltering = false;
/**
* This will prevent a filter event on a checkbox state change.
* It's used for programmatic changes to the checkboxes when rebuilding
* the filter each time is expensive.
*
* @return boolean &emsp; true if filtering is prevented
*/
public static boolean isFilteringPrevented() {
return preventFiltering;
}
/**
* This will prevent a filter event on a checkbox state change.
* It's used for programmatic changes to the checkboxes when rebuilding
* the filter each time is expensive.
*
* @param bool0 &emsp; true to prevent filtering
*/
public static void setPreventFiltering(final boolean bool0) {
preventFiltering = bool0;
}
/**
* Fills and returns a JPanel with checkboxes for color filter set.
*
* @return {@link javax.swing.JPanel}
*/
public static JPanel populateColorFilters() {
final JPanel pnl = new JPanel(new WrapLayout(SwingConstants.CENTER, 10, 5));
pnl.setOpaque(false);
MAP_COLOR_CHECKBOXES.clear();
for (FilterProperty p : COLOR_FILTER_PROPERTIES) {
ChbPnl chbPnl = new ChbPnl(p.getImage(), p.getTooltip());
MAP_COLOR_CHECKBOXES.put(p, chbPnl);
pnl.add(chbPnl);
}
return pnl;
}
/**
* Fills and returns a JPanel with checkboxes for type filter set.
*
* @return {@link javax.swing.JPanel}
*/
public static JPanel populateTypeFilters() {
final JPanel pnl = new JPanel(new WrapLayout(SwingConstants.CENTER, 10, 5));
pnl.setOpaque(false);
MAP_TYPE_CHECKBOXES.clear();
for (FilterProperty p : TYPE_FILTER_PROPERTIES) {
ChbPnl chbPnl = new ChbPnl(p.getImage(), p.getTooltip());
MAP_TYPE_CHECKBOXES.put(p, chbPnl);
pnl.add(chbPnl);
}
return pnl;
}
/** Turns all type checkboxes off or on.
* @param select0 &emsp; boolean */
public static void toggleTypeCheckboxes(final boolean select0) {
for (ChbPnl p : MAP_TYPE_CHECKBOXES.values()) {
p.getCheckBox().setSelected(select0);
}
}
/** Turns all color checkboxes off or on.
* @param select0 &emsp; boolean */
public static void toggleColorCheckboxes(final boolean select0) {
for (ChbPnl p : MAP_COLOR_CHECKBOXES.values()) {
p.getCheckBox().setSelected(select0);
}
}
/**
* Assembles checkboxes for color and returns a filter predicate.
* <br><br> * <br><br>
* Handles "multicolor" label, which is quite tricky. * Handles "multicolor" label, which is quite tricky.
*
* @return Predicate<CardPrinted>
*/ */
public static Predicate<CardPrinted> buildColorFilter() { public static Predicate<CardPrinted> buildColorAndTypeFilter(Map<SEditorUtil.StatTypes, FLabel> statLabels) {
if (MAP_COLOR_CHECKBOXES.isEmpty()) { return Predicates.alwaysTrue(); }
final List<Predicate<CardRules>> colors = new ArrayList<Predicate<CardRules>>(); final List<Predicate<CardRules>> colors = new ArrayList<Predicate<CardRules>>();
final List<Predicate<CardRules>> types = new ArrayList<Predicate<CardRules>>();
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.WHITE).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_WHITE); } boolean wantMulticolor = false;
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.BLUE).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_BLUE); } Predicate<CardRules> preExceptMulti = null;
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.BLACK).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_BLACK); } for (SEditorUtil.StatTypes s : SEditorUtil.StatTypes.values()) {
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.RED).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_RED); } switch (s) {
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.GREEN).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_GREEN); } case WHITE: case BLUE: case BLACK: case RED: case GREEN: case COLORLESS:
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.COLORLESS).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_COLORLESS); } if (statLabels.get(s).isSelected()) { colors.add(s.predicate); }
break;
case MULTICOLOR:
wantMulticolor = statLabels.get(s).isSelected();
preExceptMulti = wantMulticolor ? null : Predicates.not(CardRulesPredicates.Presets.IS_MULTICOLOR);
break;
case LAND: case ARTIFACT: case CREATURE: case ENCHANTMENT: case PLANESWALKER: case INSTANT: case SORCERY:
if (statLabels.get(s).isSelected()) { types.add(s.predicate); }
break;
final Predicate<CardRules> preColors = colors.size() == 6 ? null : Predicates.or(colors); case TOTAL:
// ignore
break;
boolean wantMulticolor = MAP_COLOR_CHECKBOXES.get(FilterProperty.MULTICOLOR).getCheckBox().isSelected(); default:
final Predicate<CardRules> preExceptMulti = wantMulticolor ? null : Predicates.not(CardRulesPredicates.Presets.IS_MULTICOLOR); throw new RuntimeException("unhandled enum value: " + s);
}
}
Predicate<CardRules> preFinal = colors.isEmpty() && wantMulticolor ? CardRulesPredicates.Presets.IS_MULTICOLOR : optimizedAnd(preExceptMulti, preColors); Predicate<CardRules> preColors = colors.size() == 6 ? null : Predicates.or(colors);
Predicate<CardRules> preFinal = colors.isEmpty() && wantMulticolor ?
CardRulesPredicates.Presets.IS_MULTICOLOR : optimizedAnd(preExceptMulti, preColors);
if (null == preFinal && 7 == types.size()) {
return Predicates.alwaysTrue();
}
Predicate<CardPrinted> typesFinal = Predicates.compose(Predicates.or(types), CardPrinted.FN_GET_RULES);
if (null == preFinal) { if (null == preFinal) {
return Predicates.alwaysTrue(); return typesFinal;
} }
return Predicates.compose(preFinal, CardPrinted.FN_GET_RULES); Predicate<CardPrinted> colorFinal = Predicates.compose(preFinal, CardPrinted.FN_GET_RULES);
if (7 == types.size()) {
return colorFinal;
}
return Predicates.and(colorFinal, typesFinal);
} }
/** /**
* Filters the set/format combo box. * builds a string search filter
*
* @return Predicate<CardPrinted>
*/ */
public static Predicate<CardPrinted> buildSetAndFormatFilter() { public static Predicate<CardPrinted> buildTextFilter(String text, boolean invert, boolean inName, boolean inType, boolean inText) {
// Set/Format filter if (text.trim().isEmpty()) {
JComboBox cbox = VFilters.SINGLETON_INSTANCE.getCbxSets();
if (cbox.getSelectedIndex() == 0) {
return Predicates.alwaysTrue(); return Predicates.alwaysTrue();
} }
final Object selected = cbox.getSelectedItem(); String[] splitText = text
final Predicate<CardPrinted> filter;
if (selected instanceof CardEdition) {
filter = CardPrinted.Predicates.printedInSets(((CardEdition) selected).getCode());
} else {
filter = ((GameFormat) selected).getFilterRules();
}
return filter;
}
/**
* Assembles checkboxes for type and returns a filter predicate.
*
* @return Predicate<CardPrinted>
*/
public static Predicate<CardPrinted> buildTypeFilter() {
if (MAP_TYPE_CHECKBOXES.isEmpty()) { return Predicates.alwaysTrue(); }
final List<Predicate<CardRules>> ors = new ArrayList<Predicate<CardRules>>();
if (MAP_TYPE_CHECKBOXES.get(FilterProperty.LAND).getCheckBox().isSelected()) { ors.add(CardRulesPredicates.Presets.IS_LAND); }
if (MAP_TYPE_CHECKBOXES.get(FilterProperty.ARTIFACT).getCheckBox().isSelected()) { ors.add(CardRulesPredicates.Presets.IS_ARTIFACT); }
if (MAP_TYPE_CHECKBOXES.get(FilterProperty.CREATURE).getCheckBox().isSelected()) { ors.add(CardRulesPredicates.Presets.IS_CREATURE); }
if (MAP_TYPE_CHECKBOXES.get(FilterProperty.ENCHANTMENT).getCheckBox().isSelected()) { ors.add(CardRulesPredicates.Presets.IS_ENCHANTMENT); }
if (MAP_TYPE_CHECKBOXES.get(FilterProperty.PLANESWALKER).getCheckBox().isSelected()) { ors.add(CardRulesPredicates.Presets.IS_PLANESWALKER); }
if (MAP_TYPE_CHECKBOXES.get(FilterProperty.INSTANT).getCheckBox().isSelected()) { ors.add(CardRulesPredicates.Presets.IS_INSTANT); }
if (MAP_TYPE_CHECKBOXES.get(FilterProperty.SORCERY).getCheckBox().isSelected()) { ors.add(CardRulesPredicates.Presets.IS_SORCERY); }
if (ors.size() == 7) {
return Predicates.alwaysTrue();
}
return Predicates.compose(Predicates.or(ors), CardPrinted.FN_GET_RULES);
}
/**
* Validates text field input (from txfContains and txfWithout),
* then assembles AND and NOT predicates accordingly, ANDs
* together, and returns.
*
* @return Predicate<CardPrinted>
*/
public static Predicate<CardPrinted> buildTextFilter() {
Predicate<CardRules> filterAnd = null;
Predicate<CardRules> filterNot = null;
final String strContains = VFilters.SINGLETON_INSTANCE.getTxfContains().getText();
final String strWithout = VFilters.SINGLETON_INSTANCE.getTxfWithout().getText();
final boolean useName = VFilters.SINGLETON_INSTANCE.getChbTextName().isSelected();
final boolean useType = VFilters.SINGLETON_INSTANCE.getChbTextType().isSelected();
final boolean useText = VFilters.SINGLETON_INSTANCE.getChbTextText().isSelected();
if (!strContains.isEmpty()) {
final String[] splitContains = strContains
.replaceAll(",", "") .replaceAll(",", "")
.replaceAll(" ", " ") .replaceAll(" ", " ")
.toLowerCase().split(" "); .toLowerCase().split(" ");
final List<Predicate<CardRules>> ands = new ArrayList<Predicate<CardRules>>(); List<Predicate<CardRules>> terms = new ArrayList<Predicate<CardRules>>();
for (String s : splitText) {
List<Predicate<CardRules>> subands = new ArrayList<Predicate<CardRules>>();
for (final String s : splitContains) { if (inName) { subands.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, s)); }
final List<Predicate<CardRules>> subands = new ArrayList<Predicate<CardRules>>(); if (inType) { subands.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, s)); }
if (useName) { subands.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, s)); }
if (useType) { subands.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, s)); }
// rules cannot compare in ignore-case way // rules cannot compare in ignore-case way
if (useText) { subands.add(CardRulesPredicates.rules(StringOp.CONTAINS, s)); } if (inText) { subands.add(CardRulesPredicates.rules(StringOp.CONTAINS, s)); }
ands.add(Predicates.or(subands)); terms.add(Predicates.or(subands));
} }
filterAnd = Predicates.and(ands); Predicate<CardRules> textFilter = invert ? Predicates.not(Predicates.or(terms)) : Predicates.and(terms);
return Predicates.compose(textFilter, CardPrinted.FN_GET_RULES);
} }
if (!strWithout.isEmpty()) { private static Predicate<CardRules> getCardRulesFieldPredicate(int min, int max, CardRulesPredicates.LeafNumber.CardField field) {
final String[] splitWithout = strWithout boolean hasMin = 0 != min;
.replaceAll(" ", " ") boolean hasMax = 10 != max;
.replaceAll(",", "")
.toLowerCase().split(" ");
final List<Predicate<CardRules>> nots = new ArrayList<Predicate<CardRules>>(); Predicate<CardRules> pMin = !hasMin ? null : new CardRulesPredicates.LeafNumber(field, ComparableOp.GT_OR_EQUAL, min);
Predicate<CardRules> pMax = !hasMax ? null : new CardRulesPredicates.LeafNumber(field, ComparableOp.LT_OR_EQUAL, max);
for (final String s : splitWithout) {
final List<Predicate<CardRules>> subnots = new ArrayList<Predicate<CardRules>>();
if (useName) { subnots.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, s)); }
if (useType) { subnots.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, s)); }
// rules cannot compare in ignore-case way
if (useText) { subnots.add(CardRulesPredicates.rules(StringOp.CONTAINS, s)); }
nots.add(Predicates.or(subnots));
}
filterNot = Predicates.not(Predicates.or(nots));
}
Predicate<CardRules> preResult = optimizedAnd(filterAnd, filterNot);
if (preResult == null) {
return Predicates.alwaysTrue();
}
return Predicates.compose(preResult, CardPrinted.FN_GET_RULES);
}
private static Predicate<CardRules> getCardRulesFieldPredicate(String min, String max, CardRulesPredicates.LeafNumber.CardField field) {
boolean hasMin = !("*".equals(min));
boolean hasMax = !("10+".equals(max));
Predicate<CardRules> pMin = !hasMin ? null : new CardRulesPredicates.LeafNumber(field, ComparableOp.GT_OR_EQUAL, Integer.valueOf(min));
Predicate<CardRules> pMax = !hasMax ? null : new CardRulesPredicates.LeafNumber(field, ComparableOp.LT_OR_EQUAL, Integer.valueOf(max));
return optimizedAnd(pMin, pMax); return optimizedAnd(pMin, pMax);
} }
@@ -341,78 +125,23 @@ public class SFilterUtil {
} }
/** /**
* Validates combo box input, assembles predicate filters for each case, * builds a filter for an interval on a card field
* stacks them all together, and returns the predicate.
*
* @return Predicate<CardPrinted>
*/ */
public static Predicate<CardPrinted> buildIntervalFilter() { public static Predicate<CardPrinted> buildIntervalFilter(
final VFilters view = VFilters.SINGLETON_INSTANCE; Map<RangeTypes, Pair<FSpinner, FSpinner>> spinners, VCardCatalog.RangeTypes field) {
Pair<FSpinner, FSpinner> sPair = spinners.get(field);
Predicate<CardRules> fieldFilter = getCardRulesFieldPredicate(
Integer.valueOf(sPair.a.getValue().toString()), Integer.valueOf(sPair.b.getValue().toString()), field.cardField);
// Must include -1 so non-creatures are included by default. if (null != fieldFilter && VCardCatalog.RangeTypes.CMC != field)
Predicate<CardRules> preToughness = getCardRulesFieldPredicate(view.getCbxTLow().getSelectedItem().toString(), view.getCbxTHigh().getSelectedItem().toString(), CardRulesPredicates.LeafNumber.CardField.TOUGHNESS); {
Predicate<CardRules> prePower = getCardRulesFieldPredicate(view.getCbxPLow().getSelectedItem().toString(), view.getCbxPHigh().getSelectedItem().toString(), CardRulesPredicates.LeafNumber.CardField.POWER); fieldFilter = Predicates.and(fieldFilter, CardRulesPredicates.Presets.IS_CREATURE);
Predicate<CardRules> preCMC = getCardRulesFieldPredicate(view.getCbxCMCLow().getSelectedItem().toString(), view.getCbxCMCHigh().getSelectedItem().toString(), CardRulesPredicates.LeafNumber.CardField.CMC); }
Predicate<CardRules> preCreature = optimizedAnd(preToughness, prePower); if (fieldFilter == null) {
preCreature = preCreature == null ? null : Predicates.and(preCreature, CardRulesPredicates.Presets.IS_CREATURE);
Predicate<CardRules> preFinal = optimizedAnd(preCMC, preCreature);
if (preFinal == null) {
return Predicates.alwaysTrue(); return Predicates.alwaysTrue();
} else { } else {
return Predicates.compose(preFinal, CardPrinted.FN_GET_RULES); return Predicates.compose(fieldFilter, CardPrinted.FN_GET_RULES);
}
}
//========== Custom class handling
/**
* A panel with a checkbox and an icon, which will toggle the
* checkbox when anywhere in the panel is clicked.
*/
@SuppressWarnings("serial")
private static class ChbPnl extends JPanel implements ItemListener {
private final JCheckBox checkBox = new JCheckBox();
private final Image img;
public ChbPnl(final Image img0, final String tooltip) {
super();
this.img = img0;
this.setOpaque(false);
checkBox.setBorder(new EmptyBorder(0, 20, 0, 0));
checkBox.setOpaque(false);
checkBox.setSelected(true);
checkBox.addItemListener(this);
checkBox.setToolTipText(tooltip);
add(checkBox);
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(final MouseEvent me) {
checkBox.doClick();
}
});
}
public JCheckBox getCheckBox() {
return this.checkBox;
}
@Override
protected void paintComponent(final Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
}
/* (non-Javadoc)
* @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
*/
@Override
public void itemStateChanged(final ItemEvent arg0) {
if (!preventFiltering) {
VFilters.SINGLETON_INSTANCE.getLayoutControl().buildFilter();
}
} }
} }
} }

View File

@@ -1,11 +1,50 @@
package forge.gui.deckeditor.controllers; package forge.gui.deckeditor.controllers;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import forge.Command; import forge.Command;
import forge.Singletons;
import forge.card.CardEdition;
import forge.card.EditionCollection;
import forge.deck.DeckBase;
import forge.game.GameFormat;
import forge.gui.deckeditor.CDeckEditorUI; import forge.gui.deckeditor.CDeckEditorUI;
import forge.gui.deckeditor.SEditorUtil;
import forge.gui.deckeditor.SFilterUtil;
import forge.gui.deckeditor.views.VCardCatalog; import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCardCatalog.RangeTypes;
import forge.gui.framework.ICDoc; import forge.gui.framework.ICDoc;
import forge.gui.home.quest.DialogChooseSets;
import forge.gui.toolbox.FLabel; import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSpinner;
import forge.item.CardPrinted;
import forge.item.InventoryItem; import forge.item.InventoryItem;
import forge.item.ItemPredicate;
import forge.quest.QuestWorld;
import forge.quest.data.GameFormatQuest;
import forge.util.Pair;
/** /**
* Controls the "card catalog" panel in the deck editor UI. * Controls the "card catalog" panel in the deck editor UI.
@@ -17,7 +56,12 @@ public enum CCardCatalog implements ICDoc {
/** */ /** */
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
// refresh analysis on add private final Set<Predicate<CardPrinted>> activePredicates = new HashSet<Predicate<CardPrinted>>();
private final Set<GameFormat> activeFormats = new HashSet<GameFormat>();
private final Set<QuestWorld> activeWorlds = new HashSet<QuestWorld>();
private final Set<RangeTypes> activeRanges = EnumSet.noneOf(RangeTypes.class);
private boolean disableFiltering = false;
private CCardCatalog() { private CCardCatalog() {
} }
@@ -38,8 +82,8 @@ public enum CCardCatalog implements ICDoc {
@Override @Override
@SuppressWarnings("serial") @SuppressWarnings("serial")
public void initialize() { public void initialize() {
// Add/remove buttons // Add/remove buttons (refresh analysis on add)
((FLabel) VCardCatalog.SINGLETON_INSTANCE.getBtnAdd()).setCommand(new Command() { VCardCatalog.SINGLETON_INSTANCE.getBtnAdd().setCommand(new Command() {
@Override @Override
public void execute() { public void execute() {
CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().addCard(); CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().addCard();
@@ -48,8 +92,7 @@ public enum CCardCatalog implements ICDoc {
CProbabilities.SINGLETON_INSTANCE.update(); CProbabilities.SINGLETON_INSTANCE.update();
} }
}); });
VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setCommand(new Command() {
((FLabel) VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4()).setCommand(new Command() {
@Override @Override
public void execute() { public void execute() {
final InventoryItem item = CDeckEditorUI.SINGLETON_INSTANCE final InventoryItem item = CDeckEditorUI.SINGLETON_INSTANCE
@@ -65,6 +108,180 @@ public enum CCardCatalog implements ICDoc {
CProbabilities.SINGLETON_INSTANCE.update(); CProbabilities.SINGLETON_INSTANCE.update();
} }
}); });
final Command updateFilterCommand = new Command() {
@Override
public void execute() {
if (!disableFiltering) {
applyCurrentFilter();
}
}
};
for (FLabel statLabel : VCardCatalog.SINGLETON_INSTANCE.getStatLabels().values()) {
statLabel.setCommand(updateFilterCommand);
}
VCardCatalog.SINGLETON_INSTANCE.getStatLabel(SEditorUtil.StatTypes.TOTAL).setCommand(new Command() {
private boolean lastToggle = true;
@Override
public void execute() {
disableFiltering = true;
lastToggle = !lastToggle;
for (SEditorUtil.StatTypes s : SEditorUtil.StatTypes.values()) {
if (SEditorUtil.StatTypes.TOTAL != s) {
VCardCatalog.SINGLETON_INSTANCE.getStatLabel(s).setSelected(lastToggle);
}
}
disableFiltering = false;
applyCurrentFilter();
}
});
// assemble add restriction menu
VCardCatalog.SINGLETON_INSTANCE.getBtnAddRestriction().setCommand(new Command() {
@Override
public void execute() {
JPopupMenu popup = new JPopupMenu("Popup");
addMenuItem(popup, "Current text search", canSearch(),
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
new Command() {
@Override
public void execute() {
addRestriction(buildSearchRestriction(), null, null);
}
});
JMenu fmt = new JMenu("Format");
for (final GameFormat f : Singletons.getModel().getFormats()) {
addMenuItem(fmt, f.getName(), !isActive(activeFormats, f), null, new Command() {
@Override
public void execute() {
addRestriction(buildFormatRestriction(f.toString(), f), activeFormats, f);
}
});
}
popup.add(fmt);
addMenuItem(popup, "Edition (set)...", true, null, new Command() {
@Override
public void execute() {
final List<String> setCodes = new ArrayList<String>();
new DialogChooseSets(setCodes, new Runnable() {
@Override
public void run() {
if (setCodes.isEmpty()) {
return;
}
GameFormat f = new GameFormat(null, setCodes, null);
StringBuilder label = new StringBuilder("Sets:");
boolean truncated = false;
for (String code : setCodes)
{
// don't let the full label get too long
if (32 > label.length()) {
label.append(" ").append(code).append(";");
} else {
truncated = true;
break;
}
}
// chop off last semicolons
label.delete(label.length() - 1, label.length());
if (truncated) {
label.append("...");
}
addRestriction(buildFormatRestriction(label.toString(), f), null, null);
}
});
}
});
JMenu range = new JMenu("Value range");
for (final RangeTypes t : RangeTypes.values()) {
addMenuItem(range, t.toLabelString() + " restriction", !isActive(activeRanges, t), null, new Command() {
@Override
public void execute() {
addRestriction(buildRangeRestriction(t), activeRanges, t);
}
});
}
popup.add(range);
JMenu world = new JMenu("Quest world");
for (final QuestWorld w : Singletons.getModel().getWorlds()) {
addMenuItem(world, w.getName(), !isActive(activeWorlds, w), null, new Command() {
@Override
public void execute() {
addRestriction(buildWorldRestriction(w), activeWorlds, w);
}
});
}
popup.add(world);
popup.show(VCardCatalog.SINGLETON_INSTANCE.getBtnAddRestriction(), 0, 0);
}
});
VCardCatalog.SINGLETON_INSTANCE.getCbSearchMode().addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent arg0) {
applyCurrentFilter();
}
});
VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 10) {
if (e.isControlDown() || e.isMetaDown()) {
if (canSearch()) {
addRestriction(buildSearchRestriction(), null, null);
}
}
}
}
@Override
public void keyReleased(KeyEvent e) {
applyCurrentFilter();
}
});
VCardCatalog.SINGLETON_INSTANCE.getLblName().setCommand(updateFilterCommand);
VCardCatalog.SINGLETON_INSTANCE.getLblType().setCommand(updateFilterCommand);
VCardCatalog.SINGLETON_INSTANCE.getLblText().setCommand(updateFilterCommand);
// ensure mins can's exceed maxes and maxes can't fall below mins
for (Pair<FSpinner, FSpinner> sPair : VCardCatalog.SINGLETON_INSTANCE.getSpinners().values()) {
final FSpinner min = sPair.a;
final FSpinner max = sPair.b;
min.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
if (Integer.parseInt(max.getValue().toString()) <
Integer.parseInt(min.getValue().toString()))
{
max.setValue(min.getValue());
}
applyCurrentFilter();
}
});
max.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
if (Integer.parseInt(min.getValue().toString()) >
Integer.parseInt(max.getValue().toString()))
{
min.setValue(max.getValue());
}
applyCurrentFilter();
}
});
}
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -73,4 +290,220 @@ public enum CCardCatalog implements ICDoc {
@Override @Override
public void update() { public void update() {
} }
@SuppressWarnings("unchecked")
public void applyCurrentFilter() {
// The main trick here is to apply a CardPrinted predicate
// to the table. CardRules will lead to difficulties.
List<Predicate<? super CardPrinted>> cardPredicates = new ArrayList<Predicate<? super CardPrinted>>();
cardPredicates.add(Predicates.instanceOf(CardPrinted.class));
cardPredicates.add(SFilterUtil.buildColorAndTypeFilter(VCardCatalog.SINGLETON_INSTANCE.getStatLabels()));
cardPredicates.addAll(activePredicates);
// apply current values in the range filters
for (RangeTypes t : RangeTypes.values()) {
if (activeRanges.contains(t)) {
cardPredicates.add(SFilterUtil.buildIntervalFilter(VCardCatalog.SINGLETON_INSTANCE.getSpinners(), t));
}
}
// get the current contents of the search box
cardPredicates.add(SFilterUtil.buildTextFilter(
VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().getText(),
0 != VCardCatalog.SINGLETON_INSTANCE.getCbSearchMode().getSelectedIndex(),
VCardCatalog.SINGLETON_INSTANCE.getLblName().isSelected(),
VCardCatalog.SINGLETON_INSTANCE.getLblType().isSelected(),
VCardCatalog.SINGLETON_INSTANCE.getLblText().isSelected()));
Predicate<? super CardPrinted> cardFilter = Predicates.and(cardPredicates);
// Until this is filterable, always show packs and decks in the card shop.
List<Predicate<? super CardPrinted>> itemPredicates = new ArrayList<Predicate<? super CardPrinted>>();
itemPredicates.add(cardFilter);
itemPredicates.add(ItemPredicate.Presets.IS_PACK);
itemPredicates.add(ItemPredicate.Presets.IS_DECK);
Predicate<CardPrinted> filter = Predicates.or(itemPredicates);
// Apply to table
// TODO: is there really no way to make this type safe?
((ACEditorBase<CardPrinted, DeckBase>)CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController())
.getTableCatalog().setFilter(filter);
}
private boolean canSearch() {
return !VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().getText().isEmpty() &&
(VCardCatalog.SINGLETON_INSTANCE.getLblName().isSelected() ||
VCardCatalog.SINGLETON_INSTANCE.getLblType().isSelected() ||
VCardCatalog.SINGLETON_INSTANCE.getLblText().isSelected());
}
private <T> boolean isActive(Set<T> activeSet, T key) {
return activeSet.contains(key);
}
private JMenuItem createMenuItem(String label, boolean enabled, KeyStroke accelerator, final Command onClick) {
JMenuItem item = new JMenuItem(label);
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (null != onClick) {
onClick.execute();
}
}
});
item.setEnabled(enabled);
item.setAccelerator(accelerator);
return item;
}
private void addMenuItem(JPopupMenu parent, String label, boolean enabled, KeyStroke accelerator, Command onClick) {
parent.add(createMenuItem(label, enabled, accelerator, onClick));
}
private void addMenuItem(JMenuItem parent, String label, boolean enabled, KeyStroke accelerator, Command onClick) {
parent.add(createMenuItem(label, enabled, accelerator, onClick));
}
@SuppressWarnings("serial")
private <T> void addRestriction(Pair<JComponent, Predicate<CardPrinted>> restriction, final Set<T> activeSet, final T key) {
final Predicate<CardPrinted> predicate = restriction.b;
if (null != predicate && activePredicates.contains(predicate)) {
return;
}
VCardCatalog.SINGLETON_INSTANCE.addRestrictionWidget(restriction.a, new Command() {
@Override
public void execute() {
if (null != key) {
activeSet.remove(key);
}
if (null != predicate) {
activePredicates.remove(predicate);
}
applyCurrentFilter();
}
});
if (null != key) {
activeSet.add(key);
}
if (null != predicate) {
activePredicates.add(predicate);
}
applyCurrentFilter();
}
private Pair<JComponent, Predicate<CardPrinted>> buildRangeRestriction(RangeTypes t) {
Pair<FSpinner, FSpinner> s = VCardCatalog.SINGLETON_INSTANCE.getSpinners().get(t);
s.a.setValue(0);
s.b.setValue(10);
return new Pair<JComponent, Predicate<CardPrinted>>(
VCardCatalog.SINGLETON_INSTANCE.buildRangeRestrictionWidget(t), null);
}
private String buildSearchRestrictionText(String text, boolean isInverse, boolean wantName, boolean wantType, boolean wantText) {
StringBuilder sb = new StringBuilder();
sb.append(isInverse ? "Without" : "Contains");
sb.append(": '").append(text).append("' in:");
if (wantName) { sb.append(" name,"); }
if (wantType) { sb.append(" type,"); }
if (wantText) { sb.append(" text,"); }
sb.delete(sb.length() - 1, sb.length()); // chop off last comma
return sb.toString();
}
private Pair<JComponent, Predicate<CardPrinted>> buildSearchRestriction() {
boolean isInverse =
VCardCatalog.SEARCH_MODE_INVERSE_INDEX == VCardCatalog.SINGLETON_INSTANCE.getCbSearchMode().getSelectedIndex();
String text = VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().getText();
boolean wantName = VCardCatalog.SINGLETON_INSTANCE.getLblName().getSelected();
boolean wantType = VCardCatalog.SINGLETON_INSTANCE.getLblType().getSelected();
boolean wantText = VCardCatalog.SINGLETON_INSTANCE.getLblText().getSelected();
String shortText = buildSearchRestrictionText(text, isInverse, wantName, wantType, wantText);
String fullText = null;
if (25 < text.length()) {
fullText = shortText;
shortText = buildSearchRestrictionText(text.substring(0, 22) + "...",
isInverse, wantName, wantType, wantText);
}
VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().setText("");
return new Pair<JComponent, Predicate<CardPrinted>>(
VCardCatalog.SINGLETON_INSTANCE.buildPlainRestrictionWidget(shortText, fullText),
SFilterUtil.buildTextFilter(text, isInverse, wantName, wantType, wantText));
}
private Pair<JComponent, Predicate<CardPrinted>> buildFormatRestriction(String displayName, GameFormat format) {
EditionCollection editions = Singletons.getModel().getEditions();
StringBuilder tooltip = new StringBuilder("<html>Sets:");
int lastLen = 0;
int lineLen = 0;
// use HTML tooltips so we can insert line breaks
List<String> sets = null == format ? null : format.getAllowedSetCodes();
if (null == sets || sets.isEmpty()) {
tooltip.append(" All");
} else {
for (String code : sets) {
// don't let a single line get too long
if (50 < lineLen) {
tooltip.append("<br>");
lastLen += lineLen;
lineLen = 0;
}
CardEdition edition = editions.get(code);
tooltip.append(" ").append(edition.getName()).append(" (").append(code).append("),");
lineLen = tooltip.length() - lastLen;
}
// chop off last comma
tooltip.delete(tooltip.length() - 1, tooltip.length());
tooltip.append("<br><br>Allowing identical cards from other sets");
}
List<String> bannedCards = null == format ? null : format.getBannedCardNames();
if (null != bannedCards && !bannedCards.isEmpty()) {
tooltip.append("<br><br>Banned:");
lastLen += lineLen;
lineLen = 0;
for (String cardName : bannedCards) {
// don't let a single line get too long
if (50 < lineLen) {
tooltip.append("<br>");
lastLen += lineLen;
lineLen = 0;
}
tooltip.append(" ").append(cardName).append(";");
lineLen = tooltip.length() - lastLen;
}
// chop off last semicolon
tooltip.delete(tooltip.length() - 1, tooltip.length());
}
tooltip.append("</html>");
return new Pair<JComponent, Predicate<CardPrinted>>(
VCardCatalog.SINGLETON_INSTANCE.buildPlainRestrictionWidget(displayName, tooltip.toString()),
format.getFilterRules());
}
private Pair<JComponent, Predicate<CardPrinted>> buildWorldRestriction(QuestWorld world) {
GameFormatQuest format = world.getFormat();
if (null == format) {
// assumes that no world other than the main world will have a null format
format = Singletons.getModel().getQuest().getMainFormat();
}
return buildFormatRestriction(world.getName(), format);
}
} }

View File

@@ -33,7 +33,6 @@ import forge.gui.deckeditor.views.VAllDecks;
import forge.gui.deckeditor.views.VCardCatalog; import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.deckeditor.views.VCurrentDeck;
import forge.gui.deckeditor.views.VDeckgen; import forge.gui.deckeditor.views.VDeckgen;
import forge.gui.deckeditor.views.VFilters;
import forge.gui.framework.DragCell; import forge.gui.framework.DragCell;
import forge.gui.framework.SRearrangingUtil; import forge.gui.framework.SRearrangingUtil;
import forge.gui.home.sanctioned.CSubmenuDraft; import forge.gui.home.sanctioned.CSubmenuDraft;
@@ -55,7 +54,6 @@ public class CEditorDraftingProcess extends ACEditorBase<CardPrinted, DeckGroup>
private IBoosterDraft boosterDraft; private IBoosterDraft boosterDraft;
private String ccAddLabel = "Add card"; private String ccAddLabel = "Add card";
private DragCell filtersParent = null;
private DragCell allDecksParent = null; private DragCell allDecksParent = null;
private DragCell deckGenParent = null; private DragCell deckGenParent = null;
@@ -297,17 +295,6 @@ public class CEditorDraftingProcess extends ACEditorBase<CardPrinted, DeckGroup>
} }
} }
if (VFilters.SINGLETON_INSTANCE.getParentCell() != null) {
filtersParent = VFilters.SINGLETON_INSTANCE.getParentCell();
filtersParent.removeDoc(VFilters.SINGLETON_INSTANCE);
VFilters.SINGLETON_INSTANCE.setParentCell(null);
// If filters was first tab, the new first tab needs re-selecting.
if (filtersParent.getDocs().size() > 0) {
filtersParent.setSelected(filtersParent.getDocs().get(0));
}
}
// Fill in gaps // Fill in gaps
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
@@ -340,16 +327,10 @@ public class CEditorDraftingProcess extends ACEditorBase<CardPrinted, DeckGroup>
VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(true); VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(true);
//Re-add tabs //Re-add tabs
if (filtersParent != null) {
filtersParent.addDoc(VFilters.SINGLETON_INSTANCE);
}
if (deckGenParent != null) { if (deckGenParent != null) {
deckGenParent.addDoc(VDeckgen.SINGLETON_INSTANCE); deckGenParent.addDoc(VDeckgen.SINGLETON_INSTANCE);
} }
if (allDecksParent != null) { if (allDecksParent != null) {
allDecksParent.addDoc(VAllDecks.SINGLETON_INSTANCE); allDecksParent.addDoc(VAllDecks.SINGLETON_INSTANCE);
} }

View File

@@ -12,7 +12,6 @@ import forge.gui.deckeditor.SEditorIO;
import forge.gui.deckeditor.SEditorIO.EditorPreference; import forge.gui.deckeditor.SEditorIO.EditorPreference;
import forge.gui.deckeditor.tables.SColumnUtil; import forge.gui.deckeditor.tables.SColumnUtil;
import forge.gui.deckeditor.tables.SColumnUtil.ColumnName; import forge.gui.deckeditor.tables.SColumnUtil.ColumnName;
import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.deckeditor.views.VCurrentDeck;
import forge.gui.deckeditor.views.VEditorPreferences; import forge.gui.deckeditor.views.VEditorPreferences;
import forge.gui.framework.ICDoc; import forge.gui.framework.ICDoc;
@@ -57,6 +56,7 @@ public enum CEditorPreferences implements ICDoc {
prefsDict.put(prefsInstance.getChbCatalogAI(), ColumnName.CAT_AI); prefsDict.put(prefsInstance.getChbCatalogAI(), ColumnName.CAT_AI);
prefsDict.put(prefsInstance.getChbCatalogPower(), ColumnName.CAT_POWER); prefsDict.put(prefsInstance.getChbCatalogPower(), ColumnName.CAT_POWER);
prefsDict.put(prefsInstance.getChbCatalogToughness(), ColumnName.CAT_TOUGHNESS); prefsDict.put(prefsInstance.getChbCatalogToughness(), ColumnName.CAT_TOUGHNESS);
prefsDict.put(prefsInstance.getChbCatalogOwned(), ColumnName.CAT_OWNED);
// Deck // Deck
prefsDict.put(prefsInstance.getChbDeckColor(), ColumnName.DECK_COLOR); prefsDict.put(prefsInstance.getChbDeckColor(), ColumnName.DECK_COLOR);
@@ -82,8 +82,6 @@ public enum CEditorPreferences implements ICDoc {
} }
// Catalog/Deck Stats // Catalog/Deck Stats
VEditorPreferences.SINGLETON_INSTANCE.getChbCatalogStats().setSelected(
SEditorIO.getPref(EditorPreference.stats_catalog));
VEditorPreferences.SINGLETON_INSTANCE.getChbDeckStats().setSelected( VEditorPreferences.SINGLETON_INSTANCE.getChbDeckStats().setSelected(
SEditorIO.getPref(EditorPreference.stats_deck)); SEditorIO.getPref(EditorPreference.stats_deck));
VEditorPreferences.SINGLETON_INSTANCE.getChbCardDisplayUnique().setSelected( VEditorPreferences.SINGLETON_INSTANCE.getChbCardDisplayUnique().setSelected(
@@ -94,9 +92,6 @@ public enum CEditorPreferences implements ICDoc {
if (!SEditorIO.getPref(EditorPreference.stats_deck)) { if (!SEditorIO.getPref(EditorPreference.stats_deck)) {
VCurrentDeck.SINGLETON_INSTANCE.getPnlStats().setVisible(false); VCurrentDeck.SINGLETON_INSTANCE.getPnlStats().setVisible(false);
} }
if (!SEditorIO.getPref(EditorPreference.stats_catalog)) {
VCardCatalog.SINGLETON_INSTANCE.getPnlStats().setVisible(false);
}
boolean wantElastic = SEditorIO.getPref(EditorPreference.elastic_columns); boolean wantElastic = SEditorIO.getPref(EditorPreference.elastic_columns);
boolean wantUnique = SEditorIO.getPref(EditorPreference.display_unique_only); boolean wantUnique = SEditorIO.getPref(EditorPreference.display_unique_only);
@@ -110,13 +105,6 @@ public enum CEditorPreferences implements ICDoc {
curEditor.getTableDeck().updateView(true); curEditor.getTableDeck().updateView(true);
} }
VEditorPreferences.SINGLETON_INSTANCE.getChbCatalogStats().addItemListener(new ItemListener() {
@Override public void itemStateChanged(final ItemEvent e) {
VCardCatalog.SINGLETON_INSTANCE.getPnlStats().setVisible(
((JCheckBox) e.getSource()).isSelected());
SEditorIO.setPref(EditorPreference.stats_catalog, ((JCheckBox) e.getSource()).isSelected());
SEditorIO.savePreferences(); } });
VEditorPreferences.SINGLETON_INSTANCE.getChbDeckStats().addItemListener(new ItemListener() { VEditorPreferences.SINGLETON_INSTANCE.getChbDeckStats().addItemListener(new ItemListener() {
@Override public void itemStateChanged(final ItemEvent e) { @Override public void itemStateChanged(final ItemEvent e) {
VCurrentDeck.SINGLETON_INSTANCE.getPnlStats().setVisible( VCurrentDeck.SINGLETON_INSTANCE.getPnlStats().setVisible(

View File

@@ -117,15 +117,14 @@ public final class CEditorQuestCardShop extends ACEditorBase<InventoryItem, Deck
final List<TableColumnInfo<InventoryItem>> columnsCatalog = SColumnUtil.getCatalogDefaultColumns(); final List<TableColumnInfo<InventoryItem>> columnsCatalog = SColumnUtil.getCatalogDefaultColumns();
final List<TableColumnInfo<InventoryItem>> columnsDeck = SColumnUtil.getDeckDefaultColumns(); final List<TableColumnInfo<InventoryItem>> columnsDeck = SColumnUtil.getDeckDefaultColumns();
// Add "price", "decks", and "new" column in catalog and deck // Add spell shop-specific columns
columnsCatalog.add(SColumnUtil.getColumn(ColumnName.CAT_PURCHASE_PRICE)); columnsCatalog.add(SColumnUtil.getColumn(ColumnName.CAT_PURCHASE_PRICE));
columnsCatalog.get(columnsCatalog.size() - 1).setSortAndDisplayFunctions( columnsCatalog.get(columnsCatalog.size() - 1).setSortAndDisplayFunctions(
this.fnPriceCompare, this.fnPriceGet); this.fnPriceCompare, this.fnPriceGet);
// card shop doesn't need "New" column columnsCatalog.add(1, SColumnUtil.getColumn(ColumnName.CAT_OWNED));
//columnsCatalog.add(SColumnUtil.getColumn(ColumnName.CAT_NEW)); columnsCatalog.get(1).setSortAndDisplayFunctions(
//columnsCatalog.get(columnsCatalog.size() - 1).setSortAndDisplayFunctions( questData.getCards().getFnOwnedCompare(), questData.getCards().getFnOwnedGet());
// this.questData.getCards().getFnNewCompare(), this.questData.getCards().getFnNewGet());
columnsDeck.add(SColumnUtil.getColumn(ColumnName.DECK_SALE_PRICE)); columnsDeck.add(SColumnUtil.getColumn(ColumnName.DECK_SALE_PRICE));
columnsDeck.get(columnsDeck.size() - 1).setSortAndDisplayFunctions( columnsDeck.get(columnsDeck.size() - 1).setSortAndDisplayFunctions(
@@ -139,7 +138,7 @@ public final class CEditorQuestCardShop extends ACEditorBase<InventoryItem, Deck
columnsDeck.get(columnsDeck.size() - 1).setSortAndDisplayFunctions( columnsDeck.get(columnsDeck.size() - 1).setSortAndDisplayFunctions(
this.fnDeckCompare, this.fnDeckGet); this.fnDeckCompare, this.fnDeckGet);
// don't need AI column for eaither table // don't need AI column for either table
columnsCatalog.remove(SColumnUtil.getColumn(ColumnName.CAT_AI)); columnsCatalog.remove(SColumnUtil.getColumn(ColumnName.CAT_AI));
columnsDeck.remove(SColumnUtil.getColumn(ColumnName.DECK_AI)); columnsDeck.remove(SColumnUtil.getColumn(ColumnName.DECK_AI));

View File

@@ -1,181 +0,0 @@
package forge.gui.deckeditor.controllers;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import forge.Command;
import forge.deck.DeckBase;
import forge.gui.deckeditor.CDeckEditorUI;
import forge.gui.deckeditor.SFilterUtil;
import forge.gui.deckeditor.views.VFilters;
import forge.gui.framework.ICDoc;
import forge.gui.toolbox.FLabel;
import forge.item.CardPrinted;
import forge.item.InventoryItem;
import forge.item.ItemPredicate;
/**
* Controls the "filters" panel in the deck editor UI.
*
* <br><br><i>(C at beginning of class name denotes a control class.)</i>
*
*/
public enum CFilters implements ICDoc {
/** */
SINGLETON_INSTANCE;
private boolean filtersAllEnabled = true;
//========== Overridden methods
/* (non-Javadoc)
* @see forge.gui.framework.ICDoc#getCommandOnSelect()
*/
@Override
public Command getCommandOnSelect() {
return null;
}
/* (non-Javadoc)
* @see forge.gui.framework.ICDoc#initialize()
*/
@SuppressWarnings("serial")
@Override
public void initialize() {
final ItemListener iliFilter = new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent arg0) {
if (!SFilterUtil.isFilteringPrevented()) {
buildFilter();
}
}
};
VFilters.SINGLETON_INSTANCE.getCbxSets().addItemListener(iliFilter);
VFilters.SINGLETON_INSTANCE.getCbxPLow().addItemListener(iliFilter);
VFilters.SINGLETON_INSTANCE.getCbxPHigh().addItemListener(iliFilter);
VFilters.SINGLETON_INSTANCE.getCbxTLow().addItemListener(iliFilter);
VFilters.SINGLETON_INSTANCE.getCbxTHigh().addItemListener(iliFilter);
VFilters.SINGLETON_INSTANCE.getCbxCMCLow().addItemListener(iliFilter);
VFilters.SINGLETON_INSTANCE.getCbxCMCHigh().addItemListener(iliFilter);
((FLabel) VFilters.SINGLETON_INSTANCE.getBtnToggle()).setCommand(new Command() {
@Override
public void execute() {
SFilterUtil.setPreventFiltering(true);
toggleColorTypeSetFilter();
SFilterUtil.setPreventFiltering(false);
buildFilter();
}
});
((FLabel) VFilters.SINGLETON_INSTANCE.getBtnResetIntervals()).setCommand(new Command() {
@Override
public void execute() {
SFilterUtil.setPreventFiltering(true);
VFilters.SINGLETON_INSTANCE.getCbxPLow().setSelectedIndex(0);
VFilters.SINGLETON_INSTANCE.getCbxTLow().setSelectedIndex(0);
VFilters.SINGLETON_INSTANCE.getCbxCMCLow().setSelectedIndex(0);
VFilters.SINGLETON_INSTANCE.getCbxPHigh().setSelectedIndex(
VFilters.SINGLETON_INSTANCE.getCbxPHigh().getItemCount() - 1);
VFilters.SINGLETON_INSTANCE.getCbxTHigh().setSelectedIndex(
VFilters.SINGLETON_INSTANCE.getCbxTHigh().getItemCount() - 1);
VFilters.SINGLETON_INSTANCE.getCbxCMCHigh().setSelectedIndex(
VFilters.SINGLETON_INSTANCE.getCbxCMCHigh().getItemCount() - 1);
SFilterUtil.setPreventFiltering(false);
buildFilter();
}
});
((FLabel) VFilters.SINGLETON_INSTANCE.getBtnResetText()).setCommand(new Command() {
@Override
public void execute() {
VFilters.SINGLETON_INSTANCE.getTxfContains().setText("");
VFilters.SINGLETON_INSTANCE.getTxfWithout().setText("");
buildFilter();
}
});
VFilters.SINGLETON_INSTANCE.getTxfContains().addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(final KeyEvent e) {
if (e.getKeyCode() == 10) { buildFilter(); }
}
});
VFilters.SINGLETON_INSTANCE.getTxfWithout().addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(final KeyEvent e) {
if (e.getKeyCode() == 10) { buildFilter(); }
}
});
}
/* (non-Javadoc)
* @see forge.gui.framework.ICDoc#update()
*/
@Override
public void update() {
}
/**
* Clear filter button_action performed.
*
* @param e
* the e
*/
private <TItem extends InventoryItem, TModel extends DeckBase> void toggleColorTypeSetFilter() {
VFilters.SINGLETON_INSTANCE.getCbxSets().setSelectedIndex(0);
if (filtersAllEnabled) {
filtersAllEnabled = false;
SFilterUtil.toggleColorCheckboxes(false);
SFilterUtil.toggleTypeCheckboxes(false);
}
else {
filtersAllEnabled = true;
SFilterUtil.toggleColorCheckboxes(true);
SFilterUtil.toggleTypeCheckboxes(true);
}
}
//===========
/**
*
* Assembles filter from the ones available. To prevent a block
* of filters from being used, set its parent panel's visibility to false.
*
* @param <TItem> &emsp; extends InventoryItem
* @param <TModel> &emsp; extends DeckBase
*/
@SuppressWarnings("unchecked")
public <TItem extends InventoryItem, TModel extends DeckBase> void buildFilter() {
// The main trick here is to apply a CardPrinted predicate
// to the table. CardRules will lead to difficulties.
final ACEditorBase<TItem, TModel> ed = (ACEditorBase<TItem, TModel>)
CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController();
Predicate<? super CardPrinted> classFilter = Predicates.instanceOf(CardPrinted.class);
Predicate<CardPrinted> color = SFilterUtil.buildColorFilter();
Predicate<CardPrinted> type = SFilterUtil.buildTypeFilter();
Predicate<CardPrinted> set = SFilterUtil.buildSetAndFormatFilter();
Predicate<CardPrinted> text = SFilterUtil.buildTextFilter();
Predicate<CardPrinted> interval = SFilterUtil.buildIntervalFilter();
// Until this is filterable, always show packs and decks in the card shop.
Predicate<? super CardPrinted> cardFilter = Predicates.and(classFilter, color, type, set, text, interval);
Predicate<? super CardPrinted> itemFilter = Predicates.or(cardFilter, ItemPredicate.Presets.IS_PACK, ItemPredicate.Presets.IS_DECK);
// Apply to table
ed.getTableCatalog().setFilter((Predicate<TItem>) itemFilter);
}
}

View File

@@ -19,6 +19,7 @@ Forge Team
*/ */
package forge.gui.deckeditor.tables; package forge.gui.deckeditor.tables;
import java.awt.Cursor;
import java.awt.event.FocusAdapter; import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent; import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
@@ -225,7 +226,7 @@ public final class EditorTableModel<T extends InventoryItem> extends AbstractTab
header.addMouseListener(new MouseAdapter() { header.addMouseListener(new MouseAdapter() {
@Override @Override
public void mouseClicked(final MouseEvent e) { public void mouseClicked(final MouseEvent e) {
if (null == header.getResizingColumn()) { if (Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR) != header.getCursor()) {
headerClicked(e); headerClicked(e);
} }
} }

View File

@@ -72,6 +72,7 @@ public final class SColumnUtil {
CAT_AI, /** */ CAT_AI, /** */
CAT_NEW, /** */ CAT_NEW, /** */
CAT_PURCHASE_PRICE, /** */ CAT_PURCHASE_PRICE, /** */
CAT_OWNED, /** */
DECK_QUANTITY, /** */ DECK_QUANTITY, /** */
DECK_NAME, /** */ DECK_NAME, /** */
DECK_COST, /** */ DECK_COST, /** */

View File

@@ -46,8 +46,6 @@ public class TableColumnInfo<T> extends TableColumn {
/** */ /** */
public TableColumnInfo() { public TableColumnInfo() {
super(); super();
setResizable(true);
setMinWidth(30);
} }
/** /**

View File

@@ -1,8 +1,10 @@
package forge.gui.deckeditor.views; package forge.gui.deckeditor.views;
import javax.swing.JLabel;
import javax.swing.JTable; import javax.swing.JTable;
import forge.gui.deckeditor.SEditorUtil;
import forge.gui.toolbox.FLabel;
/** /**
* Dictates methods needed for a class to act as a container for * Dictates methods needed for a class to act as a container for
* a EditorTableView deck editing component. * a EditorTableView deck editing component.
@@ -19,47 +21,5 @@ public interface ITableContainer {
*/ */
void setTableView(JTable tbl0); void setTableView(JTable tbl0);
// Various card count total labels FLabel getStatLabel(SEditorUtil.StatTypes s);
/** @return {@link javax.swing.JLabel} */
JLabel getLblTotal();
/** @return {@link javax.swing.JLabel} */
JLabel getLblBlack();
/** @return {@link javax.swing.JLabel} */
JLabel getLblBlue();
/** @return {@link javax.swing.JLabel} */
JLabel getLblGreen();
/** @return {@link javax.swing.JLabel} */
JLabel getLblRed();
/** @return {@link javax.swing.JLabel} */
JLabel getLblWhite();
/** @return {@link javax.swing.JLabel} */
JLabel getLblColorless();
/** @return {@link javax.swing.JLabel} */
JLabel getLblArtifact();
/** @return {@link javax.swing.JLabel} */
JLabel getLblEnchantment();
/** @return {@link javax.swing.JLabel} */
JLabel getLblCreature();
/** @return {@link javax.swing.JLabel} */
JLabel getLblSorcery();
/** @return {@link javax.swing.JLabel} */
JLabel getLblInstant();
/** @return {@link javax.swing.JLabel} */
JLabel getLblPlaneswalker();
/** @return {@link javax.swing.JLabel} */
JLabel getLblLand();
} }

View File

@@ -1,12 +1,22 @@
package forge.gui.deckeditor.views; package forge.gui.deckeditor.views;
import javax.swing.ImageIcon; import java.awt.Container;
import javax.swing.JLabel; import java.awt.FlowLayout;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import forge.Command;
import forge.card.CardRulesPredicates;
import forge.gui.WrapLayout;
import forge.gui.deckeditor.SEditorUtil; import forge.gui.deckeditor.SEditorUtil;
import forge.gui.deckeditor.controllers.CCardCatalog; import forge.gui.deckeditor.controllers.CCardCatalog;
import forge.gui.framework.DragCell; import forge.gui.framework.DragCell;
@@ -15,6 +25,10 @@ import forge.gui.framework.EDocID;
import forge.gui.framework.IVDoc; import forge.gui.framework.IVDoc;
import forge.gui.toolbox.FLabel; import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSkin; import forge.gui.toolbox.FSkin;
import forge.gui.toolbox.FSpinner;
import forge.gui.toolbox.FTextField;
import forge.util.Pair;
import forge.util.TextUtil;
/** /**
* Assembles Swing components of card catalog in deck editor. * Assembles Swing components of card catalog in deck editor.
@@ -26,54 +40,74 @@ public enum VCardCatalog implements IVDoc<CCardCatalog>, ITableContainer {
/** */ /** */
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
public static final int SEARCH_MODE_INVERSE_INDEX = 1;
// Fields used with interface IVDoc // Fields used with interface IVDoc
private DragCell parentCell; private DragCell parentCell;
private final DragTab tab = new DragTab("Card Catalog"); private final DragTab tab = new DragTab("Card Catalog");
// Total and color count labels // panel where special instructions appear
private final JPanel pnlStats = new JPanel();
private final JLabel lblTotal = buildLabel(SEditorUtil.ICO_TOTAL);
private final JLabel lblBlack = buildLabel(SEditorUtil.ICO_BLACK);
private final JLabel lblBlue = buildLabel(SEditorUtil.ICO_BLUE);
private final JLabel lblGreen = buildLabel(SEditorUtil.ICO_GREEN);
private final JLabel lblRed = buildLabel(SEditorUtil.ICO_RED);
private final JLabel lblWhite = buildLabel(SEditorUtil.ICO_WHITE);
private final JLabel lblColorless = buildLabel(SEditorUtil.ICO_COLORLESS);
// Card type labels
private final JLabel lblArtifact = buildLabel(SEditorUtil.ICO_ARTIFACT);
private final JLabel lblCreature = buildLabel(SEditorUtil.ICO_CREATURE);
private final JLabel lblEnchantment = buildLabel(SEditorUtil.ICO_ENCHANTMENT);
private final JLabel lblInstant = buildLabel(SEditorUtil.ICO_INSTANT);
private final JLabel lblLand = buildLabel(SEditorUtil.ICO_LAND);
private final JLabel lblPlaneswalker = buildLabel(SEditorUtil.ICO_PLANESWALKER);
private final JLabel lblSorcery = buildLabel(SEditorUtil.ICO_SORCERY);
private final JLabel lblTitle = new FLabel.Builder()
.fontSize(14).build();
private final JPanel pnlHeader = new JPanel(new MigLayout("insets 0, gap 0")); private final JPanel pnlHeader = new JPanel(new MigLayout("insets 0, gap 0"));
private final FLabel lblTitle = new FLabel.Builder().fontSize(14).build();
// Total and color count labels/filter toggles
private final JPanel pnlStats = new JPanel();
private final Map<SEditorUtil.StatTypes, FLabel> statLabels =
new HashMap<SEditorUtil.StatTypes, FLabel>();
// card transfer buttons
private final JPanel pnlAddButtons = private final JPanel pnlAddButtons =
new JPanel(new MigLayout("insets 0, gap 0, ax center, hidemode 3")); new JPanel(new MigLayout("insets 0, gap 0, ax center, hidemode 3"));
private final FLabel btnAdd = new FLabel.Builder()
private final JLabel btnAdd = new FLabel.Builder()
.fontSize(14) .fontSize(14)
.text("Add card") .text("Add card")
.tooltip("Add selected card to current deck (or double click the row)") .tooltip("Add selected card to current deck (or double click the row)")
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS))
.iconScaleAuto(false).hoverable(true).build(); .iconScaleAuto(false).hoverable(true).build();
private final FLabel btnAdd4 = new FLabel.Builder()
private final JLabel btnAdd4 = new FLabel.Builder()
.fontSize(14) .fontSize(14)
.text("Add 4 of card") .text("Add 4 of card")
.tooltip("Add up to 4 of selected card to current deck") .tooltip("Add up to 4 of selected card to current deck")
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS))
.iconScaleAuto(false).hoverable(true).build(); .iconScaleAuto(false).hoverable(true).build();
// restriction button and search widgets
private final JPanel pnlSearch = new JPanel(new MigLayout("insets 0, gap 5px, center"));
private final FLabel btnAddRestriction = new FLabel.Builder()
.text("Filter by")
.tooltip("Filter shown cards by various properties")
.hoverable(true).opaque(true).reactOnMouseDown(true).build();
private final JComboBox cbSearchMode = new JComboBox();
private final JTextField txfSearch = new FTextField.Builder().build();
private final FLabel lblName = new FLabel.Builder().text("Name").selectable(true).selected(true).hoverable(true).opaque(true).build();
private final FLabel lblType = new FLabel.Builder().text("Type").selectable(true).selected(true).hoverable(true).opaque(true).build();
private final FLabel lblText = new FLabel.Builder().text("Text").selectable(true).selected(true).hoverable(true).opaque(true).build();
private final JPanel pnlRestrictions = new JPanel(new WrapLayout(FlowLayout.LEFT, 10, 5));
// restriction widgets
public static enum RangeTypes {
CMC (CardRulesPredicates.LeafNumber.CardField.CMC),
POWER (CardRulesPredicates.LeafNumber.CardField.POWER),
TOUGHNESS (CardRulesPredicates.LeafNumber.CardField.TOUGHNESS);
public final CardRulesPredicates.LeafNumber.CardField cardField;
RangeTypes(CardRulesPredicates.LeafNumber.CardField cardField) {
this.cardField = cardField;
}
public String toLabelString() {
if (this == CMC) { return toString(); }
return TextUtil.enumToLabel(this);
}
}
private final Map<RangeTypes, Pair<FSpinner, FSpinner>> spinners = new HashMap<RangeTypes, Pair<FSpinner, FSpinner>>();
// card table
private JTable tblCards = null; private JTable tblCards = null;
private final JScrollPane scroller = new JScrollPane(); private final JScrollPane scroller = new JScrollPane();
//========== Constructor //========== Constructor
/** */ /** */
private VCardCatalog() { private VCardCatalog() {
@@ -82,238 +116,172 @@ public enum VCardCatalog implements IVDoc<CCardCatalog>, ITableContainer {
scroller.setBorder(null); scroller.setBorder(null);
scroller.getViewport().setBorder(null); scroller.getViewport().setBorder(null);
lblTotal.setToolTipText("Total Card Count");
lblBlack.setToolTipText("Black Card Count");
lblBlue.setToolTipText("Blue Card Count");
lblGreen.setToolTipText("Green Card Count");
lblRed.setToolTipText("Red Card Count");
lblWhite.setToolTipText("White Card Count");
lblColorless.setToolTipText("Total Card Count");
lblArtifact.setToolTipText("Artifact Card Count");
lblCreature.setToolTipText("Creature Card Count");
lblColorless.setToolTipText("Colorless Card Count");
lblEnchantment.setToolTipText("Enchantment Card Count");
lblInstant.setToolTipText("Instant Card Count");
lblLand.setToolTipText("Land Card Count");
lblPlaneswalker.setToolTipText("Planeswalker Card Count");
lblSorcery.setToolTipText("Sorcery Card Count");
pnlStats.setOpaque(false); pnlStats.setOpaque(false);
pnlStats.setLayout(new MigLayout("insets 0, gap 5px, ax center, wrap 7")); pnlStats.setLayout(new MigLayout("insets 0, gap 5px, ax center, wrap 7"));
final String constraints = "w 57px!, h 20px!"; for (SEditorUtil.StatTypes s : SEditorUtil.StatTypes.values()) {
pnlStats.add(lblTotal, constraints); FLabel label = buildToggleLabel(s, SEditorUtil.StatTypes.TOTAL != s);
pnlStats.add(lblWhite, constraints); statLabels.put(s, label);
pnlStats.add(lblBlue, constraints); pnlStats.add(label, "w 57px!, h 20px!");
pnlStats.add(lblBlack, constraints); }
pnlStats.add(lblRed, constraints);
pnlStats.add(lblGreen, constraints);
pnlStats.add(lblColorless, constraints);
pnlStats.add(lblLand, constraints); statLabels.get(SEditorUtil.StatTypes.TOTAL).setToolTipText("Total cards (click to toggle all filters)");
pnlStats.add(lblArtifact, constraints);
pnlStats.add(lblCreature, constraints);
pnlStats.add(lblEnchantment, constraints);
pnlStats.add(lblPlaneswalker, constraints);
pnlStats.add(lblInstant, constraints);
pnlStats.add(lblSorcery, constraints);
pnlAddButtons.setOpaque(false); pnlAddButtons.setOpaque(false);
pnlAddButtons.add(btnAdd, "w 30%!, h 30px!, gap 0 0 5px 5px"); pnlAddButtons.add(btnAdd, "w 30%!, h 30px!, gap 0 0 5px 5px");
pnlAddButtons.add(btnAdd4, "w 30%!, h 30px!, gap 5% 5% 5px 5px"); pnlAddButtons.add(btnAdd4, "w 30%!, h 30px!, gap 5% 5% 5px 5px");
pnlSearch.setOpaque(false);
pnlSearch.add(btnAddRestriction, "center, width pref+4");
cbSearchMode.addItem("With");
cbSearchMode.addItem("Without");
pnlSearch.add(cbSearchMode, "center");
pnlSearch.add(txfSearch, "pushx, growx");
pnlSearch.add(new FLabel.Builder().text("in").build());
pnlSearch.add(lblName, "width pref+4");
pnlSearch.add(lblType, "width pref+4");
pnlSearch.add(lblText, "width pref+4");
pnlRestrictions.setOpaque(false);
pnlHeader.setOpaque(false); pnlHeader.setOpaque(false);
pnlHeader.add(lblTitle, "w 100%!, h 100%!"); pnlHeader.add(lblTitle, "w 100%!, h 100%!");
// fill spinner map
for (RangeTypes t : RangeTypes.values()) {
spinners.put(t, new Pair<FSpinner, FSpinner>(
new FSpinner.Builder().maxValue(10).build(),
new FSpinner.Builder().maxValue(10).build()));
}
} }
//========== Overridden from IVDoc //========== Overridden from IVDoc
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getDocumentID()
*/
@Override @Override
public EDocID getDocumentID() { public EDocID getDocumentID() {
return EDocID.EDITOR_CATALOG; return EDocID.EDITOR_CATALOG;
} }
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getTabLabel()
*/
@Override @Override
public DragTab getTabLabel() { public DragTab getTabLabel() {
return tab; return tab;
} }
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getLayoutControl()
*/
@Override @Override
public CCardCatalog getLayoutControl() { public CCardCatalog getLayoutControl() {
return CCardCatalog.SINGLETON_INSTANCE; return CCardCatalog.SINGLETON_INSTANCE;
} }
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#setParentCell(forge.gui.framework.DragCell)
*/
@Override @Override
public void setParentCell(DragCell cell0) { public void setParentCell(DragCell cell0) {
this.parentCell = cell0; this.parentCell = cell0;
} }
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getParentCell()
*/
@Override @Override
public DragCell getParentCell() { public DragCell getParentCell() {
return this.parentCell; return this.parentCell;
} }
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#populate()
*/
@Override @Override
public void populate() { public void populate() {
parentCell.getBody().setLayout(new MigLayout("insets 0, gap 0, wrap, hidemode 3")); JPanel parentBody = parentCell.getBody();
parentCell.getBody().add(pnlHeader, "w 98%!, h 30px!, gap 1% 0 1% 10px"); parentBody.setLayout(new MigLayout("insets 0, gap 0, wrap, hidemode 3"));
parentCell.getBody().add(pnlStats, "w 96%, h 50px!, gap 2% 0 1% 1%"); parentBody.add(pnlHeader, "w 98%!, h 30px!, gap 1% 1% 0 0");
parentCell.getBody().add(pnlAddButtons, "w 96%!, gap 2% 0 0 0"); parentBody.add(pnlStats, "w 96%, h 50px!, gap 2% 0 1% 1%");
parentCell.getBody().add(scroller, "w 98%!, h 100% - 35px, gap 1% 0 1% 1%"); parentBody.add(pnlAddButtons, "w 96%!, gapleft 1%");
parentBody.add(pnlSearch, "w 96%, gapleft 1%");
parentBody.add(pnlRestrictions, "w 96%, gapleft 1%, gapright push");
parentBody.add(scroller, "w 98%!, h 100% - 35px, gap 1% 0 0 1%");
} }
//========== Overridden from ITableContainer //========== Overridden from ITableContainer
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#setTableView()
*/
@Override @Override
public void setTableView(final JTable tbl0) { public void setTableView(final JTable tbl0) {
this.tblCards = tbl0; this.tblCards = tbl0;
scroller.setViewportView(tblCards); scroller.setViewportView(tblCards);
} }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblTotal()
*/
@Override @Override
public JLabel getLblTotal() { return lblTotal; } public FLabel getStatLabel(SEditorUtil.StatTypes s) {
return statLabels.get(s);
/* (non-Javadoc) }
* @see forge.gui.deckeditor.views.ITableContainer#getLblBlack()
*/
@Override
public JLabel getLblBlack() { return lblBlack; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblBlue()
*/
@Override
public JLabel getLblBlue() { return lblBlue; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblGreen()
*/
@Override
public JLabel getLblGreen() { return lblGreen; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblRed()
*/
@Override
public JLabel getLblRed() { return lblRed; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblWhite()
*/
@Override
public JLabel getLblWhite() { return lblWhite; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblColorless()
*/
@Override
public JLabel getLblColorless() { return lblColorless; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblArtifact()
*/
@Override
public JLabel getLblArtifact() { return lblArtifact; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblEnchantment()
*/
@Override
public JLabel getLblEnchantment() { return lblEnchantment; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblCreature()
*/
@Override
public JLabel getLblCreature() { return lblCreature; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblSorcery()
*/
@Override
public JLabel getLblSorcery() { return lblSorcery; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblInstant()
*/
@Override
public JLabel getLblInstant() { return lblInstant; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblPlaneswalker()
*/
@Override
public JLabel getLblPlaneswalker() { return lblPlaneswalker; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblLand()
*/
@Override
public JLabel getLblLand() { return lblLand; }
//========== Accessor/mutator methods //========== Accessor/mutator methods
public JPanel getPnlHeader() { return pnlHeader; }
public FLabel getLblTitle() { return lblTitle; }
public JPanel getPnlAddButtons() { return pnlAddButtons; }
public FLabel getBtnAdd() { return btnAdd; }
public FLabel getBtnAdd4() { return btnAdd4; }
public FLabel getLblName() { return lblName; }
public FLabel getLblType() { return lblType; }
public FLabel getLblText() { return lblText; }
/** @return {@link javax.swing.JLabel} */ public FLabel getBtnAddRestriction() { return btnAddRestriction; }
public JLabel getLblTitle() { public JComboBox getCbSearchMode() { return cbSearchMode; }
return lblTitle; public JTextField getTxfSearch() { return txfSearch; }
public Map<SEditorUtil.StatTypes, FLabel> getStatLabels() {
return statLabels;
} }
public Map<RangeTypes, Pair<FSpinner, FSpinner>> getSpinners() {
/** @return {@link javax.swing.JLabel} */ return spinners;
public JLabel getBtnAdd() {
return btnAdd;
}
/** @return {@link javax.swing.JLabel} */
public JLabel getBtnAdd4() {
return btnAdd4;
}
/** @return {@link javax.swing.JPanel} */
public JPanel getPnlHeader() {
return pnlHeader;
}
/** @return {@link javax.swing.JPanel} */
public JPanel getPnlStats() {
return pnlStats;
}
/** @return {@link javax.swing.JPanel} */
public JPanel getPnlAddButtons() {
return pnlAddButtons;
} }
//========== Other methods //========== Other methods
private FLabel buildToggleLabel(SEditorUtil.StatTypes s, boolean selectable) {
private JLabel buildLabel(final ImageIcon icon0) { return new FLabel.Builder()
final JLabel lbl = new FLabel.Builder().text("0") .icon(s.img).iconScaleAuto(false)
.icon(icon0).iconScaleAuto(false) .text("0").fontSize(11)
.fontSize(11) .tooltip(s.toLabelString())
.hoverable(true).selectable(selectable).selected(selectable)
.build(); .build();
}
return lbl; @SuppressWarnings("serial")
public void addRestrictionWidget(JComponent component, final Command onRemove) {
final JPanel pnl = new JPanel(new MigLayout("insets 2, gap 2, h 30!"));
pnl.setOpaque(false);
pnl.setBorder(BorderFactory.createMatteBorder(1, 2, 1, 2, FSkin.getColor(FSkin.Colors.CLR_TEXT)));
final Container parent = pnlRestrictions.getParent();
pnl.add(component, "h 30!, center");
pnl.add(new FLabel.Builder().text("X").fontSize(10).hoverable(true)
.tooltip("Remove filter").cmdClick(new Command() {
@Override
public void execute() {
pnlRestrictions.remove(pnl);
pnlRestrictions.validate();
parent.validate();
parent.repaint();
onRemove.execute();
}
}).build(), "top");
pnlRestrictions.add(pnl, "h 30!");
pnlRestrictions.validate();
parent.validate();
parent.repaint();
}
public JComponent buildRangeRestrictionWidget(RangeTypes t) {
JPanel pnl = new JPanel(new MigLayout("insets 0, gap 2"));
pnl.setOpaque(false);
Pair<FSpinner, FSpinner> s = spinners.get(t);
pnl.add(s.a, "w 45!");
pnl.add(new FLabel.Builder().text("<=").fontSize(11).build());
pnl.add(new FLabel.Builder().text(t.toLabelString()).fontSize(11).build());
pnl.add(new FLabel.Builder().text("<=").fontSize(11).build());
pnl.add(s.b, "w 45!");
return pnl;
}
public JComponent buildPlainRestrictionWidget(String label, String tooltip) {
return new FLabel.Builder().text(label).tooltip(tooltip).fontSize(11).build();
} }
} }

View File

@@ -1,8 +1,8 @@
package forge.gui.deckeditor.views; package forge.gui.deckeditor.views;
import java.awt.Insets; import java.util.HashMap;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
@@ -101,7 +101,7 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_EDIT)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_EDIT))
.iconScaleAuto(false).hoverable(true).build(); .iconScaleAuto(false).hoverable(true).build();
private final JTextField txfTitle = new FTextField(); private final JTextField txfTitle = new FTextField.Builder().text("[New Deck]").build();
private final JPanel pnlRemove = new JPanel(); private final JPanel pnlRemove = new JPanel();
private final JPanel pnlHeader = new JPanel(); private final JPanel pnlHeader = new JPanel();
@@ -110,21 +110,8 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.fontSize(14).build(); .fontSize(14).build();
private final JPanel pnlStats = new JPanel(); private final JPanel pnlStats = new JPanel();
private final JLabel lblTotal = buildLabel(SEditorUtil.ICO_TOTAL); private final Map<SEditorUtil.StatTypes, FLabel> statLabels =
private final JLabel lblBlack = buildLabel(SEditorUtil.ICO_BLACK); new HashMap<SEditorUtil.StatTypes, FLabel>();
private final JLabel lblBlue = buildLabel(SEditorUtil.ICO_BLUE);
private final JLabel lblGreen = buildLabel(SEditorUtil.ICO_GREEN);
private final JLabel lblRed = buildLabel(SEditorUtil.ICO_RED);
private final JLabel lblWhite = buildLabel(SEditorUtil.ICO_WHITE);
private final JLabel lblColorless = buildLabel(SEditorUtil.ICO_COLORLESS);
private final JLabel lblArtifact = buildLabel(SEditorUtil.ICO_ARTIFACT);
private final JLabel lblCreature = buildLabel(SEditorUtil.ICO_CREATURE);
private final JLabel lblEnchantment = buildLabel(SEditorUtil.ICO_ENCHANTMENT);
private final JLabel lblInstant = buildLabel(SEditorUtil.ICO_INSTANT);
private final JLabel lblLand = buildLabel(SEditorUtil.ICO_LAND);
private final JLabel lblPlaneswalker = buildLabel(SEditorUtil.ICO_PLANESWALKER);
private final JLabel lblSorcery = buildLabel(SEditorUtil.ICO_SORCERY);
private JTable tblCards = null; private JTable tblCards = null;
private final JScrollPane scroller = new JScrollPane(tblCards); private final JScrollPane scroller = new JScrollPane(tblCards);
@@ -132,16 +119,6 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
//========== Constructor //========== Constructor
private VCurrentDeck() { private VCurrentDeck() {
// Title text area
txfTitle.setText("[New Deck]");
txfTitle.setMargin(new Insets(5, 5, 5, 5));
txfTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
txfTitle.setOpaque(true);
txfTitle.setEditable(true);
txfTitle.setFocusable(true);
txfTitle.setOpaque(true);
txfTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
// Header area // Header area
pnlHeader.setOpaque(false); pnlHeader.setOpaque(false);
pnlHeader.setLayout(new MigLayout("insets 0, gap 0, ax center, hidemode 3")); pnlHeader.setLayout(new MigLayout("insets 0, gap 0, ax center, hidemode 3"));
@@ -166,41 +143,13 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
scroller.setBorder(null); scroller.setBorder(null);
scroller.getViewport().setBorder(null); scroller.getViewport().setBorder(null);
lblTotal.setToolTipText("Total Card Count");
lblBlack.setToolTipText("Black Card Count");
lblBlue.setToolTipText("Blue Card Count");
lblGreen.setToolTipText("Green Card Count");
lblRed.setToolTipText("Red Card Count");
lblWhite.setToolTipText("White Card Count");
lblColorless.setToolTipText("Total Card Count");
lblArtifact.setToolTipText("Artifact Card Count");
lblCreature.setToolTipText("Creature Card Count");
lblColorless.setToolTipText("Colorless Card Count");
lblEnchantment.setToolTipText("Enchantment Card Count");
lblInstant.setToolTipText("Instant Card Count");
lblLand.setToolTipText("Land Card Count");
lblPlaneswalker.setToolTipText("Planeswalker Card Count");
lblSorcery.setToolTipText("Sorcery Card Count");
pnlStats.setOpaque(false); pnlStats.setOpaque(false);
pnlStats.setLayout(new MigLayout("insets 0, gap 5px, ax center, wrap 7")); pnlStats.setLayout(new MigLayout("insets 0, gap 5px, ax center, wrap 7"));
for (SEditorUtil.StatTypes s : SEditorUtil.StatTypes.values()) {
final String constraints = "w 55px!, h 20px!"; FLabel label = buildLabel(s);
pnlStats.add(lblTotal, constraints); statLabels.put(s, label);
pnlStats.add(lblWhite, constraints); pnlStats.add(label, "w 55px!, h 20px!");
pnlStats.add(lblBlue, constraints); }
pnlStats.add(lblBlack, constraints);
pnlStats.add(lblRed, constraints);
pnlStats.add(lblGreen, constraints);
pnlStats.add(lblColorless, constraints);
pnlStats.add(lblLand, constraints);
pnlStats.add(lblArtifact, constraints);
pnlStats.add(lblCreature, constraints);
pnlStats.add(lblEnchantment, constraints);
pnlStats.add(lblPlaneswalker, constraints);
pnlStats.add(lblInstant, constraints);
pnlStats.add(lblSorcery, constraints);
pnlRemoveButtons.setOpaque(false); pnlRemoveButtons.setOpaque(false);
pnlRemoveButtons.add(btnRemove, "w 30%!, h 30px!, gap 0 0 5px 5px"); pnlRemoveButtons.add(btnRemove, "w 30%!, h 30px!, gap 0 0 5px 5px");
@@ -278,95 +227,12 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
scroller.setViewportView(tblCards); scroller.setViewportView(tblCards);
} }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblTotal()
*/
@Override
public JLabel getLblTotal() { return lblTotal; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblTotal()
*/
public JLabel getLblTitle() { return lblTitle; } public JLabel getLblTitle() { return lblTitle; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblBlack()
*/
@Override @Override
public JLabel getLblBlack() { return lblBlack; } public FLabel getStatLabel(SEditorUtil.StatTypes s) {
return statLabels.get(s);
/* (non-Javadoc) }
* @see forge.gui.deckeditor.views.ITableContainer#getLblBlue()
*/
@Override
public JLabel getLblBlue() { return lblBlue; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblGreen()
*/
@Override
public JLabel getLblGreen() { return lblGreen; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblRed()
*/
@Override
public JLabel getLblRed() { return lblRed; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblWhite()
*/
@Override
public JLabel getLblWhite() { return lblWhite; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblColorless()
*/
@Override
public JLabel getLblColorless() { return lblColorless; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblArtifact()
*/
@Override
public JLabel getLblArtifact() { return lblArtifact; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblEnchantment()
*/
@Override
public JLabel getLblEnchantment() { return lblEnchantment; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblCreature()
*/
@Override
public JLabel getLblCreature() { return lblCreature; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblSorcery()
*/
@Override
public JLabel getLblSorcery() { return lblSorcery; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblInstant()
*/
@Override
public JLabel getLblInstant() { return lblInstant; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblPlaneswalker()
*/
@Override
public JLabel getLblPlaneswalker() { return lblPlaneswalker; }
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#getLblLand()
*/
@Override
public JLabel getLblLand() { return lblLand; }
//========== Retrieval //========== Retrieval
@@ -432,12 +298,11 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
//========== Other methods //========== Other methods
private JLabel buildLabel(final ImageIcon icon0) { private FLabel buildLabel(SEditorUtil.StatTypes s) {
final JLabel lbl = new FLabel.Builder().text("0") return new FLabel.Builder()
.icon(icon0).iconScaleAuto(false) .icon(s.img).iconScaleAuto(false)
.fontSize(11) .text("0").fontSize(11)
.tooltip(s.toLabelString())
.build(); .build();
return lbl;
} }
} }

View File

@@ -52,6 +52,7 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
private JCheckBox chbCatalogAI = new FCheckBox("AI"); private JCheckBox chbCatalogAI = new FCheckBox("AI");
private JCheckBox chbCatalogPower = new FCheckBox("Power"); private JCheckBox chbCatalogPower = new FCheckBox("Power");
private JCheckBox chbCatalogToughness = new FCheckBox("Toughness"); private JCheckBox chbCatalogToughness = new FCheckBox("Toughness");
private JCheckBox chbCatalogOwned = new FCheckBox("Owned (Spell shop)");
private JCheckBox chbDeckColor = new FCheckBox("Color"); private JCheckBox chbDeckColor = new FCheckBox("Color");
private JCheckBox chbDeckRarity = new FCheckBox("Rarity"); private JCheckBox chbDeckRarity = new FCheckBox("Rarity");
@@ -62,7 +63,6 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
private JCheckBox chbDeckToughness = new FCheckBox("Toughness"); private JCheckBox chbDeckToughness = new FCheckBox("Toughness");
private JCheckBox chbDeckStats = new FCheckBox("Show stats in current deck"); private JCheckBox chbDeckStats = new FCheckBox("Show stats in current deck");
private JCheckBox chbCatalogStats = new FCheckBox("Show stats in card catalog");
private JCheckBox chbElasticColumns = new FCheckBox("Use elastic resizing when changing column widths"); private JCheckBox chbElasticColumns = new FCheckBox("Use elastic resizing when changing column widths");
private JCheckBox chbCardDisplayUnique = new FCheckBox("Show unique cards only (only affects Constructed)"); private JCheckBox chbCardDisplayUnique = new FCheckBox("Show unique cards only (only affects Constructed)");
@@ -84,6 +84,7 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
chbCatalogAI.setFont(FSkin.getFont(12)); chbCatalogAI.setFont(FSkin.getFont(12));
chbCatalogPower.setFont(FSkin.getFont(12)); chbCatalogPower.setFont(FSkin.getFont(12));
chbCatalogToughness.setFont(FSkin.getFont(12)); chbCatalogToughness.setFont(FSkin.getFont(12));
chbCatalogOwned.setFont(FSkin.getFont(12));
chbDeckColor.setFont(FSkin.getFont(12)); chbDeckColor.setFont(FSkin.getFont(12));
chbDeckRarity.setFont(FSkin.getFont(12)); chbDeckRarity.setFont(FSkin.getFont(12));
@@ -94,17 +95,14 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
chbDeckToughness.setFont(FSkin.getFont(12)); chbDeckToughness.setFont(FSkin.getFont(12));
chbDeckStats.setFont(FSkin.getFont(12)); chbDeckStats.setFont(FSkin.getFont(12));
chbCatalogStats.setFont(FSkin.getFont(12));
chbElasticColumns.setFont(FSkin.getFont(12)); chbElasticColumns.setFont(FSkin.getFont(12));
chbDeckStats.setSelected(true); chbDeckStats.setSelected(true);
chbCatalogStats.setSelected(true);
chbElasticColumns.setSelected(false); chbElasticColumns.setSelected(false);
chbCardDisplayUnique.setFont(FSkin.getFont(12)); chbCardDisplayUnique.setFont(FSkin.getFont(12));
chbCardDisplayUnique.setSelected(false); chbCardDisplayUnique.setSelected(false);
pnl.add(lblStats, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1"); pnl.add(lblStats, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1");
pnl.add(chbCatalogStats, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1");
pnl.add(chbDeckStats, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1"); pnl.add(chbDeckStats, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1");
pnl.add(chbElasticColumns, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1"); pnl.add(chbElasticColumns, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1");
@@ -116,7 +114,8 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
pnl.add(chbCatalogSet, constraints); pnl.add(chbCatalogSet, constraints);
pnl.add(chbCatalogPower, constraints); pnl.add(chbCatalogPower, constraints);
pnl.add(chbCatalogToughness, constraints); pnl.add(chbCatalogToughness, constraints);
pnl.add(chbCatalogAI, constraints + ", wrap"); pnl.add(chbCatalogAI, constraints);
pnl.add(chbCatalogOwned, constraints + ", wrap");
pnl.add(lblDeck, constraints + ", span 2 1"); pnl.add(lblDeck, constraints + ", span 2 1");
pnl.add(chbDeckColor, constraints); pnl.add(chbDeckColor, constraints);
@@ -224,6 +223,11 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
return chbCatalogToughness; return chbCatalogToughness;
} }
/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getChbCatalogOwned() {
return chbCatalogOwned;
}
/** @return {@link javax.swing.JCheckBox} */ /** @return {@link javax.swing.JCheckBox} */
public JCheckBox getChbDeckColor() { public JCheckBox getChbDeckColor() {
return chbDeckColor; return chbDeckColor;
@@ -269,15 +273,8 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
return chbElasticColumns; return chbElasticColumns;
} }
/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getChbCatalogStats() {
return chbCatalogStats;
}
/** @return {@link javax.swing.JCheckBox} */ /** @return {@link javax.swing.JCheckBox} */
public JCheckBox getChbCardDisplayUnique() { public JCheckBox getChbCardDisplayUnique() {
return chbCardDisplayUnique; return chbCardDisplayUnique;
} }
//========== Other methods
} }

View File

@@ -1,333 +0,0 @@
package forge.gui.deckeditor.views;
import java.awt.Insets;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.MatteBorder;
import net.miginfocom.swing.MigLayout;
import forge.Singletons;
import forge.card.CardEdition;
import forge.game.GameFormat;
import forge.gui.deckeditor.SFilterUtil;
import forge.gui.deckeditor.controllers.CFilters;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
import forge.gui.framework.IVDoc;
import forge.gui.toolbox.FCheckBox;
import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSkin;
import forge.gui.toolbox.FTextField;
/**
* Assembles Swing components of deck editor filter tab.
*
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
*/
public enum VFilters implements IVDoc<CFilters> {
/** */
SINGLETON_INSTANCE;
// Fields used with interface IVDoc
private DragCell parentCell;
private final DragTab tab = new DragTab("Filters");
// Text filter components
private final JTextField txfContains = new FTextField();
private final JTextField txfWithout = new FTextField();
private final JLabel lblContains = new FLabel.Builder()
.text("Contains:").fontSize(14).build();
private final JLabel lblWithout = new FLabel.Builder()
.text("Without:").fontSize(14).build();
private final JCheckBox chbName = new FCheckBox("Name");
private final JCheckBox chbType = new FCheckBox("Type");
private final JCheckBox chbText = new FCheckBox("Text");
// Interval filter components
private final JComboBox cbxSets = new JComboBox();
private final JComboBox cbxPLow = new JComboBox();
private final JComboBox cbxPHigh = new JComboBox();
private final JComboBox cbxTLow = new JComboBox();
private final JComboBox cbxTHigh = new JComboBox();
private final JComboBox cbxCMCLow = new JComboBox();
private final JComboBox cbxCMCHigh = new JComboBox();
private final JLabel lblP = new FLabel.Builder()
.fontSize(12).text(" <= Power <= ").build();
private final JLabel lblT = new FLabel.Builder()
.fontSize(12).text(" <= Toughness <= ").build();
private final JLabel lblCMC = new FLabel.Builder()
.fontSize(12).text(" <= CMC <= ").build();
// Title labels
private final JLabel lblProperties = new FLabel.Builder()
.text("Properties").tooltip("Filter by color, type, set, or format. Click to toggle.")
.hoverable(true).fontSize(14).build();
private final JLabel lblText = new FLabel.Builder()
.text("Card Text").tooltip("Filter by card name, type, and text, space delimited. Click to reset.")
.hoverable(true).fontSize(14).build();
private final JLabel lblIntervals = new FLabel.Builder()
.text("Intervals").tooltip("Filter by power, toughness, or converted mana cost. Click to reset.")
.hoverable(true).fontSize(14).build();
// Container components
private final JPanel pnlText = new JPanel(new MigLayout(
"insets 0, gap 0, wrap 3, ax center"));
private final JPanel pnlIntervals = new JPanel(new MigLayout(
"insets 0, gap 0, wrap 3, ax center"));
private JPanel pnlContainer = new JPanel(new MigLayout("insets 0, gap 0, wrap"));
private JScrollPane scroller = new JScrollPane(pnlContainer);
//========== Constructor
private VFilters() {
String constraints = "";
// Sets/formats combo box
cbxSets.addItem("All sets and formats");
for (final GameFormat s : Singletons.getModel().getFormats()) {
cbxSets.addItem(s);
}
for (final CardEdition s : Singletons.getModel().getEditions()) {
cbxSets.addItem(s);
}
// Color/type searches
lblProperties.setBorder(new MatteBorder(0, 0, 1, 0,
FSkin.getColor(FSkin.Colors.CLR_BORDERS)));
lblText.setBorder(new MatteBorder(0, 0, 1, 0,
FSkin.getColor(FSkin.Colors.CLR_BORDERS)));
lblIntervals.setBorder(new MatteBorder(0, 0, 1, 0,
FSkin.getColor(FSkin.Colors.CLR_BORDERS)));
// Text search
txfContains.setMargin(new Insets(5, 5, 5, 5));
txfContains.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
txfContains.setOpaque(true);
txfContains.setEditable(true);
txfContains.setFocusable(true);
txfContains.setOpaque(true);
txfContains.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
txfWithout.setMargin(new Insets(5, 5, 5, 5));
txfWithout.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
txfWithout.setOpaque(true);
txfWithout.setEditable(true);
txfWithout.setFocusable(true);
txfWithout.setOpaque(true);
txfWithout.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
pnlText.setOpaque(false);
pnlText.add(lblText, "w 210px!, h 25px!");
pnlText.add(lblContains, "w 80px!, h 30px!");
pnlText.add(txfContains, "pushx, growx, span 2 1, gap 5px 5px 2px 2px, h 30px!");
pnlText.add(lblWithout, "w 80px!, h 30px!");
pnlText.add(txfWithout, "pushx, growx, span 2 1, gap 5px 5px 2px 2px, h 30px!");
pnlText.add(chbName, "pushx, growx, w 70px!, h 25px!, gap 5px 5px 2px 2px");
pnlText.add(chbType, "pushx, growx, w 70px!, h 25px!, gap 0 5px 2px 2px");
pnlText.add(chbText, "w 60px!, h 25px!, gap 0 5px 2px 2px");
chbName.setSelected(true);
chbType.setSelected(true);
chbText.setSelected(true);
cbxPLow.addItem("*");
cbxTLow.addItem("*");
cbxCMCLow.addItem("*");
// Interval search
for (int i = 0; i < 10; i++) {
cbxPLow.addItem(i);
cbxTLow.addItem(i);
cbxCMCLow.addItem(i);
cbxPHigh.addItem(i);
cbxTHigh.addItem(i);
cbxCMCHigh.addItem(i);
}
cbxPHigh.addItem("10+");
cbxTHigh.addItem("10+");
cbxCMCHigh.addItem("10+");
cbxPLow.setSelectedItem("*");
cbxTLow.setSelectedItem("*");
cbxCMCLow.setSelectedItem("*");
cbxPHigh.setSelectedItem("10+");
cbxTHigh.setSelectedItem("10+");
cbxCMCHigh.setSelectedItem("10+");
constraints = "w 80px!, h 25px!, gap 0 0 0 0";
pnlIntervals.add(cbxPLow, constraints);
pnlIntervals.add(lblP, "w 100px!, h 25px!");
pnlIntervals.add(cbxPHigh, constraints);
pnlIntervals.add(cbxTLow, constraints);
pnlIntervals.add(lblT, "w 100px!, h 25px!");
pnlIntervals.add(cbxTHigh, constraints);
pnlIntervals.add(cbxCMCLow, constraints);
pnlIntervals.add(lblCMC, "w 100px!, h 25px!");
pnlIntervals.add(cbxCMCHigh, constraints);
pnlIntervals.setOpaque(false);
// Core layout
final String constraints2 = "w 90%!, gap 5% 0 1% 0";
pnlContainer.add(lblProperties, "w 90%!, h 25px!, gap 5% 0 1% 0");
pnlContainer.add(SFilterUtil.populateColorFilters(), constraints2);
pnlContainer.add(SFilterUtil.populateTypeFilters(), constraints2);
pnlContainer.add(cbxSets, constraints2 + ", h 25px!");
pnlContainer.add(lblText, "w 90%!, h 25px!, gap 5% 0 15px 0");
pnlContainer.add(pnlText, constraints2);
pnlContainer.add(lblIntervals, "w 90%!, h 25px!, gap 5% 0 15px 0");
pnlContainer.add(pnlIntervals, constraints2);
pnlContainer.setOpaque(false);
scroller.setOpaque(false);
scroller.getViewport().setOpaque(false);
scroller.setBorder(null);
scroller.getViewport().setBorder(null);
}
//========== Overridden methods
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getDocumentID()
*/
@Override
public EDocID getDocumentID() {
return EDocID.EDITOR_FILTERS;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getTabLabel()
*/
@Override
public DragTab getTabLabel() {
return tab;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getLayoutControl()
*/
@Override
public CFilters getLayoutControl() {
return CFilters.SINGLETON_INSTANCE;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#setParentCell(forge.gui.framework.DragCell)
*/
@Override
public void setParentCell(final DragCell cell0) {
this.parentCell = cell0;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getParentCell()
*/
@Override
public DragCell getParentCell() {
return this.parentCell;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#populate()
*/
@Override
public void populate() {
parentCell.getBody().setLayout(new MigLayout("insets 0, gap 0, wrap"));
parentCell.getBody().add(scroller, "w 96%!, h 96%, gap 2% 0 2% 0");
}
//========== Retrieval methods
/** @return {javax.swing.JLabel} */
public JLabel getBtnToggle() {
return lblProperties;
}
/** @return {javax.swing.JLabel} */
public JLabel getBtnResetText() {
return lblText;
}
/** @return {javax.swing.JLabel} */
public JLabel getBtnResetIntervals() {
return lblIntervals;
}
/** @return {javax.swing.JComboBox} */
public JComboBox getCbxSets() {
return cbxSets;
}
/** @return {javax.swing.JTextField} */
public JTextField getTxfContains() {
return txfContains;
}
/** @return {javax.swing.JTextField} */
public JTextField getTxfWithout() {
return txfWithout;
}
/** @return {javax.swing.JComboBox} */
public JComboBox getCbxPLow() {
return cbxPLow;
}
/** @return {javax.swing.JComboBox} */
public JComboBox getCbxPHigh() {
return cbxPHigh;
}
/** @return {javax.swing.JComboBox} */
public JComboBox getCbxTLow() {
return cbxTLow;
}
/** @return {javax.swing.JComboBox} */
public JComboBox getCbxTHigh() {
return cbxTHigh;
}
/** @return {javax.swing.JComboBox} */
public JComboBox getCbxCMCLow() {
return cbxCMCLow;
}
/** @return {javax.swing.JComboBox} */
public JComboBox getCbxCMCHigh() {
return cbxCMCHigh;
}
/** @return {javax.swing.JCheckBox} */
public JCheckBox getChbTextName() {
return chbName;
}
/** @return {javax.swing.JCheckBox} */
public JCheckBox getChbTextType() {
return chbType;
}
/** @return {javax.swing.JCheckBox} */
public JCheckBox getChbTextText() {
return chbText;
}
//========== Custom class handling
}

View File

@@ -43,22 +43,22 @@ public enum VStatistics implements IVDoc<CStatistics> {
// Total and color count labels // Total and color count labels
private final JPanel pnlStats = new JPanel(); private final JPanel pnlStats = new JPanel();
private final JLabel lblMulti = buildLabel(SEditorUtil.ICO_MULTI, true); private final JLabel lblMulti = buildLabel(SEditorUtil.StatTypes.MULTICOLOR, true);
private final JLabel lblBlack = buildLabel(SEditorUtil.ICO_BLACK, false); private final JLabel lblBlack = buildLabel(SEditorUtil.StatTypes.BLACK, false);
private final JLabel lblBlue = buildLabel(SEditorUtil.ICO_BLUE, true); private final JLabel lblBlue = buildLabel(SEditorUtil.StatTypes.BLUE, true);
private final JLabel lblGreen = buildLabel(SEditorUtil.ICO_GREEN, false); private final JLabel lblGreen = buildLabel(SEditorUtil.StatTypes.GREEN, false);
private final JLabel lblRed = buildLabel(SEditorUtil.ICO_RED, true); private final JLabel lblRed = buildLabel(SEditorUtil.StatTypes.RED, true);
private final JLabel lblWhite = buildLabel(SEditorUtil.ICO_WHITE, false); private final JLabel lblWhite = buildLabel(SEditorUtil.StatTypes.WHITE, false);
private final JLabel lblColorless = buildLabel(SEditorUtil.ICO_COLORLESS, true); private final JLabel lblColorless = buildLabel(SEditorUtil.StatTypes.COLORLESS, true);
// Card type labels // Card type labels
private final JLabel lblArtifact = buildLabel(SEditorUtil.ICO_ARTIFACT, true); private final JLabel lblArtifact = buildLabel(SEditorUtil.StatTypes.ARTIFACT, true);
private final JLabel lblCreature = buildLabel(SEditorUtil.ICO_CREATURE, false); private final JLabel lblCreature = buildLabel(SEditorUtil.StatTypes.CREATURE, false);
private final JLabel lblEnchantment = buildLabel(SEditorUtil.ICO_ENCHANTMENT, true); private final JLabel lblEnchantment = buildLabel(SEditorUtil.StatTypes.ENCHANTMENT, true);
private final JLabel lblInstant = buildLabel(SEditorUtil.ICO_INSTANT, false); private final JLabel lblInstant = buildLabel(SEditorUtil.StatTypes.INSTANT, false);
private final JLabel lblLand = buildLabel(SEditorUtil.ICO_LAND, true); private final JLabel lblLand = buildLabel(SEditorUtil.StatTypes.LAND, true);
private final JLabel lblPlaneswalker = buildLabel(SEditorUtil.ICO_PLANESWALKER, false); private final JLabel lblPlaneswalker = buildLabel(SEditorUtil.StatTypes.PLANESWALKER, false);
private final JLabel lblSorcery = buildLabel(SEditorUtil.ICO_SORCERY, true); private final JLabel lblSorcery = buildLabel(SEditorUtil.StatTypes.SORCERY, true);
// CMC labels // CMC labels
private final JLabel lblCMC0 = buildLabel( private final JLabel lblCMC0 = buildLabel(
@@ -251,9 +251,9 @@ public enum VStatistics implements IVDoc<CStatistics> {
//========== Other methods //========== Other methods
private JLabel buildLabel(final ImageIcon icon0, final boolean zebra) { private JLabel buildLabel(ImageIcon icon, boolean zebra) {
final JLabel lbl = new FLabel.Builder().text("0") final JLabel lbl = new FLabel.Builder().text("0")
.icon(icon0).iconScaleAuto(false) .icon(icon).iconScaleAuto(false)
.fontSize(11).build(); .fontSize(11).build();
if (zebra) { if (zebra) {
@@ -263,4 +263,8 @@ public enum VStatistics implements IVDoc<CStatistics> {
return lbl; return lbl;
} }
private JLabel buildLabel(SEditorUtil.StatTypes statType, boolean zebra) {
return buildLabel(statType.img, zebra);
}
} }

View File

@@ -8,7 +8,6 @@ import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.deckeditor.views.VCurrentDeck;
import forge.gui.deckeditor.views.VDeckgen; import forge.gui.deckeditor.views.VDeckgen;
import forge.gui.deckeditor.views.VEditorPreferences; import forge.gui.deckeditor.views.VEditorPreferences;
import forge.gui.deckeditor.views.VFilters;
import forge.gui.deckeditor.views.VProbabilities; import forge.gui.deckeditor.views.VProbabilities;
import forge.gui.deckeditor.views.VStatistics; import forge.gui.deckeditor.views.VStatistics;
import forge.gui.home.gauntlet.VSubmenuGauntletBuild; import forge.gui.home.gauntlet.VSubmenuGauntletBuild;
@@ -51,7 +50,6 @@ public enum EDocID { /** */
CARD_DETAIL (VDetail.SINGLETON_INSTANCE), /** */ CARD_DETAIL (VDetail.SINGLETON_INSTANCE), /** */
CARD_ANTES (VAntes.SINGLETON_INSTANCE), /** */ CARD_ANTES (VAntes.SINGLETON_INSTANCE), /** */
EDITOR_FILTERS (VFilters.SINGLETON_INSTANCE), /** */
EDITOR_PREFERENCES (VEditorPreferences.SINGLETON_INSTANCE), /** */ EDITOR_PREFERENCES (VEditorPreferences.SINGLETON_INSTANCE), /** */
EDITOR_ALLDECKS (VAllDecks.SINGLETON_INSTANCE), /** */ EDITOR_ALLDECKS (VAllDecks.SINGLETON_INSTANCE), /** */
EDITOR_STATISTICS (VStatistics.SINGLETON_INSTANCE), /** */ EDITOR_STATISTICS (VStatistics.SINGLETON_INSTANCE), /** */

View File

@@ -190,7 +190,9 @@ public final class SLayoutIO {
} }
else if (element.getName().getLocalPart().equals("doc")) { else if (element.getName().getLocalPart().equals("doc")) {
event = reader.nextEvent(); event = reader.nextEvent();
try {
cell.addDoc(EDocID.valueOf(event.asCharacters().getData()).getDoc()); cell.addDoc(EDocID.valueOf(event.asCharacters().getData()).getDoc());
} catch (IllegalArgumentException e) { /* ignore; just don't add invalid element */ }
} }
} }
} }

View File

@@ -1,7 +1,6 @@
package forge.gui.home.gauntlet; package forge.gui.home.gauntlet;
import java.awt.Color; import java.awt.Color;
import java.awt.Insets;
import javax.swing.ButtonGroup; import javax.swing.ButtonGroup;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
@@ -68,7 +67,7 @@ public enum VSubmenuGauntletBuild implements IVSubmenu<CSubmenuGauntletBuild> {
private final JScrollPane scrRight = new FScrollPane(lstRight, private final JScrollPane scrRight = new FScrollPane(lstRight,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
private final JTextField txfFilename = new FTextField(); private final JTextField txfFilename = new FTextField.Builder().text(GauntletIO.TXF_PROMPT).build();
private final FLabel lblDesc1 = new FLabel.Builder() private final FLabel lblDesc1 = new FLabel.Builder()
.text("Left/right arrows add or remove decks.") .text("Left/right arrows add or remove decks.")
@@ -139,16 +138,6 @@ public enum VSubmenuGauntletBuild implements IVSubmenu<CSubmenuGauntletBuild> {
grpRadios.add(radColorDecks); grpRadios.add(radColorDecks);
grpRadios.add(radThemeDecks); grpRadios.add(radThemeDecks);
// Text areas
txfFilename.setText(GauntletIO.TXF_PROMPT);
txfFilename.setMargin(new Insets(5, 5, 5, 5));
txfFilename.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
txfFilename.setOpaque(true);
txfFilename.setEditable(true);
txfFilename.setFocusable(true);
txfFilename.setOpaque(true);
txfFilename.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
// File handling panel // File handling panel
final FLabel lblFilename = new FLabel.Builder() final FLabel lblFilename = new FLabel.Builder()
.text("Gauntlet Name:").fontSize(14).build(); .text("Gauntlet Name:").fontSize(14).build();

View File

@@ -61,11 +61,11 @@ public enum CSubmenuQuestData implements ICDoc {
new Command() { @Override public void execute() { newQuest(); } }); new Command() { @Override public void execute() { newQuest(); } });
view.getBtnCustomFormat().setCommand(new Command() { @Override public void execute() { view.getBtnCustomFormat().setCommand(new Command() { @Override public void execute() {
new DialogCustomFormat(customFormatCodes); new DialogChooseSets(customFormatCodes, null);
} }); } });
view.getBtnPrizeCustomFormat().setCommand(new Command() { @Override public void execute() { view.getBtnPrizeCustomFormat().setCommand(new Command() { @Override public void execute() {
new DialogCustomFormat(customPrizeFormatCodes); new DialogChooseSets(customPrizeFormatCodes, null);
} }); } });
} }

View File

@@ -21,7 +21,7 @@ import forge.Singletons;
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
*/ */
public class DialogCustomFormat extends JDialog { public class DialogChooseSets extends JDialog {
private static final long serialVersionUID = 3155211532871888181L; private static final long serialVersionUID = 3155211532871888181L;
private JScrollPane scrollPane; private JScrollPane scrollPane;
@@ -29,6 +29,7 @@ public class DialogCustomFormat extends JDialog {
private final JButton btnCancel = new JButton("Cancel"); private final JButton btnCancel = new JButton("Cancel");
private final JPanel buttonPanel = new JPanel(); private final JPanel buttonPanel = new JPanel();
private final List<String> customFormat; private final List<String> customFormat;
private final Runnable onOk;
private final List<JCheckBox> choices = new ArrayList<JCheckBox>(); private final List<JCheckBox> choices = new ArrayList<JCheckBox>();
@@ -39,9 +40,11 @@ public class DialogCustomFormat extends JDialog {
* GameFormatQuest, the user-defined format to update * GameFormatQuest, the user-defined format to update
* *
*/ */
public DialogCustomFormat(List<String> userFormat) { public DialogChooseSets(List<String> userFormat, Runnable onOk) {
customFormat = userFormat; customFormat = userFormat;
this.onOk = onOk;
if (customFormat == null) { if (customFormat == null) {
throw new RuntimeException("Null GameFormatQuest in DialogCustomFormat"); throw new RuntimeException("Null GameFormatQuest in DialogCustomFormat");
} }
@@ -66,7 +69,6 @@ public class DialogCustomFormat extends JDialog {
int getIdx = 0; int getIdx = 0;
JPanel p = new JPanel(); JPanel p = new JPanel();
p.setSize(600, 400);
p.setLayout(new GridLayout(rows, columns, 10, 0)); p.setLayout(new GridLayout(rows, columns, 10, 0));
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++) {
@@ -75,7 +77,7 @@ public class DialogCustomFormat extends JDialog {
JCheckBox box; JCheckBox box;
if (getIdx < numEditions) { if (getIdx < numEditions) {
CardEdition edition = getIdx < numEditions ? editions.get(getIdx) : null; CardEdition edition = getIdx < numEditions ? editions.get(getIdx) : null;
box = new JCheckBox(edition.getName()); box = new JCheckBox(String.format("%s (%s)", edition.getName(), edition.getCode()));
box.setName(edition.getCode()); box.setName(edition.getCode());
box.setSelected(customFormat.contains(edition.getCode())); box.setSelected(customFormat.contains(edition.getCode()));
choices.add(box); choices.add(box);
@@ -98,6 +100,8 @@ public class DialogCustomFormat extends JDialog {
} }
}); });
buttonPanel.add(btnOK, BorderLayout.WEST); buttonPanel.add(btnOK, BorderLayout.WEST);
getRootPane().setDefaultButton(btnOK);
btnCancel.addActionListener(new ActionListener() { btnCancel.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(final ActionEvent arg0) { public void actionPerformed(final ActionEvent arg0) {
@@ -109,7 +113,7 @@ public class DialogCustomFormat extends JDialog {
this.setSize(600, 450); this.setSize(600, 450);
this.setLocationRelativeTo(null); this.setLocationRelativeTo(null);
this.setTitle("Choose sets for custom format:"); this.setTitle("Choose sets");
this.setVisible(true); this.setVisible(true);
} }
@@ -146,5 +150,9 @@ public class DialogCustomFormat extends JDialog {
customFormat.add(box.getName()); customFormat.add(box.getName());
} }
} }
if (null != onOk) {
onOk.run();
}
} }
} }

View File

@@ -51,7 +51,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
* <code>new FLabel.Builder().method1(foo).method2(bar).method3(baz)...</code> * <code>new FLabel.Builder().method1(foo).method2(bar).method3(baz)...</code>
* <br>and then call build() to make the label (don't forget that part). * <br>and then call build() to make the label (don't forget that part).
*/ */
public static class Builder extends FLabel { public static class Builder {
//========== Default values for FLabel are set here. //========== Default values for FLabel are set here.
private double bldIconScaleFactor = 0.8; private double bldIconScaleFactor = 0.8;
private int bldFontStyle = Font.PLAIN; private int bldFontStyle = Font.PLAIN;
@@ -61,10 +61,12 @@ public class FLabel extends JLabel implements ILocalRepaint {
private Point bldIconInsets = new Point(0, 0); private Point bldIconInsets = new Point(0, 0);
private boolean bldSelectable = false; private boolean bldSelectable = false;
private boolean bldSelected = false;
private boolean bldHoverable = false; private boolean bldHoverable = false;
private boolean bldOpaque = false; private boolean bldOpaque = false;
private boolean bldIconInBackground = false; private boolean bldIconInBackground = false;
private boolean bldIconScaleAuto = true; private boolean bldIconScaleAuto = true;
private boolean reactOnMouseDown = false;
private String bldText, bldToolTip; private String bldText, bldToolTip;
private ImageIcon bldIcon; private ImageIcon bldIcon;
@@ -104,6 +106,14 @@ public class FLabel extends JLabel implements ILocalRepaint {
* @return {@link forge.gui.toolbox.Builder} */ * @return {@link forge.gui.toolbox.Builder} */
public Builder selectable(final boolean b0) { this.bldSelectable = b0; return this; } public Builder selectable(final boolean b0) { this.bldSelectable = b0; return this; }
/**@param b0 &emsp; boolean
* @return {@link forge.gui.toolbox.Builder} */
public Builder selected(final boolean b0) { this.bldSelected = b0; return this; }
/**@param b0 &emsp; boolean that controls when the label responds to mouse events
* @return {@link forge.gui.toolbox.Builder} */
public Builder reactOnMouseDown(final boolean b0) { this.reactOnMouseDown = b0; return this; }
/**@param c0 &emsp; {@link forge.Command} to execute if clicked /**@param c0 &emsp; {@link forge.Command} to execute if clicked
* @return {@link forge.gui.toolbox.Builder} */ * @return {@link forge.gui.toolbox.Builder} */
public Builder cmdClick(final Command c0) { this.bldCmd = c0; return this; } public Builder cmdClick(final Command c0) { this.bldCmd = c0; return this; }
@@ -158,6 +168,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
this.iconInBackground = b0.bldIconInBackground; this.iconInBackground = b0.bldIconInBackground;
this.iconScaleAuto = b0.bldIconScaleAuto; this.iconScaleAuto = b0.bldIconScaleAuto;
this.selectable = b0.bldSelectable; this.selectable = b0.bldSelectable;
this.selected = b0.bldSelected;
this.iconAlignX = b0.bldIconAlignX; this.iconAlignX = b0.bldIconAlignX;
this.iconInsets = b0.bldIconInsets; this.iconInsets = b0.bldIconInsets;
@@ -165,8 +176,8 @@ public class FLabel extends JLabel implements ILocalRepaint {
this.setFontSize(b0.bldFontSize); this.setFontSize(b0.bldFontSize);
this.setIconAlpha(b0.bldIconAlpha); this.setIconAlpha(b0.bldIconAlpha);
this.setCommand(b0.bldCmd); this.setCommand(b0.bldCmd);
this.setReactOnMouseDown(b0.reactOnMouseDown);
this.setFontAlign(b0.bldFontAlign); this.setFontAlign(b0.bldFontAlign);
this.setText(b0.bldText);
this.setToolTipText(b0.bldToolTip); this.setToolTipText(b0.bldToolTip);
this.setHoverable(b0.bldHoverable); this.setHoverable(b0.bldHoverable);
@@ -176,8 +187,6 @@ public class FLabel extends JLabel implements ILocalRepaint {
// Non-custom display properties // Non-custom display properties
this.setForeground(clrText); this.setForeground(clrText);
this.setBackground(clrInactive); this.setBackground(clrInactive);
this.setVerticalTextPosition(SwingConstants.CENTER);
this.setVerticalAlignment(SwingConstants.CENTER);
// Resize adapter // Resize adapter
this.removeComponentListener(cadResize); this.removeComponentListener(cadResize);
@@ -202,7 +211,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
private int fontStyle, iconAlignX; private int fontStyle, iconAlignX;
private int iw, ih; private int iw, ih;
private boolean selectable, selected, hoverable, hovered, opaque, private boolean selectable, selected, hoverable, hovered, opaque,
iconInBackground, iconScaleAuto; iconInBackground, iconScaleAuto, reactOnMouseDown;
private Point iconInsets; private Point iconInsets;
// Various variables used in image rendering. // Various variables used in image rendering.
@@ -246,19 +255,35 @@ public class FLabel extends JLabel implements ILocalRepaint {
private final MouseAdapter madEvents = new MouseAdapter() { private final MouseAdapter madEvents = new MouseAdapter() {
@Override @Override
public void mouseEntered(final MouseEvent e) { public void mouseEntered(final MouseEvent e) {
if (hoverable) {
hovered = true; repaintSelf(); hovered = true; repaintSelf();
} }
}
@Override @Override
public void mouseExited(final MouseEvent e) { public void mouseExited(final MouseEvent e) {
if (hoverable) {
hovered = false; repaintSelf(); hovered = false; repaintSelf();
} }
}
private void _doMouseAction() {
if (selectable) { setSelected(!selected); }
if (cmdClick != null && FLabel.this.isEnabled()) { cmdClick.execute(); }
}
@Override
public void mousePressed(MouseEvent e) {
if (reactOnMouseDown) {
_doMouseAction();
}
}
@Override @Override
public void mouseClicked(final MouseEvent e) { public void mouseClicked(final MouseEvent e) {
if (cmdClick != null && FLabel.this.isEnabled()) { cmdClick.execute(); } if (!reactOnMouseDown) {
if (!selectable) { return; } _doMouseAction();
if (selected) { setSelected(false); } }
else { setSelected(true); }
} }
}; };
@@ -278,6 +303,10 @@ public class FLabel extends JLabel implements ILocalRepaint {
repaintSelf(); repaintSelf();
} }
public boolean getSelected() {
return this.selected;
}
/** Sets alpha if icon is in background. /** Sets alpha if icon is in background.
* @param f0 &emsp; float */ * @param f0 &emsp; float */
// NOT public; must be set when label is built. // NOT public; must be set when label is built.
@@ -359,6 +388,10 @@ public class FLabel extends JLabel implements ILocalRepaint {
this.cmdClick = c0; this.cmdClick = c0;
} }
public void setReactOnMouseDown(boolean b0) {
this.reactOnMouseDown = b0;
}
@Override @Override
public void setOpaque(final boolean b0) { public void setOpaque(final boolean b0) {
// Must be overridden to allow drawing order of background, icon, string // Must be overridden to allow drawing order of background, icon, string

View File

@@ -0,0 +1,49 @@
package forge.gui.toolbox;
import java.awt.Insets;
import javax.swing.JFormattedTextField;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.text.NumberFormatter;
/**
* A custom instance of JSpinner using Forge skin properties. Only numeric
* integer spinners are implemented, since that's all we've needed so far.
*
*/
@SuppressWarnings("serial")
public class FSpinner extends JSpinner {
public static class Builder {
//========== Default values for FTextField are set here.
private int initialValue = 0;
private int minValue = 0;
private int maxValue = Integer.MAX_VALUE;
private String toolTip;
public FSpinner build() { return new FSpinner(this); }
public Builder initialValue(int i0) { initialValue = i0; return this; }
public Builder minValue(int i0) { minValue = i0; return this; }
public Builder maxValue(int i0) { maxValue = i0; return this; }
public Builder tooltip(String s0) { toolTip = s0; return this; }
}
private FSpinner(Builder builder) {
this.setOpaque(false);
this.setModel(new SpinnerNumberModel(builder.initialValue, builder.minValue, builder.maxValue, 1));
this.setEditor(new JSpinner.NumberEditor(this, "##"));
JFormattedTextField txt = ((JSpinner.NumberEditor)this.getEditor()).getTextField();
((NumberFormatter)txt.getFormatter()).setAllowsInvalid(false);
txt.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
txt.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
txt.setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT));
txt.setMargin(new Insets(5, 5, 5, 5));
txt.setOpaque(true);
this.setToolTipText(builder.toolTip);
this.setFocusable(true);
}
}

View File

@@ -1,6 +1,11 @@
package forge.gui.toolbox; package forge.gui.toolbox;
import java.awt.Insets;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
/** /**
* A custom instance of JTextArea using Forge skin properties. * A custom instance of JTextArea using Forge skin properties.
@@ -8,13 +13,64 @@ import javax.swing.JTextField;
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class FTextField extends JTextField { public class FTextField extends JTextField {
/** */ /**
public FTextField() { * Uses the Builder pattern to facilitate/encourage inline styling.
super(); * Credit to Effective Java 2 (Joshua Bloch).
* Methods in builder can be chained. To declare:
* <code>new FTextField.Builder().method1(foo).method2(bar).method3(baz)...</code>
* <br>and then call build() to make the widget (don't forget that part).
*/
public static class Builder {
//========== Default values for FTextField are set here.
private int maxLength = 0; // <=0 indicates no maximum
private boolean readonly = false;
private String text;
private String toolTip;
public FTextField build() { return new FTextField(this); }
public Builder maxLength(int i0) { maxLength = i0; return this; }
public Builder readonly(boolean b0) { readonly = b0; return this; }
public Builder text(String s0) { text = s0; return this; }
public Builder tooltip(String s0) { toolTip = s0; return this; }
}
private FTextField(Builder builder) {
this.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); this.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
this.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
this.setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT)); this.setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT));
this.setOpaque(false); this.setMargin(new Insets(5, 5, 5, 5));
this.setFocusable(false); this.setOpaque(true);
this.setEditable(false);
if (0 < builder.maxLength)
{
this.setDocument(new _LengthLimitedDocument(builder.maxLength));
}
this.setEditable(!builder.readonly);
this.setText(builder.text);
this.setToolTipText(builder.toolTip);
this.setFocusable(true);
}
private static class _LengthLimitedDocument extends PlainDocument {
private final int _limit;
_LengthLimitedDocument(int limit) { _limit = limit; }
// called each time a character is typed or a string is pasted
@Override
public void insertString(int offset, String s, AttributeSet attributeSet)
throws BadLocationException {
if (_limit <= this.getLength()) {
return;
}
int newLen = this.getLength() + s.length();
if (_limit < newLen) {
s = s.substring(0, _limit - this.getLength());
}
super.insertString(offset, s, attributeSet);
}
} }
} }

View File

@@ -137,6 +137,13 @@ public class QuestController {
return (getWorldFormat() == null ? this.questFormat : getWorldFormat()); return (getWorldFormat() == null ? this.questFormat : getWorldFormat());
} }
/**
* Gets the custom format for the main world, if any.
*/
public GameFormatQuest getMainFormat() {
return this.questFormat;
}
/** /**
* Gets the current event. * Gets the current event.
* *

View File

@@ -0,0 +1,237 @@
package forge.quest;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import forge.Singletons;
import forge.item.CardDb;
import forge.item.CardPrinted;
import forge.card.CardRules;
import forge.item.InventoryItem;
import forge.item.ItemPool;
/**
* Resolves a card chooser InventoryItem into a CardPrinted.
* The initial version includes "duplicate", other type may be added later.
*
*/
public class QuestRewardCardChooser implements InventoryItem {
/**
* Possible types for this object.
*/
public enum poolType {
/** The player's own cardpool (duplicate card). */
playerCards,
/** Filtered by a predicate that will be parsed. */
predicateFilter
}
private poolType type;
private final String description;
private final Predicate<CardPrinted> predicates;
/**
* The constructor.
* The parameter indicates the more specific type.
* @param setType String, the type of the choosable card.
* @param creationParameters String, used to build the predicates and description for the predicateFilter type
*/
public QuestRewardCardChooser(final poolType setType, final String[] creationParameters) {
type = setType;
if (type == poolType.playerCards) {
description = "a duplicate card";
predicates = null;
} else {
description = buildDescription(creationParameters);
predicates = buildPredicates(creationParameters);
}
}
private String buildDescription(final String [] input) {
final String defaultDescription = "a card";
if (input == null || input.length < 1) {
return defaultDescription;
}
String buildDesc = null;
for (String s : input) {
if (s.startsWith("desc:") || s.startsWith("Desc:")) {
String[] tmp = s.split(":");
if (tmp.length > 1) {
buildDesc = new String(tmp[1]);
} else {
buildDesc = new String();
}
} else if (buildDesc != null) {
if (s.contains(":")) {
return buildDesc;
} else {
buildDesc = buildDesc + " " + s;
}
}
}
if (buildDesc != null) {
return buildDesc;
}
return defaultDescription;
}
private Predicate<CardPrinted> buildPredicates(final String [] input) {
if (input == null || input.length < 1) {
return null;
}
Predicate<CardPrinted> filters = Singletons.getModel().getQuest().getFormat().getFilterPrinted();
Predicate<CardRules> filterRules = null;
Predicate<CardPrinted> filterRarity = null;
for (String s : input) {
if (s.startsWith("sets:") || s.startsWith("Sets:")) {
final String[] tmp = s.split(":");
if (tmp.length > 1) {
String [] setcodes = tmp[1].split(",");
if (setcodes.length > 0) {
List<String> sets = new ArrayList<String>();
for (String code : setcodes) {
if (Singletons.getModel().getEditions().contains(code)) {
// System.out.println("Set " + code + " was found!");
sets.add(code);
}
// else { System.out.println("Unknown set code " + code); }
}
if (sets.size() > 0) {
filters = CardPrinted.Predicates.printedInSets(sets, true);
}
}
}
} else if (s.startsWith("rules:") || s.startsWith("Rules:")) {
final String[] tmp = s.split(":");
if (tmp.length > 1) {
String [] ruleCodes = tmp[1].split(",");
if (ruleCodes.length > 0) {
for (String rule : ruleCodes) {
final Predicate<CardRules> newRule = BoosterUtils.parseRulesLimitation(rule);
if (newRule != null) {
filterRules = (filterRules == null ? newRule : Predicates.and(filterRules, newRule));
}
}
}
}
} else if (s.startsWith("rarity:") || s.startsWith("Rarity:")) {
final String[] tmp = s.split(":");
if (tmp.length > 1) {
String [] rarityCodes = tmp[1].split(",");
if (rarityCodes.length > 0) {
for (String rarity : rarityCodes) {
if (rarity.startsWith("C") || rarity.startsWith("c")) {
filterRarity = (filterRarity == null ? CardPrinted.Predicates.Presets.IS_COMMON : Predicates.or(filterRarity, CardPrinted.Predicates.Presets.IS_COMMON));
} else if (rarity.startsWith("U") || rarity.startsWith("u")) {
filterRarity = (filterRarity == null ? CardPrinted.Predicates.Presets.IS_UNCOMMON : Predicates.or(filterRarity, CardPrinted.Predicates.Presets.IS_UNCOMMON));
} else if (rarity.startsWith("R") || rarity.startsWith("r")) {
filterRarity = (filterRarity == null ? CardPrinted.Predicates.Presets.IS_RARE : Predicates.or(filterRarity, CardPrinted.Predicates.Presets.IS_RARE));
} else if (rarity.startsWith("M") || rarity.startsWith("m")) {
filterRarity = (filterRarity == null ? CardPrinted.Predicates.Presets.IS_MYTHIC_RARE : Predicates.or(filterRarity, CardPrinted.Predicates.Presets.IS_MYTHIC_RARE));
}
}
}
}
}
}
if (filterRules != null) {
final Predicate<CardPrinted> rulesPrinted = Predicates.compose(filterRules, CardPrinted.FN_GET_RULES);
filters = Predicates.and(filters, rulesPrinted);
}
if (filterRarity != null) {
filters = Predicates.and(filters, filterRarity);
}
return filters;
}
/**
* The name.
*
* @return the name
*/
@Override
public String getName() {
return description;
}
/**
* A QuestRewardCardChooser ought to always be resolved to an actual card, hence no images.
*
* @return an empty string
*/
@Override
public String getImageFilename() {
return "";
}
/**
* The item type.
*
* @return item type
*/
@Override
public String getItemType() {
switch (type) {
case playerCards:
return "duplicate card";
case predicateFilter: default:
return "chosen card";
}
}
/**
* Get type as enum.
* @return enum, item type.
*/
public poolType getType() {
return type;
}
/**
* Produces a list of options to choose from.
*
* @return a List<CardPrinted> or null if could not create a list.
*/
public final List<CardPrinted> getChoices() {
if (type == poolType.playerCards) {
final ItemPool<CardPrinted> playerCards = Singletons.getModel().getQuest().getAssets().getCardPool();
if (!playerCards.isEmpty()) { // Maybe a redundant check since it's hard to win a duel without any cards...
List<CardPrinted> cardChoices = new ArrayList<CardPrinted>();
for (final Map.Entry<CardPrinted, Integer> card : playerCards) {
cardChoices.add(card.getKey());
}
Collections.sort(cardChoices);
return Collections.unmodifiableList(cardChoices);
}
} else if (type == poolType.predicateFilter) {
List<CardPrinted> cardChoices = new ArrayList<CardPrinted>();
for (final CardPrinted card : Iterables.filter(CardDb.instance().getAllTraditionalCards(), predicates)) {
cardChoices.add(card);
}
Collections.sort(cardChoices);
return Collections.unmodifiableList(cardChoices);
} else {
throw new RuntimeException("Unknown QuestRewardCardType: " + type);
}
return null;
}
}

View File

@@ -576,20 +576,10 @@ public final class QuestUtilCards {
this.qa.getNewCardList().clear(); this.qa.getNewCardList().clear();
} }
/**
* Gets the fn new compare.
*
* @return the fnNewCompare
*/
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnNewCompare() { public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnNewCompare() {
return this.fnNewCompare; return this.fnNewCompare;
} }
/**
* Gets the fn new get.
*
* @return the fnNewGet
*/
public Function<Entry<InventoryItem, Integer>, Object> getFnNewGet() { public Function<Entry<InventoryItem, Integer>, Object> getFnNewGet() {
return this.fnNewGet; return this.fnNewGet;
} }
@@ -600,7 +590,8 @@ public final class QuestUtilCards {
// deck editors // deck editors
// Maybe we should consider doing so later // Maybe we should consider doing so later
/** The fn new compare. */ /** The fn new compare. */
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnNewCompare = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() { private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnNewCompare =
new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override @Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) { public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return QuestUtilCards.this.qa.getNewCardList().contains(from.getKey()) ? Integer.valueOf(1) : Integer return QuestUtilCards.this.qa.getNewCardList().contains(from.getKey()) ? Integer.valueOf(1) : Integer
@@ -609,10 +600,38 @@ public final class QuestUtilCards {
}; };
/** The fn new get. */ /** The fn new get. */
private final Function<Entry<InventoryItem, Integer>, Object> fnNewGet = new Function<Entry<InventoryItem, Integer>, Object>() { private final Function<Entry<InventoryItem, Integer>, Object> fnNewGet =
new Function<Entry<InventoryItem, Integer>, Object>() {
@Override @Override
public Object apply(final Entry<InventoryItem, Integer> from) { public Object apply(final Entry<InventoryItem, Integer> from) {
return QuestUtilCards.this.qa.getNewCardList().contains(from.getKey()) ? "NEW" : ""; return QuestUtilCards.this.qa.getNewCardList().contains(from.getKey()) ? "NEW" : "";
} }
}; };
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnOwnedCompare() {
return this.fnOwnedCompare;
}
public Function<Entry<InventoryItem, Integer>, Object> getFnOwnedGet() {
return this.fnOwnedGet;
}
// These functions provide a way to sort and compare cards in the spell shop according to how many are already owned
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnOwnedCompare =
new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
InventoryItem i = from.getKey();
return i instanceof CardPrinted ? QuestUtilCards.this.qa.getCardPool().count((CardPrinted)i) : null;
}
};
private final Function<Entry<InventoryItem, Integer>, Object> fnOwnedGet =
new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
InventoryItem i = from.getKey();
return i instanceof CardPrinted ? QuestUtilCards.this.qa.getCardPool().count((CardPrinted)i) : null;
}
};
} }

View File

@@ -0,0 +1,11 @@
package forge.util;
public class Pair<T, V> {
public final T a;
public final V b;
public Pair(T a, V b) {
this.a = a;
this.b = b;
}
}

View File

@@ -2,6 +2,7 @@ package forge.util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -78,4 +79,12 @@ public class TextUtil {
return result.toArray(ArrayUtils.EMPTY_STRING_ARRAY); return result.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
} }
/**
* Converts an enum value to a printable label but upcasing the first letter
* and lcasing all subsequent letters
*/
public static String enumToLabel(Enum<?> val) {
return val.toString().substring(0, 1).toUpperCase(Locale.ENGLISH) +
val.toString().substring(1).toLowerCase(Locale.ENGLISH);
}
} }

View File

@@ -35,8 +35,6 @@ public enum FView {
/** */ /** */
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
/** */
public static final Integer TARGETING_LAYER = JLayeredPane.MODAL_LAYER - 1;
private final List<DragCell> allCells = new ArrayList<DragCell>(); private final List<DragCell> allCells = new ArrayList<DragCell>();
private SplashFrame frmSplash; private SplashFrame frmSplash;
@@ -84,8 +82,7 @@ public enum FView {
// Note: when adding new panels here, keep in mind that the layered pane // Note: when adding new panels here, keep in mind that the layered pane
// has a null layout, so new components will be W0 x H0 pixels - gotcha! // has a null layout, so new components will be W0 x H0 pixels - gotcha!
// FControl has a method called "sizeComponents" which will fix this. // FControl has a method called "sizeComponents" which will fix this.
lpnDocument.add(TargetingOverlay.SINGLETON_INSTANCE.getPanel(), TARGETING_LAYER); lpnDocument.add(TargetingOverlay.SINGLETON_INSTANCE.getPanel(), JLayeredPane.MODAL_LAYER);
pnlInsets.add(pnlContent, BorderLayout.CENTER); pnlInsets.add(pnlContent, BorderLayout.CENTER);
pnlInsets.setBackgroundTexture(FSkin.getIcon(FSkin.Backgrounds.BG_TEXTURE)); pnlInsets.setBackgroundTexture(FSkin.getIcon(FSkin.Backgrounds.BG_TEXTURE));
pnlInsets.setCornerDiameter(0); pnlInsets.setCornerDiameter(0);