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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -23,12 +23,11 @@
*/ */
package forge.gui; package forge.gui;
import javax.swing.*; import java.awt.Dimension;
import javax.swing.plaf.ComponentUI; import java.awt.FontMetrics;
import javax.swing.plaf.LabelUI; import java.awt.Graphics;
import javax.swing.plaf.basic.BasicLabelUI; import java.awt.Insets;
import javax.swing.text.*; import java.awt.Rectangle;
import java.awt.*;
import java.awt.event.ComponentEvent; import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener; import java.awt.event.ComponentListener;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
@@ -36,6 +35,20 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; 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 * Label UI delegate that supports multiple lines and line wrapping. Hard line
@@ -49,6 +62,7 @@ import java.util.List;
* <p/> * <p/>
* Example of usage: * Example of usage:
* <p/> * <p/>
*
* <pre> * <pre>
* JLabel myLabel = new JLabel(); * JLabel myLabel = new JLabel();
* myLabel.setUI(MultiLineLabelUI.labelUI); * myLabel.setUI(MultiLineLabelUI.labelUI);
@@ -61,7 +75,7 @@ import java.util.List;
* by overriding {@link #paintEnabledText(JLabel, Graphics, String, int, int)} * by overriding {@link #paintEnabledText(JLabel, Graphics, String, int, int)}
* and {@link #paintDisabledText(JLabel, Graphics, String, int, int)}. This * and {@link #paintDisabledText(JLabel, Graphics, String, int, int)}. This
* class is designed to be easily extended by subclasses. * class is designed to be easily extended by subclasses.
* *
* @author Samuel Sjoberg, http://samuelsjoberg.com * @author Samuel Sjoberg, http://samuelsjoberg.com
* @version 1.3.0 * @version 1.3.0
*/ */
@@ -70,7 +84,7 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/** /**
* Shared instance of the UI delegate. * 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 * 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"; public static final String PROPERTY_KEY = "WrappedText";
// Static references to avoid heap allocations. // Static references to avoid heap allocations.
/** Constant <code>paintIconR</code> */ /** Constant <code>paintIconR</code>. */
protected static Rectangle paintIconR = new Rectangle(); private static Rectangle paintIconR = new Rectangle();
/** Constant <code>paintTextR</code> */
protected static Rectangle paintTextR = new Rectangle(); /** Constant <code>paintTextR</code>. */
/** Constant <code>paintViewR</code> */ private static Rectangle paintTextR = new Rectangle();
protected static Rectangle paintViewR = new Rectangle();
/** Constant <code>paintViewInsets</code> */ /** Constant <code>paintViewR</code>. */
protected static Insets paintViewInsets = new Insets(0, 0, 0, 0); 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. * Font metrics of the JLabel being rendered.
*/ */
protected FontMetrics metrics; private FontMetrics metrics;
/** /**
* Default size of the lines list. * Default size of the lines list.
*/ */
protected static int defaultSize = 4; private static int defaultSize = 4;
/** /**
* Get the shared UI instance. * Get the shared UI instance.
* @param c *
* @param c the c
* @return a ComponentUI * @return a ComponentUI
*/ */
public static ComponentUI createUI(JComponent c) { public static ComponentUI createUI(final JComponent c) {
return labelUI; return MultiLineLabelUI.getLabelUI();
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
protected void uninstallDefaults(JLabel c) { @Override
protected void uninstallDefaults(final JLabel c) {
super.uninstallDefaults(c); super.uninstallDefaults(c);
clearCache(c); this.clearCache(c);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
protected void installListeners(JLabel c) { @Override
protected void installListeners(final JLabel c) {
super.installListeners(c); super.installListeners(c);
c.addComponentListener(this); c.addComponentListener(this);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
protected void uninstallListeners(JLabel c) { @Override
protected void uninstallListeners(final JLabel c) {
super.uninstallListeners(c); super.uninstallListeners(c);
c.removeComponentListener(this); c.removeComponentListener(this);
} }
/** /**
* Clear the wrapped line cache. * 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) { protected void clearCache(final JLabel l) {
l.putClientProperty(PROPERTY_KEY, null); l.putClientProperty(MultiLineLabelUI.PROPERTY_KEY, null);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public void propertyChange(PropertyChangeEvent e) { @Override
public void propertyChange(final PropertyChangeEvent e) {
super.propertyChange(e); super.propertyChange(e);
final String name = e.getPropertyName(); final String name = e.getPropertyName();
if (name.equals("text") || "font".equals(name)) { 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 * Calculate the paint rectangles for the icon and text for the passed
* label. * label.
* *
* @param l a label * @param l
* @param fm the font metrics to use, or <code>null</code> to get the font * a label
* metrics from the label * @param fm
* @param width label width * the font metrics to use, or <code>null</code> to get the font
* @param height label height * 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) { if (fm == null) {
fm = l.getFontMetrics(l.getFont()); fm = l.getFontMetrics(l.getFont());
} }
metrics = fm; this.metrics = fm;
String text = l.getText(); final String text = l.getText();
Icon icon = l.getIcon(); final Icon icon = l.getIcon();
Insets insets = l.getInsets(paintViewInsets); final Insets insets = l.getInsets(MultiLineLabelUI.paintViewInsets);
paintViewR.x = insets.left; MultiLineLabelUI.paintViewR.x = insets.left;
paintViewR.y = insets.top; MultiLineLabelUI.paintViewR.y = insets.top;
paintViewR.width = width - (insets.left + insets.right); MultiLineLabelUI.paintViewR.width = width - (insets.left + insets.right);
paintViewR.height = height - (insets.top + insets.bottom); MultiLineLabelUI.paintViewR.height = height - (insets.top + insets.bottom);
paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0; MultiLineLabelUI.paintIconR.x = 0;
paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 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> * <p>
* * prepareGraphics.
* @param g a {@link java.awt.Graphics} object. * </p>
*
* @param g
* a {@link java.awt.Graphics} object.
*/ */
protected void prepareGraphics(Graphics g) { protected void prepareGraphics(final Graphics g) {
} }
/** {@inheritDoc} */ /** {@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 // parent's update method fills the background
prepareGraphics(g); this.prepareGraphics(g);
JLabel label = (JLabel) c; final JLabel label = (JLabel) c;
String text = label.getText(); final String text = label.getText();
Icon icon = (label.isEnabled()) ? label.getIcon() : label final Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();
.getDisabledIcon();
if ((icon == null) && (text == null)) { if ((icon == null) && (text == null)) {
return; 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) { if (icon != null) {
icon.paintIcon(c, g, paintIconR.x, paintIconR.y); icon.paintIcon(c, g, MultiLineLabelUI.paintIconR.x, MultiLineLabelUI.paintIconR.y);
} }
if (text != null) { if (text != null) {
View v = (View) c.getClientProperty("html"); final View v = (View) c.getClientProperty("html");
if (v != null) { if (v != null) {
// HTML view disables multi-line painting. // HTML view disables multi-line painting.
v.paint(g, paintTextR); v.paint(g, MultiLineLabelUI.paintTextR);
} else { } else {
// Paint the multi line text // Paint the multi line text
paintTextLines(g, label, fm); this.paintTextLines(g, label, fm);
} }
} }
} }
/** /**
* Paint the wrapped text lines. * Paint the wrapped text lines.
* *
* @param g graphics component to paint on * @param g
* @param label the label being painted * graphics component to paint on
* @param fm font metrics for current font * @param label
* the label being painted
* @param fm
* font metrics for current font
*/ */
protected void paintTextLines(Graphics g, JLabel label, FontMetrics fm) { protected void paintTextLines(final Graphics g, final JLabel label, final FontMetrics fm) {
List<String> lines = getTextLines(label); final List<String> lines = this.getTextLines(label);
// Available component height to paint on. // Available component height to paint on.
int height = getAvailableHeight(label); final int height = this.getAvailableHeight(label);
int textHeight = lines.size() * fm.getHeight(); int textHeight = lines.size() * fm.getHeight();
while (textHeight > height) { while (textHeight > height) {
// Remove one line until no. of visible lines is found. // Remove one line until no. of visible lines is found.
textHeight -= fm.getHeight(); textHeight -= fm.getHeight();
} }
paintTextR.height = Math.min(textHeight, height); MultiLineLabelUI.paintTextR.height = Math.min(textHeight, height);
paintTextR.y = alignmentY(label, fm, paintTextR); MultiLineLabelUI.paintTextR.y = this.alignmentY(label, fm, MultiLineLabelUI.paintTextR);
int textX = paintTextR.x; final int textX = MultiLineLabelUI.paintTextR.x;
int textY = paintTextR.y; int textY = MultiLineLabelUI.paintTextR.y;
for (Iterator<String> it = lines.iterator(); it.hasNext() for (final Iterator<String> it = lines.iterator(); it.hasNext()
&& paintTextR.contains(textX, textY + getAscent(fm)); textY += fm && MultiLineLabelUI.paintTextR.contains(textX, textY + MultiLineLabelUI.getAscent(fm)); textY += fm
.getHeight()) { .getHeight()) {
String text = it.next().trim(); String text = it.next().trim();
if (it.hasNext() if (it.hasNext()
&& !paintTextR.contains(textX, textY + fm.getHeight() && !MultiLineLabelUI.paintTextR.contains(textX,
+ getAscent(fm))) { textY + fm.getHeight() + MultiLineLabelUI.getAscent(fm))) {
// The last visible row, add a clip indication. // 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()) { if (label.isEnabled()) {
paintEnabledText(label, g, text, x, textY); this.paintEnabledText(label, g, text, x, textY);
} else { } 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 * Returns the available height to paint text on. This is the height of the
* passed component with insets subtracted. * passed component with insets subtracted.
* *
* @param l a component * @param l
* a component
* @return the available height * @return the available height
*/ */
protected int getAvailableHeight(JLabel l) { protected int getAvailableHeight(final JLabel l) {
l.getInsets(paintViewInsets); l.getInsets(MultiLineLabelUI.paintViewInsets);
return l.getHeight() - paintViewInsets.top - paintViewInsets.bottom; return l.getHeight() - MultiLineLabelUI.paintViewInsets.top - MultiLineLabelUI.paintViewInsets.bottom;
} }
/** /**
* Add a clip indication to the string. It is important that the string * Add a clip indication to the string. It is important that the string
* length does not exceed the length or the original string. * length does not exceed the length or the original string.
* *
* @param text the to be painted * @param text
* @param fm font metrics * the to be painted
* @param bounds the text bounds * @param fm
* font metrics
* @param bounds
* the text bounds
* @return the clipped string * @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 // Fast and lazy way to insert a clip indication is to simply replace
// the last characters in the string with the clip indication. // the last characters in the string with the clip indication.
// A better way would be to use metrics and calculate how many (if any) // 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 * Establish the vertical text alignment. The default alignment is to center
* the text in the label. * the text in the label.
* *
* @param label the label to paint * @param label
* @param fm font metrics * the label to paint
* @param bounds the text bounds rectangle * @param fm
* font metrics
* @param bounds
* the text bounds rectangle
* @return the vertical text alignment, defaults to CENTER. * @return the vertical text alignment, defaults to CENTER.
*/ */
protected int alignmentY(JLabel label, FontMetrics fm, Rectangle bounds) { protected int alignmentY(final JLabel label, final FontMetrics fm, final Rectangle bounds) {
final int height = getAvailableHeight(label); final int height = this.getAvailableHeight(label);
int textHeight = bounds.height; final int textHeight = bounds.height;
if (label instanceof MultiLineLabel) { if (label instanceof MultiLineLabel) {
int align = ((MultiLineLabel) label).getVerticalTextAlignment(); final int align = ((MultiLineLabel) label).getVerticalTextAlignment();
switch (align) { switch (align) {
case JLabel.TOP: case SwingConstants.TOP:
return getAscent(fm) + paintViewInsets.top; return MultiLineLabelUI.getAscent(fm) + MultiLineLabelUI.paintViewInsets.top;
case JLabel.BOTTOM: case SwingConstants.BOTTOM:
return getAscent(fm) + height - paintViewInsets.top return (((MultiLineLabelUI.getAscent(fm) + height) - MultiLineLabelUI.paintViewInsets.top) + MultiLineLabelUI.paintViewInsets.bottom)
+ paintViewInsets.bottom - textHeight; - textHeight;
default: default:
} }
} }
// Center alignment // Center alignment
int textY = paintViewInsets.top + (height - textHeight) / 2 final int textY = MultiLineLabelUI.paintViewInsets.top + ((height - textHeight) / 2)
+ getAscent(fm); + MultiLineLabelUI.getAscent(fm);
return Math.max(textY, getAscent(fm) + paintViewInsets.top); return Math.max(textY, MultiLineLabelUI.getAscent(fm) + MultiLineLabelUI.paintViewInsets.top);
} }
/** /**
* <p>getAscent.</p> * <p>
* * getAscent.
* @param fm a {@link java.awt.FontMetrics} object. * </p>
*
* @param fm
* a {@link java.awt.FontMetrics} object.
* @return a int. * @return a int.
*/ */
private static int getAscent(FontMetrics fm) { private static int getAscent(final FontMetrics fm) {
return fm.getAscent() + fm.getLeading(); return fm.getAscent() + fm.getLeading();
} }
/** /**
* Establish the horizontal text alignment. The default alignment is left * Establish the horizontal text alignment. The default alignment is left
* aligned text. * aligned text.
* *
* @param label the label to paint * @param label
* @param fm font metrics * the label to paint
* @param s the string to paint * @param fm
* @param bounds the text bounds rectangle * 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 * @return the x-coordinate to use when painting for proper alignment
*/ */
protected int alignmentX(JLabel label, FontMetrics fm, String s, protected int alignmentX(final JLabel label, final FontMetrics fm, final String s, final Rectangle bounds) {
Rectangle bounds) {
if (label instanceof MultiLineLabel) { if (label instanceof MultiLineLabel) {
int align = ((MultiLineLabel) label).getHorizontalTextAlignment(); final int align = ((MultiLineLabel) label).getHorizontalTextAlignment();
switch (align) { switch (align) {
case JLabel.RIGHT: case SwingConstants.RIGHT:
return bounds.x + paintViewR.width - fm.stringWidth(s); return (bounds.x + MultiLineLabelUI.paintViewR.width) - fm.stringWidth(s);
case JLabel.CENTER: case SwingConstants.CENTER:
return bounds.x + paintViewR.width / 2 - fm.stringWidth(s) / 2; return (bounds.x + (MultiLineLabelUI.paintViewR.width / 2)) - (fm.stringWidth(s) / 2);
default: default:
return bounds.x; return bounds.x;
} }
} }
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 * Check the given string to see if it should be rendered as HTML. Code
* based on implementation found in * based on implementation found in
* <code>BasicHTML.isHTMLString(String)</code> in future JDKs. * <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> * @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 != null) {
if ((s.length() >= 6) && (s.charAt(0) == '<') if ((s.length() >= 6) && (s.charAt(0) == '<') && (s.charAt(5) == '>')) {
&& (s.charAt(5) == '>')) { final String tag = s.substring(1, 5);
String tag = s.substring(1, 5);
return tag.equalsIgnoreCase("html"); return tag.equalsIgnoreCase("html");
} }
} }
@@ -383,11 +436,12 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public Dimension getPreferredSize(JComponent c) { @Override
Dimension d = super.getPreferredSize(c); public Dimension getPreferredSize(final JComponent c) {
JLabel label = (JLabel) 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 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) { if (c.getParent() != null) {
// Ensure that preferred width never exceeds the available width // Ensure that preferred width never exceeds the available width
// (including its border insets) of the parent container. // (including its border insets) of the parent container.
Insets insets = c.getParent().getInsets(); final Insets insets = c.getParent().getInsets();
Dimension size = c.getParent().getSize(); final Dimension size = c.getParent().getSize();
if (size.width > 0) { if (size.width > 0) {
// If width isn't set component shouldn't adjust. // If width isn't set component shouldn't adjust.
d.width = size.width - insets.left - insets.right; 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 // The preferred height is either the preferred height of the text
// lines, or the height of the icon. // 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; 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 * The preferred height of the label is the height of the lines with added
* top and bottom insets. * top and bottom insets.
* *
* @param label the label * @param label
* the label
* @return the preferred height of the wrapped lines. * @return the preferred height of the wrapped lines.
*/ */
protected int getPreferredHeight(JLabel label) { protected int getPreferredHeight(final JLabel label) {
int numOfLines = getTextLines(label).size(); final int numOfLines = this.getTextLines(label).size();
Insets insets = label.getInsets(paintViewInsets); final Insets insets = label.getInsets(MultiLineLabelUI.paintViewInsets);
return numOfLines * metrics.getHeight() + insets.top + insets.bottom; return (numOfLines * this.metrics.getHeight()) + insets.top + insets.bottom;
} }
/** /**
* Get the lines of text contained in the text label. The prepared lines is * Get the lines of text contained in the text label. The prepared lines is
* cached as a client property, accessible via {@link #PROPERTY_KEY}. * 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. * @return the text lines of the label.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected List<String> getTextLines(JLabel l) { protected List<String> getTextLines(final JLabel l) {
List<String> lines = (List<String>) l.getClientProperty(PROPERTY_KEY); List<String> lines = (List<String>) l.getClientProperty(MultiLineLabelUI.PROPERTY_KEY);
if (lines == null) { if (lines == null) {
lines = prepareLines(l); lines = this.prepareLines(l);
l.putClientProperty(PROPERTY_KEY, lines); l.putClientProperty(MultiLineLabelUI.PROPERTY_KEY, lines);
} }
return lines; return lines;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public void componentHidden(ComponentEvent e) { @Override
public void componentHidden(final ComponentEvent e) {
// Don't care // Don't care
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public void componentMoved(ComponentEvent e) { @Override
public void componentMoved(final ComponentEvent e) {
// Don't care // Don't care
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public void componentResized(ComponentEvent e) { @Override
clearCache((JLabel) e.getSource()); public void componentResized(final ComponentEvent e) {
this.clearCache((JLabel) e.getSource());
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
public void componentShown(ComponentEvent e) { @Override
public void componentShown(final ComponentEvent e) {
// Don't care // Don't care
} }
/** /**
* Prepare the text lines for rendering. The lines are wrapped to fit in the * Prepare the text lines for rendering. The lines are wrapped to fit in the
* current available space for text. Explicit line breaks are preserved. * 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 * @return a list of text lines to render
*/ */
protected List<String> prepareLines(JLabel l) { protected List<String> prepareLines(final JLabel l) {
List<String> lines = new ArrayList<String>(defaultSize); final List<String> lines = new ArrayList<String>(MultiLineLabelUI.defaultSize);
String text = l.getText(); final String text = l.getText();
if (text == null) { if (text == null) {
return null; // Null guard return null; // Null guard
} }
PlainDocument doc = new PlainDocument(); final PlainDocument doc = new PlainDocument();
try { try {
doc.insertString(0, text, null); doc.insertString(0, text, null);
} catch (BadLocationException e) { } catch (final BadLocationException e) {
return null; return null;
} }
Element root = doc.getDefaultRootElement(); final Element root = doc.getDefaultRootElement();
for (int i = 0, j = root.getElementCount(); i < j; i++) { for (int i = 0, j = root.getElementCount(); i < j; i++) {
wrap(lines, root.getElement(i)); this.wrap(lines, root.getElement(i));
} }
return lines; return lines;
} }
/** /**
* If necessary, wrap the text into multiple lines. * If necessary, wrap the text into multiple lines.
* *
* @param lines line array in which to store the wrapped lines * @param lines
* @param elem the document element containing the text content * 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) { protected void wrap(final List<String> lines, final Element elem) {
int p1 = elem.getEndOffset(); final int p1 = elem.getEndOffset();
Document doc = elem.getDocument(); final Document doc = elem.getDocument();
for (int p0 = elem.getStartOffset(); p0 < p1; ) { for (int p0 = elem.getStartOffset(); p0 < p1;) {
int p = calculateBreakPosition(doc, p0, p1); final int p = this.calculateBreakPosition(doc, p0, p1);
try { try {
lines.add(doc.getText(p0, p - p0)); 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); throw new Error("Can't get line text. p0=" + p0 + " p=" + p);
} }
p0 = (p == p0) ? p1 : 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. * Calculate the position on which to break (wrap) the line.
* *
* @param doc the document * @param doc
* @param p0 start position * the document
* @param p1 end position * @param p0
* start position
* @param p1
* end position
* @return the actual end position, will be <code>p1</code> if content does * @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>. * not need to wrap, otherwise it will be less than <code>p1</code>.
*/ */
protected int calculateBreakPosition(Document doc, int p0, int p1) { protected int calculateBreakPosition(final Document doc, final int p0, final int p1) {
Segment segment = SegmentCache.getSegment(); final Segment segment = SegmentCache.getSegment();
try { try {
doc.getText(p0, p1 - p0, segment); doc.getText(p0, p1 - p0, segment);
} catch (BadLocationException e) { } catch (final BadLocationException e) {
throw new Error("Can't get line text"); throw new Error("Can't get line text");
} }
int width = paintTextR.width; final int width = MultiLineLabelUI.paintTextR.width;
int p = p0 final int p = p0 + Utilities.getBreakLocation(segment, this.metrics, 0, width, null, p0);
+ Utilities.getBreakLocation(segment, metrics, 0, width, null,
p0);
SegmentCache.releaseSegment(segment); SegmentCache.releaseSegment(segment);
return p; 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. * Static singleton {@link Segment} cache.
* *
* @author Samuel Sjoberg * @author Samuel Sjoberg
* @see javax.swing.text.SegmentCache * @see javax.swing.text.SegmentCache
*/ */
@@ -547,7 +625,7 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/** /**
* Reused segments. * Reused segments.
*/ */
private ArrayList<Segment> segments = new ArrayList<Segment>(2); private final ArrayList<Segment> segments = new ArrayList<Segment>(2);
/** /**
* Singleton instance. * Singleton instance.
@@ -563,13 +641,13 @@ public class MultiLineLabelUI extends BasicLabelUI implements ComponentListener
/** /**
* Returns a <code>Segment</code>. When done, the <code>Segment</code> * Returns a <code>Segment</code>. When done, the <code>Segment</code>
* should be recycled by invoking {@link #releaseSegment(Segment)}. * should be recycled by invoking {@link #releaseSegment(Segment)}.
* *
* @return a <code>Segment</code>. * @return a <code>Segment</code>.
*/ */
public static Segment getSegment() { public static Segment getSegment() {
int size = cache.segments.size(); final int size = SegmentCache.cache.segments.size();
if (size > 0) { if (size > 0) {
return cache.segments.remove(size - 1); return SegmentCache.cache.segments.remove(size - 1);
} }
return new Segment(); 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 * Releases a <code>Segment</code>. A segment should not be used after
* it is released, and a segment should never be released more than * it is released, and a segment should never be released more than
* once. * once.
*
* @param segment the segment
*/ */
public static void releaseSegment(Segment segment) { public static void releaseSegment(final Segment segment) {
segment.array = null; segment.array = null;
segment.count = 0; 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.JProgressBar;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
import net.slightlymagic.braids.util.UtilFunctions; import net.slightlymagic.braids.util.UtilFunctions;
import net.slightlymagic.braids.util.progress_monitor.BaseProgressMonitor; 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 * GUI Progress Monitor that displays the ETA (Estimated Time of Arrival or
* completion) on some platforms and supports one or multiple phases of * completion) on some platforms and supports one or multiple phases of
* progress. * progress.
* *
* In this implementation, each phase opens a new dialog. * In this implementation, each phase opens a new dialog.
*/ */
public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor { public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor {
@@ -22,54 +23,65 @@ public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor {
private transient String title; private transient String title;
/** /**
* Convenience for * Convenience for MultiPhaseProgressMonitorWithETA(title, numPhases,
* MultiPhaseProgressMonitorWithETA(title, numPhases, totalUnitsFirstPhase, * totalUnitsFirstPhase, minUIUpdateIntervalSec, null).
* 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[]) * @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, 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); this(neoTitle, numPhases, totalUnitsFirstPhase, minUIUpdateIntervalSec, null);
} }
/** /**
* Create a GUI progress monitor and open its first dialog. * Create a GUI progress monitor and open its first dialog.
* *
* Like all swing components, this constructor must be invoked from the * Like all swing components, this constructor must be invoked from the
* swing Event Dispatching Thread. The rest of the methods of this class * swing Event Dispatching Thread. The rest of the methods of this class are
* are exempt from this requirement. * exempt from this requirement.
* *
* @param neoTitle the title to give the dialog box(es) * @param neoTitle
* * the title to give the dialog box(es)
* @param numPhases the total number of phases to expect *
* * @param numPhases
* @param totalUnitsFirstPhase the total number of units that will be * the total number of phases to expect
* processed in the first phase *
* * @param totalUnitsFirstPhase
* @param minUIUpdateIntervalSec the approximate interval at which to * the total number of units that will be processed in the first
* update the dialog box in seconds * phase
* *
* @param phaseWeights see BaseProgressMonitor * @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[]) * @see BaseProgressMonitor#BaseProgressMonitor(int,long,float,float[])
*/ */
public MultiPhaseProgressMonitorWithETA(final String neoTitle, final int numPhases, 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
final float[] phaseWeights) // by
{ // Braids
super(numPhases, totalUnitsFirstPhase, minUIUpdateIntervalSec, // on
phaseWeights); // 8/18/11
// 11:16
// PM
final float[] phaseWeights) {
super(numPhases, totalUnitsFirstPhase, minUIUpdateIntervalSec, phaseWeights);
if (!SwingUtilities.isEventDispatchThread()) { if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from within an event dispatch thread"); throw new IllegalStateException("must be called from within an event dispatch thread");
@@ -77,80 +89,105 @@ public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor {
this.title = neoTitle; this.title = neoTitle;
if (totalUnitsFirstPhase > 0 && dialog == null) { if ((totalUnitsFirstPhase > 0) && (this.dialog == null)) {
throw new IllegalStateException("dialog is null"); throw new IllegalStateException("dialog is null");
} }
} }
/** /**
* For developer testing. * For developer testing.
* *
* @param args ignored * @param args
* ignored
*/ */
public static void main(final String[] args) { 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 SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on
public void run() { // 8/18/11 11:16 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});
final SwingWorker<Object, Object> worker = new SwingWorker<Object, Object>() {
@Override @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++) { final SwingWorker<Object, Object> worker = new SwingWorker<Object, Object>() {
monitor.incrementUnitsCompletedThisPhase(1); @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 { for (int i = 0; i <= totalUnitsFirstPhase; i++) {
Thread.sleep(1); monitor.incrementUnitsCompletedThisPhase(1);
} catch (InterruptedException ignored) {
// blank 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++) { worker.execute();
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();
}
});
} }
/* (non-Javadoc)
* @see net.slightlymagic.braids.util.progress_monitor.BaseProgressMonitor#setTotalUnitsThisPhase(long)
*/
@Override @Override
/** /**
* @param numUnits cannot be higher than Integer.MAX_VALUE * @param numUnits cannot be higher than Integer.MAX_VALUE
@@ -166,38 +203,52 @@ public class MultiPhaseProgressMonitorWithETA extends BaseProgressMonitor {
if (numUnits > 0) { if (numUnits > 0) {
// dialog must exist before we exit this method. // dialog must exist before we exit this method.
UtilFunctions.invokeInEventDispatchThreadAndWait(new Runnable() { // NOPMD by Braids on 8/18/11 11:17 PM UtilFunctions.invokeInEventDispatchThreadAndWait(new Runnable() { // NOPMD
public void run() { // by
// (Re)create the progress bar. // Braids
if (dialog != null) { // on
dialog.dispose(); // 8/18/11
dialog = null; // 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 SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on
public void run() { // 8/18/11 11:18 PM
dialog.setTitle(title); @Override
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); public void run() {
dialog.setVisible(true); MultiPhaseProgressMonitorWithETA.this.dialog
dialog.setResizable(true); .setTitle(MultiPhaseProgressMonitorWithETA.this.title);
dialog.getProgressBar().setIndeterminate(false); MultiPhaseProgressMonitorWithETA.this.dialog
dialog.setProgressRange(0, (int) numUnits); .setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.reset(); 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(); final JProgressBar bar = MultiPhaseProgressMonitorWithETA.this.dialog.getProgressBar();
bar.setString(""); bar.setString("");
bar.setStringPainted(true); bar.setStringPainted(true);
bar.setValue(0); bar.setValue(0);
} }
}); });
} }
/* (non-Javadoc)
* @see net.slightlymagic.braids.util.progress_monitor.BaseProgressMonitor#incrementUnitsCompletedThisPhase(long)
*/
@Override @Override
/** /**
* @see net.slightlymagic.braids.util.progress_monitor.ProgressMonitor#incrementUnitsCompletedThisPhase(long) * @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) { public final void incrementUnitsCompletedThisPhase(final long numUnits) {
super.incrementUnitsCompletedThisPhase(numUnits); super.incrementUnitsCompletedThisPhase(numUnits);
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on 8/18/11 11:18 PM SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on
public void run() { // 8/18/11 11:18 PM
for (int i = 0; i < numUnits; i++) { @Override
dialog.increment(); public void run() {
} for (int i = 0; i < numUnits; i++) {
} MultiPhaseProgressMonitorWithETA.this.dialog.increment();
}); }
}
});
if (shouldUpdateUI()) { if (this.shouldUpdateUI()) {
if ((getNumPhases() > 1)) { if ((this.getNumPhases() > 1)) {
displayUpdate( this.displayUpdate("Phase " + this.getCurrentPhase() + ". "
"Phase " + getCurrentPhase() + ". " // + getUnitsCompletedSoFarThisPhase() + " units processed. "
//+ getUnitsCompletedSoFarThisPhase() + " units processed. " // + "Overall: " + getTotalPercentCompleteAsString() +
//+ "Overall: " + getTotalPercentCompleteAsString() + "% complete, " // "% complete, "
+ "Overall ETA in " + getRelativeETAAsString() + "." + "Overall ETA in " + this.getRelativeETAAsString() + ".");
); } else {
} this.displayUpdate(
else { // "Overall: " +
displayUpdate( this.getUnitsCompletedSoFarThisPhase() + " units processed; "
//"Overall: " + // + "(" + getTotalPercentCompleteAsString() + "%); "
getUnitsCompletedSoFarThisPhase() + " units processed; " + "ETA in " + this.getRelativeETAAsString() + ".");
//+ "(" + getTotalPercentCompleteAsString() + "%); "
+ "ETA in " + getRelativeETAAsString() + "."
);
} }
} }
if (getCurrentPhase() == getNumPhases() if ((this.getCurrentPhase() == this.getNumPhases())
&& getUnitsCompletedSoFarThisPhase() >= getTotalUnitsThisPhase()) && (this.getUnitsCompletedSoFarThisPhase() >= this.getTotalUnitsThisPhase())) {
{ this.displayUpdate("Done!");
displayUpdate("Done!");
} }
} }
/** /**
* Shows the message inside the progress dialog; does not always work on * Shows the message inside the progress dialog; does not always work on all
* all platforms. * platforms.
* *
* @param message the message to display * @param message
* the message to display
*/ */
public final void displayUpdate(final String message) { 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() { public void run() {
// i've been having trouble getting the dialog to display its title. // i've been having trouble getting the dialog to display its
dialog.setTitle(title); // title.
MultiPhaseProgressMonitorWithETA.this.dialog.setTitle(MultiPhaseProgressMonitorWithETA.this.title);
JProgressBar bar = dialog.getProgressBar(); final JProgressBar bar = MultiPhaseProgressMonitorWithETA.this.dialog.getProgressBar();
bar.setString(message); bar.setString(message);
justUpdatedUI(); MultiPhaseProgressMonitorWithETA.this.justUpdatedUI();
} }
}; };
if (SwingUtilities.isEventDispatchThread()) { if (SwingUtilities.isEventDispatchThread()) {
proc.run(); proc.run();
} } else {
else {
SwingUtilities.invokeLater(proc); SwingUtilities.invokeLater(proc);
} }
} }
/* (non-Javadoc)
* @see net.slightlymagic.braids.util.progress_monitor.BaseProgressMonitor#dispose()
*/
@Override @Override
public final void dispose() { public final void dispose() {
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on 8/18/11 11:18 PM SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on
public void run() { // 8/18/11 11:18 PM
getDialog().dispose(); @Override
} public void run() {
}); MultiPhaseProgressMonitorWithETA.this.getDialog().dispose();
}
});
} }
/** /**
* Gets the dialog.
*
* @return the JDialog for the current phase; use this judiciously to * @return the JDialog for the current phase; use this judiciously to
* manipulate the dialog directly. * manipulate the dialog directly.
*/ */
public final JDialog getDialog() { public final JDialog getDialog() {
return dialog; return this.dialog;
} }
} }

View File

@@ -1,2 +1,3 @@
/** Forge Card Game */ /** Forge Card Game. */
package forge.gui; 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 i = 0; i < Constant.Color.BASIC_LANDS.length; i++) {
for (int j = 0; j < 18; j++) { 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 i = 0; i < Constant.Color.BASIC_LANDS.length; i++) {
for (int j = 0; j < 18; j++) { 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]);
} }
} }