checkstyle

This commit is contained in:
jendave
2011-11-01 06:40:30 +00:00
parent 1727b94781
commit 7e3c52797e
12 changed files with 1126 additions and 823 deletions

View File

@@ -636,7 +636,7 @@ public class BoosterDraftAI {
BoosterDraftAI.colorToLand.put(Constant.Color.RED, "Mountain");
BoosterDraftAI.colorToLand.put(Constant.Color.WHITE, "Plains");
// initilize deck array and playerColors list
// Initialize deck array and playerColors list
for (int i = 0; i < this.deck.length; i++) {
this.deck[i] = new CardList();
this.playerColors.add(new DeckColors());

View File

@@ -42,7 +42,7 @@ public class SealedDeck {
private final List<Closure1<List<CardPrinted>, BoosterGenerator>> packs = new ArrayList<Closure1<List<CardPrinted>, BoosterGenerator>>();
/** The Land set code. */
public String LandSetCode[] = { "" };
private String[] landSetCode = { "" };
/**
* <p>
@@ -61,7 +61,7 @@ public class SealedDeck {
this.packs.add(picker);
}
this.LandSetCode[0] = CardDb.instance().getCard("Plains").getSet();
this.getLandSetCode()[0] = CardDb.instance().getCard("Plains").getSet();
} else if (sealedType.equals("Block")) {
final Object o = GuiUtils.getChoice("Choose Block", SetUtils.getBlocks().toArray());
@@ -102,10 +102,10 @@ public class SealedDeck {
}
}
this.LandSetCode[0] = block.getLandSet().getCode();
this.getLandSetCode()[0] = block.getLandSet().getCode();
} else if (sealedType.equals("Custom")) {
String dList[];
String[] dList;
final ArrayList<CustomLimited> customs = new ArrayList<CustomLimited>();
// get list of custom draft files
@@ -162,7 +162,7 @@ public class SealedDeck {
this.packs.add(picker);
}
this.LandSetCode[0] = draft.LandSetCode;
this.getLandSetCode()[0] = draft.LandSetCode;
}
}
}
@@ -200,14 +200,14 @@ public class SealedDeck {
int landsNeeded = 18;
int nCreatures = 15;
final CardList AIPlayables = aiCardpool.filter(new CardListFilter() {
final CardList aiPlayables = aiCardpool.filter(new CardListFilter() {
@Override
public boolean addCard(final Card c) {
return !(c.getSVar("RemAIDeck").equals("True"));
}
});
CardList creatures = AIPlayables.getType("Creature");
CardList creatures = aiPlayables.getType("Creature");
CardListUtil.sortByEvaluateCreature(creatures);
final CardList colorChooserList = new CardList(); // choose colors based
@@ -217,8 +217,8 @@ public class SealedDeck {
colorChooserList.add(creatures.get(i));
}
final int colorCounts[] = { 0, 0, 0, 0, 0 };
final String colors[] = Constant.Color.ONLY_COLORS;
final int[] colorCounts = { 0, 0, 0, 0, 0 };
final String[] colors = Constant.Color.ONLY_COLORS;
for (int i = 0; i < colors.length; i++) {
colorCounts[i] = colorChooserList.getColor(colors[i]).size();
}
@@ -236,15 +236,15 @@ public class SealedDeck {
}
final DeckColors dcAI = new DeckColors();
dcAI.Color1 = colors[0];
dcAI.Color2 = colors[1];
dcAI.Splash = colors[2];
dcAI.Mana1 = dcAI.ColorToMana(colors[0]);
dcAI.Mana2 = dcAI.ColorToMana(colors[1]);
dcAI.ManaS = dcAI.ColorToMana(colors[2]);
dcAI.color1 = colors[0];
dcAI.color2 = colors[1];
dcAI.splash = colors[2];
dcAI.mana1 = dcAI.colorToMana(colors[0]);
dcAI.mana2 = dcAI.colorToMana(colors[1]);
dcAI.manaS = dcAI.colorToMana(colors[2]);
creatures = AIPlayables.getType("Creature").getOnly2Colors(dcAI.Color1, dcAI.Color2);
creatures.addAll(AIPlayables.getType("Artifact").getType("Creature"));
creatures = aiPlayables.getType("Creature").getOnly2Colors(dcAI.color1, dcAI.color2);
creatures.addAll(aiPlayables.getType("Artifact").getType("Creature"));
CardListUtil.sortByEvaluateCreature(creatures);
int i = 0;
@@ -253,67 +253,67 @@ public class SealedDeck {
deck.add(c);
aiCardpool.remove(c);
AIPlayables.remove(c);
aiPlayables.remove(c);
cardsNeeded--;
nCreatures--;
i++;
}
final CardList splashCreatures = AIPlayables.getType("Creature").getColor(dcAI.Splash);
final CardList splashCreatures = aiPlayables.getType("Creature").getColor(dcAI.splash);
while ((nCreatures > 1) && (splashCreatures.size() > 1)) {
final Card c = splashCreatures.get(MyRandom.getRandom().nextInt(splashCreatures.size() - 1));
deck.add(c);
aiCardpool.remove(c);
AIPlayables.remove(c);
aiPlayables.remove(c);
splashCreatures.remove(c);
cardsNeeded--;
nCreatures--;
}
final CardList walkers = AIPlayables.getType("Planeswalker").getOnly2Colors(dcAI.Color1, dcAI.Color2);
final CardList walkers = aiPlayables.getType("Planeswalker").getOnly2Colors(dcAI.color1, dcAI.color2);
if (walkers.size() > 0) {
deck.add(walkers.get(0));
AIPlayables.remove(walkers.get(0));
aiPlayables.remove(walkers.get(0));
aiCardpool.remove(walkers.get(0));
cardsNeeded--;
}
final CardList spells = AIPlayables.getType("Instant").getOnly2Colors(dcAI.Color1, dcAI.Color2);
spells.addAll(AIPlayables.getType("Sorcery").getOnly2Colors(dcAI.Color1, dcAI.Color2));
spells.addAll(AIPlayables.getType("Enchantment").getOnly2Colors(dcAI.Color1, dcAI.Color2));
final CardList spells = aiPlayables.getType("Instant").getOnly2Colors(dcAI.color1, dcAI.color2);
spells.addAll(aiPlayables.getType("Sorcery").getOnly2Colors(dcAI.color1, dcAI.color2));
spells.addAll(aiPlayables.getType("Enchantment").getOnly2Colors(dcAI.color1, dcAI.color2));
while ((cardsNeeded > 0) && (spells.size() > 1)) {
final Card c = spells.get(MyRandom.getRandom().nextInt(spells.size() - 1));
deck.add(c);
spells.remove(c);
AIPlayables.remove(c);
aiPlayables.remove(c);
aiCardpool.remove(c);
cardsNeeded--;
}
final CardList splashSpells = AIPlayables.getType("Instant").getColor(dcAI.Splash);
splashSpells.addAll(AIPlayables.getType("Sorcery").getColor(dcAI.Splash));
final CardList splashSpells = aiPlayables.getType("Instant").getColor(dcAI.splash);
splashSpells.addAll(aiPlayables.getType("Sorcery").getColor(dcAI.splash));
while ((cardsNeeded > 0) && (splashSpells.size() > 1)) {
final Card c = splashSpells.get(MyRandom.getRandom().nextInt(splashSpells.size() - 1));
deck.add(c);
splashSpells.remove(c);
AIPlayables.remove(c);
aiPlayables.remove(c);
aiCardpool.remove(c);
cardsNeeded--;
}
final CardList lands = AIPlayables.getType("Land");
final CardList lands = aiPlayables.getType("Land");
if (lands.size() > 0) {
final DeckColors AIdc = dcAI; // just for the filter
final DeckColors aiDC = dcAI; // just for the filter
lands.filter(new CardListFilter() {
@Override
public boolean addCard(final Card c) {
final ArrayList<Ability_Mana> maList = c.getManaAbility();
for (int j = 0; j < maList.size(); j++) {
if (maList.get(j).canProduce(AIdc.Mana1) || maList.get(j).canProduce(AIdc.Mana2)) {
if (maList.get(j).canProduce(aiDC.mana1) || maList.get(j).canProduce(aiDC.mana2)) {
return true;
}
}
@@ -328,16 +328,16 @@ public class SealedDeck {
deck.add(c);
aiCardpool.remove(c);
AIPlayables.remove(c);
aiPlayables.remove(c);
landsNeeded--;
}
}
if (landsNeeded > 0) // attempt to optimize basic land counts
// according to color representation
{
final CCnt ClrCnts[] = { new CCnt("Plains", 0), new CCnt("Island", 0), new CCnt("Swamp", 0),
if (landsNeeded > 0) {
// attempt to optimize basic land counts
// according to color representation
final CCnt[] clrCnts = { new CCnt("Plains", 0), new CCnt("Island", 0), new CCnt("Swamp", 0),
new CCnt("Mountain", 0), new CCnt("Forest", 0) };
// count each card color using mana costs
@@ -350,15 +350,15 @@ public class SealedDeck {
final char c = mc.charAt(j);
if (c == 'W') {
ClrCnts[0].setCount(ClrCnts[0].getCount() + 1);
clrCnts[0].setCount(clrCnts[0].getCount() + 1);
} else if (c == 'U') {
ClrCnts[1].setCount(ClrCnts[1].getCount() + 1);
clrCnts[1].setCount(clrCnts[1].getCount() + 1);
} else if (c == 'B') {
ClrCnts[2].setCount(ClrCnts[2].getCount() + 1);
clrCnts[2].setCount(clrCnts[2].getCount() + 1);
} else if (c == 'R') {
ClrCnts[3].setCount(ClrCnts[3].getCount() + 1);
clrCnts[3].setCount(clrCnts[3].getCount() + 1);
} else if (c == 'G') {
ClrCnts[4].setCount(ClrCnts[4].getCount() + 1);
clrCnts[4].setCount(clrCnts[4].getCount() + 1);
}
}
}
@@ -366,25 +366,25 @@ public class SealedDeck {
// total of all ClrCnts
int totalColor = 0;
for (i = 0; i < 5; i++) {
totalColor += ClrCnts[i].getCount();
totalColor += clrCnts[i].getCount();
}
for (i = 0; i < 5; i++) {
if (ClrCnts[i].getCount() > 0) { // calculate number of
if (clrCnts[i].getCount() > 0) { // calculate number of
// lands for
// each color
final float p = (float) ClrCnts[i].getCount() / (float) totalColor;
final float p = (float) clrCnts[i].getCount() / (float) totalColor;
final int nLand = (int) (landsNeeded * p) + 1;
// tmpDeck += "nLand-" + ClrCnts[i].Color + ":" + nLand
// + "\n";
if (Constant.Runtime.DEV_MODE[0]) {
System.out.println("Basics[" + ClrCnts[i].getColor() + "]:" + nLand);
System.out.println("Basics[" + clrCnts[i].getColor() + "]:" + nLand);
}
for (int j = 0; j <= nLand; j++) {
final Card c = AllZone.getCardFactory().getCard(ClrCnts[i].getColor(),
final Card c = AllZone.getCardFactory().getCard(clrCnts[i].getColor(),
AllZone.getComputerPlayer());
c.setCurSetCode(this.LandSetCode[0]);
c.setCurSetCode(this.getLandSetCode()[0]);
deck.add(c);
landsNeeded--;
}
@@ -392,10 +392,10 @@ public class SealedDeck {
}
int n = 0;
while (landsNeeded > 0) {
if (ClrCnts[n].getCount() > 0) {
final Card c = AllZone.getCardFactory().getCard(ClrCnts[n].getColor(),
if (clrCnts[n].getCount() > 0) {
final Card c = AllZone.getCardFactory().getCard(clrCnts[n].getColor(),
AllZone.getComputerPlayer());
c.setCurSetCode(this.LandSetCode[0]);
c.setCurSetCode(this.getLandSetCode()[0]);
deck.add(c);
landsNeeded--;
@@ -423,28 +423,42 @@ public class SealedDeck {
return aiDeck;
}
/**
* @return the landSetCode
*/
public String[] getLandSetCode() {
return landSetCode;
}
/**
* @param landSetCode the landSetCode to set
*/
public void setLandSetCode(String[] landSetCode) {
this.landSetCode = landSetCode; // TODO: Add 0 to parameter's name.
}
/**
* The Class DeckColors.
*/
class DeckColors {
/** The Color1. */
public String Color1 = "none";
private String color1 = "none";
/** The Color2. */
public String Color2 = "none";
private String color2 = "none";
/** The Splash. */
public String Splash = "none";
private String splash = "none";
/** The Mana1. */
public String Mana1 = "";
private String mana1 = "";
/** The Mana2. */
public String Mana2 = "";
private String mana2 = "";
/** The Mana s. */
public String ManaS = "";
private String manaS = "";
/**
* Instantiates a new deck colors.
@@ -457,8 +471,8 @@ public class SealedDeck {
* the sp
*/
public DeckColors(final String c1, final String c2, final String sp) {
this.Color1 = c1;
this.Color2 = c2;
this.color1 = c1;
this.color2 = c2;
// Splash = sp;
}
@@ -476,13 +490,13 @@ public class SealedDeck {
* the color
* @return the string
*/
public String ColorToMana(final String color) {
final String Mana[] = { "W", "U", "B", "R", "G" };
final String Clrs[] = { "white", "blue", "black", "red", "green" };
public String colorToMana(final String color) {
final String[] mana = { "W", "U", "B", "R", "G" };
final String[] clrs = { "white", "blue", "black", "red", "green" };
for (int i = 0; i < Constant.Color.ONLY_COLORS.length; i++) {
if (Clrs[i].equals(color)) {
return Mana[i];
if (clrs[i].equals(color)) {
return mana[i];
}
}

View File

@@ -6,8 +6,22 @@
package forge.gui;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.Collections;
import java.util.List;
import javax.swing.*;
import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
@@ -18,91 +32,104 @@ import forge.gui.game.CardDetailPanel;
import forge.gui.game.CardPicturePanel;
import forge.item.CardPrinted;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.List;
import static java.util.Collections.unmodifiableList;
import static javax.swing.JOptionPane.*;
/**
* A simple class that shows a list of cards in a dialog with preview in its right part.
*
* A simple class that shows a list of cards in a dialog with preview in its
* right part.
*
* @author Forge
* @version $Id: ListChooser.java 9708 2011-08-09 19:34:12Z jendave $
*/
public class CardListViewer {
//Data and number of choices for the list
private List<CardPrinted> list;
// Data and number of choices for the list
private final List<CardPrinted> list;
//Decoration
private String title;
// Decoration
private final String title;
//Flag: was the dialog already shown?
// Flag: was the dialog already shown?
private boolean called;
//initialized before; listeners may be added to it
private JList jList;
private CardDetailPanel detail;
private CardPicturePanel picture;
// initialized before; listeners may be added to it
private final JList jList;
private final CardDetailPanel detail;
private final CardPicturePanel picture;
//Temporarily stored for event handlers during show
// Temporarily stored for event handlers during show
private JDialog dialog;
private JOptionPane optionPane;
private Action ok;
private final JOptionPane optionPane;
private final Action ok;
public CardListViewer(String title, List<CardPrinted> list) {
/**
* Instantiates a new card list viewer.
*
* @param title the title
* @param list the list
*/
public CardListViewer(final String title, final List<CardPrinted> list) {
this(title, "", list, null);
}
public CardListViewer(String title, String message, List<CardPrinted> list) {
/**
* Instantiates a new card list viewer.
*
* @param title the title
* @param message the message
* @param list the list
*/
public CardListViewer(final String title, final String message, final List<CardPrinted> list) {
this(title, message, list, null);
}
public CardListViewer(String title, String message, List<CardPrinted> list, Icon dialogIcon) {
/**
* Instantiates a new card list viewer.
*
* @param title the title
* @param message the message
* @param list the list
* @param dialogIcon the dialog icon
*/
public CardListViewer(final String title, final String message, final List<CardPrinted> list, final Icon dialogIcon) {
this.title = title;
this.list = unmodifiableList(list);
jList = new JList(new ChooserListModel());
detail = new CardDetailPanel(null);
picture = new CardPicturePanel(null);
ok = new CloseAction(OK_OPTION, "OK");
this.list = Collections.unmodifiableList(list);
this.jList = new JList(new ChooserListModel());
this.detail = new CardDetailPanel(null);
this.picture = new CardPicturePanel(null);
this.ok = new CloseAction(JOptionPane.OK_OPTION, "OK");
Object[] options = new Object[]{new JButton(ok)};
final Object[] options = new Object[] { new JButton(this.ok) };
final JPanel threeCols = new JPanel();
threeCols.add(new JScrollPane(this.jList));
threeCols.add(this.picture);
threeCols.add(this.detail);
threeCols.setLayout(new java.awt.GridLayout(1, 3, 6, 0));
this.optionPane = new JOptionPane(new Object[] { message, threeCols }, JOptionPane.INFORMATION_MESSAGE,
JOptionPane.DEFAULT_OPTION, dialogIcon, options, options[0]);
JPanel threeCols = new JPanel();
threeCols.add(new JScrollPane(jList));
threeCols.add(picture);
threeCols.add(detail);
threeCols.setLayout( new java.awt.GridLayout(1, 3, 6, 0) );
optionPane = new JOptionPane(new Object[]{message, threeCols},
INFORMATION_MESSAGE, DEFAULT_OPTION, dialogIcon, options, options[0]);
// selection is here
jList.getSelectionModel().addListSelectionListener(new SelListener());
this.jList.getSelectionModel().addListSelectionListener(new SelListener());
}
/**
* Shows the dialog and returns after the dialog was closed.
*
*
* @return a boolean.
*/
public synchronized boolean show() {
if (called) throw new IllegalStateException("Already shown");
jList.setSelectedIndex(0);
dialog = optionPane.createDialog(optionPane.getParent(), title);
dialog.setSize(720,360);
dialog.addWindowFocusListener(new CardListFocuser());
dialog.setVisible(true);
dialog.toFront();
dialog.dispose();
called = true;
if (this.called) {
throw new IllegalStateException("Already shown");
}
this.jList.setSelectedIndex(0);
this.dialog = this.optionPane.createDialog(this.optionPane.getParent(), this.title);
this.dialog.setSize(720, 360);
this.dialog.addWindowFocusListener(new CardListFocuser());
this.dialog.setVisible(true);
this.dialog.toFront();
this.dialog.dispose();
this.called = true;
return true;
}
@@ -110,59 +137,70 @@ public class CardListViewer {
private static final long serialVersionUID = 3871965346333840556L;
public int getSize() { return list.size(); }
public Object getElementAt(int index) { return list.get(index); }
@Override
public int getSize() {
return CardListViewer.this.list.size();
}
@Override
public Object getElementAt(final int index) {
return CardListViewer.this.list.get(index);
}
}
private class CloseAction extends AbstractAction {
private static final long serialVersionUID = -8426767786083886936L;
private int value;
private final int value;
public CloseAction(int value, String label) {
public CloseAction(final int value, final String label) {
super(label);
this.value = value;
}
public void actionPerformed(ActionEvent e) {
optionPane.setValue(value);
@Override
public void actionPerformed(final ActionEvent e) {
CardListViewer.this.optionPane.setValue(this.value);
}
}
private class CardListFocuser implements WindowFocusListener {
@Override
public void windowGainedFocus(final WindowEvent e) {
jList.grabFocus();
CardListViewer.this.jList.grabFocus();
}
@Override
public void windowLostFocus(final WindowEvent e) { } }
public void windowLostFocus(final WindowEvent e) {
}
}
private class SelListener implements ListSelectionListener {
private Card[] cache = null;
@Override
public void valueChanged(final ListSelectionEvent e) {
int row = jList.getSelectedIndex();
final int row = CardListViewer.this.jList.getSelectedIndex();
// (String) jList.getSelectedValue();
if (row >= 0 && row < list.size()) {
CardPrinted cp = list.get(row);
ensureCacheHas(row, cp);
detail.setCard(cache[row]);
picture.setCard(cp);
if ((row >= 0) && (row < CardListViewer.this.list.size())) {
final CardPrinted cp = CardListViewer.this.list.get(row);
this.ensureCacheHas(row, cp);
CardListViewer.this.detail.setCard(this.cache[row]);
CardListViewer.this.picture.setCard(cp);
}
}
private void ensureCacheHas(int row, CardPrinted cp) {
if (cache == null) { cache = new Card[list.size()]; }
if (null == cache[row]) {
Card card = AllZone.getCardFactory().getCard(cp.getName(), null);
private void ensureCacheHas(final int row, final CardPrinted cp) {
if (this.cache == null) {
this.cache = new Card[CardListViewer.this.list.size()];
}
if (null == this.cache[row]) {
final Card card = AllZone.getCardFactory().getCard(cp.getName(), null);
card.setCurSetCode(cp.getSet());
card.setImageFilename(CardUtil.buildFilename(card));
cache[row] = card;
}
this.cache[row] = card;
}
}
}

View File

@@ -1,59 +1,67 @@
package forge.gui;
/**
* ForgeAction.java
*
* Created on 02.09.2009
*/
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.JMenuItem;
import forge.properties.ForgeProps;
import javax.swing.*;
/**
* The class ForgeAction.
*
*
* @author Clemens Koza
* @version V0.0 02.09.2009
*/
public abstract class ForgeAction extends AbstractAction {
/** Constant <code>serialVersionUID=-1881183151063146955L</code> */
/** Constant <code>serialVersionUID=-1881183151063146955L</code>. */
private static final long serialVersionUID = -1881183151063146955L;
private String property;
private final String property;
/**
* <p>Constructor for ForgeAction.</p>
*
* @param property A Property key containing the keys "/button" and "/menu".
* <p>
* Constructor for ForgeAction.
* </p>
*
* @param property
* A Property key containing the keys "/button" and "/menu".
*/
public ForgeAction(String property) {
public ForgeAction(final String property) {
super(ForgeProps.getLocalized(property + "/button"));
this.property = property;
putValue("buttonText", ForgeProps.getLocalized(property + "/button"));
putValue("menuText", ForgeProps.getLocalized(property + "/menu"));
this.putValue("buttonText", ForgeProps.getLocalized(property + "/button"));
this.putValue("menuText", ForgeProps.getLocalized(property + "/menu"));
}
/**
* <p>Getter for the field <code>property</code>.</p>
*
* <p>
* Getter for the field <code>property</code>.
* </p>
*
* @return a {@link java.lang.String} object.
*/
protected String getProperty() {
return property;
return this.property;
}
/**
* <p>setupButton.</p>
* <p>
* setupButton.
* </p>
*
* @param <T> a T object.
* @param button a T object.
* @return a T object.
* @param <T> a T object.
*/
public <T extends AbstractButton> T setupButton(T button) {
public <T extends AbstractButton> T setupButton(final T button) {
button.setAction(this);
button.setText((String) getValue(button instanceof JMenuItem ? "menuText" : "buttonText"));
button.setText((String) this.getValue(button instanceof JMenuItem ? "menuText" : "buttonText"));
return button;
}
}

View File

@@ -1,19 +1,5 @@
package forge.gui;
import forge.AllZone;
import forge.Card;
import forge.properties.ForgeProps;
import forge.properties.NewConstants;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.slightlymagic.braids.util.UtilFunctions;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
@@ -28,6 +14,19 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.slightlymagic.braids.util.UtilFunctions;
import forge.AllZone;
import forge.Card;
import forge.properties.ForgeProps;
import forge.properties.NewConstants;
/**
* <p>
* GuiUtils class.
@@ -52,13 +51,13 @@ public final class GuiUtils {
public static void setWidthToMax(final Collection<Component> components) {
int maxWidth = 0;
for (Component c : components) {
for (final Component c : components) {
if (c.getPreferredSize().getWidth() > maxWidth) {
maxWidth = (int) c.getPreferredSize().getWidth();
}
}
for (Component c : components) {
for (final Component c : components) {
c.setMinimumSize(new Dimension(maxWidth, (int) c.getPreferredSize().getHeight()));
c.setMaximumSize(new Dimension(maxWidth, (int) c.getPreferredSize().getHeight()));
c.setPreferredSize(new Dimension(maxWidth, (int) c.getPreferredSize().getHeight()));
@@ -117,7 +116,7 @@ public final class GuiUtils {
* a int.
*/
public static void setFontSize(final Component component, final int newSize) {
Font oldFont = component.getFont();
final Font oldFont = component.getFont();
component.setFont(oldFont.deriveFont((float) newSize));
}
@@ -131,8 +130,8 @@ public final class GuiUtils {
* @return a {@link javax.swing.ImageIcon} object.
*/
public static ImageIcon getIconFromFile(final String filename) {
File base = ForgeProps.getFile(NewConstants.IMAGE_ICON);
File file = new File(base, filename);
final File base = ForgeProps.getFile(NewConstants.IMAGE_ICON);
final File file = new File(base, filename);
if (filename.equals("") || !file.exists()) {
return null;
} else {
@@ -145,15 +144,17 @@ public final class GuiUtils {
* getResizedIcon.
* </p>
*
* @param filename String.
* @param scale Double.
* @param filename
* String.
* @param scale
* Double.
* @return {@link javax.swing.ImageIcon} object
*/
public static ImageIcon getResizedIcon(final String filename, final double scale) {
ImageIcon icon = getIconFromFile(filename);
final ImageIcon icon = GuiUtils.getIconFromFile(filename);
int w = (int) (icon.getIconWidth() * scale);
int h = (int) (icon.getIconHeight() * scale);
final int w = (int) (icon.getIconWidth() * scale);
final int h = (int) (icon.getIconHeight() * scale);
return new ImageIcon(icon.getImage().getScaledInstance(w, h, Image.SCALE_SMOOTH));
}
@@ -163,13 +164,15 @@ public final class GuiUtils {
* getResizedIcon.
* </p>
*
* @param icon ImageIcon
* @param scale Double
* @param icon
* ImageIcon
* @param scale
* Double
* @return {@link javax.swing.ImageIcon} object
*/
public static ImageIcon getResizedIcon(final ImageIcon icon, final double scale) {
int w = (int) (icon.getIconWidth() * scale);
int h = (int) (icon.getIconHeight() * scale);
final int w = (int) (icon.getIconWidth() * scale);
final int h = (int) (icon.getIconHeight() * scale);
return new ImageIcon(icon.getImage().getScaledInstance(w, h, Image.SCALE_SMOOTH));
}
@@ -208,54 +211,44 @@ public final class GuiUtils {
/**
* Convenience for getChoices(message, 0, 1, choices).
*
* @see #getChoices(String, int, int, Object...)
*
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @param <T>
* is automatically inferred.
*
*
* @param <T> is automatically inferred.
* @param message a {@link java.lang.String} object.
* @param choices a T object.
* @return null if choices is missing, empty, or if the users' choices are
* empty; otherwise, returns the first item in the List returned by
* getChoices.
* empty; otherwise, returns the first item in the List returned by
* getChoices.
* @see #getChoices(String, int, int, Object...)
*/
public static <T> T getChoiceOptional(final String message, final T... choices) {
if (choices == null || choices.length == 0) {
if ((choices == null) || (choices.length == 0)) {
return null;
}
List<T> choice = getChoices(message, 0, 1, choices);
final List<T> choice = GuiUtils.getChoices(message, 0, 1, choices);
return choice.isEmpty() ? null : choice.get(0);
} // getChoiceOptional(String,T...)
/**
* Like getChoiceOptional, but this takes an Iterator instead of a variable
* number of arguments.
*
*
* @param message
* a {@link java.lang.String} object.
* @param choices
* an Iterator over T objects.
* @param <T>
* is automatically inferred.
*
*
* @param <T> is automatically inferred.
* @param message a {@link java.lang.String} object.
* @param choices an Iterator over T objects.
* @return null if choices is missing, empty, or if the users' choices are
* empty; otherwise, returns the first item in the List returned by
* getChoices.
* empty; otherwise, returns the first item in the List returned by
* getChoices.
*/
public static <T> T getChoiceOptional(final String message, final Iterator<T> choices) {
if (choices == null | !choices.hasNext()) {
if ((choices == null) | !choices.hasNext()) {
return null;
}
// TODO this is an expensive operation; it would be better to
// update getChoices to accept an Iterator.
T[] choicesArray = UtilFunctions.iteratorToArray(choices);
final T[] choicesArray = UtilFunctions.iteratorToArray(choices);
List<T> choice = getChoices(message, 0, 1, choicesArray);
final List<T> choice = GuiUtils.getChoices(message, 0, 1, choicesArray);
return choice.isEmpty() ? null : choice.get(0);
} // getChoiceOptional(String,Iterator<T>)
@@ -264,17 +257,14 @@ public final class GuiUtils {
* <p>
* getChoice.
* </p>
*
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @param <T>
* a T object.
*
* @param <T> a T object.
* @param message a {@link java.lang.String} object.
* @param choices a T object.
* @return a T object.
*/
public static <T> T getChoice(final String message, final T... choices) {
List<T> choice = getChoices(message, 1, 1, choices);
final List<T> choice = GuiUtils.getChoices(message, 1, 1, choices);
assert choice.size() == 1;
return choice.get(0);
} // getChoice()
@@ -284,17 +274,14 @@ public final class GuiUtils {
* <p>
* getChoicesOptional.
* </p>
*
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @param <T>
* a T object.
*
* @param <T> a T object.
* @param message a {@link java.lang.String} object.
* @param choices a T object.
* @return a {@link java.util.List} object.
*/
public static <T> List<T> getChoicesOptional(final String message, final T... choices) {
return getChoices(message, 0, choices.length, choices);
return GuiUtils.getChoices(message, 0, choices.length, choices);
} // getChoice()
// returned Object will never be null
@@ -302,17 +289,14 @@ public final class GuiUtils {
* <p>
* getChoices.
* </p>
*
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @param <T>
* a T object.
*
* @param <T> a T object.
* @param message a {@link java.lang.String} object.
* @param choices a T object.
* @return a {@link java.util.List} object.
*/
public static <T> List<T> getChoices(final String message, final T... choices) {
return getChoices(message, 1, choices.length, choices);
return GuiUtils.getChoices(message, 1, choices.length, choices);
} // getChoice()
// returned Object will never be null
@@ -320,25 +304,21 @@ public final class GuiUtils {
* <p>
* getChoices.
* </p>
*
* @param message
* a {@link java.lang.String} object.
* @param min
* a int.
* @param max
* a int.
* @param choices
* a T object.
* @param <T>
* a T object.
*
* @param <T> a T object.
* @param message a {@link java.lang.String} object.
* @param min a int.
* @param max a int.
* @param choices a T object.
* @return a {@link java.util.List} object.
*/
public static <T> List<T> getChoices(final String message, final int min, final int max, final T... choices) {
ListChooser<T> c = new ListChooser<T>(message, min, max, choices);
final ListChooser<T> c = new ListChooser<T>(message, min, max, choices);
final JList list = c.getJList();
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(final ListSelectionEvent ev) {
if (list.getSelectedValue() instanceof Card && AllZone.getDisplay() != null) {
if ((list.getSelectedValue() instanceof Card) && (AllZone.getDisplay() != null)) {
AllZone.getDisplay().setCard((Card) list.getSelectedValue());
}
}
@@ -354,8 +334,8 @@ public final class GuiUtils {
* a fully laid-out frame
*/
public static void centerFrame(final Window frame) {
Dimension screen = frame.getToolkit().getScreenSize();
Rectangle bounds = frame.getBounds();
final Dimension screen = frame.getToolkit().getScreenSize();
final Rectangle bounds = frame.getBounds();
bounds.width = frame.getWidth();
bounds.height = frame.getHeight();
bounds.x = (screen.width - bounds.width) / 2;
@@ -367,18 +347,19 @@ public final class GuiUtils {
* Attempts to create a font from a filename. Concise error reported if
* exceptions found.
*
* @param filename String
* @param filename
* String
* @return Font
*/
public static Font newFont(final String filename) {
File file = new File(filename);
final File file = new File(filename);
Font ttf = null;
try {
ttf = Font.createFont(Font.TRUETYPE_FONT, file);
} catch (FontFormatException e) {
} catch (final FontFormatException e) {
System.err.println("GuiUtils > newFont: bad font format \"" + filename + "\"");
} catch (IOException e) {
} catch (final IOException e) {
System.err.println("GuiUtils > newFont: can't find \"" + filename + "\"");
}
return ttf;

View File

@@ -6,279 +6,382 @@
package forge.gui;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;
import static javax.swing.JOptionPane.*;
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
/**
* A simple class that shows a list of choices in a dialog. Two properties influence the behavior of a list
* chooser: minSelection and maxSelection. These two give the allowed number of selected items for the dialog to be
* A simple class that shows a list of choices in a dialog. Two properties
* influence the behavior of a list chooser: minSelection and maxSelection.
* These two give the allowed number of selected items for the dialog to be
* closed.
* <ul>
* <li>If minSelection is 0, there will be a Cancel button.</li>
* <li>If minSelection is 0 or 1, double-clicking a choice will also close the dialog.</li>
* <li>If the number of selections is out of bounds, the "OK" button is disabled.</li>
* <li>The dialog was "committed" if "OK" was clicked or a choice was double clicked.</li>
* <li>If minSelection is 0 or 1, double-clicking a choice will also close the
* dialog.</li>
* <li>If the number of selections is out of bounds, the "OK" button is
* disabled.</li>
* <li>The dialog was "committed" if "OK" was clicked or a choice was double
* clicked.</li>
* <li>The dialog was "canceled" if "Cancel" or "X" was clicked.</li>
* <li>If the dialog was canceled, the selection will be empty.</li>
* <li>
* </ul>
*
* @param <T> the generic type
* @author Forge
* @version $Id$
*/
public class ListChooser<T> {
//Data and number of choices for the list
// Data and number of choices for the list
private List<T> list;
private int minChoices, maxChoices;
//Decoration
// Decoration
private String title;
//Flag: was the dialog already shown?
// Flag: was the dialog already shown?
private boolean called;
//initialized before; listeners may be added to it
// initialized before; listeners may be added to it
private JList jList;
//Temporarily stored for event handlers during show
// Temporarily stored for event handlers during show
private JDialog d;
private JOptionPane p;
private Action ok, cancel;
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param list a T object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param list
* a T object.
*/
public ListChooser(String title, T... list) {
public ListChooser(final String title, final T... list) {
this(title, 1, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param numChoices a int.
* @param list a T object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param numChoices
* a int.
* @param list
* a T object.
*/
public ListChooser(String title, int numChoices, T... list) {
public ListChooser(final String title, final int numChoices, final T... list) {
this(title, numChoices, numChoices, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param minChoices a int.
* @param maxChoices a int.
* @param list a T object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param minChoices
* a int.
* @param maxChoices
* a int.
* @param list
* a T object.
*/
public ListChooser(String title, int minChoices, int maxChoices, T... list) {
public ListChooser(final String title, final int minChoices, final int maxChoices, final T... list) {
this(title, null, minChoices, maxChoices, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param message a {@link java.lang.String} object.
* @param list a T object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param message
* a {@link java.lang.String} object.
* @param list
* a T object.
*/
public ListChooser(String title, String message, T... list) {
public ListChooser(final String title, final String message, final T... list) {
this(title, message, 1, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param message a {@link java.lang.String} object.
* @param numChoices a int.
* @param list a T object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param message
* a {@link java.lang.String} object.
* @param numChoices
* a int.
* @param list
* a T object.
*/
public ListChooser(String title, String message, int numChoices, T... list) {
public ListChooser(final String title, final String message, final int numChoices, final T... list) {
this(title, message, numChoices, numChoices, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param message a {@link java.lang.String} object.
* @param minChoices a int.
* @param maxChoices a int.
* @param list a T object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param message
* a {@link java.lang.String} object.
* @param minChoices
* a int.
* @param maxChoices
* a int.
* @param list
* a T object.
*/
public ListChooser(String title, String message, int minChoices, int maxChoices, T... list) {
this(title, message, minChoices, maxChoices, asList(list));
public ListChooser(final String title, final String message, final int minChoices, final int maxChoices,
final T... list) {
this(title, message, minChoices, maxChoices, Arrays.asList(list));
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param list a {@link java.util.List} object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param list
* a {@link java.util.List} object.
*/
public ListChooser(String title, List<T> list) {
public ListChooser(final String title, final List<T> list) {
this(title, 1, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param numChoices a int.
* @param list a {@link java.util.List} object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param numChoices
* a int.
* @param list
* a {@link java.util.List} object.
*/
public ListChooser(String title, int numChoices, List<T> list) {
public ListChooser(final String title, final int numChoices, final List<T> list) {
this(title, numChoices, numChoices, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param minChoices a int.
* @param maxChoices a int.
* @param list a {@link java.util.List} object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param minChoices
* a int.
* @param maxChoices
* a int.
* @param list
* a {@link java.util.List} object.
*/
public ListChooser(String title, int minChoices, int maxChoices, List<T> list) {
public ListChooser(final String title, final int minChoices, final int maxChoices, final List<T> list) {
this(title, null, minChoices, maxChoices, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param message a {@link java.lang.String} object.
* @param list a {@link java.util.List} object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param message
* a {@link java.lang.String} object.
* @param list
* a {@link java.util.List} object.
*/
public ListChooser(String title, String message, List<T> list) {
public ListChooser(final String title, final String message, final List<T> list) {
this(title, message, 1, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param message a {@link java.lang.String} object.
* @param numChoices a int.
* @param list a {@link java.util.List} object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param message
* a {@link java.lang.String} object.
* @param numChoices
* a int.
* @param list
* a {@link java.util.List} object.
*/
public ListChooser(String title, String message, int numChoices, List<T> list) {
public ListChooser(final String title, final String message, final int numChoices, final List<T> list) {
this(title, message, numChoices, numChoices, list);
}
/**
* <p>Constructor for ListChooser.</p>
*
* @param title a {@link java.lang.String} object.
* @param message a {@link java.lang.String} object.
* @param minChoices a int.
* @param maxChoices a int.
* @param list a {@link java.util.List} object.
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param message
* a {@link java.lang.String} object.
* @param minChoices
* a int.
* @param maxChoices
* a int.
* @param list
* a {@link java.util.List} object.
*/
public ListChooser(String title, String message, int minChoices, int maxChoices, List<T> list) {
public ListChooser(final String title, final String message, final int minChoices, final int maxChoices,
final List<T> list) {
this.title = title;
this.minChoices = minChoices;
this.maxChoices = maxChoices;
this.list = unmodifiableList(list);
jList = new JList(new ChooserListModel());
ok = new CloseAction(OK_OPTION, "OK");
ok.setEnabled(minChoices == 0);
cancel = new CloseAction(CANCEL_OPTION, "Cancel");
this.list = Collections.unmodifiableList(list);
this.jList = new JList(new ChooserListModel());
this.ok = new CloseAction(JOptionPane.OK_OPTION, "OK");
this.ok.setEnabled(minChoices == 0);
this.cancel = new CloseAction(JOptionPane.CANCEL_OPTION, "Cancel");
Object[] options;
if (minChoices == 0) options = new Object[]{new JButton(ok), new JButton(cancel)};
else options = new Object[]{new JButton(ok)};
if (maxChoices == 1) { jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); }
if (minChoices == 0) {
options = new Object[] { new JButton(this.ok), new JButton(this.cancel) };
} else {
options = new Object[] { new JButton(this.ok) };
}
if (maxChoices == 1) {
this.jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
p = new JOptionPane(new Object[]{message, new JScrollPane(jList)}, QUESTION_MESSAGE, DEFAULT_OPTION,
null, options, options[0]);
jList.getSelectionModel().addListSelectionListener(new SelListener());
jList.addMouseListener(new DblListener());
this.p = new JOptionPane(new Object[] { message, new JScrollPane(this.jList) }, JOptionPane.QUESTION_MESSAGE,
JOptionPane.DEFAULT_OPTION, null, options, options[0]);
this.jList.getSelectionModel().addListSelectionListener(new SelListener());
this.jList.addMouseListener(new DblListener());
}
/**
* <p>getChoices.</p>
*
* <p>
* getChoices.
* </p>
*
* @return a {@link java.util.List} object.
*/
public List<T> getChoices() {
return list;
return this.list;
}
/**
* Returns the JList used in the list chooser. this is useful for registering listeners before showing the
* dialog.
*
* Returns the JList used in the list chooser. this is useful for
* registering listeners before showing the dialog.
*
* @return a {@link javax.swing.JList} object.
*/
public JList getJList() {
return jList;
return this.jList;
}
/**
* Shows the dialog and returns after the dialog was closed.
*
*
* @return a boolean.
*/
public synchronized boolean show() {
if (called) throw new IllegalStateException("Already shown");
if (this.called) {
throw new IllegalStateException("Already shown");
}
Integer value;
do {
d = p.createDialog(p.getParent(), title);
if (minChoices != 0) d.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
jList.setSelectedIndex(0);
d.addWindowFocusListener(new WindowFocusListener() {
@Override public void windowGainedFocus(final WindowEvent e) { jList.grabFocus(); }
@Override public void windowLostFocus(final WindowEvent e) { }
this.d = this.p.createDialog(this.p.getParent(), this.title);
if (this.minChoices != 0) {
this.d.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
}
this.jList.setSelectedIndex(0);
this.d.addWindowFocusListener(new WindowFocusListener() {
@Override
public void windowGainedFocus(final WindowEvent e) {
ListChooser.this.jList.grabFocus();
}
@Override
public void windowLostFocus(final WindowEvent e) {
}
});
d.setVisible(true);
d.dispose();
value = (Integer) p.getValue();
if (value == null || value != OK_OPTION) jList.clearSelection();
//can't stop closing by ESC, so repeat if cancelled
} while (minChoices != 0 && value != OK_OPTION);
//this assert checks if we really don't return on a cancel if input is mandatory
assert minChoices == 0 || value == OK_OPTION;
called = true;
return value != null && value == OK_OPTION;
this.d.setVisible(true);
this.d.dispose();
value = (Integer) this.p.getValue();
if ((value == null) || (value != JOptionPane.OK_OPTION)) {
this.jList.clearSelection();
// can't stop closing by ESC, so repeat if cancelled
}
} while ((this.minChoices != 0) && (value != JOptionPane.OK_OPTION));
// this assert checks if we really don't return on a cancel if input is
// mandatory
assert (this.minChoices == 0) || (value == JOptionPane.OK_OPTION);
this.called = true;
return (value != null) && (value == JOptionPane.OK_OPTION);
}
/**
* Returns if the dialog was closed by pressing "OK" or double clicking an option the last time
* Returns if the dialog was closed by pressing "OK" or double clicking an
* option the last time.
*
* @return a boolean.
*/
public boolean isCommitted() {
if (!called) throw new IllegalStateException("not yet shown");
return (Integer) p.getValue() == OK_OPTION;
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
return (Integer) this.p.getValue() == JOptionPane.OK_OPTION;
}
/**
* Returns the selected indices as a list of integers
* Returns the selected indices as a list of integers.
*
* @return a {@link java.util.List} object.
*/
public List<Integer> getSelectedIndices() {
if (!called) throw new IllegalStateException("not yet shown");
final int[] indices = jList.getSelectedIndices();
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
final int[] indices = this.jList.getSelectedIndices();
return new AbstractList<Integer>() {
@Override
public int size() {
@@ -286,20 +389,23 @@ public class ListChooser<T> {
}
@Override
public Integer get(int index) {
public Integer get(final int index) {
return indices[index];
}
};
}
/**
* Returns the selected values as a list of objects. no casts are necessary when retrieving the objects.
*
* Returns the selected values as a list of objects. no casts are necessary
* when retrieving the objects.
*
* @return a {@link java.util.List} object.
*/
public List<T> getSelectedValues() {
if (!called) throw new IllegalStateException("not yet shown");
final Object[] selected = jList.getSelectedValues();
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
final Object[] selected = this.jList.getSelectedValues();
return new AbstractList<T>() {
@Override
public int size() {
@@ -308,82 +414,95 @@ public class ListChooser<T> {
@SuppressWarnings("unchecked")
@Override
public T get(int index) {
public T get(final int index) {
return (T) selected[index];
}
};
}
/**
* Returns the (minimum) selected index, or -1
* Returns the (minimum) selected index, or -1.
*
* @return a int.
*/
public int getSelectedIndex() {
if (!called) throw new IllegalStateException("not yet shown");
return jList.getSelectedIndex();
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
return this.jList.getSelectedIndex();
}
/**
* Returns the (first) selected value, or null
* Returns the (first) selected value, or null.
*
* @return a T object.
*/
@SuppressWarnings("unchecked")
public T getSelectedValue() {
if (!called) throw new IllegalStateException("not yet shown");
return (T) jList.getSelectedValue();
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
return (T) this.jList.getSelectedValue();
}
/**
* <p>commit.</p>
* <p>
* commit.
* </p>
*/
private void commit() {
if (ok.isEnabled()) p.setValue(OK_OPTION);
if (this.ok.isEnabled()) {
this.p.setValue(JOptionPane.OK_OPTION);
}
}
private class ChooserListModel extends AbstractListModel {
private static final long serialVersionUID = 3871965346333840556L;
@Override
public int getSize() {
return list.size();
return ListChooser.this.list.size();
}
public Object getElementAt(int index) {
return list.get(index);
@Override
public Object getElementAt(final int index) {
return ListChooser.this.list.get(index);
}
}
private class CloseAction extends AbstractAction {
private static final long serialVersionUID = -8426767786083886936L;
private int value;
private final int value;
public CloseAction(int value, String label) {
public CloseAction(final int value, final String label) {
super(label);
this.value = value;
}
public void actionPerformed(ActionEvent e) {
p.setValue(value);
@Override
public void actionPerformed(final ActionEvent e) {
ListChooser.this.p.setValue(this.value);
}
}
private class SelListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
int num = jList.getSelectedIndices().length;
ok.setEnabled(num >= minChoices && num <= maxChoices);
@Override
public void valueChanged(final ListSelectionEvent e) {
final int num = ListChooser.this.jList.getSelectedIndices().length;
ListChooser.this.ok
.setEnabled((num >= ListChooser.this.minChoices) && (num <= ListChooser.this.maxChoices));
}
}
private class DblListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) commit();
public void mouseClicked(final MouseEvent e) {
if (e.getClickCount() == 2) {
ListChooser.this.commit();
}
}
}
}

View File

@@ -23,9 +23,10 @@
*/
package forge.gui;
import javax.swing.*;
import java.awt.*;
import java.awt.Rectangle;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
/**
* A {@link JLabel} with support for multi-line text that wraps when the line
@@ -33,7 +34,7 @@ import java.awt.*;
* {@link MultiLineLabelUI}, the default UI delegate of this component. The text
* in the label can be horizontally and vertically aligned, relative to the
* bounds of the component.
*
*
* @author Samuel Sjoberg, http://samuelsjoberg.com
* @version 1.0.0
*/
@@ -47,12 +48,12 @@ public class MultiLineLabel extends JLabel {
/**
* Horizontal text alignment.
*/
private int halign = LEFT;
private int halign = SwingConstants.LEFT;
/**
* Vertical text alignment.
*/
private int valign = CENTER;
private int valign = SwingConstants.CENTER;
/**
* Cache to save heap allocations.
@@ -64,66 +65,70 @@ public class MultiLineLabel extends JLabel {
*/
public MultiLineLabel() {
super();
setUI(MultiLineLabelUI.labelUI);
this.setUI(MultiLineLabelUI.getLabelUI());
}
/**
* Creates a new label with <code>text</code> value.
*
* @param text the value of the label
*
* @param text
* the value of the label
*/
public MultiLineLabel(String text) {
public MultiLineLabel(final String text) {
this();
setText(text);
this.setText(text);
}
/**
* {@inheritDoc}
*
*
* @return a {@link java.awt.Rectangle} object.
*/
@Override
public Rectangle getBounds() {
if (bounds == null) {
bounds = new Rectangle();
if (this.bounds == null) {
this.bounds = new Rectangle();
}
return super.getBounds(bounds);
return super.getBounds(this.bounds);
}
/**
* Set the vertical text alignment.
*
* @param alignment vertical alignment
*
* @param alignment
* vertical alignment
*/
public void setVerticalTextAlignment(int alignment) {
firePropertyChange("verticalTextAlignment", valign, alignment);
valign = alignment;
public void setVerticalTextAlignment(final int alignment) {
this.firePropertyChange("verticalTextAlignment", this.valign, alignment);
this.valign = alignment;
}
/**
* Set the horizontal text alignment.
*
* @param alignment horizontal alignment
*
* @param alignment
* horizontal alignment
*/
public void setHorizontalTextAlignment(int alignment) {
firePropertyChange("horizontalTextAlignment", halign, alignment);
halign = alignment;
public void setHorizontalTextAlignment(final int alignment) {
this.firePropertyChange("horizontalTextAlignment", this.halign, alignment);
this.halign = alignment;
}
/**
* Get the vertical text alignment.
*
*
* @return vertical text alignment
*/
public int getVerticalTextAlignment() {
return valign;
return this.valign;
}
/**
* Get the horizontal text alignment.
*
*
* @return horizontal text alignment
*/
public int getHorizontalTextAlignment() {
return halign;
return this.halign;
}
}

View File

@@ -23,12 +23,11 @@
*/
package forge.gui;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.LabelUI;
import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.text.*;
import java.awt.*;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.beans.PropertyChangeEvent;
@@ -36,6 +35,20 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.LabelUI;
import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.PlainDocument;
import javax.swing.text.Segment;
import javax.swing.text.Utilities;
import javax.swing.text.View;
/**
* Label UI delegate that supports multiple lines and line wrapping. Hard line
@@ -49,6 +62,7 @@ import java.util.List;
* <p/>
* Example of usage:
* <p/>
*
* <pre>
* JLabel myLabel = new JLabel();
* myLabel.setUI(MultiLineLabelUI.labelUI);
@@ -61,7 +75,7 @@ import java.util.List;
* by overriding {@link #paintEnabledText(JLabel, Graphics, String, int, int)}
* and {@link #paintDisabledText(JLabel, Graphics, String, int, int)}. This
* class is designed to be easily extended by subclasses.
*
*
* @author Samuel Sjoberg, http://samuelsjoberg.com
* @version 1.3.0
*/
@@ -70,7 +84,7 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/**
* Shared instance of the UI delegate.
*/
public static LabelUI labelUI = new MultiLineLabelUI();
private static LabelUI labelUI = new MultiLineLabelUI();
/**
* Client property key used to store the calculated wrapped lines on the
@@ -79,187 +93,213 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
public static final String PROPERTY_KEY = "WrappedText";
// Static references to avoid heap allocations.
/** Constant <code>paintIconR</code> */
protected static Rectangle paintIconR = new Rectangle();
/** Constant <code>paintTextR</code> */
protected static Rectangle paintTextR = new Rectangle();
/** Constant <code>paintViewR</code> */
protected static Rectangle paintViewR = new Rectangle();
/** Constant <code>paintViewInsets</code> */
protected static Insets paintViewInsets = new Insets(0, 0, 0, 0);
/** Constant <code>paintIconR</code>. */
private static Rectangle paintIconR = new Rectangle();
/** Constant <code>paintTextR</code>. */
private static Rectangle paintTextR = new Rectangle();
/** Constant <code>paintViewR</code>. */
private static Rectangle paintViewR = new Rectangle();
/** Constant <code>paintViewInsets</code>. */
private static Insets paintViewInsets = new Insets(0, 0, 0, 0);
/**
* Font metrics of the JLabel being rendered.
*/
protected FontMetrics metrics;
private FontMetrics metrics;
/**
* Default size of the lines list.
*/
protected static int defaultSize = 4;
private static int defaultSize = 4;
/**
* Get the shared UI instance.
* @param c
*
* @param c the c
* @return a ComponentUI
*/
public static ComponentUI createUI(JComponent c) {
return labelUI;
public static ComponentUI createUI(final JComponent c) {
return MultiLineLabelUI.getLabelUI();
}
/** {@inheritDoc} */
protected void uninstallDefaults(JLabel c) {
@Override
protected void uninstallDefaults(final JLabel c) {
super.uninstallDefaults(c);
clearCache(c);
this.clearCache(c);
}
/** {@inheritDoc} */
protected void installListeners(JLabel c) {
@Override
protected void installListeners(final JLabel c) {
super.installListeners(c);
c.addComponentListener(this);
}
/** {@inheritDoc} */
protected void uninstallListeners(JLabel c) {
@Override
protected void uninstallListeners(final JLabel c) {
super.uninstallListeners(c);
c.removeComponentListener(this);
}
/**
* Clear the wrapped line cache.
*
* @param l the label containing a cached value
*
* @param l
* the label containing a cached value
*/
protected void clearCache(JLabel l) {
l.putClientProperty(PROPERTY_KEY, null);
protected void clearCache(final JLabel l) {
l.putClientProperty(MultiLineLabelUI.PROPERTY_KEY, null);
}
/** {@inheritDoc} */
public void propertyChange(PropertyChangeEvent e) {
@Override
public void propertyChange(final PropertyChangeEvent e) {
super.propertyChange(e);
final String name = e.getPropertyName();
if (name.equals("text") || "font".equals(name)) {
clearCache((JLabel) e.getSource());
this.clearCache((JLabel) e.getSource());
}
}
/**
* Calculate the paint rectangles for the icon and text for the passed
* label.
*
* @param l a label
* @param fm the font metrics to use, or <code>null</code> to get the font
* metrics from the label
* @param width label width
* @param height label height
*
* @param l
* a label
* @param fm
* the font metrics to use, or <code>null</code> to get the font
* metrics from the label
* @param width
* label width
* @param height
* label height
*/
protected void updateLayout(JLabel l, FontMetrics fm, int width, int height) {
protected void updateLayout(final JLabel l, FontMetrics fm, final int width, final int height) {
if (fm == null) {
fm = l.getFontMetrics(l.getFont());
}
metrics = fm;
this.metrics = fm;
String text = l.getText();
Icon icon = l.getIcon();
Insets insets = l.getInsets(paintViewInsets);
final String text = l.getText();
final Icon icon = l.getIcon();
final Insets insets = l.getInsets(MultiLineLabelUI.paintViewInsets);
paintViewR.x = insets.left;
paintViewR.y = insets.top;
paintViewR.width = width - (insets.left + insets.right);
paintViewR.height = height - (insets.top + insets.bottom);
MultiLineLabelUI.paintViewR.x = insets.left;
MultiLineLabelUI.paintViewR.y = insets.top;
MultiLineLabelUI.paintViewR.width = width - (insets.left + insets.right);
MultiLineLabelUI.paintViewR.height = height - (insets.top + insets.bottom);
paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;
MultiLineLabelUI.paintIconR.x = 0;
MultiLineLabelUI.paintIconR.y = 0;
MultiLineLabelUI.paintIconR.width = 0;
MultiLineLabelUI.paintIconR.height = 0;
MultiLineLabelUI.paintTextR.x = 0;
MultiLineLabelUI.paintTextR.y = 0;
MultiLineLabelUI.paintTextR.width = 0;
MultiLineLabelUI.paintTextR.height = 0;
layoutCL(l, fm, text, icon, paintViewR, paintIconR, paintTextR);
this.layoutCL(l, fm, text, icon, MultiLineLabelUI.paintViewR, MultiLineLabelUI.paintIconR,
MultiLineLabelUI.paintTextR);
}
/**
* <p>prepareGraphics.</p>
*
* @param g a {@link java.awt.Graphics} object.
* <p>
* prepareGraphics.
* </p>
*
* @param g
* a {@link java.awt.Graphics} object.
*/
protected void prepareGraphics(Graphics g) {
protected void prepareGraphics(final Graphics g) {
}
/** {@inheritDoc} */
public void paint(Graphics g, JComponent c) {
@Override
public void paint(final Graphics g, final JComponent c) {
// parent's update method fills the background
prepareGraphics(g);
this.prepareGraphics(g);
JLabel label = (JLabel) c;
String text = label.getText();
Icon icon = (label.isEnabled()) ? label.getIcon() : label
.getDisabledIcon();
final JLabel label = (JLabel) c;
final String text = label.getText();
final Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();
if ((icon == null) && (text == null)) {
return;
}
FontMetrics fm = g.getFontMetrics();
final FontMetrics fm = g.getFontMetrics();
updateLayout(label, fm, c.getWidth(), c.getHeight());
this.updateLayout(label, fm, c.getWidth(), c.getHeight());
if (icon != null) {
icon.paintIcon(c, g, paintIconR.x, paintIconR.y);
icon.paintIcon(c, g, MultiLineLabelUI.paintIconR.x, MultiLineLabelUI.paintIconR.y);
}
if (text != null) {
View v = (View) c.getClientProperty("html");
final View v = (View) c.getClientProperty("html");
if (v != null) {
// HTML view disables multi-line painting.
v.paint(g, paintTextR);
v.paint(g, MultiLineLabelUI.paintTextR);
} else {
// Paint the multi line text
paintTextLines(g, label, fm);
this.paintTextLines(g, label, fm);
}
}
}
/**
* Paint the wrapped text lines.
*
* @param g graphics component to paint on
* @param label the label being painted
* @param fm font metrics for current font
*
* @param g
* graphics component to paint on
* @param label
* the label being painted
* @param fm
* font metrics for current font
*/
protected void paintTextLines(Graphics g, JLabel label, FontMetrics fm) {
List<String> lines = getTextLines(label);
protected void paintTextLines(final Graphics g, final JLabel label, final FontMetrics fm) {
final List<String> lines = this.getTextLines(label);
// Available component height to paint on.
int height = getAvailableHeight(label);
final int height = this.getAvailableHeight(label);
int textHeight = lines.size() * fm.getHeight();
while (textHeight > height) {
// Remove one line until no. of visible lines is found.
textHeight -= fm.getHeight();
}
paintTextR.height = Math.min(textHeight, height);
paintTextR.y = alignmentY(label, fm, paintTextR);
MultiLineLabelUI.paintTextR.height = Math.min(textHeight, height);
MultiLineLabelUI.paintTextR.y = this.alignmentY(label, fm, MultiLineLabelUI.paintTextR);
int textX = paintTextR.x;
int textY = paintTextR.y;
final int textX = MultiLineLabelUI.paintTextR.x;
int textY = MultiLineLabelUI.paintTextR.y;
for (Iterator<String> it = lines.iterator(); it.hasNext()
&& paintTextR.contains(textX, textY + getAscent(fm)); textY += fm
for (final Iterator<String> it = lines.iterator(); it.hasNext()
&& MultiLineLabelUI.paintTextR.contains(textX, textY + MultiLineLabelUI.getAscent(fm)); textY += fm
.getHeight()) {
String text = it.next().trim();
if (it.hasNext()
&& !paintTextR.contains(textX, textY + fm.getHeight()
+ getAscent(fm))) {
&& !MultiLineLabelUI.paintTextR.contains(textX,
textY + fm.getHeight() + MultiLineLabelUI.getAscent(fm))) {
// The last visible row, add a clip indication.
text = clip(text, fm, paintTextR);
text = this.clip(text, fm, MultiLineLabelUI.paintTextR);
}
int x = alignmentX(label, fm, text, paintTextR);
final int x = this.alignmentX(label, fm, text, MultiLineLabelUI.paintTextR);
if (label.isEnabled()) {
paintEnabledText(label, g, text, x, textY);
this.paintEnabledText(label, g, text, x, textY);
} else {
paintDisabledText(label, g, text, x, textY);
this.paintDisabledText(label, g, text, x, textY);
}
}
}
@@ -267,25 +307,29 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/**
* Returns the available height to paint text on. This is the height of the
* passed component with insets subtracted.
*
* @param l a component
*
* @param l
* a component
* @return the available height
*/
protected int getAvailableHeight(JLabel l) {
l.getInsets(paintViewInsets);
return l.getHeight() - paintViewInsets.top - paintViewInsets.bottom;
protected int getAvailableHeight(final JLabel l) {
l.getInsets(MultiLineLabelUI.paintViewInsets);
return l.getHeight() - MultiLineLabelUI.paintViewInsets.top - MultiLineLabelUI.paintViewInsets.bottom;
}
/**
* Add a clip indication to the string. It is important that the string
* length does not exceed the length or the original string.
*
* @param text the to be painted
* @param fm font metrics
* @param bounds the text bounds
*
* @param text
* the to be painted
* @param fm
* font metrics
* @param bounds
* the text bounds
* @return the clipped string
*/
protected String clip(String text, FontMetrics fm, Rectangle bounds) {
protected String clip(final String text, final FontMetrics fm, final Rectangle bounds) {
// Fast and lazy way to insert a clip indication is to simply replace
// the last characters in the string with the clip indication.
// A better way would be to use metrics and calculate how many (if any)
@@ -299,65 +343,74 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/**
* Establish the vertical text alignment. The default alignment is to center
* the text in the label.
*
* @param label the label to paint
* @param fm font metrics
* @param bounds the text bounds rectangle
*
* @param label
* the label to paint
* @param fm
* font metrics
* @param bounds
* the text bounds rectangle
* @return the vertical text alignment, defaults to CENTER.
*/
protected int alignmentY(JLabel label, FontMetrics fm, Rectangle bounds) {
final int height = getAvailableHeight(label);
int textHeight = bounds.height;
protected int alignmentY(final JLabel label, final FontMetrics fm, final Rectangle bounds) {
final int height = this.getAvailableHeight(label);
final int textHeight = bounds.height;
if (label instanceof MultiLineLabel) {
int align = ((MultiLineLabel) label).getVerticalTextAlignment();
final int align = ((MultiLineLabel) label).getVerticalTextAlignment();
switch (align) {
case JLabel.TOP:
return getAscent(fm) + paintViewInsets.top;
case JLabel.BOTTOM:
return getAscent(fm) + height - paintViewInsets.top
+ paintViewInsets.bottom - textHeight;
default:
case SwingConstants.TOP:
return MultiLineLabelUI.getAscent(fm) + MultiLineLabelUI.paintViewInsets.top;
case SwingConstants.BOTTOM:
return (((MultiLineLabelUI.getAscent(fm) + height) - MultiLineLabelUI.paintViewInsets.top) + MultiLineLabelUI.paintViewInsets.bottom)
- textHeight;
default:
}
}
// Center alignment
int textY = paintViewInsets.top + (height - textHeight) / 2
+ getAscent(fm);
return Math.max(textY, getAscent(fm) + paintViewInsets.top);
final int textY = MultiLineLabelUI.paintViewInsets.top + ((height - textHeight) / 2)
+ MultiLineLabelUI.getAscent(fm);
return Math.max(textY, MultiLineLabelUI.getAscent(fm) + MultiLineLabelUI.paintViewInsets.top);
}
/**
* <p>getAscent.</p>
*
* @param fm a {@link java.awt.FontMetrics} object.
* <p>
* getAscent.
* </p>
*
* @param fm
* a {@link java.awt.FontMetrics} object.
* @return a int.
*/
private static int getAscent(FontMetrics fm) {
private static int getAscent(final FontMetrics fm) {
return fm.getAscent() + fm.getLeading();
}
/**
* Establish the horizontal text alignment. The default alignment is left
* aligned text.
*
* @param label the label to paint
* @param fm font metrics
* @param s the string to paint
* @param bounds the text bounds rectangle
*
* @param label
* the label to paint
* @param fm
* font metrics
* @param s
* the string to paint
* @param bounds
* the text bounds rectangle
* @return the x-coordinate to use when painting for proper alignment
*/
protected int alignmentX(JLabel label, FontMetrics fm, String s,
Rectangle bounds) {
protected int alignmentX(final JLabel label, final FontMetrics fm, final String s, final Rectangle bounds) {
if (label instanceof MultiLineLabel) {
int align = ((MultiLineLabel) label).getHorizontalTextAlignment();
final int align = ((MultiLineLabel) label).getHorizontalTextAlignment();
switch (align) {
case JLabel.RIGHT:
return bounds.x + paintViewR.width - fm.stringWidth(s);
case JLabel.CENTER:
return bounds.x + paintViewR.width / 2 - fm.stringWidth(s) / 2;
default:
return bounds.x;
case SwingConstants.RIGHT:
return (bounds.x + MultiLineLabelUI.paintViewR.width) - fm.stringWidth(s);
case SwingConstants.CENTER:
return (bounds.x + (MultiLineLabelUI.paintViewR.width / 2)) - (fm.stringWidth(s) / 2);
default:
return bounds.x;
}
}
return bounds.x;
@@ -367,15 +420,15 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
* Check the given string to see if it should be rendered as HTML. Code
* based on implementation found in
* <code>BasicHTML.isHTMLString(String)</code> in future JDKs.
*
* @param s the string
*
* @param s
* the string
* @return <code>true</code> if string is HTML, otherwise <code>false</code>
*/
private static boolean isHTMLString(String s) {
private static boolean isHTMLString(final String s) {
if (s != null) {
if ((s.length() >= 6) && (s.charAt(0) == '<')
&& (s.charAt(5) == '>')) {
String tag = s.substring(1, 5);
if ((s.length() >= 6) && (s.charAt(0) == '<') && (s.charAt(5) == '>')) {
final String tag = s.substring(1, 5);
return tag.equalsIgnoreCase("html");
}
}
@@ -383,11 +436,12 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
}
/** {@inheritDoc} */
public Dimension getPreferredSize(JComponent c) {
Dimension d = super.getPreferredSize(c);
JLabel label = (JLabel) c;
@Override
public Dimension getPreferredSize(final JComponent c) {
final Dimension d = super.getPreferredSize(c);
final JLabel label = (JLabel) c;
if (isHTMLString(label.getText())) {
if (MultiLineLabelUI.isHTMLString(label.getText())) {
return d; // HTML overrides everything and we don't need to process
}
@@ -398,19 +452,19 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
if (c.getParent() != null) {
// Ensure that preferred width never exceeds the available width
// (including its border insets) of the parent container.
Insets insets = c.getParent().getInsets();
Dimension size = c.getParent().getSize();
final Insets insets = c.getParent().getInsets();
final Dimension size = c.getParent().getSize();
if (size.width > 0) {
// If width isn't set component shouldn't adjust.
d.width = size.width - insets.left - insets.right;
}
}
updateLayout(label, null, d.width, d.height);
this.updateLayout(label, null, d.width, d.height);
// The preferred height is either the preferred height of the text
// lines, or the height of the icon.
d.height = Math.max(d.height, getPreferredHeight(label));
d.height = Math.max(d.height, this.getPreferredHeight(label));
return d;
}
@@ -418,93 +472,102 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/**
* The preferred height of the label is the height of the lines with added
* top and bottom insets.
*
* @param label the label
*
* @param label
* the label
* @return the preferred height of the wrapped lines.
*/
protected int getPreferredHeight(JLabel label) {
int numOfLines = getTextLines(label).size();
Insets insets = label.getInsets(paintViewInsets);
return numOfLines * metrics.getHeight() + insets.top + insets.bottom;
protected int getPreferredHeight(final JLabel label) {
final int numOfLines = this.getTextLines(label).size();
final Insets insets = label.getInsets(MultiLineLabelUI.paintViewInsets);
return (numOfLines * this.metrics.getHeight()) + insets.top + insets.bottom;
}
/**
* Get the lines of text contained in the text label. The prepared lines is
* cached as a client property, accessible via {@link #PROPERTY_KEY}.
*
* @param l the label
*
* @param l
* the label
* @return the text lines of the label.
*/
@SuppressWarnings("unchecked")
protected List<String> getTextLines(JLabel l) {
List<String> lines = (List<String>) l.getClientProperty(PROPERTY_KEY);
protected List<String> getTextLines(final JLabel l) {
List<String> lines = (List<String>) l.getClientProperty(MultiLineLabelUI.PROPERTY_KEY);
if (lines == null) {
lines = prepareLines(l);
l.putClientProperty(PROPERTY_KEY, lines);
lines = this.prepareLines(l);
l.putClientProperty(MultiLineLabelUI.PROPERTY_KEY, lines);
}
return lines;
}
/** {@inheritDoc} */
public void componentHidden(ComponentEvent e) {
@Override
public void componentHidden(final ComponentEvent e) {
// Don't care
}
/** {@inheritDoc} */
public void componentMoved(ComponentEvent e) {
@Override
public void componentMoved(final ComponentEvent e) {
// Don't care
}
/** {@inheritDoc} */
public void componentResized(ComponentEvent e) {
clearCache((JLabel) e.getSource());
@Override
public void componentResized(final ComponentEvent e) {
this.clearCache((JLabel) e.getSource());
}
/** {@inheritDoc} */
public void componentShown(ComponentEvent e) {
@Override
public void componentShown(final ComponentEvent e) {
// Don't care
}
/**
* Prepare the text lines for rendering. The lines are wrapped to fit in the
* current available space for text. Explicit line breaks are preserved.
*
* @param l the label to render
*
* @param l
* the label to render
* @return a list of text lines to render
*/
protected List<String> prepareLines(JLabel l) {
List<String> lines = new ArrayList<String>(defaultSize);
String text = l.getText();
protected List<String> prepareLines(final JLabel l) {
final List<String> lines = new ArrayList<String>(MultiLineLabelUI.defaultSize);
final String text = l.getText();
if (text == null) {
return null; // Null guard
}
PlainDocument doc = new PlainDocument();
final PlainDocument doc = new PlainDocument();
try {
doc.insertString(0, text, null);
} catch (BadLocationException e) {
} catch (final BadLocationException e) {
return null;
}
Element root = doc.getDefaultRootElement();
final Element root = doc.getDefaultRootElement();
for (int i = 0, j = root.getElementCount(); i < j; i++) {
wrap(lines, root.getElement(i));
this.wrap(lines, root.getElement(i));
}
return lines;
}
/**
* If necessary, wrap the text into multiple lines.
*
* @param lines line array in which to store the wrapped lines
* @param elem the document element containing the text content
*
* @param lines
* line array in which to store the wrapped lines
* @param elem
* the document element containing the text content
*/
protected void wrap(List<String> lines, Element elem) {
int p1 = elem.getEndOffset();
Document doc = elem.getDocument();
for (int p0 = elem.getStartOffset(); p0 < p1; ) {
int p = calculateBreakPosition(doc, p0, p1);
protected void wrap(final List<String> lines, final Element elem) {
final int p1 = elem.getEndOffset();
final Document doc = elem.getDocument();
for (int p0 = elem.getStartOffset(); p0 < p1;) {
final int p = this.calculateBreakPosition(doc, p0, p1);
try {
lines.add(doc.getText(p0, p - p0));
} catch (BadLocationException e) {
} catch (final BadLocationException e) {
throw new Error("Can't get line text. p0=" + p0 + " p=" + p);
}
p0 = (p == p0) ? p1 : p;
@@ -513,32 +576,47 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/**
* Calculate the position on which to break (wrap) the line.
*
* @param doc the document
* @param p0 start position
* @param p1 end position
*
* @param doc
* the document
* @param p0
* start position
* @param p1
* end position
* @return the actual end position, will be <code>p1</code> if content does
* not need to wrap, otherwise it will be less than <code>p1</code>.
*/
protected int calculateBreakPosition(Document doc, int p0, int p1) {
Segment segment = SegmentCache.getSegment();
protected int calculateBreakPosition(final Document doc, final int p0, final int p1) {
final Segment segment = SegmentCache.getSegment();
try {
doc.getText(p0, p1 - p0, segment);
} catch (BadLocationException e) {
} catch (final BadLocationException e) {
throw new Error("Can't get line text");
}
int width = paintTextR.width;
int p = p0
+ Utilities.getBreakLocation(segment, metrics, 0, width, null,
p0);
final int width = MultiLineLabelUI.paintTextR.width;
final int p = p0 + Utilities.getBreakLocation(segment, this.metrics, 0, width, null, p0);
SegmentCache.releaseSegment(segment);
return p;
}
/**
* @return the labelUI
*/
public static LabelUI getLabelUI() {
return labelUI;
}
/**
* @param labelUI the labelUI to set
*/
public static void setLabelUI(LabelUI labelUI) {
MultiLineLabelUI.labelUI = labelUI; // TODO: Add 0 to parameter's name.
}
/**
* Static singleton {@link Segment} cache.
*
*
* @author Samuel Sjoberg
* @see javax.swing.text.SegmentCache
*/
@@ -547,7 +625,7 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/**
* Reused segments.
*/
private ArrayList<Segment> segments = new ArrayList<Segment>(2);
private final ArrayList<Segment> segments = new ArrayList<Segment>(2);
/**
* Singleton instance.
@@ -563,13 +641,13 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/**
* Returns a <code>Segment</code>. When done, the <code>Segment</code>
* should be recycled by invoking {@link #releaseSegment(Segment)}.
*
*
* @return a <code>Segment</code>.
*/
public static Segment getSegment() {
int size = cache.segments.size();
final int size = SegmentCache.cache.segments.size();
if (size > 0) {
return cache.segments.remove(size - 1);
return SegmentCache.cache.segments.remove(size - 1);
}
return new Segment();
}
@@ -578,11 +656,13 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
* Releases a <code>Segment</code>. A segment should not be used after
* it is released, and a segment should never be released more than
* once.
*
* @param segment the segment
*/
public static void releaseSegment(Segment segment) {
public static void releaseSegment(final Segment segment) {
segment.array = null;
segment.count = 0;
cache.segments.add(segment);
SegmentCache.cache.segments.add(segment);
}
}
}

View File

@@ -4,6 +4,7 @@ import javax.swing.JDialog;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
import net.slightlymagic.braids.util.UtilFunctions;
import net.slightlymagic.braids.util.progress_monitor.BaseProgressMonitor;
@@ -13,7 +14,7 @@ import forge.Gui_ProgressBarWindow;
* GUI Progress Monitor that displays the ETA (Estimated Time of Arrival or
* completion) on some platforms and supports one or multiple phases of
* progress.
*
*
* In this implementation, each phase opens a new dialog.
*/
public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor {
@@ -22,54 +23,65 @@ public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor {
private transient String title;
/**
* Convenience for
* MultiPhaseProgressMonitorWithETA(title, numPhases, totalUnitsFirstPhase,
* minUIUpdateIntervalSec, null).
* Convenience for MultiPhaseProgressMonitorWithETA(title, numPhases,
* totalUnitsFirstPhase, minUIUpdateIntervalSec, null).
*
* @param neoTitle the title to give the dialog box(es)
* @param numPhases the total number of phases to expect
* @param totalUnitsFirstPhase the total number of units that will be processed in the first
* phase
* @param minUIUpdateIntervalSec the approximate interval at which to update the dialog box in
* seconds
* @see #MultiPhaseProgressMonitorWithETA(String,int,long,float,float[])
*
* @param neoTitle the title to give the dialog box(es)
*
* @param numPhases the total number of phases to expect
*
* @param totalUnitsFirstPhase the total number of units that will be
* processed in the first phase
*
* @param minUIUpdateIntervalSec the approximate interval at which to
* update the dialog box in seconds
*/
public MultiPhaseProgressMonitorWithETA(final String neoTitle, final int numPhases,
final long totalUnitsFirstPhase, final float minUIUpdateIntervalSec) // NOPMD by Braids on 8/18/11 11:16 PM
final long totalUnitsFirstPhase, final float minUIUpdateIntervalSec) // NOPMD
// by
// Braids
// on
// 8/18/11
// 11:16
// PM
{
this(neoTitle, numPhases, totalUnitsFirstPhase, minUIUpdateIntervalSec, null);
}
/**
* Create a GUI progress monitor and open its first dialog.
*
*
* Like all swing components, this constructor must be invoked from the
* swing Event Dispatching Thread. The rest of the methods of this class
* are exempt from this requirement.
*
* @param neoTitle the title to give the dialog box(es)
*
* @param numPhases the total number of phases to expect
*
* @param totalUnitsFirstPhase the total number of units that will be
* processed in the first phase
*
* @param minUIUpdateIntervalSec the approximate interval at which to
* update the dialog box in seconds
*
* @param phaseWeights see BaseProgressMonitor
*
* swing Event Dispatching Thread. The rest of the methods of this class are
* exempt from this requirement.
*
* @param neoTitle
* the title to give the dialog box(es)
*
* @param numPhases
* the total number of phases to expect
*
* @param totalUnitsFirstPhase
* the total number of units that will be processed in the first
* phase
*
* @param minUIUpdateIntervalSec
* the approximate interval at which to update the dialog box in
* seconds
*
* @param phaseWeights
* see BaseProgressMonitor
*
* @see BaseProgressMonitor#BaseProgressMonitor(int,long,float,float[])
*/
public MultiPhaseProgressMonitorWithETA(final String neoTitle, final int numPhases,
final long totalUnitsFirstPhase, final float minUIUpdateIntervalSec, // NOPMD by Braids on 8/18/11 11:16 PM
final float[] phaseWeights)
{
super(numPhases, totalUnitsFirstPhase, minUIUpdateIntervalSec,
phaseWeights);
final long totalUnitsFirstPhase, final float minUIUpdateIntervalSec, // NOPMD
// by
// Braids
// on
// 8/18/11
// 11:16
// PM
final float[] phaseWeights) {
super(numPhases, totalUnitsFirstPhase, minUIUpdateIntervalSec, phaseWeights);
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from within an event dispatch thread");
@@ -77,80 +89,105 @@ public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor {
this.title = neoTitle;
if (totalUnitsFirstPhase > 0 && dialog == null) {
if ((totalUnitsFirstPhase > 0) && (this.dialog == null)) {
throw new IllegalStateException("dialog is null");
}
}
/**
* For developer testing.
*
* @param args ignored
*
* @param args
* ignored
*/
public static void main(final String[] args) {
System.out.println("Initializing..."); // NOPMD by Braids on 8/18/11 11:13 PM
System.out.println("Initializing..."); // NOPMD by Braids on 8/18/11
// 11:13 PM
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on 8/18/11 11:16 PM
public void run() {
final int totalUnitsFirstPhase = 5000; // NOPMD by Braids on 8/18/11 11:16 PM
final MultiPhaseProgressMonitorWithETA monitor =
new MultiPhaseProgressMonitorWithETA("Testing 2 phases", 2, totalUnitsFirstPhase, 1.0f,
new float[] {2, 1});
final SwingWorker<Object, Object> worker = new SwingWorker<Object, Object>() {
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on
// 8/18/11 11:16 PM
@Override
public Object doInBackground() {
public void run() {
System.out.println("Running..."); // NOPMD by Braids on 8/18/11 11:14 PM
final int totalUnitsFirstPhase = 5000; // NOPMD by
// Braids on
// 8/18/11 11:16
// PM
final MultiPhaseProgressMonitorWithETA monitor = new MultiPhaseProgressMonitorWithETA(
"Testing 2 phases", 2, totalUnitsFirstPhase, 1.0f, new float[] { 2, 1 });
for (int i = 0; i <= totalUnitsFirstPhase; i++) {
monitor.incrementUnitsCompletedThisPhase(1);
final SwingWorker<Object, Object> worker = new SwingWorker<Object, Object>() {
@Override
public Object doInBackground() {
System.out.print("\ri = " + i); // NOPMD by Braids on 8/18/11 11:14 PM
System.out.println("Running..."); // NOPMD by
// Braids on
// 8/18/11
// 11:14 PM
try {
Thread.sleep(1);
} catch (InterruptedException ignored) {
// blank
for (int i = 0; i <= totalUnitsFirstPhase; i++) {
monitor.incrementUnitsCompletedThisPhase(1);
System.out.print("\ri = " + i); // NOPMD by
// Braids on
// 8/18/11
// 11:14 PM
try {
Thread.sleep(1);
} catch (final InterruptedException ignored) {
// blank
}
}
System.out.println(); // NOPMD by Braids on
// 8/18/11 11:14 PM
final int totalUnitsSecondPhase = 2000; // NOPMD
// by
// Braids
// on
// 8/18/11
// 11:17
// PM
monitor.markCurrentPhaseAsComplete(totalUnitsSecondPhase);
for (int i = 0; i <= totalUnitsSecondPhase; i++) {
monitor.incrementUnitsCompletedThisPhase(1);
System.out.print("\ri = " + i); // NOPMD by
// Braids on
// 8/18/11
// 11:14 PM
try {
Thread.sleep(1);
} catch (final InterruptedException ignored) {
// blank
}
}
monitor.markCurrentPhaseAsComplete(0);
System.out.println(); // NOPMD by Braids on
// 8/18/11 11:14 PM
System.out.println("Done!"); // NOPMD by Braids
// on 8/18/11 11:14
// PM
return null;
}
}
System.out.println(); // NOPMD by Braids on 8/18/11 11:14 PM
final int totalUnitsSecondPhase = 2000; // NOPMD by Braids on 8/18/11 11:17 PM
monitor.markCurrentPhaseAsComplete(totalUnitsSecondPhase);
};
for (int i = 0; i <= totalUnitsSecondPhase; i++) {
monitor.incrementUnitsCompletedThisPhase(1);
System.out.print("\ri = " + i); // NOPMD by Braids on 8/18/11 11:14 PM
try {
Thread.sleep(1);
} catch (InterruptedException ignored) {
// blank
}
}
monitor.markCurrentPhaseAsComplete(0);
System.out.println(); // NOPMD by Braids on 8/18/11 11:14 PM
System.out.println("Done!"); // NOPMD by Braids on 8/18/11 11:14 PM
return null;
worker.execute();
}
};
worker.execute();
}
});
});
}
/* (non-Javadoc)
* @see net.slightlymagic.braids.util.progress_monitor.BaseProgressMonitor#setTotalUnitsThisPhase(long)
*/
@Override
/**
* @param numUnits cannot be higher than Integer.MAX_VALUE
@@ -166,38 +203,52 @@ public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor {
if (numUnits > 0) {
// dialog must exist before we exit this method.
UtilFunctions.invokeInEventDispatchThreadAndWait(new Runnable() { // NOPMD by Braids on 8/18/11 11:17 PM
public void run() {
// (Re)create the progress bar.
if (dialog != null) {
dialog.dispose();
dialog = null;
}
UtilFunctions.invokeInEventDispatchThreadAndWait(new Runnable() { // NOPMD
// by
// Braids
// on
// 8/18/11
// 11:17
// PM
@Override
public void run() {
// (Re)create the progress bar.
if (MultiPhaseProgressMonitorWithETA.this.dialog != null) {
MultiPhaseProgressMonitorWithETA.this.dialog.dispose();
MultiPhaseProgressMonitorWithETA.this.dialog = null;
}
dialog = new Gui_ProgressBarWindow();
}
});
MultiPhaseProgressMonitorWithETA.this.dialog = new Gui_ProgressBarWindow();
}
});
}
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on 8/18/11 11:18 PM
public void run() {
dialog.setTitle(title);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
dialog.setResizable(true);
dialog.getProgressBar().setIndeterminate(false);
dialog.setProgressRange(0, (int) numUnits);
dialog.reset();
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on
// 8/18/11 11:18 PM
@Override
public void run() {
MultiPhaseProgressMonitorWithETA.this.dialog
.setTitle(MultiPhaseProgressMonitorWithETA.this.title);
MultiPhaseProgressMonitorWithETA.this.dialog
.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
MultiPhaseProgressMonitorWithETA.this.dialog.setVisible(true);
MultiPhaseProgressMonitorWithETA.this.dialog.setResizable(true);
MultiPhaseProgressMonitorWithETA.this.dialog.getProgressBar().setIndeterminate(false);
MultiPhaseProgressMonitorWithETA.this.dialog.setProgressRange(0, (int) numUnits);
MultiPhaseProgressMonitorWithETA.this.dialog.reset();
final JProgressBar bar = dialog.getProgressBar();
bar.setString("");
bar.setStringPainted(true);
bar.setValue(0);
}
});
final JProgressBar bar = MultiPhaseProgressMonitorWithETA.this.dialog.getProgressBar();
bar.setString("");
bar.setStringPainted(true);
bar.setValue(0);
}
});
}
/* (non-Javadoc)
* @see net.slightlymagic.braids.util.progress_monitor.BaseProgressMonitor#incrementUnitsCompletedThisPhase(long)
*/
@Override
/**
* @see net.slightlymagic.braids.util.progress_monitor.ProgressMonitor#incrementUnitsCompletedThisPhase(long)
@@ -205,86 +256,92 @@ public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor {
public final void incrementUnitsCompletedThisPhase(final long numUnits) {
super.incrementUnitsCompletedThisPhase(numUnits);
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on 8/18/11 11:18 PM
public void run() {
for (int i = 0; i < numUnits; i++) {
dialog.increment();
}
}
});
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on
// 8/18/11 11:18 PM
@Override
public void run() {
for (int i = 0; i < numUnits; i++) {
MultiPhaseProgressMonitorWithETA.this.dialog.increment();
}
}
});
if (shouldUpdateUI()) {
if (this.shouldUpdateUI()) {
if ((getNumPhases() > 1)) {
displayUpdate(
"Phase " + getCurrentPhase() + ". "
//+ getUnitsCompletedSoFarThisPhase() + " units processed. "
//+ "Overall: " + getTotalPercentCompleteAsString() + "% complete, "
+ "Overall ETA in " + getRelativeETAAsString() + "."
);
}
else {
displayUpdate(
//"Overall: " +
getUnitsCompletedSoFarThisPhase() + " units processed; "
//+ "(" + getTotalPercentCompleteAsString() + "%); "
+ "ETA in " + getRelativeETAAsString() + "."
);
if ((this.getNumPhases() > 1)) {
this.displayUpdate("Phase " + this.getCurrentPhase() + ". "
// + getUnitsCompletedSoFarThisPhase() + " units processed. "
// + "Overall: " + getTotalPercentCompleteAsString() +
// "% complete, "
+ "Overall ETA in " + this.getRelativeETAAsString() + ".");
} else {
this.displayUpdate(
// "Overall: " +
this.getUnitsCompletedSoFarThisPhase() + " units processed; "
// + "(" + getTotalPercentCompleteAsString() + "%); "
+ "ETA in " + this.getRelativeETAAsString() + ".");
}
}
if (getCurrentPhase() == getNumPhases()
&& getUnitsCompletedSoFarThisPhase() >= getTotalUnitsThisPhase())
{
displayUpdate("Done!");
if ((this.getCurrentPhase() == this.getNumPhases())
&& (this.getUnitsCompletedSoFarThisPhase() >= this.getTotalUnitsThisPhase())) {
this.displayUpdate("Done!");
}
}
}
/**
* Shows the message inside the progress dialog; does not always work on
* all platforms.
*
* @param message the message to display
* Shows the message inside the progress dialog; does not always work on all
* platforms.
*
* @param message
* the message to display
*/
public final void displayUpdate(final String message) {
final Runnable proc = new Runnable() { // NOPMD by Braids on 8/18/11 11:18 PM
final Runnable proc = new Runnable() { // NOPMD by Braids on 8/18/11
// 11:18 PM
@Override
public void run() {
// i've been having trouble getting the dialog to display its title.
dialog.setTitle(title);
// i've been having trouble getting the dialog to display its
// title.
MultiPhaseProgressMonitorWithETA.this.dialog.setTitle(MultiPhaseProgressMonitorWithETA.this.title);
JProgressBar bar = dialog.getProgressBar();
final JProgressBar bar = MultiPhaseProgressMonitorWithETA.this.dialog.getProgressBar();
bar.setString(message);
justUpdatedUI();
MultiPhaseProgressMonitorWithETA.this.justUpdatedUI();
}
};
if (SwingUtilities.isEventDispatchThread()) {
proc.run();
}
else {
} else {
SwingUtilities.invokeLater(proc);
}
}
/* (non-Javadoc)
* @see net.slightlymagic.braids.util.progress_monitor.BaseProgressMonitor#dispose()
*/
@Override
public final void dispose() {
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on 8/18/11 11:18 PM
public void run() {
getDialog().dispose();
}
});
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on
// 8/18/11 11:18 PM
@Override
public void run() {
MultiPhaseProgressMonitorWithETA.this.getDialog().dispose();
}
});
}
/**
* Gets the dialog.
*
* @return the JDialog for the current phase; use this judiciously to
* manipulate the dialog directly.
*/
public final JDialog getDialog() {
return dialog;
return this.dialog;
}
}

View File

@@ -1,2 +1,3 @@
/** Forge Card Game */
/** Forge Card Game. */
package forge.gui;

View File

@@ -935,7 +935,7 @@ public class Gui_HomeScreen {
for (int i = 0; i < Constant.Color.BASIC_LANDS.length; i++) {
for (int j = 0; j < 18; j++) {
deck.addSideboard(Constant.Color.BASIC_LANDS[i] + "|" + sd.LandSetCode[0]);
deck.addSideboard(Constant.Color.BASIC_LANDS[i] + "|" + sd.getLandSetCode()[0]);
}
}

View File

@@ -391,7 +391,7 @@ public class OldGuiNewGame extends JFrame implements NewConstants, NewConstants.
for (int i = 0; i < Constant.Color.BASIC_LANDS.length; i++) {
for (int j = 0; j < 18; j++) {
deck.addSideboard(Constant.Color.BASIC_LANDS[i] + "|" + sd.LandSetCode[0]);
deck.addSideboard(Constant.Color.BASIC_LANDS[i] + "|" + sd.getLandSetCode()[0]);
}
}