From e954b40d3cdde24dbbaca0e7a4816e2480322ba8 Mon Sep 17 00:00:00 2001
From: drdev
Date: Sat, 4 Jan 2014 05:27:28 +0000
Subject: [PATCH] Skin ListChooser
---
forge-gui/CHANGES.txt | 4 +
.../src/main/java/forge/gui/GuiChoose.java | 18 +-
.../src/main/java/forge/gui/ListChooser.java | 166 ++++++++----------
.../main/java/forge/gui/toolbox/FLabel.java | 10 +-
.../main/java/forge/gui/toolbox/FList.java | 2 +-
.../java/forge/gui/toolbox/FOptionPane.java | 45 ++++-
.../src/main/java/forge/view/FTitleBar.java | 25 ++-
7 files changed, 153 insertions(+), 117 deletions(-)
diff --git a/forge-gui/CHANGES.txt b/forge-gui/CHANGES.txt
index 1f26afbee70..ecdf1dab0c7 100644
--- a/forge-gui/CHANGES.txt
+++ b/forge-gui/CHANGES.txt
@@ -14,6 +14,10 @@ Support resetting and hiding filters
Full catalog now available for sideboarding in Deck Editor
Title field and buttons now available on Current Deck pane when on other sections, with the current section name displaying above the table
+- More skinned dialogs -
+Most remaining dialogs are now skinned, including all message, confirmation, input, and list choice dialogs
+
+
- Constructed mode -
Recently a change was made to the constructed mode and this change now allows you to have up to 8 players rather than just two. The game formats that are located in the variants mode also allow up to eight players. The current user interface for this feature is fairly basic and is not very attractive. The settings tab allows you to set the number of opponents. The player tabs includes the same options that you used to see in the constructed mode.
diff --git a/forge-gui/src/main/java/forge/gui/GuiChoose.java b/forge-gui/src/main/java/forge/gui/GuiChoose.java
index 6e611d84d6d..6740a7e9c91 100644
--- a/forge-gui/src/main/java/forge/gui/GuiChoose.java
+++ b/forge-gui/src/main/java/forge/gui/GuiChoose.java
@@ -101,19 +101,18 @@ public class GuiChoose {
}
public static List getChoices(final String message, final int min, final int max, final Collection choices, final T selected, final Function display) {
- if (null == choices || choices.isEmpty()) {
- if (0 == min) {
+ if (choices == null || choices.isEmpty()) {
+ if (min == 0) {
return new ArrayList();
- } else {
- throw new RuntimeException("choice required from empty list");
}
+ throw new RuntimeException("choice required from empty list");
}
Callable> showChoice = new Callable>() {
@Override
public List call() {
ListChooser c = new ListChooser(message, min, max, choices, display);
- final JList list = c.getJList();
+ final JList list = c.getLstChoices();
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(final ListSelectionEvent ev) {
@@ -121,7 +120,8 @@ public class GuiChoose {
Card card = (Card) list.getSelectedValue();
if (card.isFaceDown() && Singletons.getControl().mayShowCard(card)) {
CMatchUI.SINGLETON_INSTANCE.setCard(card, true);
- } else {
+ }
+ else {
CMatchUI.SINGLETON_INSTANCE.setCard(card);
}
@@ -134,10 +134,12 @@ public class GuiChoose {
}
});
- if(selected != null)
+ if (selected != null) {
c.show(selected);
- else
+ }
+ else {
c.show();
+ }
GuiUtils.clearPanelSelections();
return c.getSelectedValues();
diff --git a/forge-gui/src/main/java/forge/gui/ListChooser.java b/forge-gui/src/main/java/forge/gui/ListChooser.java
index 1d976ee3f7c..4fa59f7104b 100644
--- a/forge-gui/src/main/java/forge/gui/ListChooser.java
+++ b/forge-gui/src/main/java/forge/gui/ListChooser.java
@@ -19,22 +19,17 @@
package forge.gui;
import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.MouseAdapter;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.Collection;
import java.util.List;
-import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
-import javax.swing.Action;
import javax.swing.DefaultListCellRenderer;
-import javax.swing.JButton;
-import javax.swing.JDialog;
import javax.swing.JList;
-import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
@@ -46,6 +41,9 @@ import com.google.common.base.Function;
import com.google.common.collect.Lists;
import forge.FThreads;
+import forge.gui.toolbox.FList;
+import forge.gui.toolbox.FMouseAdapter;
+import forge.gui.toolbox.FOptionPane;
/**
* A simple class that shows a list of choices in a dialog. Two properties
@@ -71,61 +69,70 @@ import forge.FThreads;
* @version $Id$
*/
public class ListChooser {
-
// Data and number of choices for the list
private List list;
private int minChoices, maxChoices;
- // Decoration
- private String title;
-
// Flag: was the dialog already shown?
private boolean called;
+
// initialized before; listeners may be added to it
- private JList jList;
- // Temporarily stored for event handlers during show
- private JDialog dialog;
- private JOptionPane optionPane;
- private Action ok, cancel;
+ private FList lstChoices;
+ private FOptionPane optionPane;
public ListChooser(final String title, final int minChoices, final int maxChoices, final Collection list, final Function display) {
FThreads.assertExecutedByEdt(true);
- this.title = title;
this.minChoices = minChoices;
this.maxChoices = maxChoices;
this.list = list.getClass().isInstance(List.class) ? (List)list : Lists.newArrayList(list);
- this.jList = new JList(new ChooserListModel());
- this.ok = new CloseAction(JOptionPane.OK_OPTION, "OK");
- this.ok.setEnabled(minChoices == 0);
- this.cancel = new CloseAction(JOptionPane.CANCEL_OPTION, "Cancel");
+ this.lstChoices = new FList(new ChooserListModel());
- Object[] options;
+ String[] options;
if (minChoices == 0) {
- options = new Object[] { new JButton(this.ok), new JButton(this.cancel) };
- } else {
- options = new Object[] { new JButton(this.ok) };
+ options = new String[] {"OK","Cancel"};
}
+ else {
+ options = new String[] {"OK"};
+ }
+
if (maxChoices == 1) {
- this.jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ this.lstChoices.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
- if( null != display )
- this.jList.setCellRenderer(new TransformedCellRenderer(display));
+ if (display != null) {
+ this.lstChoices.setCellRenderer(new TransformedCellRenderer(display));
+ }
- this.optionPane = new JOptionPane(new JScrollPane(this.jList), JOptionPane.QUESTION_MESSAGE,
- JOptionPane.DEFAULT_OPTION, null, options, options[0]);
- this.jList.getSelectionModel().addListSelectionListener(new SelListener());
- this.jList.addMouseListener(new DblListener());
+ this.optionPane = new FOptionPane(null, title, null, new JScrollPane(this.lstChoices), options, 0);
+ this.optionPane.setButtonEnabled(0, minChoices == 0);
+
+ this.lstChoices.getSelectionModel().addListSelectionListener(new SelListener());
+ this.lstChoices.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+ ListChooser.this.commit();
+ }
+ }
+ });
+ this.lstChoices.addMouseListener(new FMouseAdapter() {
+ @Override
+ public void onLeftClick(MouseEvent e) {
+ if (e.getClickCount() == 2) {
+ ListChooser.this.commit();
+ }
+ }
+ });
}
/**
- * Returns the JList used in the list chooser. this is useful for
+ * Returns the FList used in the list chooser. this is useful for
* registering listeners before showing the dialog.
*
* @return a {@link javax.swing.JList} object.
*/
- public JList getJList() {
- return this.jList;
+ public FList getLstChoices() {
+ return this.lstChoices;
}
/** @return boolean */
@@ -143,42 +150,45 @@ public class ListChooser {
if (this.called) {
throw new IllegalStateException("Already shown");
}
- Integer value;
+ int result;
do {
- this.dialog = this.optionPane.createDialog(JOptionPane.getRootFrame(), this.title);
if (this.minChoices != 0) {
- this.dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+ this.optionPane.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
}
if (list.contains(item)) {
- jList.setSelectedValue(item, true);
- } else {
- jList.setSelectedIndex(0);
+ lstChoices.setSelectedValue(item, true);
+ }
+ else {
+ lstChoices.setSelectedIndex(0);
}
- this.dialog.addWindowFocusListener(new WindowFocusListener() {
+ this.optionPane.addWindowFocusListener(new WindowFocusListener() {
@Override
public void windowGainedFocus(final WindowEvent e) {
- ListChooser.this.jList.grabFocus();
+ ListChooser.this.lstChoices.grabFocus();
}
@Override
public void windowLostFocus(final WindowEvent e) {
}
});
- this.dialog.setVisible(true);
- this.dialog.dispose();
- value = (Integer) this.optionPane.getValue();
- if ((value == null) || (value != JOptionPane.OK_OPTION)) {
- this.jList.clearSelection();
- // can't stop closing by ESC, so repeat if cancelled
+ this.optionPane.setVisible(true);
+ result = this.optionPane.getResult();
+ if (result != 0) {
+ this.lstChoices.clearSelection();
+ break;
}
- } while ((this.minChoices != 0) && (value != JOptionPane.OK_OPTION));
+ // can't stop closing by ESC, so repeat if cancelled
+ } while (this.minChoices != 0);
+
+ this.optionPane.dispose();
+
// this assert checks if we really don't return on a cancel if input is
// mandatory
- assert (this.minChoices == 0) || (value == JOptionPane.OK_OPTION);
+ assert (this.minChoices == 0) || (result == 0);
this.called = true;
- return (value != null) && (value == JOptionPane.OK_OPTION);
+ return (result == 0);
}
/**
@@ -191,7 +201,7 @@ public class ListChooser {
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
- return (Integer) this.optionPane.getValue() == JOptionPane.OK_OPTION;
+ return (this.optionPane.getResult() == 0);
}
/**
@@ -203,7 +213,7 @@ public class ListChooser {
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
- return this.jList.getSelectedIndices();
+ return this.lstChoices.getSelectedIndices();
}
/**
@@ -216,7 +226,7 @@ public class ListChooser {
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
- return this.jList.getSelectedValuesList();
+ return this.lstChoices.getSelectedValuesList();
}
/**
@@ -228,7 +238,7 @@ public class ListChooser {
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
- return this.jList.getSelectedIndex();
+ return this.lstChoices.getSelectedIndex();
}
/**
@@ -240,7 +250,7 @@ public class ListChooser {
if (!this.called) {
throw new IllegalStateException("not yet shown");
}
- return (T) this.jList.getSelectedValue();
+ return (T) this.lstChoices.getSelectedValue();
}
/**
@@ -249,13 +259,12 @@ public class ListChooser {
*
*/
private void commit() {
- if (this.ok.isEnabled()) {
- this.optionPane.setValue(JOptionPane.OK_OPTION);
+ if (this.optionPane.isButtonEnabled(0)) {
+ optionPane.setResult(0);
}
}
private class ChooserListModel extends AbstractListModel {
-
private static final long serialVersionUID = 3871965346333840556L;
@Override
@@ -269,38 +278,11 @@ public class ListChooser {
}
}
- private class CloseAction extends AbstractAction {
-
- private static final long serialVersionUID = -8426767786083886936L;
- private final int value;
-
- public CloseAction(final int value, final String label) {
- super(label);
- this.value = value;
- }
-
- @Override
- public void actionPerformed(final ActionEvent e) {
- ListChooser.this.optionPane.setValue(this.value);
- }
- }
-
private class SelListener implements ListSelectionListener {
-
@Override
public void valueChanged(final ListSelectionEvent e) {
- final int num = ListChooser.this.jList.getSelectedIndices().length;
- ListChooser.this.ok
- .setEnabled((num >= ListChooser.this.minChoices) && (num <= ListChooser.this.maxChoices));
- }
- }
-
- private class DblListener extends MouseAdapter {
- @Override
- public void mouseClicked(final MouseEvent e) {
- if (e.getClickCount() == 2) {
- ListChooser.this.commit();
- }
+ final int num = ListChooser.this.lstChoices.getSelectedIndices().length;
+ ListChooser.this.optionPane.setButtonEnabled(0, (num >= ListChooser.this.minChoices) && (num <= ListChooser.this.maxChoices));
}
}
@@ -320,13 +302,9 @@ public class ListChooser {
* @see javax.swing.ListCellRenderer#getListCellRendererComponent(javax.swing.JList, java.lang.Object, int, boolean, boolean)
*/
@Override
- public Component getListCellRendererComponent(JList extends T> list, T value, int index, boolean isSelected,
- boolean cellHasFocus) {
+ public Component getListCellRendererComponent(JList extends T> list, T value, int index, boolean isSelected, boolean cellHasFocus) {
// TODO Auto-generated method stub
return defRenderer.getListCellRendererComponent(list, transformer.apply(value), index, isSelected, cellHasFocus);
}
-
-
-
}
}
diff --git a/forge-gui/src/main/java/forge/gui/toolbox/FLabel.java b/forge-gui/src/main/java/forge/gui/toolbox/FLabel.java
index 4e98061bcfc..c2d5684e5cb 100644
--- a/forge-gui/src/main/java/forge/gui/toolbox/FLabel.java
+++ b/forge-gui/src/main/java/forge/gui/toolbox/FLabel.java
@@ -22,6 +22,7 @@ import java.awt.event.MouseEvent;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
+import javax.swing.JOptionPane;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.event.AncestorEvent;
@@ -431,9 +432,16 @@ public class FLabel extends JLabel implements ILocalRepaint {
public int getAutoSizeWidth() {
int width = 0;
if (this.getText() != null && !this.getText().isEmpty()) {
- FontMetrics metrics = this.getGraphics().getFontMetrics(this.getFont());
+ Graphics g = this.getGraphics();
+ if (g == null) {
+ g = JOptionPane.getRootFrame().getGraphics(); //fallback to root frame's graphics if needed
+ }
+ FontMetrics metrics = g.getFontMetrics(this.getFont());
width = metrics.stringWidth(this.getText());
}
+ if (this.getIcon() != null) {
+ width += this.getIcon().getIconWidth() + this.getIconTextGap();
+ }
if (opaque) {
width += 6; //account for border/padding if opaque
}
diff --git a/forge-gui/src/main/java/forge/gui/toolbox/FList.java b/forge-gui/src/main/java/forge/gui/toolbox/FList.java
index fad559dd476..b963299693b 100644
--- a/forge-gui/src/main/java/forge/gui/toolbox/FList.java
+++ b/forge-gui/src/main/java/forge/gui/toolbox/FList.java
@@ -65,7 +65,7 @@ public class FList extends JList {
lblItem.setBorder(new EmptyBorder(4, 3, 4, 3));
lblItemSkin.setBackground(FSkin.getColor(hasFocus() ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE));
lblItemSkin.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
- lblItemSkin.setFont(FSkin.getFont(13));
+ lblItemSkin.setFont(FSkin.getFont(12));
lblItem.setOpaque(isSelected);
return lblItem;
}
diff --git a/forge-gui/src/main/java/forge/gui/toolbox/FOptionPane.java b/forge-gui/src/main/java/forge/gui/toolbox/FOptionPane.java
index bcdf9d529b8..dba19b080c0 100644
--- a/forge-gui/src/main/java/forge/gui/toolbox/FOptionPane.java
+++ b/forge-gui/src/main/java/forge/gui/toolbox/FOptionPane.java
@@ -117,13 +117,7 @@ public class FOptionPane extends FDialog {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
- SwingUtilities.invokeLater(new Runnable() { //delay so enter can confirm input choice first
- @Override
- public void run() {
- optionPane.result = 0;
- optionPane.setVisible(false);
- }
- });
+ optionPane.setResult(0);
}
}
});
@@ -142,8 +136,9 @@ public class FOptionPane extends FDialog {
}
private int result = -1; //default result to -1, indicating dialog closed without choosing option
+ private final FButton[] buttons;
- private FOptionPane(String message, String title, SkinImage icon, Component comp, String[] options, int defaultOption) {
+ public FOptionPane(String message, String title, SkinImage icon, Component comp, String[] options, int defaultOption) {
this.setTitle(title);
int padding = 10;
@@ -176,7 +171,7 @@ public class FOptionPane extends FDialog {
FontMetrics metrics = JOptionPane.getRootFrame().getGraphics().getFontMetrics(btnMeasure.getFont());
int maxTextWidth = 0;
- final FButton[] buttons = new FButton[optionCount];
+ buttons = new FButton[optionCount];
for (int i = 0; i < optionCount; i++) {
int textWidth = metrics.stringWidth(options[i]);
if (textWidth > maxTextWidth) {
@@ -252,4 +247,36 @@ public class FOptionPane extends FDialog {
this.setSize(width, this.getHeight() + buttonHeight); //resize dialog again to account for buttons
}
+
+ @Override
+ public void setVisible(boolean visible) {
+ if (this.isVisible() == visible) { return; }
+
+ if (visible) {
+ result = -1; //default result to -1 when shown, indicating dialog closed without choosing option
+ }
+ super.setVisible(visible);
+ }
+
+ public int getResult() {
+ return result;
+ }
+
+ public void setResult(int result0) {
+ this.result = result0;
+ SwingUtilities.invokeLater(new Runnable() { //delay hiding so action can finish first
+ @Override
+ public void run() {
+ setVisible(false);
+ }
+ });
+ }
+
+ public boolean isButtonEnabled(int index) {
+ return buttons[index].isEnabled();
+ }
+
+ public void setButtonEnabled(int index, boolean enabled) {
+ buttons[index].setEnabled(enabled);
+ }
}
diff --git a/forge-gui/src/main/java/forge/view/FTitleBar.java b/forge-gui/src/main/java/forge/view/FTitleBar.java
index d4b28d000d2..78c6861fa68 100644
--- a/forge-gui/src/main/java/forge/view/FTitleBar.java
+++ b/forge-gui/src/main/java/forge/view/FTitleBar.java
@@ -1,15 +1,21 @@
package forge.view;
+import java.awt.Dimension;
import java.awt.Image;
+
import javax.swing.ImageIcon;
import javax.swing.JLabel;
+import javax.swing.JOptionPane;
import javax.swing.SpringLayout;
+
import forge.gui.toolbox.FSkin;
@SuppressWarnings("serial")
public class FTitleBar extends FTitleBarBase {
+ private static final FSkin.SkinFont skinFont = FSkin.getFont(12);
+
private final JLabel lblTitle = new JLabel();
-
+
public FTitleBar(ITitleBarOwner owner0) {
super(owner0);
skin.setMatteBorder(0, 0, 1, 0, bottomEdgeColor);
@@ -17,10 +23,10 @@ public class FTitleBar extends FTitleBarBase {
setTitle(owner0.getTitle()); //set default title based on frame title
setIconImage(owner0.getIconImage()); //set default icon image based on frame icon image
FSkin.get(lblTitle).setForeground(foreColor);
- FSkin.get(lblTitle).setFont(FSkin.getFont(12));
+ FSkin.get(lblTitle).setFont(skinFont);
addControls();
}
-
+
@Override
protected void addControls() {
add(lblTitle);
@@ -32,8 +38,9 @@ public class FTitleBar extends FTitleBarBase {
@Override
public void setTitle(String title) {
this.lblTitle.setText(title);
+ updatePreferredSize();
}
-
+
@Override
public void setIconImage(Image image) {
if (image != null) {
@@ -42,5 +49,15 @@ public class FTitleBar extends FTitleBarBase {
else {
this.lblTitle.setIcon(null);
}
+ updatePreferredSize();
+ }
+
+ private void updatePreferredSize() {
+ int width = skinFont.measureTextWidth(JOptionPane.getRootFrame().getGraphics(), this.lblTitle.getText());
+ if (this.lblTitle.getIcon() != null) {
+ width += this.lblTitle.getIcon().getIconWidth() + this.lblTitle.getIconTextGap();
+ }
+ width += btnClose.getPreferredSize().width;
+ this.setPreferredSize(new Dimension(width + 10, visibleHeight));
}
}
\ No newline at end of file