. Well, we don't
have to wait any longer..
JDIC is broken up into five components and one incubator project:
The Desktop component is the simplest and possibly most useful of the
JDIC components. Its entire existence is devoted to basic desktop services
like opening a file in the right editor, starting an email message, or
sending a URL to the default web browser. These are all things that require
a lot of work under the hood to build, but very little to use. If you want
to tell the OS to open a Microsoft Word document, then just call
Desktop.open(new File("resume.doc"));. It's that simple.
Desktop.open(new File("resume.doc"));
The org.jdesktop.jdic.desktop package only has three
classes: Desktop, Message, and
DesktopException. The Desktop class is static and cannot be
instantiated. It has methods for opening, editing, and printing files. You
can also open a new email and populate it with text. This is where the
Message class comes in, which lets you set the recipient,
body, attachments, and all of the other email parts.
org.jdesktop.jdic.desktop
Desktop
DesktopException
The best thing about the Desktop components package is how easy it is to use. You
don't have to register any special drivers or change configuration based on
the current platform. That's all done for you under the hood. As long as
the jdic.jar file is in your classpath and the correct native lib is in your
library path (usually you just put it with the .jars) then the code will
simply work. Here is a one-line example to launch a browser:
import org.jdesktop.jdic.desktop.*;
import java.net.*;
public class DesktopTest {
public static void main(String[] args)
throws Exception {
Desktop.browse(
new URL("")
);
}
}
The next core component of JDIC is the Filetypes package,
which sets file type associations. This means you can tell the operating
system what program to use with what files, such as always opening text
files using Word instead of Notepad. Using this API you can query, set, and
delete file type associations based on file extensions and mime types.
Given that file type associations are usually quite operating-system-specific, this API is more useful for retrieving associations or registering
the application itself rather than for setting associations. For example,
the usual text file association under Windows is to call
notepad.exe in a well-known directory. Under Gnome, it might be
to call /usr/local/bin/gedit. Since this is system-specific it
probably isn't very useful to set associations except to tie a Java
application to its own file types. Still, no matter what you do
with it, the Filetypes component handles all of the heavy lifting for you,
dealing with the registry and MIME-type database.
notepad.exe
/usr/local/bin/gedit
Here is a short example of setting file associations:
import org.jdesktop.jdic.filetypes.*;
import java.net.*;
public class FileTypesTest {
public static void main(String[] args)
throws Exception {
Action action = new Action("open",
"C:\\WINDOWS\\system32\\notepad.exe %1");
Association assoc = new Association();
assoc.addFileExtension(".mchat");
assoc.setMimeType("application/mad-chatter");
assoc.addAction(action);
AssociationService svc = new AssociationService();
svc.registerUserAssociation(assoc);
}
}
The first two lines of the main
method create an Action that will
open the file (represented by %1)
with notepad.exe. The next four lines
create an association between the action and the
.mchat file extension. I threw the
MIME-type in there for good measure. In the past,
most operating systems relied exclusively on the
file extension or proprietary metadata to
determine the file type. These days, however, most
operating systems are moving towards MIME
settings for all file typing, so it's good to
start using them now. The last two lines actually
register the association with the system. As with
all JDIC APIs, as long as the native lib is in
your library path, you don't need to do anything
special to get it to work.
main
Action
%1
The third main component of JDIC is the Browser. Unlike the previous
two, which just give you access to system services, this component gives you
a real AWT widget to use in graphical applications. Previously, you could
use third-party embedded components or all-Java browsers (see "HTML Renderer Shootout, Part 1"), but JDIC lets you embed the user's default web
browser inside of your application, opening the door to many possibilities.
Now writing things like RSS readers with full web support becomes possible.
Downloading will also be faster, because you won't have to include the
native browser with your application.
The Browser API gives you access to a few browser events and control
over the history (forward, back, refresh). Future revisions of the API are
expected to provide even more access to the browser and any loaded
documents.
Using the browser from your application is really quite easy:
import org.jdesktop.jdic.browser.*;
import java.net.*;
import javax.swing.*;
public class BrowserTest {
public static void main(String[] args) throws Exception {
WebBrowser browser = new WebBrowser();
browser.setURL(new URL(""));
JFrame frame = new JFrame("Browser Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(browser);
frame.pack();
frame.setSize(500,500);
frame.setVisible(true);
}
}
As you can see, the WebBrowser object is just an AWT component that you
can drop into a standard JFrame. The first line of the main method creates
a new WebBrowser and the second sets the URL you want to show. The
rest of the code creates a frame, adds the browser to it, and makes the
frame visible. Once running, its display looks like Figure 1.
WebBrowser
Figure 1. Embedded WebBrowser
Remember that the WebBrowser is a native AWT component, so you may run into
issues combining it with Swing. The two rules for mixing them is 1) never
overlap Swing and AWT components, and 2) call
setLightWeightPopupEnabled(false)
on your menus or they will disappear behind the browser component. See this
Swing Connection article for more on mixing
AWT and Swing.
setLightWeightPopupEnabled(false)
Right now, the Browser component will use the user's default web browser,
which usually means Internet Explorer or Mozilla, and you can't bundle the
necessary parts of Mozilla with your application like you can with JRex. This behavior is probably okay for
Windows, where IE is pretty much guaranteed to be there, but this will be
more problematic on Linux where, the default browser may not be Mozilla
(it may be Konquorer in KDE, for example). Hopefully these issues will be resolved as
the project matures, but right now it's still quite useful for a variety of
projects.
Unlike the rest of JDIC, the Packager module is not an API. Instead, it
is a set of command-line tools that convert JNLP (Java Web Start)
applications into native installers. (rpms for Linux, pkgs for Solaris, and
msis for Windows). This doesn't mean your application is turned into an .exe
like with JSmooth or JExePack; it simply gives you a
one-click installer for a Web Start application. After the program is
installed, it will update itself over the Internet, use the JNLP descriptor,
and do all of the other things that Web Start applications do.
rpm
pkg
msi
The Packager component requires J2SE 5.0 and
native tools. For Windows, you will also need to install Microsoft's MSI
SDK. Once your environment is set up, you can use the command-line tools
jnlp2msi, jnlp2rpm, and jnlp2pkg to
convert your Web Start application into a platform-specific installer.
jnlp2msi
jnlp2rpm
jnlp2pkg
The Tray Icon API used to be an incubator project, but due to the
diligent efforts of the java.net community, it has matured and been promoted
to a full JDIC component status. It's entire purpose is to create
those little program state-icons in the lower-right-hand corner of your
screen, assuming your operating system has a system tray concept. In
practice, this means Windows and Linux. Mac OS X users are out of luck (or
better off, depending on your point of view). It also supports pop-up menus
and automatic tooltips for the icons. Like the rest of JDIC, system-tray
support requires native code, but you can code against a Java API with a
pre-compiled native library.
Since the API is pretty small in scope, there
are only two classes: SystemTray and
TrayIcon. The SystemTray class has a
static factory method for accessing the default
system tray. TrayIcon lets you attach a
JPopupMenu and an Icon
to the next available space on the system tray.
Finally, call
SystemTray.getDefaultSystemTray().addTrayIcon()
to get your pop-up to appear. Let's examine a small
example:
SystemTray
TrayIcon
JPopupMenu
Icon
SystemTray.getDefaultSystemTray().addTrayIcon()
import org.jdesktop.jdic.tray.*;
import java.awt.event.*;
import javax.swing.*;
public class SystemTrayTest {
public static JMenuItem quit;
public SystemTrayTest() {
JPopupMenu menu = new JPopupMenu("My Menu");
menu.add(new JMenuItem("Test 1"));
menu.add(new JMenuItem("Test 2"));
quit = new JMenuItem("Quit");
quit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}});
menu.add(quit);
ImageIcon icon = new ImageIcon("duke.gif");
TrayIcon tray_icon = new TrayIcon(icon, "System Tray Test!", menu);
SystemTray tray = SystemTray.getDefaultSystemTray();
tray.addTrayIcon(tray_icon);
}
public static void main(String[] args) {
new SystemTrayTest();
}
}
In the first few lines of the SystemTrayTest constructor we create a
JPopupMenu with three menu items. The last one, quit, adds an
ActionListener to quit the program. Now, instead of adding the menu to a menu bar or
JComponent, we put the menu into the constructor of a TrayIcon. The
ImageIcon for the system tray image is also passed into the TrayIcon,
along with text for a tooltip. Finally, we add the TrayIcon to the
default SystemTray and the program is done. Compile this with tray.jar
in your classpath and tray.dll in your library path (usually the working
directory). The icon and its menus are shown in Figure 2.
SystemTrayTest
quit
ActionListener
ImageIcon
Figure 2. Tray API Example
The Tray API also supports animated GIF icons and left-click actions. With
this API, you can make your application completely disappear into the taskbar
until needed.
From the start, JDIC was designed to actively encourage and develop new
APIs. To facilitate project growth they created an incubator project, where
developers can commit code and try out ideas. If they ideas are good enough
and the implementations mature, the project can be promoted to a full JDIC
module or even spun out into its own complete project.
The JDIC team wants more contributors, so please join in. You will have
to sign and fax in the JCA (Joint Copyright Agreement), since parts of JDIC
may eventually be pulled into future versions of Java. They are looking for
cross-platform APIs with native implementations. This means that Java
bindings to Gnome would not be appropriate, since they are specific to Gnome,
but a cross-platform API for drawing non-rectangular windows (my personal
wish) would be very welcome.
I've saved my favorite API for last. JDIC has one major incubator
project right now: a toolkit to create cross-platform screensavers called
SaverBeans. Like the rest of JDIC, you can code entirely in Java, letting a
pre-built native library handle the messy details. The project consists of
an API for handling callbacks, an XML file for configuration, and an Ant
task that produces the platform-specific screensaver executables
(.scrs for Windows and shell scripts for Unix) with their
support files.
Writing a screensaver is a bit more complicated than using the other
APIs, so I have saved this one for part two of this series. However, if you
want to get started right away, you can download the SDK
and a collection of community-built screensavers.
Though JDIC is still beta, it shows great promise. Changes have been
coming fast and furious as open source developers embrace and extend it.
Work is already under way to fold in older projects, fix the bugs, support
the Mac, and eventually migrate parts of JDIC to the core runtime.
Though it seemed to come out of nowhere, JDIC is something that many
Java developers have been wanting for a long time. Now that it's here, we
can really develop Java applications that do everything native programs do.
I'll see you in a few weeks, when we will convert a particle simulator into
a top-notch screensaver.
Joshua Marinacci first tried Java in 1995 at the request of his favorite TA and has never looked back.
Java Sketchbook: The HTML Renderer Shootout, Part free offerings in the HTML rendering space.
View all java.net Articles.