Gridarta Editor
ScriptArchEditor.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.scripts;
21 
22 import java.awt.Color;
23 import java.awt.Component;
24 import java.awt.Container;
25 import java.awt.FlowLayout;
26 import java.awt.Frame;
27 import java.awt.Insets;
28 import java.awt.event.ActionEvent;
29 import java.awt.event.ActionListener;
30 import java.io.File;
31 import java.io.IOException;
32 import javax.swing.AbstractButton;
33 import javax.swing.BorderFactory;
34 import javax.swing.Box;
35 import javax.swing.BoxLayout;
36 import javax.swing.JButton;
37 import javax.swing.JComboBox;
38 import javax.swing.JDialog;
39 import javax.swing.JFileChooser;
40 import javax.swing.JLabel;
41 import javax.swing.JOptionPane;
42 import javax.swing.JPanel;
43 import javax.swing.JTextField;
44 import javax.swing.WindowConstants;
45 import javax.swing.filechooser.FileFilter;
46 import javax.swing.text.JTextComponent;
62 import net.sf.japi.swing.action.ActionBuilder;
63 import net.sf.japi.swing.action.ActionBuilderFactory;
64 import net.sf.japi.util.Arrays2;
65 import org.jetbrains.annotations.NotNull;
66 
71 public class ScriptArchEditor<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
72 
76  @NotNull
77  private static final ActionBuilder ACTION_BUILDER = ActionBuilderFactory.getInstance().getActionBuilder("net.sf.gridarta");
78 
82  @NotNull
84 
88  @NotNull
89  private final String scriptEnding;
90 
94  @NotNull
95  private final PathManager pathManager;
96 
100  @NotNull
102 
103  @NotNull
104  private final JComboBox<?> eventTypeBox;
105 
106  @NotNull
107  private final FileFilter scriptFileFilter;
108 
112  @NotNull
114 
118  @NotNull
120 
121  @NotNull
122  private final JComboBox<String> pluginNameBox;
123 
124  @NotNull
125  private JTextComponent inputScriptPath;
126 
127  @NotNull
128  private JTextComponent inputOptions;
129 
133  @NotNull
135 
148  public ScriptArchEditor(@NotNull final ScriptedEventFactory<G, A, R> scriptedEventFactory, @NotNull final String scriptEnding, @NotNull final String name, @NotNull final ScriptArchUtils scriptArchUtils, @NotNull final FileFilter scriptFileFilter, @NotNull final ProjectSettings projectSettings, @NotNull final MapManager<?, ?, ?> mapManager, @NotNull final PathManager pathManager, @NotNull final ScriptEditControl scriptEditControl) {
149  this.scriptedEventFactory = scriptedEventFactory;
150  this.scriptEnding = scriptEnding;
151  this.scriptArchUtils = scriptArchUtils;
152  this.pathManager = pathManager;
153  this.scriptEditControl = scriptEditControl;
154 
155  pluginNameBox = new JComboBox<>(new String[] { name });
156  pluginNameBox.setSelectedIndex(0);
157 
159  this.scriptFileFilter = scriptFileFilter;
160  this.projectSettings = projectSettings;
161  this.mapManager = mapManager;
162  }
163 
164  @NotNull
165  private static JComboBox<?> createEventTypeBox(@NotNull final ScriptArchUtils scriptArchUtils) {
166  final String[] valuesArray = scriptArchUtils.getEventNames();
167  final JComboBox<?> tmpEventTypeBox = new JComboBox<>(valuesArray);
168  tmpEventTypeBox.setSelectedIndex(Arrays2.linearEqualitySearch("say", valuesArray));
169  return tmpEventTypeBox;
170  }
171 
179  public void addEventScript(@NotNull final G gameObject, @NotNull final ScriptArchData<G, A, R> scriptArchData, @NotNull final Frame parent) {
180  final String archName = gameObject.getBestName();
181  // create a reasonable default script name for lazy users :-)
182  final String defScriptName = ScriptUtils.chooseDefaultScriptName(mapManager.getLocalMapDir(), archName, scriptEnding, pathManager);
183 
184  // initialize popup frame
185  final JDialog newScriptFrame = new JDialog(parent, ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventTitleNew"), true);
186  newScriptFrame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
187 
188  final JPanel mainPanel = new JPanel();
189  mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
190  mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 2, 5));
191 
192  // first line: heading
193  final Container line1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
194  final Component headingLabel = new JLabel(ActionBuilderUtils.format(ACTION_BUILDER, "scriptedEventHeading", archName));
195  headingLabel.setForeground(Color.black);
196  line1.add(headingLabel);
197  mainPanel.add(line1);
198 
199  // event type
200  mainPanel.add(Box.createVerticalStrut(10));
201  final Container line2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
202  final Component typeLabel = ActionBuilderUtils.newLabel(ACTION_BUILDER, "scriptedEventType");
203  line2.add(typeLabel);
204  line2.add(eventTypeBox);
205  //mainPanel.add(line2);
206  line2.add(Box.createHorizontalStrut(10));
207 
208  // plugin name
209  final Component pluginLabel = ActionBuilderUtils.newLabel(ACTION_BUILDER, "scriptedEventPlugin");
210  line2.add(pluginLabel);
211  line2.add(pluginNameBox);
212  mainPanel.add(line2);
213 
214  // path
215  mainPanel.add(Box.createVerticalStrut(5));
216  final Container line3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
217  final Component scriptFileLabel = ActionBuilderUtils.newLabel(ACTION_BUILDER, "scriptedEventScript");
218  line3.add(scriptFileLabel);
219  mainPanel.add(line3);
220  inputScriptPath = new JTextField(defScriptName, 20);
221  final AbstractButton browseButton = new JButton("...");
222  browseButton.setMargin(new Insets(0, 10, 0, 10));
223  browseButton.addActionListener(new ActionListener() {
224 
225  @Override
226  public void actionPerformed(@NotNull final ActionEvent e) {
227  final File home = mapManager.getLocalMapDir();
228 
229  final JFileChooser fileChooser = new JFileChooser();
230  fileChooser.setDialogTitle(ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventSelectFile"));
231  fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
232  FileChooserUtils.setCurrentDirectory(fileChooser, home);
233  fileChooser.setMultiSelectionEnabled(false);
234  fileChooser.setFileFilter(scriptFileFilter);
235 
236  if (fileChooser.showOpenDialog(newScriptFrame) == JFileChooser.APPROVE_OPTION) {
237  // user has selected a file
238  final File f = fileChooser.getSelectedFile();
240  }
241  }
242  });
243  line3.add(inputScriptPath);
244  line3.add(browseButton);
245  mainPanel.add(line3);
246 
247  // options
248  mainPanel.add(Box.createVerticalStrut(5));
249  final Container line4 = new JPanel(new FlowLayout(FlowLayout.LEFT));
250  line4.add(new JLabel(ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventOptions")));
251  inputOptions = new JTextField("", 20);
252  line4.add(inputOptions);
253  mainPanel.add(line4);
254 
255  // description
256  final Container line5 = new JPanel(new FlowLayout(FlowLayout.LEFT));
257  final JPanel textPanel = new JPanel();
258  textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS));
259  final Component label1 = ActionBuilderUtils.newLabel(ACTION_BUILDER, "scriptedEventInfo1");
260  textPanel.add(label1);
261  final Component label2 = ActionBuilderUtils.newLabel(ACTION_BUILDER, "scriptedEventInfo2");
262  textPanel.add(label2);
263  line5.add(textPanel);
264  mainPanel.add(line5);
265 
266  // button panel:
267  mainPanel.add(Box.createVerticalStrut(10));
268  final Container line6 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
269  final AbstractButton nsOkButton = new JButton(ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventOk"));
270  nsOkButton.addActionListener(new ActionListener() {
271 
272  @Override
273  public void actionPerformed(@NotNull final ActionEvent e) {
274  createNewEvent(newScriptFrame, scriptArchData, gameObject);
275  }
276 
277  });
278  line6.add(nsOkButton);
279 
280  final AbstractButton cancelButton = new JButton(ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventCancel"));
281  cancelButton.addActionListener(new ActionListener() {
282 
283  @Override
284  public void actionPerformed(@NotNull final ActionEvent e) {
285  newScriptFrame.setVisible(false);
286  }
287 
288  });
289  line6.add(cancelButton);
290  mainPanel.add(line6);
291 
292  newScriptFrame.getContentPane().add(mainPanel);
293  newScriptFrame.pack();
294  newScriptFrame.setLocationRelativeTo(parent);
295  newScriptFrame.setVisible(true);
296  }
297 
298  private void createNewEvent(@NotNull final Component frame, @NotNull final ScriptArchData<G, A, R> scriptArchData, @NotNull final G gameObject) {
299  final StringBuilder scriptPath = new StringBuilder(inputScriptPath.getText().trim().replace('\\', '/'));
300  final String options = inputOptions.getText().trim();
301  final int eventType = scriptArchUtils.indexToEventType(eventTypeBox.getSelectedIndex());
302  final String pluginName = ((String) pluginNameBox.getSelectedItem()).trim();
303 
304  final File localMapDir = mapManager.getLocalMapDir();
305 
306  // first check if that event type is not already in use
307  final GameObject<G, A, R> replaceObject = scriptArchData.getScriptedEvent(eventType, gameObject);
308  if (replaceObject != null) {
309  // collision with existing event -> ask user: replace?
310  if (JOptionPane.showConfirmDialog(frame, ActionBuilderUtils.format(ACTION_BUILDER, "scriptedEventReplace", scriptArchUtils.typeName(eventType)), ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventReplaceTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE) == JOptionPane.NO_OPTION) {
311  // bail out
312  return;
313  }
314  }
315 
316  String absScriptPath;
317  if (scriptPath.length() > 0 && scriptPath.charAt(0) == '/') {
318  // script path is absolute
319  final File mapDir = projectSettings.getMapsDirectory();
320  if (!mapDir.exists()) {
321  // if map dir doesn't exist, this is not going to work
322  frame.setVisible(false);
323  ACTION_BUILDER.showMessageDialog(frame, "mapDirDoesntExist", mapDir);
324  return;
325  }
326 
327  absScriptPath = mapDir.getAbsolutePath() + scriptPath;
328  } else {
329  // script path is relative
330  absScriptPath = localMapDir.getAbsolutePath() + "/" + scriptPath;
331  }
332 
333  // now check if the specified path points to an existing script
334  File newScriptFile = new File(absScriptPath);
335  if (!newScriptFile.exists() && !absScriptPath.endsWith(scriptEnding)) {
336  absScriptPath += scriptEnding;
337  scriptPath.append(scriptEnding);
338  newScriptFile = new File(absScriptPath);
339  }
340 
341  if (newScriptFile.exists()) {
342  if (newScriptFile.isFile()) {
343  // file exists -> link it to the event
344  final ScriptedEvent<G, A, R> event;
345  try {
346  event = scriptedEventFactory.newScriptedEvent(eventType, pluginName, scriptPath.toString(), options);
347  } catch (final UndefinedEventArchetypeException ex) {
348  JOptionPane.showMessageDialog(frame, ActionBuilderUtils.format(ACTION_BUILDER, "scriptedEventCreateError", eventType, ex.getMessage()), ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventCreateErrorTitle"), JOptionPane.ERROR_MESSAGE);
349  return;
350  }
351  if (replaceObject != null) {
352  replaceObject.remove();
353  }
354  gameObject.addLast(event.getEventArch());
355  frame.setVisible(false); // close dialog
356  }
357 
358  return;
359  }
360 
361  if (!absScriptPath.endsWith(scriptEnding)) {
362  absScriptPath += scriptEnding;
363  scriptPath.append(scriptEnding);
364  newScriptFile = new File(absScriptPath);
365  }
366 
367  // file does not exist -> aks user: create new file?
368  if (JOptionPane.showConfirmDialog(frame, ActionBuilderUtils.format(ACTION_BUILDER, "scriptedEventCreate", newScriptFile.getName()), ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventCreateTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE) != JOptionPane.YES_OPTION) {
369  return;
370  }
371 
372  boolean couldCreateFile = false; // true when file creation successful
373  try {
374  // try to create new empty file
375  couldCreateFile = newScriptFile.createNewFile();
376  } catch (final IOException e) {
377  /* ignore (really?) */
378  }
379 
380  if (!couldCreateFile) {
381  JOptionPane.showMessageDialog(frame, ActionBuilderUtils.format(ACTION_BUILDER, "scriptedEventFileError", newScriptFile.getName()), ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventFileErrorTitle"), JOptionPane.ERROR_MESSAGE);
382  return;
383  }
384 
385  // file has been created, now link it to the event
386  final ScriptedEvent<G, A, R> event;
387  try {
388  event = scriptedEventFactory.newScriptedEvent(eventType, pluginName, scriptPath.toString(), options);
389  } catch (final UndefinedEventArchetypeException ex) {
390  JOptionPane.showMessageDialog(frame, ActionBuilderUtils.format(ACTION_BUILDER, "scriptedEventCreateError", eventType, ex.getMessage()), ActionBuilderUtils.getString(ACTION_BUILDER, "scriptedEventCreateErrorTitle"), JOptionPane.ERROR_MESSAGE);
391  return;
392  }
393  if (replaceObject != null) {
394  replaceObject.remove();
395  }
396  gameObject.addLast(event.getEventArch());
397  frame.setVisible(false); // close dialog
398 
399  // open new script file
400  scriptEditControl.openScriptFile(newScriptFile);
401  }
402 
403 }
net.sf.gridarta.model.scripts.ScriptUtils.chooseDefaultScriptName
static String chooseDefaultScriptName(@NotNull final File baseDir, final String archetypeName, final String scriptEnding, @NotNull final PathManager pathManager)
Definition: ScriptUtils.java:102
net.sf.gridarta.model.mapmanager
Definition: AbstractMapManager.java:20
net.sf.gridarta.model.scripts.ScriptedEventFactory
Definition: ScriptedEventFactory.java:31
net.sf.gridarta.model.scripts.ScriptUtils.localizeEventPath
static String localizeEventPath(@NotNull final File localMapDir, final File f, @NotNull final File mapDir)
Definition: ScriptUtils.java:52
net.sf.gridarta.textedit.scripteditor
Definition: Actions.java:20
net.sf.gridarta.gui.scripts.ScriptArchEditor.scriptArchUtils
final ScriptArchUtils scriptArchUtils
Definition: ScriptArchEditor.java:83
net.sf.gridarta.model.mapmanager.MapManager
Definition: MapManager.java:37
net.sf.gridarta.gui.scripts.ScriptArchEditor.scriptEnding
final String scriptEnding
Definition: ScriptArchEditor.java:89
net.sf.gridarta
net.sf.gridarta.utils.FileChooserUtils.setCurrentDirectory
static void setCurrentDirectory(@NotNull final JFileChooser fileChooser, @Nullable final File dir)
Definition: FileChooserUtils.java:48
net.sf
net.sf.gridarta.model.io.PathManager
Definition: PathManager.java:39
net.sf.gridarta.model.scripts
Definition: AbstractScriptedEvent.java:20
net.sf.gridarta.model.scripts.ScriptArchUtils.indexToEventType
int indexToEventType(int index)
net.sf.gridarta.model.archetype
Definition: AbstractArchetype.java:20
net.sf.gridarta.gui.scripts.ScriptArchEditor.projectSettings
final ProjectSettings projectSettings
Definition: ScriptArchEditor.java:113
net.sf.gridarta.model.gameobject.GameObject
Definition: GameObject.java:36
net.sf.gridarta.utils.ActionBuilderUtils.newLabel
static JLabel newLabel(@NotNull final ActionBuilder actionBuilder, @NotNull final String key)
Definition: ActionBuilderUtils.java:117
net.sf.gridarta.textedit
net.sf.gridarta.gui.scripts.ScriptArchEditor.createNewEvent
void createNewEvent(@NotNull final Component frame, @NotNull final ScriptArchData< G, A, R > scriptArchData, @NotNull final G gameObject)
Definition: ScriptArchEditor.java:298
net.sf.gridarta.model.scripts.ScriptArchUtils
Definition: ScriptArchUtils.java:26
net.sf.gridarta.model.scripts.ScriptUtils
Definition: ScriptUtils.java:29
net.sf.gridarta.model.scripts.ScriptedEvent
Definition: ScriptedEvent.java:31
net.sf.gridarta.model.gameobject
Definition: AbstractGameObject.java:20
net
net.sf.gridarta.gui.scripts.ScriptArchEditor.scriptFileFilter
final FileFilter scriptFileFilter
Definition: ScriptArchEditor.java:107
net.sf.gridarta.gui.scripts.ScriptArchEditor.mapManager
final MapManager<?, ?, ?> mapManager
Definition: ScriptArchEditor.java:119
net.sf.gridarta.model.scripts.UndefinedEventArchetypeException
Definition: UndefinedEventArchetypeException.java:29
net.sf.gridarta.gui.scripts.ScriptArchEditor.addEventScript
void addEventScript(@NotNull final G gameObject, @NotNull final ScriptArchData< G, A, R > scriptArchData, @NotNull final Frame parent)
Definition: ScriptArchEditor.java:179
net.sf.gridarta.model.maparchobject.MapArchObject
Definition: MapArchObject.java:40
net.sf.gridarta.model.mapmanager.MapManager.getLocalMapDir
File getLocalMapDir()
net.sf.gridarta.gui.scripts.ScriptArchEditor
Definition: ScriptArchEditor.java:71
net.sf.gridarta.gui.scripts.ScriptArchEditor.pluginNameBox
final JComboBox< String > pluginNameBox
Definition: ScriptArchEditor.java:122
net.sf.gridarta.gui.scripts.ScriptArchEditor.eventTypeBox
final JComboBox<?> eventTypeBox
Definition: ScriptArchEditor.java:104
net.sf.gridarta.model.scripts.ScriptArchUtils.getEventNames
String[] getEventNames()
net.sf.gridarta.utils.ActionBuilderUtils.format
static String format(@NotNull final ActionBuilder actionBuilder, @NotNull final String key, @NotNull final Object... args)
Definition: ActionBuilderUtils.java:101
net.sf.gridarta.model.scripts.ScriptArchUtils.typeName
String typeName(int eventType)
net.sf.gridarta.utils.ActionBuilderUtils.getString
static String getString(@NotNull final ActionBuilder actionBuilder, @NotNull final String key, @NotNull final String defaultValue)
Definition: ActionBuilderUtils.java:71
net.sf.gridarta.model.scripts.ScriptedEventFactory.newScriptedEvent
ScriptedEvent< G, A, R > newScriptedEvent(int eventType, @NotNull String pluginName, @NotNull String scriptPath, @NotNull String options)
net.sf.gridarta.textedit.scripteditor.ScriptEditControl.openScriptFile
void openScriptFile(@NotNull final File file)
Definition: ScriptEditControl.java:155
net.sf.gridarta.model.io
Definition: AbstractArchetypeParser.java:20
net.sf.gridarta.model.settings.ProjectSettings
Definition: ProjectSettings.java:29
net.sf.gridarta.gui.scripts.ScriptArchEditor.ScriptArchEditor
ScriptArchEditor(@NotNull final ScriptedEventFactory< G, A, R > scriptedEventFactory, @NotNull final String scriptEnding, @NotNull final String name, @NotNull final ScriptArchUtils scriptArchUtils, @NotNull final FileFilter scriptFileFilter, @NotNull final ProjectSettings projectSettings, @NotNull final MapManager<?, ?, ?> mapManager, @NotNull final PathManager pathManager, @NotNull final ScriptEditControl scriptEditControl)
Definition: ScriptArchEditor.java:148
net.sf.gridarta.gui.scripts.ScriptArchEditor.inputOptions
JTextComponent inputOptions
Definition: ScriptArchEditor.java:128
net.sf.gridarta.textedit.scripteditor.ScriptEditControl
Definition: ScriptEditControl.java:59
net.sf.gridarta.model
net.sf.gridarta.model.archetype.Archetype
Definition: Archetype.java:41
net.sf.gridarta.model.gameobject.GameObject.remove
void remove()
net.sf.gridarta.utils.FileChooserUtils
Definition: FileChooserUtils.java:31
net.sf.gridarta.utils.ActionBuilderUtils
Definition: ActionBuilderUtils.java:31
net.sf.gridarta.model.maparchobject
Definition: AbstractMapArchObject.java:20
net.sf.gridarta.model.settings.ProjectSettings.getMapsDirectory
File getMapsDirectory()
net.sf.gridarta.gui.scripts.ScriptArchEditor.createEventTypeBox
static JComboBox<?> createEventTypeBox(@NotNull final ScriptArchUtils scriptArchUtils)
Definition: ScriptArchEditor.java:165
net.sf.gridarta.gui.scripts.ScriptArchEditor.scriptEditControl
final ScriptEditControl scriptEditControl
Definition: ScriptArchEditor.java:101
net.sf.gridarta.gui.scripts.ScriptArchEditor.ACTION_BUILDER
static final ActionBuilder ACTION_BUILDER
Definition: ScriptArchEditor.java:77
net.sf.gridarta.gui.scripts.ScriptArchEditor.pathManager
final PathManager pathManager
Definition: ScriptArchEditor.java:95
net.sf.gridarta.utils
Definition: ActionBuilderUtils.java:20
net.sf.gridarta.model.settings
Definition: AbstractDefaultProjectSettings.java:20
net.sf.gridarta.model.scripts.ScriptedEvent.getEventArch
G getEventArch()
net.sf.gridarta.gui.scripts.ScriptArchEditor.scriptedEventFactory
final ScriptedEventFactory< G, A, R > scriptedEventFactory
Definition: ScriptArchEditor.java:134
net.sf.gridarta.model.scripts.ScriptArchData
Definition: ScriptArchData.java:35
net.sf.gridarta.gui.scripts.ScriptArchEditor.inputScriptPath
JTextComponent inputScriptPath
Definition: ScriptArchEditor.java:125