Gridarta Editor
ShortcutsManager.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2023 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.shortcuts;
21 
22 import java.awt.Component;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Comparator;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.prefs.AbstractPreferences;
31 import java.util.prefs.BackingStoreException;
32 import java.util.prefs.Preferences;
33 import javax.swing.Action;
34 import javax.swing.ActionMap;
35 import javax.swing.KeyStroke;
36 import net.sf.gridarta.MainControl;
40 import net.sf.japi.swing.action.ActionBuilder;
41 import net.sf.japi.swing.action.DummyAction;
42 import org.jetbrains.annotations.NotNull;
43 import org.jetbrains.annotations.Nullable;
44 
50 public class ShortcutsManager implements Iterable<Action> {
51 
55  @NotNull
56  private static final String PREFERENCES_SHORTCUT_PREFIX = "shortcut.";
57 
61  @NotNull
62  private static final String PREFERENCES_COMMENT_PREFIX = "prefs." + PREFERENCES_SHORTCUT_PREFIX;
63 
67  @NotNull
68  private final Collection<String> ignoreActions = new HashSet<>();
69 
73  @NotNull
74  private static final Comparator<Action> ACTION_COMPARATOR = (o1, o2) -> ActionUtils.getActionName(o1).compareToIgnoreCase(ActionUtils.getActionName(o2));
75 
79  @NotNull
80  private final ActionBuilder actionBuilder;
81 
85  @NotNull
86  private final Preferences preferences = Preferences.userNodeForPackage(MainControl.class);
87 
92  public ShortcutsManager(@NotNull final ActionBuilder actionBuilder) {
93  this.actionBuilder = actionBuilder;
94  }
95 
99  public void loadShortcuts() {
100  ignoreActions.addAll(Arrays.asList(StringUtils.PATTERN_SPACES.split(ActionBuilderUtils.getString(actionBuilder, "shortcutsIgnoreActions"), 0)));
101 
102  for (final Action action : this) {
103  final Object acceleratorKey = action.getValue(Action.ACCELERATOR_KEY);
104  if (acceleratorKey != null) {
105  action.putValue(ActionUtils.DEFAULT_ACCELERATOR_KEY, acceleratorKey);
106  }
107  }
108 
109  final Preferences commentPreferences = new AbstractPreferences(null, "") {
110 
111  @Override
112  protected void putSpi(final String key, final String value) {
113  throw new UnsupportedOperationException("unsupported operation: key=" + key + ", value=" + value);
114  }
115 
116  @Nullable
117  @Override
118  protected String getSpi(@NotNull final String key) {
119  if (!key.startsWith(PREFERENCES_COMMENT_PREFIX)) {
120  return null;
121  }
122 
123  final String actionKey = key.substring(PREFERENCES_COMMENT_PREFIX.length());
124  final Action action = actionBuilder.getAction(actionKey);
125  if (action == null || !isValidAction(action)) {
126  return null;
127  }
128 
129  return actionBuilder.format("prefs.shortcut", ActionUtils.getActionName(action));
130  }
131 
132  @Override
133  protected void removeSpi(final String key) {
134  throw new UnsupportedOperationException("unsupported operation: key=" + key);
135  }
136 
137  @Override
138  protected void removeNodeSpi() {
139  throw new UnsupportedOperationException("unsupported operation");
140  }
141 
142  @Override
143  protected String [] keysSpi() {
144  throw new UnsupportedOperationException("unsupported operation");
145  }
146 
147  @Override
148  protected String[] childrenNamesSpi() {
149  throw new UnsupportedOperationException("unsupported operation");
150  }
151 
152  @Override
153  protected AbstractPreferences childSpi(final String name) {
154  throw new UnsupportedOperationException("unsupported operation: name=" + name);
155  }
156 
157  @Override
158  protected void syncSpi() {
159  // ignore
160  }
161 
162  @Override
163  protected void flushSpi() {
164  // ignore
165  }
166 
167  };
168  actionBuilder.addPref(commentPreferences);
169 
170  for (final Action action : this) {
171  final String value = preferences.get(PREFERENCES_SHORTCUT_PREFIX + ActionUtils.getActionId(action), null);
172  if (value != null) {
173  if (value.equals(ActionUtils.NO_SHORTCUT)) {
174  action.putValue(Action.ACCELERATOR_KEY, null);
175  } else {
176  final Object acceleratorKey = KeyStroke.getKeyStroke(value);
177  if (acceleratorKey != null) {
178  action.putValue(Action.ACCELERATOR_KEY, acceleratorKey);
179  }
180  }
181  }
182  }
183  }
184 
188  public void saveShortcuts() {
189  try {
190  for (final String key : preferences.keys()) {
191  if (key.startsWith(PREFERENCES_SHORTCUT_PREFIX)) {
192  preferences.remove(key);
193  }
194  }
195  } catch (final BackingStoreException ignored) {
196  // ignore: just keep excess keys
197  }
198 
199  for (final Action action : this) {
200  final String acceleratorKey = ActionUtils.getShortcutDescription(action, Action.ACCELERATOR_KEY);
201  final String defaultAcceleratorKey = ActionUtils.getShortcutDescription(action, ActionUtils.DEFAULT_ACCELERATOR_KEY);
202  final String preferencesKey = PREFERENCES_SHORTCUT_PREFIX + ActionUtils.getActionId(action);
203  if (acceleratorKey.equals(defaultAcceleratorKey)) {
204  preferences.remove(preferencesKey);
205  } else {
206  preferences.put(preferencesKey, acceleratorKey);
207  }
208  }
209  }
210 
215  public void showShortcutsDialog(@NotNull final Component parentComponent) {
216  final ShortcutsDialog shortcutsDialog = new ShortcutsDialog(parentComponent, this);
217  shortcutsDialog.showDialog(parentComponent);
218  }
219 
223  public void revertAll() {
224  for (final Action action : this) {
225  action.putValue(Action.ACCELERATOR_KEY, action.getValue(ActionUtils.DEFAULT_ACCELERATOR_KEY));
226  }
227  }
228 
233  @Override
234  public Iterator<Action> iterator() {
235  final List<Action> result = new ArrayList<>();
236  final ActionMap actionMap = actionBuilder.getActionMap();
237  for (final Object key : actionMap.allKeys()) {
238  if (key instanceof String) {
239  final Action action = actionMap.get(key);
240  assert action != null;
241  if (isValidAction(action)) {
242  result.add(action);
243  }
244  }
245  }
246  result.sort(ACTION_COMPARATOR);
247  return result.iterator();
248  }
249 
255  private boolean isValidAction(@NotNull final Action action) {
256  if (action instanceof DummyAction) {
257  return false;
258  }
259 
260  final String id;
261  try {
262  id = ActionUtils.getActionId(action);
263  } catch (final IllegalArgumentException ignored) {
264  return false;
265  }
266 
267  return !ignoreActions.contains(id);
268  }
269 
270 }
name
name
Definition: ArchetypeTypeSetParserTest-ignoreDefaultAttribute1-result.txt:2
net.sf.gridarta.utils.ActionUtils.getActionId
static String getActionId(@NotNull final Action action)
Returns an Action's ID string.
Definition: ActionUtils.java:90
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager
Manager for shortcuts of all Actions in an {} instance.
Definition: ShortcutsManager.java:50
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.isValidAction
boolean isValidAction(@NotNull final Action action)
Returns whether an Action is a global action.
Definition: ShortcutsManager.java:255
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.ignoreActions
final Collection< String > ignoreActions
The action names to hide.
Definition: ShortcutsManager.java:68
net.sf.gridarta
Base package of all Gridarta classes.
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.actionBuilder
final ActionBuilder actionBuilder
The managed ActionBuilder.
Definition: ShortcutsManager.java:80
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.revertAll
void revertAll()
Reverts all shortcuts to their default values.
Definition: ShortcutsManager.java:223
net.sf
net.sf.gridarta.utils.ActionUtils.getActionName
static String getActionName(@NotNull final Action action)
Returns the name of an Action.
Definition: ActionUtils.java:72
net.sf.gridarta.utils.ActionUtils.getShortcutDescription
static String getShortcutDescription(@NotNull final Action action, @NotNull final String key)
Returns a description of the shortcut of an Action.
Definition: ActionUtils.java:163
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.saveShortcuts
void saveShortcuts()
Saves all shortcuts to the preferences.
Definition: ShortcutsManager.java:188
net.sf.gridarta.utils.ActionUtils
Utility class implementing Action related functions.
Definition: ActionUtils.java:33
net.sf.gridarta.utils.ActionUtils.NO_SHORTCUT
static final String NO_SHORTCUT
The shortcut description for actions without shortcuts.
Definition: ActionUtils.java:52
net
net.sf.gridarta.utils.ActionUtils.DEFAULT_ACCELERATOR_KEY
static final String DEFAULT_ACCELERATOR_KEY
Action key to store the default shortcut.
Definition: ActionUtils.java:58
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.iterator
Iterator< Action > iterator()
Returns all Actions.
Definition: ShortcutsManager.java:234
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.PREFERENCES_SHORTCUT_PREFIX
static final String PREFERENCES_SHORTCUT_PREFIX
The prefix for preferences keys for shortcuts.
Definition: ShortcutsManager.java:56
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.showShortcutsDialog
void showShortcutsDialog(@NotNull final Component parentComponent)
Displays a dialog to edit shortcuts.
Definition: ShortcutsManager.java:215
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.loadShortcuts
void loadShortcuts()
Restores all shortcuts from the preferences.
Definition: ShortcutsManager.java:99
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.preferences
final Preferences preferences
The Preferences for storing/restoring shortcuts.
Definition: ShortcutsManager.java:86
net.sf.gridarta.utils.ActionBuilderUtils.getString
static String getString(@NotNull final ActionBuilder actionBuilder, @NotNull final String key, @NotNull final String defaultValue)
Returns the value of a key.
Definition: ActionBuilderUtils.java:71
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsDialog.showDialog
void showDialog(@NotNull final Component parentComponent)
Opens the dialog.
Definition: ShortcutsDialog.java:208
net.sf.gridarta.utils.StringUtils
Utility class for string manipulation.
Definition: StringUtils.java:31
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.ShortcutsManager
ShortcutsManager(@NotNull final ActionBuilder actionBuilder)
Creates a new instance.
Definition: ShortcutsManager.java:92
net.sf.gridarta.utils.StringUtils.PATTERN_SPACES
static final Pattern PATTERN_SPACES
The pattern that matches a non-empty sequence of spaces.
Definition: StringUtils.java:73
net.sf.gridarta.utils.ActionBuilderUtils
Utility class for ActionBuilder related functions.
Definition: ActionBuilderUtils.java:31
net.sf.gridarta.utils
Definition: ActionBuilderUtils.java:20
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.ACTION_COMPARATOR
static final Comparator< Action > ACTION_COMPARATOR
A Comparator that compares Actions by name.
Definition: ShortcutsManager.java:74
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsDialog
Definition: ShortcutsDialog.java:65
net.sf.gridarta.gui.dialog.shortcuts.ShortcutsManager.PREFERENCES_COMMENT_PREFIX
static final String PREFERENCES_COMMENT_PREFIX
The prefix for preferences keys for shortcut comments.
Definition: ShortcutsManager.java:62
net.sf.gridarta.MainControl
Interface used as preferences location.
Definition: MainControl.java:27