Gridarta Editor
DefaultFileControl.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.misc;
21 
22 import java.awt.Component;
23 import java.io.File;
24 import java.io.IOException;
25 import javax.swing.JFileChooser;
26 import javax.swing.JOptionPane;
27 import javax.swing.filechooser.FileFilter;
46 import net.sf.japi.swing.action.ActionBuilder;
47 import net.sf.japi.swing.action.ActionBuilderFactory;
48 import org.jetbrains.annotations.NotNull;
49 import org.jetbrains.annotations.Nullable;
50 
55 public class DefaultFileControl<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> implements FileControl<G, A, R> {
56 
60  @NotNull
61  private static final ActionBuilder ACTION_BUILDER = ActionBuilderFactory.getInstance().getActionBuilder("net.sf.gridarta");
62 
66  @NotNull
68 
72  @NotNull
74 
78  @NotNull
80 
84  @NotNull
86 
90  @NotNull
92 
96  @NotNull
97  private final Component parent;
98 
102  @NotNull
103  private final FileFilter mapFileFilter;
104 
108  @NotNull
109  private final FileFilter scriptFileFilter;
110 
114  @NotNull
116 
120  @NotNull
121  private final String scriptExtension;
122 
126  @NotNull
128 
132  @NotNull
133  private final PathManager pathManager;
134 
139  @Nullable
140  private JFileChooser fileChooser;
141 
157  public DefaultFileControl(@NotNull final ProjectSettings projectSettings, @NotNull final VolatileSettings volatileSettings, @NotNull final MapImageCache<G, A, R> mapImageCache, @NotNull final MapManager<G, A, R> mapManager, @NotNull final MapViewsManager<G, A, R> mapViewsManager, @NotNull final Component parent, @NotNull final FileFilter mapFileFilter, @NotNull final FileFilter scriptFileFilter, @NotNull final NewMapDialogFactory<G, A, R> newMapDialogFactory, @NotNull final String scriptExtension, @NotNull final ScriptEditControl scriptEditControl, @NotNull final PathManager pathManager) {
158  this.projectSettings = projectSettings;
159  this.volatileSettings = volatileSettings;
160  this.mapImageCache = mapImageCache;
161  this.mapManager = mapManager;
162  this.mapViewsManager = mapViewsManager;
163  this.parent = parent;
164  this.mapFileFilter = mapFileFilter;
165  this.scriptFileFilter = scriptFileFilter;
166  this.newMapDialogFactory = newMapDialogFactory;
167  this.scriptExtension = scriptExtension;
168  this.scriptEditControl = scriptEditControl;
169  this.pathManager = pathManager;
170  }
171 
176  @NotNull
177  private JFileChooser createFileChooser() {
178  final JFileChooser tmpFileChooser = new JFileChooser();
179  tmpFileChooser.setDialogTitle(ActionBuilderUtils.getString(ACTION_BUILDER, "fileDialog.title"));
180  tmpFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
181  tmpFileChooser.setMultiSelectionEnabled(true);
182  tmpFileChooser.addChoosableFileFilter(scriptFileFilter);
183  tmpFileChooser.addChoosableFileFilter(mapFileFilter);
184  if (projectSettings.getMapsDirectory().exists()) {
185  FileChooserUtils.setCurrentDirectory(tmpFileChooser, projectSettings.getMapsDirectory());
186  }
187  tmpFileChooser.setAccessory(new MapPreviewAccessory(mapImageCache, tmpFileChooser));
188  return tmpFileChooser;
189  }
190 
191  @Override
192  public void openFile(final boolean mapFile) {
193  if (fileChooser == null) {
194  fileChooser = createFileChooser();
195  }
196  final JFileChooser tmpFileChooser = fileChooser;
197  if (mapFile) {
198  tmpFileChooser.setFileFilter(mapFileFilter);
199  } else {
200  tmpFileChooser.setFileFilter(scriptFileFilter);
201  }
203  final int returnVal = tmpFileChooser.showOpenDialog(parent);
204  if (returnVal != JFileChooser.APPROVE_OPTION) {
205  return;
206  }
207 
208  final File[] files = tmpFileChooser.getSelectedFiles();
209  for (final File file : files) {
210  final boolean isScriptFile = file.getName().toLowerCase().endsWith(scriptExtension);
211  if (file.isFile()) {
212  if (isScriptFile) {
213  scriptEditControl.openScriptFile(file.getAbsolutePath());
214  } else {
215  try {
216  mapViewsManager.openMapFileWithView(file, null, null);
217  } catch (final IOException ex) {
218  reportLoadError(file, ex.getMessage());
219  }
220  }
221  } else if (!file.exists()) {
222  if (isScriptFile) {
223  scriptEditControl.newScript(); // TODO: pass filename
224  } else {
225  newMapDialogFactory.showNewMapDialog(); // XXX: pass file
226  }
227  } // If neither branch matches, it's a directory - what to do with directories?
228  }
229  }
230 
231  @Override
232  public boolean save(@NotNull final MapControl<G, A, R> mapControl) {
233  final MapFile mapFile = mapControl.getMapModel().getMapFile();
234  if (mapFile != null) {
235  try {
236  mapControl.save();
237  } catch (final IOException ex) {
238  reportSaveError(mapFile.getFile(), ex.getMessage());
239  return false;
240  }
241  return true;
242  }
243 
244  return saveAs(mapControl);
245  }
246 
247  @Override
248  public void saveAllMaps() {
249  for (final MapControl<G, A, R> mapControl : mapManager.getOpenedMaps()) {
250  if (mapControl.getMapModel().isModified() && !save(mapControl)) {
251  return;
252  }
253  }
254  }
255 
256  @Override
257  public boolean closeAllMaps() {
258  while (true) {
259  final MapControl<G, A, R> mapControl = mapManager.getOpenMap();
260  if (mapControl == null) {
261  break;
262  }
263 
264  if (!confirmSaveChanges(mapControl)) {
265  return false;
266  }
267 
268  mapManager.closeMap(mapControl);
269  }
270 
271  return true;
272  }
273 
274  @Override
275  public boolean saveAs(@NotNull final MapControl<G, A, R> mapControl) {
276  final File file = saveMapAs(mapControl);
277  if (file == null) {
278  return false;
279  }
280 
281  try {
282  mapControl.saveAs(pathManager.getMapFile(file));
283  } catch (final IOException ex) {
284  reportSaveError(file, ex.getMessage());
285  return false;
286  }
287 
288  return true;
289  }
290 
296  @Nullable
297  private File saveMapAs(@NotNull final MapControl<G, A, R> mapControl) {
298  final JFileChooser saveFileChooser = new JFileChooser();
299  saveFileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
300  saveFileChooser.setDialogTitle("Save Map Or Script As");
301  saveFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
302  saveFileChooser.setMultiSelectionEnabled(false);
303  saveFileChooser.resetChoosableFileFilters();
304  saveFileChooser.addChoosableFileFilter(scriptFileFilter);
305  saveFileChooser.setFileFilter(mapFileFilter);
306 
307  final MapFile mapFile = mapControl.getMapModel().getMapFile();
308  final File defaultDir = mapFile == null ? null : mapFile.getFile().getParentFile();
309  if (defaultDir != null && defaultDir.exists()) {
310  FileChooserUtils.setCurrentDirectory(saveFileChooser, defaultDir);
311  saveFileChooser.setSelectedFile(mapFile.getFile());
312  } else {
313  final File currentSaveMapDirectory = volatileSettings.getCurrentSaveMapDirectory();
314  FileChooserUtils.setCurrentDirectory(saveFileChooser, currentSaveMapDirectory);
315  saveFileChooser.setSelectedFile(new File(currentSaveMapDirectory, mapFile == null ? CommonConstants.DEFAULT_MAP_FILENAME : mapFile.getFile().getName()));
316  }
317 
318  final int returnVal = saveFileChooser.showSaveDialog(parent);
319  if (returnVal != JFileChooser.APPROVE_OPTION) {
320  return null;
321  }
322 
323  volatileSettings.setCurrentSaveMapDirectory(saveFileChooser.getCurrentDirectory());
324  final File file = saveFileChooser.getSelectedFile();
325  if (file.exists() && ACTION_BUILDER.showConfirmDialog(parent, JOptionPane.WARNING_MESSAGE, JOptionPane.OK_CANCEL_OPTION, "overwriteOtherFile", file.getName()) != JOptionPane.OK_OPTION) {
326  return null;
327  }
328 
329  return file;
330  }
331 
332  @Override
333  public boolean confirmSaveChanges(@NotNull final MapControl<G, A, R> mapControl) {
334  if (mapControl.getMapModel().isModified()) {
335  final int result = ACTION_BUILDER.showConfirmDialog(parent, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, "confirmSaveChanges", mapControl.getMapModel().getMapArchObject().getMapName());
336  if (result == JOptionPane.YES_OPTION) {
337  if (!save(mapControl)) {
338  return false;
339  }
340  } else if (result == JOptionPane.CANCEL_OPTION || result == JOptionPane.CLOSED_OPTION) {
341  return false;
342  }
343  }
344 
345  return true;
346  }
347 
348  @Override
349  public void reportSaveError(@NotNull final MapControl<G, A, R> mapControl, @NotNull final String message) {
350  final MapFile mapFile = mapControl.getMapModel().getMapFile();
351  assert mapFile != null;
352  reportSaveError(mapFile.getFile(), message);
353  }
354 
355  @Override
356  public void reportSaveError(@NotNull final File mapFile, @NotNull final String message) {
357  ACTION_BUILDER.showMessageDialog(parent, "encodeMapFile", mapFile, message);
358  }
359 
360  @Override
361  public void reportLoadError(@Nullable final File file, @NotNull final String message) {
362  ACTION_BUILDER.showMessageDialog(parent, "openFileLoadMap", file == null ? "<unknown>" : file, message);
363  }
364 
365  @Override
366  public void reportOutOfMapBoundsDeleted(@NotNull final File file, final int outOfMapBoundsDeleted, @NotNull final StringBuilder outOfMapBoundsObjects) {
367  ACTION_BUILDER.showMessageDialog(parent, "openFileOutOfMapBoundsDeleted", file, outOfMapBoundsDeleted, outOfMapBoundsObjects);
368  }
369 
370  @Override
371  public void reportOutOfMemory(@NotNull final File file) {
372  ACTION_BUILDER.showMessageDialog(parent, "mapOutOfMemory", file);
373  }
374 
375  @Override
376  public void reportTeleportCharacterError(@NotNull final String mapPath, @NotNull final String message) {
377  ACTION_BUILDER.showMessageDialog(parent, "teleportCharacterError", mapPath, message);
378  }
379 
380 }
final FileFilter mapFileFilter
The FileFilter for selecting map files.
void reportSaveError(@NotNull final MapControl< G, A, R > mapControl, @NotNull final String message)
Reports an error while saving a map file to the user.
This class contains methods for converting relative map paths to absolute map paths and vice versa...
A MapManager manages all opened maps.
Definition: MapManager.java:37
void reportLoadError(@Nullable final File file, @NotNull final String message)
Graphical User Interface of Gridarta.
Reading and writing of maps, handling of paths.
Settings that apply to a project.
void reportTeleportCharacterError(@NotNull final String mapPath, @NotNull final String message)
Reports an error while teleporting a character to the current map.
Utility class for JFileChooser related functions.
MapFile getMapFile(@NotNull final AbsoluteMapPath mapPath)
Returns a MapFile instance from an AbsoluteMapPath.
void reportSaveError(@NotNull final File mapFile, @NotNull final String message)
Reports an error while saving a map file to the user.
final MapManager< G, A, R > mapManager
The MapManager.
File saveMapAs(@NotNull final MapControl< G, A, R > mapControl)
Displays a "save as" dialog.
void setCurrentSaveMapDirectory(@NotNull File currentSaveMapDirectory)
Sets the default directory for saving maps.
final MapImageCache< G, A, R > mapImageCache
The MapImageCache.
final Component parent
The parent component for showing dialog boxes.
void showNewMapDialog()
Shows a dialog for creating a new map.
Class with constants used in Gridarta and derivates.
Default FileControl implementation.
JFileChooser createFileChooser()
Creates the JFileChooser for opening a file.
File getCurrentSaveMapDirectory()
Returns the default directory for saving maps.
void openScriptFile(@NotNull final String pathName)
Open a new empty script document.
static String getString(@NotNull final ActionBuilder actionBuilder, @NotNull final String key, @NotNull final String defaultValue)
Returns the value of a key.
final MapViewsManager< G, A, R > mapViewsManager
The MapViewsManager.
void reportOutOfMemory(@NotNull final File file)
Base package of all Gridarta classes.
static void setCurrentDirectory(@NotNull final JFileChooser fileChooser, @Nullable final File dir)
Calls JFileChooser#setCurrentDirectory(File).
This package contains the classes for the script editor used within the editor to create and modify P...
Definition: Actions.java:20
Reflects a game object (object on a map).
Definition: GameObject.java:36
MapView< G, A, R > openMapFileWithView(@NotNull final MapFile mapFile, @Nullable final Point viewPosition, @Nullable final Point centerSquare)
Load a map file and create a map view.
final NewMapDialogFactory< G, A, R > newMapDialogFactory
The NewMapDialogFactory.
static final String DEFAULT_MAP_FILENAME
Default file name for new maps.
void reportOutOfMapBoundsDeleted(@NotNull final File file, final int outOfMapBoundsDeleted, @NotNull final StringBuilder outOfMapBoundsObjects)
static final ActionBuilder ACTION_BUILDER
The ActionBuilder.
GameObjects are the objects based on Archetypes found on maps.
Caches icon and preview images for map files.
void openFile(final boolean mapFile)
The user wants to edit a file.
DefaultFileControl(@NotNull final ProjectSettings projectSettings, @NotNull final VolatileSettings volatileSettings, @NotNull final MapImageCache< G, A, R > mapImageCache, @NotNull final MapManager< G, A, R > mapManager, @NotNull final MapViewsManager< G, A, R > mapViewsManager, @NotNull final Component parent, @NotNull final FileFilter mapFileFilter, @NotNull final FileFilter scriptFileFilter, @NotNull final NewMapDialogFactory< G, A, R > newMapDialogFactory, @NotNull final String scriptExtension, @NotNull final ScriptEditControl scriptEditControl, @NotNull final PathManager pathManager)
Creates a new instance.
final String scriptExtension
The file extension for script files.
Base classes for rendering maps.
JFileChooser fileChooser
The JFileChooser for opening a file.
final VolatileSettings volatileSettings
The VolatileSettings.
ScriptEditControl - Manages events and data flow for the script editor entity.
Utility class to create NewMapDialog instances.
Utility class for ActionBuilder related functions.
final FileFilter scriptFileFilter
The FileFilter for selecting script files.
Currently nothing more than a marker interface for unification.
Definition: MapControl.java:35
final ProjectSettings projectSettings
The ProjectSettings.
void closeMap(@NotNull MapControl< G, A, R > mapControl)
Closes the given map, ignoring modified status.
boolean confirmSaveChanges(@NotNull final MapControl< G, A, R > mapControl)
Asks the user whether to save changes of a map.
File getFile()
Returns a File for this map file.
Definition: MapFile.java:102
boolean save(@NotNull final MapControl< G, A, R > mapControl)
Save one map.
Abstract base class for MapPreviewAccessories which are used for previewing maps in JFileChoosers...
MapControl< G, A, R > getOpenMap()
Returns one open map.
static void sanitizeCurrentDirectory(@NotNull final JFileChooser fileChooser)
Makes sure the current directory of a JFileChooser is valid.
File getMapsDirectory()
Returns the default maps directory.
final ScriptEditControl scriptEditControl
The ScriptEditControl to forward to.
void newScript()
Open a new empty script document.
boolean closeAllMaps()
Invoked when the user wants to close all maps.
boolean saveAs(@NotNull final MapControl< G, A, R > mapControl)
Asks the user for a filename, then saves the map.
List< MapControl< G, A, R > > getOpenedMaps()
Returns all opened maps.
The location of a map file with a map directory.
Definition: MapFile.java:31
final PathManager pathManager
The PathManager for creating MapFile instances.
Settings that are not retained across editor restarts.