Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AbstractIcon: Null Protection for ImageIcons and Separating Dialogs out from the Choosers beneath #2509

Merged
14 changes: 7 additions & 7 deletions megamek/src/megamek/client/ui/swing/ChatLounge.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
import megamek.client.generator.RandomCallsignGenerator;
import megamek.client.ui.Messages;
import megamek.client.ui.swing.boardview.BoardView1;
import megamek.client.ui.swing.dialog.imageChooser.CamoChooser;
import megamek.client.ui.swing.dialog.imageChooser.CamoChooserDialog;
import megamek.client.ui.swing.util.MenuScroller;
import megamek.client.ui.swing.util.PlayerColors;
import megamek.client.ui.swing.widget.SkinSpecification;
Expand Down Expand Up @@ -177,7 +177,7 @@ public void doneLoading() {
}
};

private CamoChooser camoDialog;
private CamoChooserDialog camoDialog;

//region Action Commands
private static final String NAME_COMMAND = "NAME";
Expand Down Expand Up @@ -458,7 +458,7 @@ public String getToolTipText(MouseEvent e) {
butCamo.setPreferredSize(new Dimension(84, 72));
butCamo.setActionCommand("camo");
butCamo.addActionListener(e -> {
// Show the CamoChooser for the selected player
// Show the CamoChooserDialog for the selected player
IPlayer player = getPlayerSelected().getLocalPlayer();
int result = camoDialog.showDialog(player);

Expand All @@ -477,7 +477,7 @@ public String getToolTipText(MouseEvent e) {
butCamo.setIcon(player.getCamouflage().getImageIcon());
getPlayerSelected().sendPlayerInfo();
});
camoDialog = new CamoChooser(clientgui.getFrame());
camoDialog = new CamoChooserDialog(clientgui.getFrame());
refreshCamos();

butChangeStart = new JButton(Messages.getString("ChatLounge.butChangeStart"));
Expand Down Expand Up @@ -2341,7 +2341,7 @@ public void customizeMech(Entity entity) {
}

/**
* Displays a CamoChooser to choose an individual camo for
* Displays a CamoChooserDialog to choose an individual camo for
* the given vector of entities. The camo will only be applied
* to units configurable by the local player, i.e. his own units
* or those of his bots.
Expand All @@ -2351,9 +2351,9 @@ public void mechCamo(Vector<Entity> entities) {
return;
}

// Display the CamoChooser and await the result
// Display the CamoChooserDialog and await the result
// The dialog is preset to the first selected unit's settings
CamoChooser mcd = new CamoChooser(clientgui.getFrame());
CamoChooserDialog mcd = new CamoChooserDialog(clientgui.getFrame());
int result = mcd.showDialog(entities.get(0));

// If the dialog was canceled or nothing was selected, do nothing
Expand Down
6 changes: 3 additions & 3 deletions megamek/src/megamek/client/ui/swing/CustomPilotView.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
import megamek.client.generator.RandomCallsignGenerator;
import megamek.client.ui.GBC;
import megamek.client.ui.Messages;
import megamek.client.ui.swing.dialog.imageChooser.AbstractIconChooser;
import megamek.client.ui.swing.dialog.imageChooser.PortraitChooser;
import megamek.client.ui.swing.dialog.imageChooser.AbstractIconChooserDialog;
import megamek.client.ui.swing.dialog.imageChooser.PortraitChooserDialog;
import megamek.common.Entity;
import megamek.common.EntitySelector;
import megamek.common.Infantry;
Expand Down Expand Up @@ -102,7 +102,7 @@ public CustomPilotView(CustomMechDialog parent, Entity entity, int slot, boolean
portraitButton.setPreferredSize(new Dimension(72, 72));
portraitButton.setName("portrait");
portraitButton.addActionListener(e -> {
AbstractIconChooser portraitDialog = new PortraitChooser(parent,
AbstractIconChooserDialog portraitDialog = new PortraitChooserDialog(parent,
entity.getCrew().getPortrait(slot));
int result = portraitDialog.showDialog();
if (result == JOptionPane.OK_OPTION) {
Expand Down
4 changes: 2 additions & 2 deletions megamek/src/megamek/client/ui/swing/ScenarioDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import javax.swing.SwingConstants;

import megamek.client.ui.Messages;
import megamek.client.ui.swing.dialog.imageChooser.CamoChooser;
import megamek.client.ui.swing.dialog.imageChooser.CamoChooserDialog;
import megamek.common.IPlayer;
import megamek.common.Player;
import megamek.common.icons.AbstractIcon;
Expand Down Expand Up @@ -79,7 +79,7 @@ public ScenarioDialog(final JFrame frame, Player[] pa) {
curButton.setText(Messages.getString("MegaMek.NoCamoBtn"));
curButton.setPreferredSize(new Dimension(84, 72));

CamoChooser camoDialog = new CamoChooser(frame);
CamoChooserDialog camoDialog = new CamoChooserDialog(frame);
curButton.addActionListener(e -> {
int result = camoDialog.showDialog(curPlayer);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,61 +18,28 @@
*/
package megamek.client.ui.swing.dialog.imageChooser;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import megamek.client.ui.swing.GUIPreferences;
import megamek.common.annotations.Nullable;
import megamek.common.icons.AbstractIcon;
import megamek.common.util.fileUtils.DirectoryItems;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.ListCellRenderer;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.MouseInputAdapter;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

import megamek.client.ui.Messages;
import megamek.client.ui.swing.GUIPreferences;
import megamek.common.annotations.Nullable;
import megamek.common.icons.AbstractIcon;
import megamek.common.util.fileUtils.DirectoryItems;

/**
* Creates a dialog that allows players to select a directory from
* a directory tree and choose an image from the images in that directory.
* Subclasses must provide the getItems() method that translates
* a given category (directory) selected in the tree to a list
* of items (images) to show in the list.
* Subclasses can provide getSearchedItems() that translates a given search
* String to the list of "found" items. If this is provided, showSearch(true)
* should be called in the constructor to show the search panel.
*/
public abstract class AbstractIconChooser extends JDialog implements TreeSelectionListener {
public abstract class AbstractIconChooser extends JPanel implements TreeSelectionListener {
//region Variable Declarations
private static final long serialVersionUID = -7836502700465322620L;
protected static final GUIPreferences GUIP = GUIPreferences.getInstance();

// display frames
private JSplitPane splitPane;

Expand All @@ -85,28 +52,13 @@ public abstract class AbstractIconChooser extends JDialog implements TreeSelecti
// image selection list
protected ImageList imageList;

/** True when the user canceled. */
private boolean wasCanceled = false;

/** When true, icons from all subdirectories of the current selection are shown. */
protected boolean includeSubDirs = true;
//endregion Variable Declarations

//region Constructors
/**
* Creates a dialog that allows players to choose a directory from
* a directory tree and an image from the images in that directory.
*
* @param parent The Window (dialog or frame) hosting this dialog
* @param title the dialog title
* @param renderer A ListCellRenderer<AbstractIcon> to show the images
* @param tree the JTree with the directories
*/
public AbstractIconChooser(Window parent, AbstractIcon icon, String title,
ListCellRenderer<AbstractIcon> renderer, JTree tree) {
super(parent, title, ModalityType.APPLICATION_MODAL);

initialize(renderer, tree);
public AbstractIconChooser(JTree tree, AbstractIcon icon) {
initialize(tree);

if (icon != null) {
setSelection(icon);
Expand All @@ -115,17 +67,9 @@ public AbstractIconChooser(Window parent, AbstractIcon icon, String title,
//endregion Constructors

//region Initialization
private void initialize(ListCellRenderer<AbstractIcon> renderer, JTree tree) {
private void initialize(JTree tree) {
// Set up the image list (right panel)
imageList = new ImageList(renderer);
imageList.addMouseListener(new MouseInputAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
select();
}
}
});
imageList = new ImageList(new AbstractIconRenderer());
JScrollPane scrpImages = new JScrollPane(imageList);
scrpImages.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrpImages.setMinimumSize(new Dimension(500, 240));
Expand All @@ -139,42 +83,11 @@ public void mouseClicked(MouseEvent e) {
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, scrpTree, scrpImages);
splitPane.setResizeWeight(0.5);

splitPane.setDividerLocation(GUIPreferences.getInstance().getInt(GUIPreferences.IMAGE_CHOOSER_SPLIT_POS));

setLayout(new BorderLayout());
JPanel searchPanel = searchPanel();
add(searchPanel, BorderLayout.PAGE_START);
add(searchPanel(), BorderLayout.PAGE_START);
add(splitPane, BorderLayout.CENTER);
add(buttonPanel(), BorderLayout.PAGE_END);

// Size and position of the dialog
setMinimumSize(new Dimension(480, 240));
splitPane.setDividerLocation(GUIP.getInt(GUIPreferences.IMAGE_CHOOSER_SPLIT_POS));
setSize(GUIP.getImageChoiceSizeWidth(), GUIP.getImageChoiceSizeHeight());
setLocation(GUIP.getImageChoicePosX(), GUIP.getImageChoicePosY());

// Make the close "X" cancel the dialog
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
cancel();
}
});
}

/** Constructs the bottom panel with the Okay and Cancel buttons. */
private JPanel buttonPanel() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 2));

JButton btnCancel = new JButton(Messages.getString("Cancel"));
btnCancel.addActionListener(evt -> cancel());

JButton btnOkay = new JButton(Messages.getString("Okay"));
btnOkay.addActionListener(evt -> select());

panel.add(btnOkay);
panel.add(btnCancel);
panel.setBorder(new EmptyBorder(5, 5, 5, 5));
return panel;
}

