[Aprog]
[aprog.git] / Aprog / src / net / sourceforge / aprog / af / AFTools.java
blob9207ae05d0e5edad81542fe6218f454f372e2668
1 /*
2 * The MIT License
3 *
4 * Copyright 2010 Codist Monk.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 package net.sourceforge.aprog.af;
27 import static javax.swing.KeyStroke.getKeyStroke;
29 import static net.sourceforge.aprog.af.AFConstants.Variables.*;
30 import static net.sourceforge.aprog.af.MacOSXTools.*;
31 import static net.sourceforge.aprog.swing.SwingTools.*;
32 import static net.sourceforge.aprog.i18n.Messages.*;
33 import static net.sourceforge.aprog.tools.Tools.*;
35 import java.awt.Component;
36 import java.lang.reflect.Method;
37 import java.lang.reflect.Proxy;
39 import javax.swing.JMenu;
40 import javax.swing.JMenuItem;
41 import javax.swing.JTabbedPane;
42 import javax.swing.KeyStroke;
43 import net.sourceforge.aprog.context.Context;
45 import net.sourceforge.aprog.swing.SwingTools;
46 import net.sourceforge.aprog.tools.AbstractInvocationHandler;
47 import net.sourceforge.aprog.tools.IllegalInstantiationException;
48 import net.sourceforge.aprog.tools.Tools;
50 /**
52 * @author codistmonk (creation 2010-09-22)
54 public final class AFTools {
56 /**
57 * @throws IllegalInstantiationException To prevent instantiation
59 private AFTools() {
60 throw new IllegalInstantiationException();
63 public static final String META = MacOSXTools.MAC_OS_X ? "meta" : "control";
65 /**
66 * Prepares the application to use the OS default look and feel.
67 * <br>On Mac OS X, sets up the use of the screen menu bar and the application name.
69 * @param applicationName
70 * <br>Not null
72 public static final void setupSystemLookAndFeel(final String applicationName) {
73 if (MAC_OS_X) {
74 useScreenMenuBar();
75 setApplicationName(applicationName);
78 useSystemLookAndFeel();
81 /**
82 * Creates a new context with the folowing properties:<ul>
83 * <li>{@link AFConstants.Variables#APPLICATION_NAME} -&gt; {@link AFConstants#APPLICATION_NAME}
84 * <li>{@link AFConstants.Variables#APPLICATION_VERSION} -&gt; {@link AFConstants#APPLICATION_VERSION}
85 * <li>{@link AFConstants.Variables#APPLICATION_COPYRIGHT} -&gt; {@link AFConstants#APPLICATION_COPYRIGHT}
86 * <li>{@link AFConstants.Variables#APPLICATION_ICON_PATH} -&gt; {@link AFConstants#APPLICATION_ICON_PATH}
87 * </ul>.
89 * @return
90 * <br>Not null
91 * <br>New
93 public static final Context newContext() {
94 final Context result = new Context();
96 result.set(APPLICATION_NAME, AFConstants.APPLICATION_NAME);
97 result.set(APPLICATION_VERSION, AFConstants.APPLICATION_VERSION);
98 result.set(APPLICATION_COPYRIGHT, AFConstants.APPLICATION_COPYRIGHT);
99 result.set(APPLICATION_ICON_PATH, AFConstants.APPLICATION_ICON_PATH);
101 return result;
105 * If {@code context} value for the key {@link AFConstants.Variables#ACTIONS_SHOW_ABOUT_DIALOG} is null,
106 * then associates a new {@link ShowAboutDialogAction} to the key.
107 * <br>On Mac OS X, if the use of the screen menu bar is enabled then registers a listener for the appropriate menu item.
109 * @param context
110 * <br>Not null
111 * <br>Shared
112 * @return An autotranslated menu item or null if the screen menu bar is used on Mac OS X
113 * <br>Maybe null
114 * <br>New
116 public static final JMenuItem newAboutItem(final Context context) {
117 checkAWT();
119 if (context.get(ACTIONS_SHOW_ABOUT_DIALOG) == null) {
120 new ShowAboutDialogAction(context);
123 if (MAC_OS_X && getUseScreenMenuBar()) {
124 enableAboutMenu();
126 if (registerMacOSXApplicationListener("handleAbout",
127 AFTools.class, "perform", context, ACTIONS_SHOW_ABOUT_DIALOG)) {
128 return null;
132 return item("About", context, ACTIONS_SHOW_ABOUT_DIALOG);
137 * @param context
138 * <br>Not null
139 * <br>Shared
140 * @return
141 * <br>Maybe null
142 * <br>New
144 public static final JMenuItem newPreferencesItem(final Context context) {
145 checkAWT();
147 if (context.get(ACTIONS_SHOW_PREFERENCES_DIALOG) == null) {
148 new ShowPreferencesDialogAction(context);
151 if (MAC_OS_X && getUseScreenMenuBar()) {
152 enablePreferencesMenu();
154 if (registerMacOSXApplicationListener("handlePreferences",
155 AFTools.class, "perform", context, ACTIONS_SHOW_PREFERENCES_DIALOG)) {
156 return null;
160 return item("Preferences...", getKeyStroke(META + " R"),
161 context, ACTIONS_SHOW_PREFERENCES_DIALOG);
166 * @param context
167 * <br>Not null
168 * <br>Shared
169 * @return
170 * <br>Maybe null
171 * <br>New
173 public static final JMenuItem newQuitItem(final Context context) {
174 checkAWT();
176 if (context.get(ACTIONS_QUIT) == null) {
177 new QuitAction(context);
180 if (MAC_OS_X && getUseScreenMenuBar()) {
181 if (registerMacOSXApplicationListener("handleQuit",
182 AFTools.class, "perform", context, ACTIONS_QUIT)) {
183 return null;
187 return item("Quit", getKeyStroke(META + " Q"),
188 context, ACTIONS_QUIT);
193 * @param context
194 * <br>Not null
195 * @param actionKey
196 * <br>Not null
198 public static final void perform(final Context context, final String actionKey) {
199 ((AbstractAFAction) context.get(actionKey)).perform();
204 * @param tabbedPane
205 * <br>Not null
206 * @param component
207 * <br>Not null
208 * @return The index of {@code component} in {@code tabbedPane}, or {@code -1} if it cannot be found
209 * <br>Range: {@code [-1 .. tabbedPane.getTabCount() - 1]}
211 public static final int indexOf(final JTabbedPane tabbedPane, final Component component) {
212 checkAWT();
214 for (int i = 0; i < tabbedPane.getTabCount(); ++i) {
215 if (component == tabbedPane.getComponentAt(i)) {
216 return i;
220 return -1;
224 * Creates a localized menu from the elements in {@code items}.
225 * <br>Uses {@link net.sourceforge.aprog.i18n.Messages#translate(java.lang.Object, java.lang.Object[])}
226 * and {@link SwingTools#menu(java.lang.String, javax.swing.JMenuItem[])}.
228 * @param translationKey
229 * <br>Not null
230 * <br>Shared
231 * @param items
232 * <br>Not null
233 * @return
234 * <br>Not null
235 * <br>New
237 public static final JMenu menu(final String translationKey, final JMenuItem... items) {
238 checkAWT();
240 return translate(SwingTools.menu(translationKey, items));
245 * @param translationKey
246 * <br>Not null
247 * <br>Shared
248 * @param context
249 * <br>Not null
250 * <br>Shared
251 * @param actionKey
252 * <br>Not null
253 * <br>Shared
254 * @return An autotranslated menu item
255 * <br>Not null
256 * <br>New
258 public static final JMenuItem item(final String translationKey, final Context context,
259 final String actionKey) {
260 checkAWT();
262 return translate(new JMenuItem(new AFSwingAction(context, actionKey)
263 .setName(translationKey)));
268 * @param translationKey
269 * <br>Not null
270 * <br>Shared
271 * @param shortcut
272 * <br>Not null
273 * <br>Shared
274 * @param context
275 * <br>Not null
276 * <br>Shared
277 * @param actionKey
278 * <br>Not null
279 * <br>Shared
280 * @return
281 * <br>Not null
282 * <br>New
284 public static final JMenuItem item(final String translationKey, final KeyStroke shortcut,
285 final Context context, final String actionKey) {
286 checkAWT();
288 return translate(new JMenuItem(new AFSwingAction(context, actionKey)
289 .setName(translationKey)
290 .setShortcut(shortcut)));
295 * @param <L> The listener type
296 * @param listenerClass
297 * <br>Not null
298 * @param listenerMethodName
299 * <br>Not null
300 * @param objectOrClass
301 * <br>Not null
302 * @param methodName
303 * <br>Not null
304 * @param arguments
305 * <br>Not null
306 * @return
307 * <br>Not null
308 * <br>New
310 @SuppressWarnings("unchecked")
311 public static final <L> L newListener(final Class<L> listenerClass, final String listenerMethodName,
312 final Object objectOrClass, final String methodName, final Object... arguments) {
313 return (L) Proxy.newProxyInstance(getCallerClass().getClassLoader(), array(listenerClass),
314 new ListenerInvocationHandler(listenerMethodName, objectOrClass, methodName, arguments));
319 * @author codistmonk (creation 2010-07-03)
321 public static final class ListenerInvocationHandler extends AbstractInvocationHandler {
323 private final String listenerMethodName;
325 private final Object objectOrClass;
327 private final String methodName;
329 private final Object[] arguments;
333 * @param listenerMethodName
334 * <br>Not null
335 * <br>Shared
336 * @param objectOrClass
337 * <br>Not null
338 * <br>Shared
339 * @param methodName
340 * <br>Not null
341 * <br>Shared
342 * @param arguments
343 * <br>Not null
344 * <br>Shared
346 public ListenerInvocationHandler(final String listenerMethodName,
347 final Object objectOrClass, final String methodName, final Object... arguments) {
348 this.listenerMethodName = listenerMethodName;
349 this.objectOrClass = objectOrClass;
350 this.methodName = methodName;
351 this.arguments = arguments;
354 @Override
355 public final Object invoke(final Object proxy,
356 final Method method, final Object[] arguments) throws Throwable {
357 if (method.getName().equals(this.listenerMethodName)) {
358 return Tools.invoke(this.objectOrClass, this.methodName, this.arguments);
361 return this.defaultInvoke(proxy, method, arguments);