diff --git a/src/dorkbox/util/Desktop.java b/src/dorkbox/util/Desktop.java new file mode 100644 index 0000000..f2d0f61 --- /dev/null +++ b/src/dorkbox/util/Desktop.java @@ -0,0 +1,146 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Copyright (C) 2016 Tres Finocchiaro, QZ Industries, LLC + * Derivative code has been released as Apache 2.0, used with permission. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import dorkbox.util.process.ShellExecutor; + +@SuppressWarnings("WeakerAccess") +public +class Desktop { + /** + * Launches the default browser to display a {@code URI}. + * + * If the default browser is not able to handle the specified {@code URI}, the application registered for handling + * {@code URIs} of the specified type is invoked. The application is determined from the protocol and path of the {@code URI}, as + * defined by the {@code URI} class. + * + * @param uri the URL to browse/open + * + * @throws IOException + */ + public static void browseURL(URI uri) throws IOException { + // Prevent GTK2/3 conflict caused by Desktop.getDesktop(), which is GTK2 only (via AWT) + if ((OS.isUnix() || OS.isLinux()) && OSUtil.DesktopEnv.isGtkLoaded && OSUtil.DesktopEnv.isGtk3) { + if (!ShellExecutor.run("xdg-open", uri.toString())) { + throw new IOException("Error running xdg-open for " + uri.toString()); + } + } + else { + if (java.awt.Desktop.isDesktopSupported() && java.awt.Desktop.getDesktop().isSupported(java.awt.Desktop.Action.BROWSE)) { + java.awt.Desktop.getDesktop().browse(uri); + } else { + throw new IOException("Current OS and desktop configuration does not support browsing for a URL"); + } + } + } + + /** + * Launches the mail composing window of the user default mail client for the specified address. + * + * @param address who the email goes to + * + * @throws IOException + */ + public static void launchEmail(String address) throws IOException { + URI uri = null; + try { + uri = new URI(address); + launchEmail(uri); + } catch (URISyntaxException e) { + throw new IOException("Invalid URI " + address); + } + } + + /** + * Launches the mail composing window of the user default mail client, filling the message fields specified by a {@code mailto:} URI. + *
+ * A mailto:
URI can specify message fields including "to", "cc", "subject", "body", etc.
+ * See The mailto URL scheme (RFC 2368) for the {@code mailto:} URI specification
+ * details.
+ *
+ * @param uri the specified {@code mailto:} URI
+ *
+ * @throws IOException
+ */
+ public static void launchEmail(final URI uri) throws IOException {
+ // Prevent GTK2/3 conflict caused by Desktop.getDesktop(), which is GTK2 only (via AWT)
+ if ((OS.isUnix() || OS.isLinux()) && OSUtil.DesktopEnv.isGtkLoaded && OSUtil.DesktopEnv.isGtk3) {
+ if (!ShellExecutor.run("xdg-email", uri.toString())) {
+ throw new IOException("Error running xdg-email for " + uri.toString());
+ }
+ }
+ else {
+ if (java.awt.Desktop.isDesktopSupported() && java.awt.Desktop.getDesktop().isSupported(java.awt.Desktop.Action.MAIL)) {
+ java.awt.Desktop.getDesktop().mail(uri);
+ } else {
+ throw new IOException("Current OS and desktop configuration does not support launching an email client");
+ }
+ }
+ }
+
+ /**
+ * Opens the specified path in the system-default file browser.
+ *
+ * Works around several OS limitations:
+ * - Apple tries to launch .app
bundle directories as applications rather than browsing contents
+ * - Linux has mixed support for Desktop.getDesktop()
. Uses the xdg-open
fallback.
+ *
+ * @param path The directory to browse
+ *
+ * @throws IOException
+ */
+ public static void browseDirectory(String path) throws IOException {
+ if (OS.isMacOsX()) {
+ File directory = new File(path);
+
+ // Mac tries to open the .app rather than browsing it. Instead, pass a child with -R to select it in finder
+ File[] files = directory.listFiles();
+ if (files != null && files.length > 0) {
+ // Get first child
+ File child = files[0];
+ if (!ShellExecutor.run("open", "-R", child.getCanonicalPath())) {
+ throw new IOException("Error opening the directory for " + path);
+ }
+ }
+ } else {
+ // Prevent GTK2/3 conflict caused by Desktop.getDesktop(), which is GTK2 only (via AWT)
+ if ((OS.isUnix() || OS.isLinux()) && OSUtil.DesktopEnv.isGtkLoaded && OSUtil.DesktopEnv.isGtk3) {
+ if (!ShellExecutor.run("xdg-open", path)) {
+ throw new IOException("Error running xdg-open for " + path);
+ }
+ }
+ else {
+ if (java.awt.Desktop.isDesktopSupported() && java.awt.Desktop.getDesktop().isSupported(java.awt.Desktop.Action.OPEN)) {
+ java.awt.Desktop.getDesktop().open(new File(path));
+ return;
+ } else {
+ throw new IOException("Current OS and desktop configuration does not support opening a directory to browse");
+ }
+ }
+ }
+
+ throw new IOException("Unable to open " + path);
+ }
+}
diff --git a/src/dorkbox/util/Framework.java b/src/dorkbox/util/Framework.java
deleted file mode 100644
index 28b69ec..0000000
--- a/src/dorkbox/util/Framework.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package dorkbox.util;
-
-import java.awt.Component;
-import java.awt.Desktop;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import javax.swing.JOptionPane;
-
-import org.slf4j.LoggerFactory;
-
-/**
- * This class defines a mix of useful methods for different frameworks such as JavaFX or SWT. Swing, being that it is builtin, and always
- * available to the JRE (JavaFX can be excluded...) is in it's own class ({@link Swing}).
- */
-public
-class Framework {
-
- public final static boolean isJavaFxLoaded;
- public final static boolean isJavaFxGtk3;
-
- public final static boolean isSwtLoaded;
- public final static boolean isSwtGtk3;
-
-
- static {
- boolean isJavaFxLoaded_ = false;
- boolean isJavaFxGtk3_ = false;
-
- boolean isSwtLoaded_ = false;
- boolean isSwtGtk3_ = false;
-
- try {
- // this is important to use reflection, because if JavaFX is not being used, calling getToolkit() will initialize it...
- java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
- m.setAccessible(true);
- ClassLoader cl = ClassLoader.getSystemClassLoader();
-
- // JavaFX Java7,8 is GTK2 only. Java9 can have it be GTK3 if -Djdk.gtk.version=3 is specified
- // see http://mail.openjdk.java.net/pipermail/openjfx-dev/2016-May/019100.html
- isJavaFxLoaded_ = (null != m.invoke(cl, "com.sun.javafx.tk.Toolkit")) || (null != m.invoke(cl, "javafx.application.Application"));
-
- if (isJavaFxLoaded_) {
- // JavaFX Java7,8 is GTK2 only. Java9 can MAYBE have it be GTK3 if `-Djdk.gtk.version=3` is specified
- // see
- // http://mail.openjdk.java.net/pipermail/openjfx-dev/2016-May/019100.html
- // https://docs.oracle.com/javafx/2/system_requirements_2-2-3/jfxpub-system_requirements_2-2-3.htm
- // from the page: JavaFX 2.2.3 for Linux requires gtk2 2.18+.
-
- isJavaFxGtk3_ = OS.javaVersion >= 9 && System.getProperty("jdk.gtk.version", "2").equals("3");
- }
-
- // maybe we should load the SWT version? (In order for us to work with SWT, BOTH must be the same!!
- // SWT is GTK2, but if -DSWT_GTK3=1 is specified, it can be GTK3
- isSwtLoaded_ = null != m.invoke(cl, "org.eclipse.swt.widgets.Display");
-
- if (isSwtLoaded_) {
- // Necessary for us to work with SWT based on version info. We can try to set us to be compatible with whatever it is set to
- // System.setProperty("SWT_GTK3", "0"); (or -DSWT_GTK3=1)
-
- // was SWT forced?
- String swt_gtk3 = System.getProperty("SWT_GTK3");
- isSwtGtk3_ = swt_gtk3 != null && !swt_gtk3.equals("0");
- if (!isSwtGtk3_) {
- // check a different property
- String property = System.getProperty("org.eclipse.swt.internal.gtk.version");
- isSwtGtk3_ = property != null && !property.startsWith("2.");
- }
- }
- } catch (Throwable e) {
- LoggerFactory.getLogger(Framework.class).debug("Error detecting if JavaFX/SWT is loaded", e);
- }
-
- isJavaFxLoaded = isJavaFxLoaded_;
- isJavaFxGtk3 = isJavaFxGtk3_;
-
- isSwtLoaded = isSwtLoaded_;
- isSwtGtk3 = isSwtGtk3_;
- }
-
- public static
- void initDispatch() {
- if (Framework.isJavaFxLoaded) {
- // This will initialize javaFX dispatch methods
- JavaFX.init();
- }
- else if (Framework.isSwtLoaded) {
- // This will initialize swt dispatch methods
- SwtBytecodeOverride.init(); // necessary to properly fix methods in {@link Swt}
- dorkbox.util.Swt.init();
- }
- }
-
-
- /**
- * Opens the given website in the default browser, or show a message saying that no default browser could be accessed.
- *
- * @param parent The parent of the error message, if raised
- * @param uri The website uri
- */
- public static
- void browse(final Component parent, final String uri) {
- boolean cannotBrowse = false;
- if (Desktop.isDesktopSupported() && Desktop.getDesktop()
- .isSupported(Desktop.Action.BROWSE)) {
- try {
- Desktop.getDesktop()
- .browse(new URI(uri));
- } catch (URISyntaxException ignored) {
- } catch (IOException ex) {
- cannotBrowse = true;
- }
- }
- else {
- cannotBrowse = true;
- }
-
- if (cannotBrowse) {
- JOptionPane.showMessageDialog(parent, "It seems that I can't open a website using your default browser, sorry.");
- }
- }
-}