- 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/CEditorQuestCardShop.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/CStatistics.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/VDeckgen.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/VStatistics.java -text
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/CSubmenuQuestDecks.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/PnlEvent.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">
<doc>CARD_PICTURE</doc>
<doc>EDITOR_PREFERENCES</doc>
<doc>EDITOR_FILTERS</doc>
</cell>
<cell x="0.38722" y="0.0" w="0.38722" h="1.0">
<doc>EDITOR_CURRENTDECK</doc>

View File

@@ -2,13 +2,12 @@
<preferences type="editor">
<pref name="display_unique_only" value="true"></pref>
<pref name="elastic_columns" value="false"></pref>
<pref name="stats_catalog" 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_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_COLOR" identifier="Color" show="true" sortpriority="3" sortstate="DESC" width="54"></col>
<col enumval="CAT_TYPE" identifier="Type" show="true" sortpriority="1" sortstate="ASC" width="217"></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="3" sortstate="ASC" width="217"></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_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_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_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_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>

View File

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

View File

@@ -39,8 +39,8 @@ public class WrapLayout extends FlowLayout {
* and the indicated horizontal and vertical gaps.
* <p>
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
* <code>FlowLayout.LEFT</code>, <code>FlowLayout.CENTER</code>,
* or <code>FlowLayout.RIGHT</code>.
* @param align the alignment value
* @param hgap the horizontal 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 forge.Card;
import forge.deck.DeckBase;
import forge.gui.CardContainer;
import forge.gui.deckeditor.SEditorIO.EditorPreference;
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.CPicture;
import forge.item.InventoryItem;
@@ -74,7 +75,7 @@ public enum CDeckEditorUI implements CardContainer {
/**
* @return ACEditorBase<?, ?>
*/
public ACEditorBase<?, ?> getCurrentEditorController() {
public ACEditorBase<? extends InventoryItem, ? extends DeckBase> getCurrentEditorController() {
return childController;
}
@@ -93,7 +94,7 @@ public enum CDeckEditorUI implements CardContainer {
childController.getTableCatalog().setWantUnique(wantUnique);
childController.getTableDeck().setWantUnique(wantUnique);
}
VFilters.SINGLETON_INSTANCE.getLayoutControl().buildFilter();
CCardCatalog.SINGLETON_INSTANCE.applyCurrentFilter();
}
//========== Other methods

View File

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

View File

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

View File

@@ -1,33 +1,21 @@
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.HashMap;
import java.util.List;
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.Predicates;
import forge.card.CardEdition;
import forge.card.CardRulesPredicates;
import forge.card.CardRules;
import forge.game.GameFormat;
import forge.gui.WrapLayout;
import forge.gui.deckeditor.views.VFilters;
import forge.card.CardRulesPredicates;
import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCardCatalog.RangeTypes;
import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSpinner;
import forge.item.CardPrinted;
import forge.util.ComparableOp;
import forge.util.Pair;
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>
*/
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>();
/**
*/
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.
* queries color filters for state and returns a predicate.
* <br><br>
* Handles "multicolor" label, which is quite tricky.
*
* @return Predicate<CardPrinted>
*/
public static Predicate<CardPrinted> buildColorFilter() {
if (MAP_COLOR_CHECKBOXES.isEmpty()) { return Predicates.alwaysTrue(); }
public static Predicate<CardPrinted> buildColorAndTypeFilter(Map<SEditorUtil.StatTypes, FLabel> statLabels) {
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); }
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.BLUE).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_BLUE); }
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.BLACK).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_BLACK); }
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.RED).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_RED); }
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.GREEN).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_GREEN); }
if (MAP_COLOR_CHECKBOXES.get(FilterProperty.COLORLESS).getCheckBox().isSelected()) { colors.add(CardRulesPredicates.Presets.IS_COLORLESS); }
boolean wantMulticolor = false;
Predicate<CardRules> preExceptMulti = null;
for (SEditorUtil.StatTypes s : SEditorUtil.StatTypes.values()) {
switch (s) {
case WHITE: case BLUE: case BLACK: case RED: case GREEN: case 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();
final Predicate<CardRules> preExceptMulti = wantMulticolor ? null : Predicates.not(CardRulesPredicates.Presets.IS_MULTICOLOR);
default:
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) {
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.
*
* @return Predicate<CardPrinted>
* builds a string search filter
*/
public static Predicate<CardPrinted> buildSetAndFormatFilter() {
// Set/Format filter
JComboBox cbox = VFilters.SINGLETON_INSTANCE.getCbxSets();
if (cbox.getSelectedIndex() == 0) {
public static Predicate<CardPrinted> buildTextFilter(String text, boolean invert, boolean inName, boolean inType, boolean inText) {
if (text.trim().isEmpty()) {
return Predicates.alwaysTrue();
}
final Object selected = cbox.getSelectedItem();
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
String[] splitText = text
.replaceAll(",", "")
.replaceAll(" ", " ")
.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) {
final List<Predicate<CardRules>> subands = new ArrayList<Predicate<CardRules>>();
if (inName) { subands.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, s)); }
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
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()) {
final String[] splitWithout = strWithout
.replaceAll(" ", " ")
.replaceAll(",", "")
.toLowerCase().split(" ");
private static Predicate<CardRules> getCardRulesFieldPredicate(int min, int max, CardRulesPredicates.LeafNumber.CardField field) {
boolean hasMin = 0 != min;
boolean hasMax = 10 != max;
final List<Predicate<CardRules>> nots = new ArrayList<Predicate<CardRules>>();
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));
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);
return optimizedAnd(pMin, pMax);
}
@@ -341,78 +125,23 @@ public class SFilterUtil {
}
/**
* Validates combo box input, assembles predicate filters for each case,
* stacks them all together, and returns the predicate.
*
* @return Predicate<CardPrinted>
* builds a filter for an interval on a card field
*/
public static Predicate<CardPrinted> buildIntervalFilter() {
final VFilters view = VFilters.SINGLETON_INSTANCE;
public static Predicate<CardPrinted> buildIntervalFilter(
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.
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);
Predicate<CardRules> preCMC = getCardRulesFieldPredicate(view.getCbxCMCLow().getSelectedItem().toString(), view.getCbxCMCHigh().getSelectedItem().toString(), CardRulesPredicates.LeafNumber.CardField.CMC);
if (null != fieldFilter && VCardCatalog.RangeTypes.CMC != field)
{
fieldFilter = Predicates.and(fieldFilter, CardRulesPredicates.Presets.IS_CREATURE);
}
Predicate<CardRules> preCreature = optimizedAnd(preToughness, prePower);
preCreature = preCreature == null ? null : Predicates.and(preCreature, CardRulesPredicates.Presets.IS_CREATURE);
Predicate<CardRules> preFinal = optimizedAnd(preCMC, preCreature);
if (preFinal == null) {
if (fieldFilter == null) {
return Predicates.alwaysTrue();
} else {
return Predicates.compose(preFinal, 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();
}
return Predicates.compose(fieldFilter, CardPrinted.FN_GET_RULES);
}
}
}

