source: josm/trunk/src/org/openstreetmap/josm/tools/PlatformHook.java@ 12756

Last change on this file since 12756 was 12748, checked in by Don-vip, 7 years ago

see #15229 - see #15182 - deprecate GuiHelper.getMenuShortcutKeyMaskEx() - replaced by PlatformHook.getMenuShortcutKeyMaskEx()

  • Property svn:eol-style set to native
File size: 11.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools;
3
4import java.awt.GraphicsEnvironment;
5import java.awt.Toolkit;
6import java.awt.event.KeyEvent;
7import java.io.BufferedReader;
8import java.io.File;
9import java.io.IOException;
10import java.io.InputStreamReader;
11import java.nio.charset.StandardCharsets;
12import java.security.KeyStore;
13import java.security.KeyStoreException;
14import java.security.NoSuchAlgorithmException;
15import java.security.cert.CertificateException;
16import java.security.cert.X509Certificate;
17import java.text.DateFormat;
18import java.util.Date;
19import java.util.List;
20
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.io.CertificateAmendment.CertAmend;
23import org.openstreetmap.josm.tools.date.DateUtils;
24
25/**
26 * This interface allows platform (operating system) dependent code
27 * to be bundled into self-contained classes.
28 * @since 1023
29 */
30public interface PlatformHook {
31
32 /**
33 * The preStartupHook will be called extremly early. It is
34 * guaranteed to be called before the GUI setup has started.
35 *
36 * Reason: On OSX we need to inform the Swing libraries
37 * that we want to be integrated with the OS before we setup our GUI.
38 */
39 default void preStartupHook() {
40 // Do nothing
41 }
42
43 /**
44 * The afterPrefStartupHook will be called early, but after
45 * the preferences have been loaded and basic processing of
46 * command line arguments is finished.
47 * It is guaranteed to be called before the GUI setup has started.
48 */
49 default void afterPrefStartupHook() {
50 // Do nothing
51 }
52
53 /**
54 * The startupHook will be called early, but after the GUI
55 * setup has started.
56 *
57 * Reason: On OSX we need to register some callbacks with the
58 * OS, so we'll receive events from the system menu.
59 * @param callback Java expiration callback, providing GUI feedback
60 * @since 12270 (signature)
61 */
62 default void startupHook(JavaExpirationCallback callback) {
63 // Do nothing
64 }
65
66 /**
67 * The openURL hook will be used to open an URL in the
68 * default web browser.
69 * @param url The URL to open
70 * @throws IOException if any I/O error occurs
71 */
72 void openUrl(String url) throws IOException;
73
74 /**
75 * The initSystemShortcuts hook will be called by the
76 * Shortcut class after the modifier groups have been read
77 * from the config, but before any shortcuts are read from
78 * it or registered from within the application.
79 *
80 * Please note that you are not allowed to register any
81 * shortuts from this hook, but only "systemCuts"!
82 *
83 * BTW: SystemCuts should be named "system:<whatever>",
84 * and it'd be best if sou'd recycle the names already used
85 * by the Windows and OSX hooks. Especially the later has
86 * really many of them.
87 *
88 * You should also register any and all shortcuts that the
89 * operation system handles itself to block JOSM from trying
90 * to use them---as that would just not work. Call setAutomatic
91 * on them to prevent the keyboard preferences from allowing the
92 * user to change them.
93 */
94 void initSystemShortcuts();
95
96 /**
97 * The makeTooltip hook will be called whenever a tooltip for
98 * a menu or button is created.
99 *
100 * Tooltips are usually not system dependent, unless the
101 * JVM is too dumb to provide correct names for all the keys.
102 *
103 * Some LAFs don't understand HTML, such as the OSX LAFs.
104 *
105 * @param name Tooltip text to display
106 * @param sc Shortcut associated (to display accelerator between parenthesis)
107 * @return Full tooltip text (name + accelerator)
108 */
109 default String makeTooltip(String name, Shortcut sc) {
110 StringBuilder result = new StringBuilder();
111 result.append("<html>").append(name);
112 if (sc != null && !sc.getKeyText().isEmpty()) {
113 result.append(" <font size='-2'>(")
114 .append(sc.getKeyText())
115 .append(")</font>");
116 }
117 return result.append("&nbsp;</html>").toString();
118 }
119
120 /**
121 * Returns the default LAF to be used on this platform to look almost as a native application.
122 * @return The default native LAF for this platform
123 */
124 String getDefaultStyle();
125
126 /**
127 * Determines if the platform allows full-screen.
128 * @return {@code true} if full screen is allowed, {@code false} otherwise
129 */
130 default boolean canFullscreen() {
131 return !GraphicsEnvironment.isHeadless() &&
132 GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isFullScreenSupported();
133 }
134
135 /**
136 * Renames a file.
137 * @param from Source file
138 * @param to Target file
139 * @return {@code true} if the file has been renamed, {@code false} otherwise
140 */
141 default boolean rename(File from, File to) {
142 return from.renameTo(to);
143 }
144
145 /**
146 * Returns a detailed OS description (at least family + version).
147 * @return A detailed OS description.
148 * @since 5850
149 */
150 String getOSDescription();
151
152 /**
153 * Returns OS build number.
154 * @return OS build number.
155 * @since 12217
156 */
157 default String getOSBuildNumber() {
158 return "";
159 }
160
161 /**
162 * Setup system keystore to add JOSM HTTPS certificate (for remote control).
163 * @param entryAlias The entry alias to use
164 * @param trustedCert the JOSM certificate for localhost
165 * @return {@code true} if something has changed as a result of the call (certificate installation, etc.)
166 * @throws KeyStoreException in case of error
167 * @throws IOException in case of error
168 * @throws CertificateException in case of error
169 * @throws NoSuchAlgorithmException in case of error
170 * @since 7343
171 */
172 default boolean setupHttpsCertificate(String entryAlias, KeyStore.TrustedCertificateEntry trustedCert)
173 throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
174 // TODO setup HTTPS certificate on Unix and OS X systems
175 return false;
176 }
177
178 /**
179 * Returns the {@code X509Certificate} matching the given certificate amendment information.
180 * @param certAmend certificate amendment
181 * @return the {@code X509Certificate} matching the given certificate amendment information, or {@code null}
182 * @throws KeyStoreException in case of error
183 * @throws IOException in case of error
184 * @throws CertificateException in case of error
185 * @throws NoSuchAlgorithmException in case of error
186 * @since 11943
187 */
188 default X509Certificate getX509Certificate(CertAmend certAmend)
189 throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
190 return null;
191 }
192
193 /**
194 * Executes a native command and returns the first line of standard output.
195 * @param command array containing the command to call and its arguments.
196 * @return first stripped line of standard output
197 * @throws IOException if an I/O error occurs
198 * @since 12217
199 */
200 default String exec(String... command) throws IOException {
201 Process p = Runtime.getRuntime().exec(command);
202 try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
203 return Utils.strip(input.readLine());
204 }
205 }
206
207 /**
208 * Returns the platform-dependent default cache directory.
209 * @return the platform-dependent default cache directory
210 * @since 7829
211 */
212 File getDefaultCacheDirectory();
213
214 /**
215 * Returns the platform-dependent default preferences directory.
216 * @return the platform-dependent default preferences directory
217 * @since 7831
218 */
219 File getDefaultPrefDirectory();
220
221 /**
222 * Returns the platform-dependent default user data directory.
223 * @return the platform-dependent default user data directory
224 * @since 7834
225 */
226 File getDefaultUserDataDirectory();
227
228 /**
229 * Returns the list of platform-dependent default datum shifting directories for the PROJ.4 library.
230 * @return the list of platform-dependent default datum shifting directories for the PROJ.4 library
231 * @since 11642
232 */
233 List<File> getDefaultProj4NadshiftDirectories();
234
235 /**
236 * Determines if the JVM is OpenJDK-based.
237 * @return {@code true} if {@code java.home} contains "openjdk", {@code false} otherwise
238 * @since 12219
239 */
240 default boolean isOpenJDK() {
241 String javaHome = System.getProperty("java.home");
242 return javaHome != null && javaHome.contains("openjdk");
243 }
244
245 /**
246 * Returns extended modifier key used as the appropriate accelerator key for menu shortcuts.
247 * It is advised everywhere to use {@link Toolkit#getMenuShortcutKeyMask()} to get the cross-platform modifier, but:
248 * <ul>
249 * <li>it returns KeyEvent.CTRL_MASK instead of KeyEvent.CTRL_DOWN_MASK. We used the extended
250 * modifier for years, and Oracle recommends to use it instead, so it's best to keep it</li>
251 * <li>the method throws a HeadlessException ! So we would need to handle it for unit tests anyway</li>
252 * </ul>
253 * @return extended modifier key used as the appropriate accelerator key for menu shortcuts
254 * @since 12748 (as a replacement to {@code GuiHelper.getMenuShortcutKeyMaskEx()})
255 */
256 default int getMenuShortcutKeyMaskEx() {
257 return KeyEvent.CTRL_DOWN_MASK;
258 }
259
260 /**
261 * Called when an outdated version of Java is detected at startup.
262 * @since 12270
263 */
264 @FunctionalInterface
265 interface JavaExpirationCallback {
266 /**
267 * Asks user to update its version of Java.
268 * @param updVersion target update version
269 * @param url download URL
270 * @param major true for a migration towards a major version of Java (8:9), false otherwise
271 * @param eolDate the EOL/expiration date
272 */
273 void askUpdateJava(String updVersion, String url, String eolDate, boolean major);
274 }
275
276 /**
277 * Checks if the running version of Java has expired, proposes to user to update it if needed.
278 * @param callback Java expiration callback
279 * @since 12270 (signature)
280 * @since 12219
281 */
282 default void checkExpiredJava(JavaExpirationCallback callback) {
283 Date expiration = Utils.getJavaExpirationDate();
284 if (expiration != null && expiration.before(new Date())) {
285 String version = Utils.getJavaLatestVersion();
286 callback.askUpdateJava(version != null ? version : "latest",
287 Main.pref.get("java.update.url", "https://www.java.com/download"),
288 DateUtils.getDateFormat(DateFormat.MEDIUM).format(expiration), false);
289 }
290 }
291
292 /**
293 * Called when interfacing with native OS functions. Currently only used with macOS.
294 * The callback must perform all GUI-related tasks associated to an OS request.
295 * The non-GUI, platform-specific tasks, are usually performed by the {@code PlatformHook}.
296 * @since 12695
297 */
298 interface NativeOsCallback {
299 /**
300 * macOS: Called when JOSM is asked to open a list of files.
301 * @param files list of files to open
302 */
303 void openFiles(List<File> files);
304
305 /**
306 * macOS: Invoked when JOSM is asked to quit.
307 * @return {@code true} if JOSM has been closed, {@code false} if the user has cancelled the operation.
308 */
309 boolean handleQuitRequest();
310
311 /**
312 * macOS: Called when JOSM is asked to show it's about dialog.
313 */
314 void handleAbout();
315
316 /**
317 * macOS: Called when JOSM is asked to show it's preferences UI.
318 */
319 void handlePreferences();
320 }
321
322 /**
323 * Registers the native OS callback. Currently only needed for macOS.
324 * @param callback the native OS callback
325 * @since 12695
326 */
327 default void setNativeOsCallback(NativeOsCallback callback) {
328 // To be implemented if needed
329 }
330}
Note: See TracBrowser for help on using the repository browser.