/** Constructs a functions panel containing the search bar. */
Expand Down Expand Up @@ -261,33 +174,23 @@ public int getSelectedIndex() {
return imageList.getSelectedIndex();
}

/** Activates the dialog and returns if the user cancelled. */
public int showDialog() {
wasCanceled = false;
setVisible(true);
// After returning from the modal dialog, save settings the return whether it was cancelled or not...
saveWindowSettings();
return wasCanceled ? JOptionPane.CANCEL_OPTION : JOptionPane.OK_OPTION;
}

/** Called when the Okay button is pressed or an image is double-clicked. */
protected void select() {
wasCanceled = false;
setVisible(false);
}

private void cancel() {
wasCanceled = true;
setVisible(false);
}
/**
* This is used to refresh the contents of the directory
*/
protected abstract void refreshDirectory();

/** Saves the position, size and split of the dialog. */
private void saveWindowSettings() {
GUIP.setValue(GUIPreferences.IMAGE_CHOOSER_POS_X, getLocation().x);
GUIP.setValue(GUIPreferences.IMAGE_CHOOSER_POS_Y, getLocation().y);
GUIP.setValue(GUIPreferences.IMAGE_CHOOSER_SIZE_WIDTH, getSize().width);
GUIP.setValue(GUIPreferences.IMAGE_CHOOSER_SIZE_HEIGHT, getSize().height);
GUIP.setValue(GUIPreferences.IMAGE_CHOOSER_SPLIT_POS, splitPane.getDividerLocation());
/**
* This method is to ONLY be called by those methods overwriting the abstract refreshDirectory
* above
* @param newTree the new directory tree
*/
protected void refreshDirectory(JTree newTree) {
treeCategories.removeTreeSelectionListener(this);
treeCategories = newTree;
treeCategories.addTreeSelectionListener(this);
scrpTree = new JScrollPane(treeCategories);
splitPane.setLeftComponent(scrpTree);
splitPane.setDividerLocation(GUIPreferences.getInstance().getInt(GUIPreferences.IMAGE_CHOOSER_SPLIT_POS));
}

/**
Expand Down Expand Up @@ -361,23 +264,9 @@ protected void setSelection(AbstractIcon icon) {
}
}

/**
* This is used to refresh the contents of the directory
*/
protected abstract void refreshDirectory();

/**
* This method is to ONLY be called by those methods overwriting the abstract refreshDirectory
* above
* @param newTree the new directory tree
*/
protected void refreshDirectory(JTree newTree) {
treeCategories.removeTreeSelectionListener(this);
treeCategories = newTree;
treeCategories.addTreeSelectionListener(this);
scrpTree = new JScrollPane(treeCategories);
splitPane.setLeftComponent(scrpTree);
splitPane.setDividerLocation(GUIP.getInt(GUIPreferences.IMAGE_CHOOSER_SPLIT_POS));
public void saveWindowSettings() {
GUIPreferences.getInstance().setValue(GUIPreferences.IMAGE_CHOOSER_SPLIT_POS,
splitPane.getDividerLocation());
}

@Override
Expand Down
Loading