View File

@@ -1,11 +1,50 @@
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.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.SEditorUtil;
import forge.gui.deckeditor.SFilterUtil;
import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCardCatalog.RangeTypes;
import forge.gui.framework.ICDoc;
import forge.gui.home.quest.DialogChooseSets;
import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSpinner;
import forge.item.CardPrinted;
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.
@@ -17,7 +56,12 @@ public enum CCardCatalog implements ICDoc {
/** */
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() {
}
@@ -38,8 +82,8 @@ public enum CCardCatalog implements ICDoc {
@Override
@SuppressWarnings("serial")
public void initialize() {
// Add/remove buttons
((FLabel) VCardCatalog.SINGLETON_INSTANCE.getBtnAdd()).setCommand(new Command() {
// Add/remove buttons (refresh analysis on add)
VCardCatalog.SINGLETON_INSTANCE.getBtnAdd().setCommand(new Command() {
@Override
public void execute() {
CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().addCard();
@@ -48,8 +92,7 @@ public enum CCardCatalog implements ICDoc {
CProbabilities.SINGLETON_INSTANCE.update();
}
});
((FLabel) VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4()).setCommand(new Command() {
VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setCommand(new Command() {
@Override
public void execute() {
final InventoryItem item = CDeckEditorUI.SINGLETON_INSTANCE
@@ -65,6 +108,180 @@ public enum CCardCatalog implements ICDoc {
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)
@@ -73,4 +290,220 @@ public enum CCardCatalog implements ICDoc {
@Override
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.VCurrentDeck;
import forge.gui.deckeditor.views.VDeckgen;
import forge.gui.deckeditor.views.VFilters;
import forge.gui.framework.DragCell;
import forge.gui.framework.SRearrangingUtil;
import forge.gui.home.sanctioned.CSubmenuDraft;
@@ -55,7 +54,6 @@ public class CEditorDraftingProcess extends ACEditorBase<CardPrinted, DeckGroup>
private IBoosterDraft boosterDraft;
private String ccAddLabel = "Add card";
private DragCell filtersParent = null;
private DragCell allDecksParent = 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
SwingUtilities.invokeLater(new Runnable() {
@Override
@@ -340,16 +327,10 @@ public class CEditorDraftingProcess extends ACEditorBase<CardPrinted, DeckGroup>
VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(true);
//Re-add tabs
if (filtersParent != null) {
filtersParent.addDoc(VFilters.SINGLETON_INSTANCE);
}
if (deckGenParent != null) {
deckGenParent.addDoc(VDeckgen.SINGLETON_INSTANCE);
}
if (allDecksParent != null) {
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.tables.SColumnUtil;
import forge.gui.deckeditor.tables.SColumnUtil.ColumnName;
import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCurrentDeck;
import forge.gui.deckeditor.views.VEditorPreferences;
import forge.gui.framework.ICDoc;
@@ -57,6 +56,7 @@ public enum CEditorPreferences implements ICDoc {
prefsDict.put(prefsInstance.getChbCatalogAI(), ColumnName.CAT_AI);
prefsDict.put(prefsInstance.getChbCatalogPower(), ColumnName.CAT_POWER);
prefsDict.put(prefsInstance.getChbCatalogToughness(), ColumnName.CAT_TOUGHNESS);
prefsDict.put(prefsInstance.getChbCatalogOwned(), ColumnName.CAT_OWNED);
// Deck
prefsDict.put(prefsInstance.getChbDeckColor(), ColumnName.DECK_COLOR);
@@ -82,8 +82,6 @@ public enum CEditorPreferences implements ICDoc {
}
// Catalog/Deck Stats
VEditorPreferences.SINGLETON_INSTANCE.getChbCatalogStats().setSelected(
SEditorIO.getPref(EditorPreference.stats_catalog));
VEditorPreferences.SINGLETON_INSTANCE.getChbDeckStats().setSelected(
SEditorIO.getPref(EditorPreference.stats_deck));
VEditorPreferences.SINGLETON_INSTANCE.getChbCardDisplayUnique().setSelected(
@@ -94,9 +92,6 @@ public enum CEditorPreferences implements ICDoc {
if (!SEditorIO.getPref(EditorPreference.stats_deck)) {
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 wantUnique = SEditorIO.getPref(EditorPreference.display_unique_only);
@@ -110,13 +105,6 @@ public enum CEditorPreferences implements ICDoc {
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() {
@Override public void itemStateChanged(final ItemEvent e) {
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>> 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.get(columnsCatalog.size() - 1).setSortAndDisplayFunctions(
this.fnPriceCompare, this.fnPriceGet);
// card shop doesn't need "New" column
//columnsCatalog.add(SColumnUtil.getColumn(ColumnName.CAT_NEW));
//columnsCatalog.get(columnsCatalog.size() - 1).setSortAndDisplayFunctions(
// this.questData.getCards().getFnNewCompare(), this.questData.getCards().getFnNewGet());
columnsCatalog.add(1, SColumnUtil.getColumn(ColumnName.CAT_OWNED));
columnsCatalog.get(1).setSortAndDisplayFunctions(
questData.getCards().getFnOwnedCompare(), questData.getCards().getFnOwnedGet());
columnsDeck.add(SColumnUtil.getColumn(ColumnName.DECK_SALE_PRICE));
columnsDeck.get(columnsDeck.size() - 1).setSortAndDisplayFunctions(
@@ -139,7 +138,7 @@ public final class CEditorQuestCardShop extends ACEditorBase<InventoryItem, Deck
columnsDeck.get(columnsDeck.size() - 1).setSortAndDisplayFunctions(
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));
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;
import java.awt.Cursor;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
@@ -225,7 +226,7 @@ public final class EditorTableModel<T extends InventoryItem> extends AbstractTab
header.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
if (null == header.getResizingColumn()) {
if (Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR) != header.getCursor()) {
headerClicked(e);
}
}

View File

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

View File

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

View File

@@ -1,8 +1,10 @@
package forge.gui.deckeditor.views;
import javax.swing.JLabel;
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
* a EditorTableView deck editing component.
@@ -19,47 +21,5 @@ public interface ITableContainer {
*/
void setTableView(JTable tbl0);
// Various card count total labels
/** @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();
FLabel getStatLabel(SEditorUtil.StatTypes s);
}

View File

@@ -1,12 +1,22 @@
package forge.gui.deckeditor.views;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import java.awt.Container;
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.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
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.controllers.CCardCatalog;
import forge.gui.framework.DragCell;
@@ -15,6 +25,10 @@ import forge.gui.framework.EDocID;
import forge.gui.framework.IVDoc;
import forge.gui.toolbox.FLabel;
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.
@@ -26,54 +40,74 @@ public enum VCardCatalog implements IVDoc<CCardCatalog>, ITableContainer {
/** */
SINGLETON_INSTANCE;
public static final int SEARCH_MODE_INVERSE_INDEX = 1;
// Fields used with interface IVDoc
private DragCell parentCell;
private final DragTab tab = new DragTab("Card Catalog");
// Total and color count labels
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();
// panel where special instructions appear
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 =
new JPanel(new MigLayout("insets 0, gap 0, ax center, hidemode 3"));
private final JLabel btnAdd = new FLabel.Builder()
private final FLabel btnAdd = new FLabel.Builder()
.fontSize(14)
.text("Add card")
.tooltip("Add selected card to current deck (or double click the row)")
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS))
.iconScaleAuto(false).hoverable(true).build();
private final JLabel btnAdd4 = new FLabel.Builder()
private final FLabel btnAdd4 = new FLabel.Builder()
.fontSize(14)
.text("Add 4 of card")
.tooltip("Add up to 4 of selected card to current deck")
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS))
.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 final JScrollPane scroller = new JScrollPane();
//========== Constructor
/** */
private VCardCatalog() {
@@ -82,238 +116,172 @@ public enum VCardCatalog implements IVDoc<CCardCatalog>, ITableContainer {
scroller.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.setLayout(new MigLayout("insets 0, gap 5px, ax center, wrap 7"));
final String constraints = "w 57px!, h 20px!";
pnlStats.add(lblTotal, constraints);
pnlStats.add(lblWhite, constraints);
pnlStats.add(lblBlue, constraints);
pnlStats.add(lblBlack, constraints);
pnlStats.add(lblRed, constraints);
pnlStats.add(lblGreen, constraints);
pnlStats.add(lblColorless, constraints);
for (SEditorUtil.StatTypes s : SEditorUtil.StatTypes.values()) {
FLabel label = buildToggleLabel(s, SEditorUtil.StatTypes.TOTAL != s);
statLabels.put(s, label);
pnlStats.add(label, "w 57px!, h 20px!");
}
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);
statLabels.get(SEditorUtil.StatTypes.TOTAL).setToolTipText("Total cards (click to toggle all filters)");
pnlAddButtons.setOpaque(false);
pnlAddButtons.add(btnAdd, "w 30%!, h 30px!, gap 0 0 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.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
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getDocumentID()
*/
@Override
public EDocID getDocumentID() {
return EDocID.EDITOR_CATALOG;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getTabLabel()
*/
@Override
public DragTab getTabLabel() {
return tab;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#getLayoutControl()
*/
@Override
public CCardCatalog getLayoutControl() {
return CCardCatalog.SINGLETON_INSTANCE;
}
/* (non-Javadoc)
* @see forge.gui.framework.IVDoc#setParentCell(forge.gui.framework.DragCell)
*/
@Override
public void setParentCell(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, hidemode 3"));
parentCell.getBody().add(pnlHeader, "w 98%!, h 30px!, gap 1% 0 1% 10px");
parentCell.getBody().add(pnlStats, "w 96%, h 50px!, gap 2% 0 1% 1%");
parentCell.getBody().add(pnlAddButtons, "w 96%!, gap 2% 0 0 0");
parentCell.getBody().add(scroller, "w 98%!, h 100% - 35px, gap 1% 0 1% 1%");
JPanel parentBody = parentCell.getBody();
parentBody.setLayout(new MigLayout("insets 0, gap 0, wrap, hidemode 3"));
parentBody.add(pnlHeader, "w 98%!, h 30px!, gap 1% 1% 0 0");
parentBody.add(pnlStats, "w 96%, h 50px!, gap 2% 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
/* (non-Javadoc)
* @see forge.gui.deckeditor.views.ITableContainer#setTableView()
*/
@Override
public void setTableView(final JTable tbl0) {
this.tblCards = tbl0;
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#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; }
public FLabel getStatLabel(SEditorUtil.StatTypes s) {
return statLabels.get(s);
}
//========== 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 JLabel getLblTitle() {
return lblTitle;
public FLabel getBtnAddRestriction() { return btnAddRestriction; }
public JComboBox getCbSearchMode() { return cbSearchMode; }
public JTextField getTxfSearch() { return txfSearch; }
public Map<SEditorUtil.StatTypes, FLabel> getStatLabels() {
return statLabels;
}
/** @return {@link javax.swing.JLabel} */
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;
public Map<RangeTypes, Pair<FSpinner, FSpinner>> getSpinners() {
return spinners;
}
//========== Other methods
private JLabel buildLabel(final ImageIcon icon0) {
final JLabel lbl = new FLabel.Builder().text("0")
.icon(icon0).iconScaleAuto(false)
.fontSize(11)
private FLabel buildToggleLabel(SEditorUtil.StatTypes s, boolean selectable) {
return new FLabel.Builder()
.icon(s.img).iconScaleAuto(false)
.text("0").fontSize(11)
.tooltip(s.toLabelString())
.hoverable(true).selectable(selectable).selected(selectable)
.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;
import java.awt.Insets;
import java.util.HashMap;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
@@ -101,7 +101,7 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_EDIT))
.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 pnlHeader = new JPanel();
@@ -110,21 +110,8 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.fontSize(14).build();
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);
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 Map<SEditorUtil.StatTypes, FLabel> statLabels =
new HashMap<SEditorUtil.StatTypes, FLabel>();
private JTable tblCards = null;
private final JScrollPane scroller = new JScrollPane(tblCards);
@@ -132,16 +119,6 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
//========== Constructor
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
pnlHeader.setOpaque(false);
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.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.setLayout(new MigLayout("insets 0, gap 5px, ax center, wrap 7"));
final String constraints = "w 55px!, h 20px!";
pnlStats.add(lblTotal, constraints);
pnlStats.add(lblWhite, constraints);
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);
for (SEditorUtil.StatTypes s : SEditorUtil.StatTypes.values()) {
FLabel label = buildLabel(s);
statLabels.put(s, label);
pnlStats.add(label, "w 55px!, h 20px!");
}
pnlRemoveButtons.setOpaque(false);
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);
}
/* (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; }
/* (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; }
public FLabel getStatLabel(SEditorUtil.StatTypes s) {
return statLabels.get(s);
}
//========== Retrieval
@@ -432,12 +298,11 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
//========== Other methods
private JLabel buildLabel(final ImageIcon icon0) {
final JLabel lbl = new FLabel.Builder().text("0")
.icon(icon0).iconScaleAuto(false)
.fontSize(11)
private FLabel buildLabel(SEditorUtil.StatTypes s) {
return new FLabel.Builder()
.icon(s.img).iconScaleAuto(false)
.text("0").fontSize(11)
.tooltip(s.toLabelString())
.build();
return lbl;
}
}

View File

@@ -52,6 +52,7 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
private JCheckBox chbCatalogAI = new FCheckBox("AI");
private JCheckBox chbCatalogPower = new FCheckBox("Power");
private JCheckBox chbCatalogToughness = new FCheckBox("Toughness");
private JCheckBox chbCatalogOwned = new FCheckBox("Owned (Spell shop)");
private JCheckBox chbDeckColor = new FCheckBox("Color");
private JCheckBox chbDeckRarity = new FCheckBox("Rarity");
@@ -62,7 +63,6 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
private JCheckBox chbDeckToughness = new FCheckBox("Toughness");
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 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));
chbCatalogPower.setFont(FSkin.getFont(12));
chbCatalogToughness.setFont(FSkin.getFont(12));
chbCatalogOwned.setFont(FSkin.getFont(12));
chbDeckColor.setFont(FSkin.getFont(12));
chbDeckRarity.setFont(FSkin.getFont(12));
@@ -94,17 +95,14 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
chbDeckToughness.setFont(FSkin.getFont(12));
chbDeckStats.setFont(FSkin.getFont(12));
chbCatalogStats.setFont(FSkin.getFont(12));
chbElasticColumns.setFont(FSkin.getFont(12));
chbDeckStats.setSelected(true);
chbCatalogStats.setSelected(true);
chbElasticColumns.setSelected(false);
chbCardDisplayUnique.setFont(FSkin.getFont(12));
chbCardDisplayUnique.setSelected(false);
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(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(chbCatalogPower, 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(chbDeckColor, constraints);
@@ -224,6 +223,11 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
return chbCatalogToughness;
}
/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getChbCatalogOwned() {
return chbCatalogOwned;
}
/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getChbDeckColor() {
return chbDeckColor;
@@ -269,15 +273,8 @@ public enum VEditorPreferences implements IVDoc<CEditorPreferences> {
return chbElasticColumns;
}
/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getChbCatalogStats() {
return chbCatalogStats;
}
/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getChbCardDisplayUnique() {
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
private final JPanel pnlStats = new JPanel();
private final JLabel lblMulti = buildLabel(SEditorUtil.ICO_MULTI, true);
private final JLabel lblBlack = buildLabel(SEditorUtil.ICO_BLACK, false);
private final JLabel lblBlue = buildLabel(SEditorUtil.ICO_BLUE, true);
private final JLabel lblGreen = buildLabel(SEditorUtil.ICO_GREEN, false);
private final JLabel lblRed = buildLabel(SEditorUtil.ICO_RED, true);
private final JLabel lblWhite = buildLabel(SEditorUtil.ICO_WHITE, false);
private final JLabel lblColorless = buildLabel(SEditorUtil.ICO_COLORLESS, true);
private final JLabel lblMulti = buildLabel(SEditorUtil.StatTypes.MULTICOLOR, true);
private final JLabel lblBlack = buildLabel(SEditorUtil.StatTypes.BLACK, false);
private final JLabel lblBlue = buildLabel(SEditorUtil.StatTypes.BLUE, true);
private final JLabel lblGreen = buildLabel(SEditorUtil.StatTypes.GREEN, false);
private final JLabel lblRed = buildLabel(SEditorUtil.StatTypes.RED, true);
private final JLabel lblWhite = buildLabel(SEditorUtil.StatTypes.WHITE, false);
private final JLabel lblColorless = buildLabel(SEditorUtil.StatTypes.COLORLESS, true);
// Card type labels
private final JLabel lblArtifact = buildLabel(SEditorUtil.ICO_ARTIFACT, true);
private final JLabel lblCreature = buildLabel(SEditorUtil.ICO_CREATURE, false);
private final JLabel lblEnchantment = buildLabel(SEditorUtil.ICO_ENCHANTMENT, true);
private final JLabel lblInstant = buildLabel(SEditorUtil.ICO_INSTANT, false);
private final JLabel lblLand = buildLabel(SEditorUtil.ICO_LAND, true);
private final JLabel lblPlaneswalker = buildLabel(SEditorUtil.ICO_PLANESWALKER, false);
private final JLabel lblSorcery = buildLabel(SEditorUtil.ICO_SORCERY, true);
private final JLabel lblArtifact = buildLabel(SEditorUtil.StatTypes.ARTIFACT, true);
private final JLabel lblCreature = buildLabel(SEditorUtil.StatTypes.CREATURE, false);
private final JLabel lblEnchantment = buildLabel(SEditorUtil.StatTypes.ENCHANTMENT, true);
private final JLabel lblInstant = buildLabel(SEditorUtil.StatTypes.INSTANT, false);
private final JLabel lblLand = buildLabel(SEditorUtil.StatTypes.LAND, true);
private final JLabel lblPlaneswalker = buildLabel(SEditorUtil.StatTypes.PLANESWALKER, false);
private final JLabel lblSorcery = buildLabel(SEditorUtil.StatTypes.SORCERY, true);
// CMC labels
private final JLabel lblCMC0 = buildLabel(
@@ -251,9 +251,9 @@ public enum VStatistics implements IVDoc<CStatistics> {
//========== 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")
.icon(icon0).iconScaleAuto(false)
.icon(icon).iconScaleAuto(false)
.fontSize(11).build();
if (zebra) {
@@ -263,4 +263,8 @@ public enum VStatistics implements IVDoc<CStatistics> {
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.VDeckgen;
import forge.gui.deckeditor.views.VEditorPreferences;
import forge.gui.deckeditor.views.VFilters;
import forge.gui.deckeditor.views.VProbabilities;
import forge.gui.deckeditor.views.VStatistics;
import forge.gui.home.gauntlet.VSubmenuGauntletBuild;
@@ -51,7 +50,6 @@ public enum EDocID { /** */
CARD_DETAIL (VDetail.SINGLETON_INSTANCE), /** */
CARD_ANTES (VAntes.SINGLETON_INSTANCE), /** */
EDITOR_FILTERS (VFilters.SINGLETON_INSTANCE), /** */
EDITOR_PREFERENCES (VEditorPreferences.SINGLETON_INSTANCE), /** */
EDITOR_ALLDECKS (VAllDecks.SINGLETON_INSTANCE), /** */
EDITOR_STATISTICS (VStatistics.SINGLETON_INSTANCE), /** */

View File

@@ -190,7 +190,9 @@ public final class SLayoutIO {
}
else if (element.getName().getLocalPart().equals("doc")) {
event = reader.nextEvent();
try {
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;
import java.awt.Color;
import java.awt.Insets;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
@@ -68,7 +67,7 @@ public enum VSubmenuGauntletBuild implements IVSubmenu<CSubmenuGauntletBuild> {
private final JScrollPane scrRight = new FScrollPane(lstRight,
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()
.text("Left/right arrows add or remove decks.")
@@ -139,16 +138,6 @@ public enum VSubmenuGauntletBuild implements IVSubmenu<CSubmenuGauntletBuild> {
grpRadios.add(radColorDecks);
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
final FLabel lblFilename = new FLabel.Builder()
.text("Gauntlet Name:").fontSize(14).build();

View File

@@ -61,11 +61,11 @@ public enum CSubmenuQuestData implements ICDoc {
new Command() { @Override public void execute() { newQuest(); } });
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() {
new DialogCustomFormat(customPrizeFormatCodes);
new DialogChooseSets(customPrizeFormatCodes, null);
} });
}

View File

@@ -21,7 +21,7 @@ import forge.Singletons;
* TODO: Write javadoc for this type.
*
*/
public class DialogCustomFormat extends JDialog {
public class DialogChooseSets extends JDialog {
private static final long serialVersionUID = 3155211532871888181L;
private JScrollPane scrollPane;
@@ -29,6 +29,7 @@ public class DialogCustomFormat extends JDialog {
private final JButton btnCancel = new JButton("Cancel");
private final JPanel buttonPanel = new JPanel();
private final List<String> customFormat;
private final Runnable onOk;
private final List<JCheckBox> choices = new ArrayList<JCheckBox>();
@@ -39,9 +40,11 @@ public class DialogCustomFormat extends JDialog {
* GameFormatQuest, the user-defined format to update
*
*/
public DialogCustomFormat(List<String> userFormat) {
public DialogChooseSets(List<String> userFormat, Runnable onOk) {
customFormat = userFormat;
this.onOk = onOk;
if (customFormat == null) {
throw new RuntimeException("Null GameFormatQuest in DialogCustomFormat");
}
@@ -66,7 +69,6 @@ public class DialogCustomFormat extends JDialog {
int getIdx = 0;
JPanel p = new JPanel();
p.setSize(600, 400);
p.setLayout(new GridLayout(rows, columns, 10, 0));
for (int row = 0; row < rows; row++) {
@@ -75,7 +77,7 @@ public class DialogCustomFormat extends JDialog {
JCheckBox box;
if (getIdx < numEditions) {
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.setSelected(customFormat.contains(edition.getCode()));
choices.add(box);
@@ -98,6 +100,8 @@ public class DialogCustomFormat extends JDialog {
}
});
buttonPanel.add(btnOK, BorderLayout.WEST);
getRootPane().setDefaultButton(btnOK);
btnCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent arg0) {
@@ -109,7 +113,7 @@ public class DialogCustomFormat extends JDialog {
this.setSize(600, 450);
this.setLocationRelativeTo(null);
this.setTitle("Choose sets for custom format:");
this.setTitle("Choose sets");
this.setVisible(true);
}
@@ -146,5 +150,9 @@ public class DialogCustomFormat extends JDialog {
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>
* <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.
private double bldIconScaleFactor = 0.8;
private int bldFontStyle = Font.PLAIN;
@@ -61,10 +61,12 @@ public class FLabel extends JLabel implements ILocalRepaint {
private Point bldIconInsets = new Point(0, 0);
private boolean bldSelectable = false;
private boolean bldSelected = false;
private boolean bldHoverable = false;
private boolean bldOpaque = false;
private boolean bldIconInBackground = false;
private boolean bldIconScaleAuto = true;
private boolean reactOnMouseDown = false;
private String bldText, bldToolTip;
private ImageIcon bldIcon;
@@ -104,6 +106,14 @@ public class FLabel extends JLabel implements ILocalRepaint {
* @return {@link forge.gui.toolbox.Builder} */
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
* @return {@link forge.gui.toolbox.Builder} */
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.iconScaleAuto = b0.bldIconScaleAuto;
this.selectable = b0.bldSelectable;
this.selected = b0.bldSelected;
this.iconAlignX = b0.bldIconAlignX;
this.iconInsets = b0.bldIconInsets;
@@ -165,8 +176,8 @@ public class FLabel extends JLabel implements ILocalRepaint {
this.setFontSize(b0.bldFontSize);
this.setIconAlpha(b0.bldIconAlpha);
this.setCommand(b0.bldCmd);
this.setReactOnMouseDown(b0.reactOnMouseDown);
this.setFontAlign(b0.bldFontAlign);
this.setText(b0.bldText);
this.setToolTipText(b0.bldToolTip);
this.setHoverable(b0.bldHoverable);
@@ -176,8 +187,6 @@ public class FLabel extends JLabel implements ILocalRepaint {
// Non-custom display properties
this.setForeground(clrText);
this.setBackground(clrInactive);
this.setVerticalTextPosition(SwingConstants.CENTER);
this.setVerticalAlignment(SwingConstants.CENTER);
// Resize adapter
this.removeComponentListener(cadResize);
@@ -202,7 +211,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
private int fontStyle, iconAlignX;
private int iw, ih;
private boolean selectable, selected, hoverable, hovered, opaque,
iconInBackground, iconScaleAuto;
iconInBackground, iconScaleAuto, reactOnMouseDown;
private Point iconInsets;
// Various variables used in image rendering.
@@ -246,19 +255,35 @@ public class FLabel extends JLabel implements ILocalRepaint {
private final MouseAdapter madEvents = new MouseAdapter() {
@Override
public void mouseEntered(final MouseEvent e) {
if (hoverable) {
hovered = true; repaintSelf();
}
}
@Override
public void mouseExited(final MouseEvent e) {
if (hoverable) {
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
public void mouseClicked(final MouseEvent e) {
if (cmdClick != null && FLabel.this.isEnabled()) { cmdClick.execute(); }
if (!selectable) { return; }
if (selected) { setSelected(false); }
else { setSelected(true); }
if (!reactOnMouseDown) {
_doMouseAction();
}
}
};
@@ -278,6 +303,10 @@ public class FLabel extends JLabel implements ILocalRepaint {
repaintSelf();
}
public boolean getSelected() {
return this.selected;
}
/** Sets alpha if icon is in background.
* @param f0 &emsp; float */
// NOT public; must be set when label is built.
@@ -359,6 +388,10 @@ public class FLabel extends JLabel implements ILocalRepaint {
this.cmdClick = c0;
}
public void setReactOnMouseDown(boolean b0) {
this.reactOnMouseDown = b0;
}
@Override
public void setOpaque(final boolean b0) {
// 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;
import java.awt.Insets;
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.
@@ -8,13 +13,64 @@ import javax.swing.JTextField;
*/
@SuppressWarnings("serial")
public class FTextField extends JTextField {
/** */
public FTextField() {
super();
/**
* Uses the Builder pattern to facilitate/encourage inline styling.
* 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.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
this.setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT));
this.setOpaque(false);
this.setFocusable(false);
this.setEditable(false);
this.setMargin(new Insets(5, 5, 5, 5));
this.setOpaque(true);
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());
}
/**
* Gets the custom format for the main world, if any.
*/
public GameFormatQuest getMainFormat() {
return this.questFormat;
}
/**
* 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();
}
/**
* Gets the fn new compare.
*
* @return the fnNewCompare
*/
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnNewCompare() {
return this.fnNewCompare;
}
/**
* Gets the fn new get.
*
* @return the fnNewGet
*/
public Function<Entry<InventoryItem, Integer>, Object> getFnNewGet() {
return this.fnNewGet;
}
@@ -600,7 +590,8 @@ public final class QuestUtilCards {
// deck editors
// Maybe we should consider doing so later
/** 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
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return QuestUtilCards.this.qa.getNewCardList().contains(from.getKey()) ? Integer.valueOf(1) : Integer
@@ -609,10 +600,38 @@ public final class QuestUtilCards {
};
/** 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
public Object apply(final Entry<InventoryItem, Integer> from) {
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.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
@@ -78,4 +79,12 @@ public class TextUtil {
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;
/** */
public static final Integer TARGETING_LAYER = JLayeredPane.MODAL_LAYER - 1;
private final List<DragCell> allCells = new ArrayList<DragCell>();
private SplashFrame frmSplash;
@@ -84,8 +82,7 @@ public enum FView {
// 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!
// 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.setBackgroundTexture(FSkin.getIcon(FSkin.Backgrounds.BG_TEXTURE));
pnlInsets.setCornerDiameter(0);