mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
Skin ListChooser
This commit is contained in:
@@ -101,19 +101,18 @@ public class GuiChoose {
|
||||
}
|
||||
|
||||
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
|
||||
if (null == choices || choices.isEmpty()) {
|
||||
if (0 == min) {
|
||||
if (choices == null || choices.isEmpty()) {
|
||||
if (min == 0) {
|
||||
return new ArrayList<T>();
|
||||
} else {
|
||||
throw new RuntimeException("choice required from empty list");
|
||||
}
|
||||
throw new RuntimeException("choice required from empty list");
|
||||
}
|
||||
|
||||
Callable<List<T>> showChoice = new Callable<List<T>>() {
|
||||
@Override
|
||||
public List<T> call() {
|
||||
ListChooser<T> c = new ListChooser<T>(message, min, max, choices, display);
|
||||
final JList<T> list = c.getJList();
|
||||
final JList<T> 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();
|
||||
|
||||
@@ -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<T> {
|
||||
|
||||
// Data and number of choices for the list
|
||||
private List<T> 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<T> jList;
|
||||
// Temporarily stored for event handlers during show
|
||||
private JDialog dialog;
|
||||
private JOptionPane optionPane;
|
||||
private Action ok, cancel;
|
||||
private FList<T> lstChoices;
|
||||
private FOptionPane optionPane;
|
||||
|
||||
public ListChooser(final String title, final int minChoices, final int maxChoices, final Collection<T> list, final Function<T, String> display) {
|
||||
FThreads.assertExecutedByEdt(true);
|
||||
this.title = title;
|
||||
this.minChoices = minChoices;
|
||||
this.maxChoices = maxChoices;
|
||||
this.list = list.getClass().isInstance(List.class) ? (List<T>)list : Lists.newArrayList(list);
|
||||
this.jList = new JList<T>(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<T>(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<T> getJList() {
|
||||
return this.jList;
|
||||
public FList<T> getLstChoices() {
|
||||
return this.lstChoices;
|
||||
}
|
||||
|
||||
/** @return boolean */
|
||||
@@ -143,42 +150,45 @@ public class ListChooser<T> {
|
||||
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<T> {
|
||||
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<T> {
|
||||
if (!this.called) {
|
||||
throw new IllegalStateException("not yet shown");
|
||||
}
|
||||
return this.jList.getSelectedIndices();
|
||||
return this.lstChoices.getSelectedIndices();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,7 +226,7 @@ public class ListChooser<T> {
|
||||
if (!this.called) {
|
||||
throw new IllegalStateException("not yet shown");
|
||||
}
|
||||
return this.jList.getSelectedValuesList();
|
||||
return this.lstChoices.getSelectedValuesList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,7 +238,7 @@ public class ListChooser<T> {
|
||||
if (!this.called) {
|
||||
throw new IllegalStateException("not yet shown");
|
||||
}
|
||||
return this.jList.getSelectedIndex();
|
||||
return this.lstChoices.getSelectedIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,7 +250,7 @@ public class ListChooser<T> {
|
||||
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<T> {
|
||||
* </p>
|
||||
*/
|
||||
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<T> {
|
||||
|
||||
private static final long serialVersionUID = 3871965346333840556L;
|
||||
|
||||
@Override
|
||||
@@ -269,38 +278,11 @@ public class ListChooser<T> {
|
||||
}
|
||||
}
|
||||
|
||||
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<T> {
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class FList<E> extends JList<E> {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user