Gridarta Editor
BrowseArchetypesDialog.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.gui.dialog.browsearchetypes;
21 
22 import java.awt.BorderLayout;
23 import java.awt.Component;
24 import java.awt.Dimension;
25 import java.awt.event.ItemEvent;
26 import java.awt.event.ItemListener;
27 import java.awt.event.MouseEvent;
28 import java.awt.event.MouseListener;
29 import java.io.File;
30 import java.io.IOException;
31 import java.util.Collection;
32 import java.util.TreeSet;
33 import javax.swing.BoxLayout;
34 import javax.swing.DefaultComboBoxModel;
35 import javax.swing.ImageIcon;
36 import javax.swing.JButton;
37 import javax.swing.JComboBox;
38 import javax.swing.JDialog;
39 import javax.swing.JFileChooser;
40 import javax.swing.JOptionPane;
41 import javax.swing.JPanel;
42 import javax.swing.JScrollPane;
43 import javax.swing.JTable;
44 import javax.swing.ListSelectionModel;
45 import javax.swing.ScrollPaneConstants;
46 import javax.swing.SwingUtilities;
47 import javax.swing.WindowConstants;
48 import javax.swing.event.ListSelectionEvent;
49 import javax.swing.event.ListSelectionListener;
50 import javax.swing.table.JTableHeader;
51 import javax.swing.table.TableColumnModel;
62 import net.sf.japi.swing.action.ActionBuilder;
63 import net.sf.japi.swing.action.ActionBuilderFactory;
64 import net.sf.japi.swing.action.ActionMethod;
65 import org.jetbrains.annotations.NotNull;
66 
71 public class BrowseArchetypesDialog<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> extends JOptionPane {
72 
76  private static final long serialVersionUID = 1L;
77 
81  @NotNull
82  private static final ActionBuilder ACTION_BUILDER = ActionBuilderFactory.getInstance().getActionBuilder("net.sf.gridarta");
83 
87  @NotNull
89 
93  @NotNull
95 
99  @NotNull
100  private final Collection<String> availableAttributes = new TreeSet<>();
101 
105  @NotNull
107 
111  @NotNull
112  private final DefaultComboBoxModel<String> addAttributeComboBoxModel = new DefaultComboBoxModel<>();
113 
118  @NotNull
119  private final JTable archetypesTable;
120 
125  @NotNull
126  private final JDialog dialog;
127 
132  @NotNull
133  private final JButton addAttributeButton;
134 
139  @NotNull
140  private final JComboBox<String> addAttributeComboBox;
141 
145  @NotNull
146  private final JFileChooser chooser = new JFileChooser();
147 
159  public BrowseArchetypesDialog(@NotNull final Component parentComponent, @NotNull final ArchetypeChooserControl<G, A, R> archetypeChooserControl, @NotNull final ObjectChooser<G, A, R> objectChooser, @NotNull final ArchetypeSet<G, A, R> archetypeSet, @NotNull final ImageIcon closingIcon) {
160  this.archetypeChooserControl = archetypeChooserControl;
161  this.objectChooser = objectChooser;
162  archetypesTableModel = new BrowseArchetypesTableModel<>(archetypeSet);
163  archetypesTable = new JTable(archetypesTableModel);
164 
165  for (final Archetype<?, ?, ?> archetype : archetypeSet.getArchetypes()) {
166  availableAttributes.addAll(archetype.getAttributeKeys());
167  }
168  if (availableAttributes.remove("value")) {
169  archetypesTableModel.addAttribute("value");
170  }
171 
172  archetypesTable.setFillsViewportHeight(true);
173  archetypesTable.setAutoCreateRowSorter(true);
174  archetypesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
175  archetypesTable.setRowSelectionAllowed(true);
176  archetypesTable.setColumnSelectionAllowed(false);
177  final ListSelectionListener listSelectionListener = new ListSelectionListener() {
178 
179  @Override
180  public void valueChanged(@NotNull final ListSelectionEvent e) {
182  }
183 
184  };
185  archetypesTable.getSelectionModel().addListSelectionListener(listSelectionListener);
186  final JTableHeader tableHeader = archetypesTable.getTableHeader();
187  tableHeader.setReorderingAllowed(true);
188  final TableHeaderCellRenderer renderer = new TableHeaderCellRenderer(closingIcon, tableHeader.getDefaultRenderer());
189  tableHeader.setDefaultRenderer(renderer);
190  final MouseListener mouseListener = new MouseListener() {
191 
195  private boolean pressed;
196 
197  @Override
198  public void mouseClicked(@NotNull final MouseEvent e) {
199  if (pressed) {
200  pressed = false;
201  if (SwingUtilities.isLeftMouseButton(e)) {
202  final TableColumnModel columnModel = archetypesTable.getColumnModel();
203  final int viewColumn = columnModel.getColumnIndexAtX(e.getX());
204  final int columnIndex = archetypesTable.convertColumnIndexToModel(viewColumn);
205  final int offsetX = renderer.getX(columnIndex);
206  int cx = 0;
207  for (int i = 0; i < columnIndex; i++) {
208  cx += columnModel.getColumn(i).getWidth();
209  }
210  final int ex = e.getX();
211  if (offsetX >= 0 && ex - cx >= offsetX) {
212  final String attribute = archetypesTableModel.removeAttribute(columnIndex);
213  if (attribute != null) {
214  availableAttributes.add(attribute);
215  updateComboBox();
216  addAttributeComboBoxModel.setSelectedItem(attribute);
217  }
218  }
219  }
220  }
221  }
222 
223  @Override
224  public void mousePressed(@NotNull final MouseEvent e) {
225  pressed = true;
226  }
227 
228  @Override
229  public void mouseReleased(@NotNull final MouseEvent e) {
230  }
231 
232  @Override
233  public void mouseEntered(@NotNull final MouseEvent e) {
234  }
235 
236  @Override
237  public void mouseExited(@NotNull final MouseEvent e) {
238  }
239 
240  };
241  tableHeader.addMouseListener(mouseListener);
242  addAttributeButton = new JButton(ACTION_BUILDER.createAction(false, "browseArchetypesAddAttribute", this));
243  addAttributeComboBox = new JComboBox<>(addAttributeComboBoxModel);
244  final ItemListener itemListener = new ItemListener() {
245 
246  @Override
247  public void itemStateChanged(@NotNull final ItemEvent e) {
248  updateActions();
249  }
250 
251  };
252  addAttributeComboBox.addItemListener(itemListener);
253  setMessage(createPanel());
254 
255  final JPanel addAttributePanel = new JPanel();
256  addAttributePanel.setLayout(new BoxLayout(addAttributePanel, BoxLayout.LINE_AXIS));
257  addAttributePanel.add(addAttributeButton);
258  addAttributePanel.add(addAttributeComboBox);
259  addAttributePanel.add(new JButton(ACTION_BUILDER.createAction(false, "browseArchetypesSave", this)));
260  setOptions(new Object[] { addAttributePanel });
261 
262  updateComboBox();
263  addAttributeComboBox.setSelectedIndex(Math.min(0, addAttributeComboBoxModel.getSize() - 1));
264 
265  dialog = createDialog(parentComponent, ActionBuilderUtils.getString(ACTION_BUILDER, "browseArchetypes.title"));
266  dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
267  dialog.setModal(false);
268  dialog.setResizable(true);
269  dialog.pack();
270  dialog.setMinimumSize(new Dimension(200, 200));
271  dialog.setSize(new Dimension(800, 600));
272  dialog.setLocationRelativeTo(parentComponent);
273  setInitialValue(archetypesTable);
274  updateActions();
275 
276  chooser.setDialogTitle(ActionBuilderUtils.getString(ACTION_BUILDER, "browseArchetypesSave.title"));
277  chooser.setFileFilter(FileFilters.CSV_FILE_FILTER);
278  }
279 
283  public void showDialog() {
284  dialog.setVisible(true);
285  dialog.toFront();
286  }
287 
292  @NotNull
293  private JPanel createPanel() {
294  final JPanel mainPanel = new JPanel(new BorderLayout());
295 
296  mainPanel.setBorder(GUIConstants.DIALOG_BORDER);
297 
298  final JScrollPane scrollPane = new JScrollPane(archetypesTable);
299  scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
300  scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
301 
302  mainPanel.add(scrollPane, BorderLayout.CENTER);
303  return mainPanel;
304  }
305 
309  @ActionMethod
311  doAddAttribute(true);
312  }
313 
317  @ActionMethod
318  public void browseArchetypesSave() {
319  chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
320  chooser.setMultiSelectionEnabled(false);
322  final int returnVal = chooser.showSaveDialog(this);
323  if (returnVal == JFileChooser.APPROVE_OPTION) {
324  File file = chooser.getSelectedFile();
325  try {
326  if (chooser.getFileFilter() == FileFilters.CSV_FILE_FILTER && !file.getName().endsWith(".csv")) {
327  file = new File(file.getParentFile(), file.getName() + ".csv");
328  }
329  archetypesTableModel.saveAsCsv(file);
330  } catch (final IOException ex) {
331  ACTION_BUILDER.showMessageDialog(this, "browseArchetypesSaveIOException", file, ex.getMessage());
332  }
333  }
334  }
335 
341  private boolean doAddAttribute(final boolean performAction) {
342  final String attributeName = (String) addAttributeComboBox.getSelectedItem();
343  if (attributeName == null) {
344  return false;
345  }
346 
347  if (performAction) {
348  if (availableAttributes.remove(attributeName)) {
349  archetypesTableModel.addAttribute(attributeName);
350  final int selectedIndex = Math.max(addAttributeComboBox.getSelectedIndex(), 0);
351  updateComboBox();
352  addAttributeComboBox.setSelectedIndex(Math.min(selectedIndex, addAttributeComboBoxModel.getSize() - 1));
353  }
354  updateActions();
355  } else if (!availableAttributes.contains(attributeName)) {
356  return false;
357  }
358 
359  return true;
360  }
361 
365  private void updateActions() {
366  addAttributeButton.setEnabled(doAddAttribute(false));
367  addAttributeComboBox.setEnabled(!availableAttributes.isEmpty());
368  }
369 
374  private void updateComboBox() {
375  addAttributeComboBoxModel.removeAllElements();
376  for (final String attribute : availableAttributes) {
377  addAttributeComboBoxModel.addElement(attribute);
378  }
379  }
380 
385  private void highlightSelectedEntry() {
386  final int index = archetypesTable.getSelectedRow();
387  if (index == -1) {
388  return;
389  }
390 
391  final R archetype = archetypesTableModel.get(archetypesTable.getRowSorter().convertRowIndexToModel(index));
392  objectChooser.moveArchetypeChooserToFront();
393  archetypeChooserControl.selectArchetype(archetype);
394  }
395 
396 }
void browseArchetypesSave()
Action method for saving the current list to a CSV file.
Graphical User Interface of Gridarta.
Reading and writing of Atrinik maps.
void addAttribute(@NotNull final String attribute)
Adds a column for an attribute to the table.
static final FileFilter CSV_FILE_FILTER
Swing FileFilter for CSV files.
final ObjectChooser< G, A, R > objectChooser
The insertion object chooser to use when selecting search results.
Utility class for JFileChooser related functions.
final JButton addAttributeButton
The button for adding the selected attribute to archetypesTable.
boolean doAddAttribute(final boolean performAction)
Adds an attribute to the table.
void updateComboBox()
Updates the contents of addAttributeComboBoxModel.
void moveArchetypeChooserToFront()
Move the Archetype Chooser in front of the Pickmap Chooser.
final JComboBox< String > addAttributeComboBox
The attribute to add to archetypesTable if addAttributeButton is selected.
void saveAsCsv(@NotNull final File file)
Saves the current contents as a CSV file.
static String getString(@NotNull final ActionBuilder actionBuilder, @NotNull final String key, @NotNull final String defaultValue)
Returns the value of a key.
final Collection< String > availableAttributes
The attribute names currently not shown.
Base package of all Gridarta classes.
Utility class defining FileFilters.
Reflects a game object (object on a map).
Definition: GameObject.java:36
final JTable archetypesTable
The JTable showing the selected archetypes.
GameObjects are the objects based on Archetypes found on maps.
final DefaultComboBoxModel< String > addAttributeComboBoxModel
The model of addAttributeComboBox.
void highlightSelectedEntry()
Highlights the selected row from archetypesTable in the insertion object chooser. ...
int getX(final int index)
Returns the x coordinate of a closing icon.
void updateActions()
Updates the actions&#39; states to reflect the current selection.
BrowseArchetypesDialog(@NotNull final Component parentComponent, @NotNull final ArchetypeChooserControl< G, A, R > archetypeChooserControl, @NotNull final ObjectChooser< G, A, R > objectChooser, @NotNull final ArchetypeSet< G, A, R > archetypeSet, @NotNull final ImageIcon closingIcon)
Creates a new instance.
void selectArchetype(@NotNull final R archetype)
Select an archetype.
Utility class for ActionBuilder related functions.
Border DIALOG_BORDER
The Border object to be used when creating dialogs.
static void sanitizeCurrentDirectory(@NotNull final JFileChooser fileChooser)
Makes sure the current directory of a JFileChooser is valid.
Interface that captures similarities between different ArchetypeSet implementations.
Common base interface for ObjectChoosers.
final BrowseArchetypesTableModel< G, A, R > archetypesTableModel
The model of archetypesTable.
final ArchetypeChooserControl< G, A, R > archetypeChooserControl
The archetype set to search.
String removeAttribute(final int index)
Removes an attribute from the table.
Defines common UI constants used in different dialogs.
final JFileChooser chooser
The JFileChooser for saving CSV files.