Monthly Archive for May, 2008

Playing with Google Guice: Look and Feel

In this example I’m showing how I use the LookAndFeelService in conjection with the EnvironmentService to configure the LAF defaults based on the runtime environment. The LookAndFeelModule allows me to configure various look and feel aspects based on the runtime environment.

The LookAndFeelModule is the starting point. You configure it and it configures the LookAndFeelService appropriately.

// create the module
LookAndFeelModule lafModule = new LookAndFeelModule();

// set the default look and feel.
lafModule.setDefaultLookAndFeel(UIManager.getSystemLookAndFeelClassName());

// now configure environment specific lafs
lafModule.registerLookAndFeel(MacOSX.class,
                              QuaquaLookAndFeel.class.getName());

I also use a replacement for JOptionPane that supports application wide and document specific option panes as required by the Mac. This too needs to be configured based on the environment we’re running on.

// Configure the MessagePaneProvider to use by default
lafModule.setDefaultMessagePaneProvider(new GenericMessagePaneProvider());

// now configure environment specific MessagePane providers
lafModule.registerMessagePaneProvider(MacOSX.class,
                                      new MacMessagePaneProvider());

Then I simply pass the module to my application launcher. The application retrieves the LookAndFeelService and invokes its configure method.

Launcher.launch(MyApplication.class, args, lafModule);

Of course instead of repeating this in every application I’ve created a default module implementation that’s preconfigured. So all I need do is:

Launcher.launch(MyApplication.class, args, new DefaultLookAndFeelModule());

And everything just works. Nice.

Playing with Google Guice: Splash Screens

The previous entry showed the creation of a (very) simple single frame application. Splash screens are common, so lets add one. Since there’s no easy way to do it for all occasions, we’ll use a Guice module to provide it for runtimes prior to Java 6.

public static void main(String[] args)
{
   URL splashImage = Main.class.getResource("/images/splash.png");

   // create the splash module for pre Java 6 runtimes.
   Module splashModule = Java5SplashScreenModule(splashImage);
   Launcher.launch(MyApplication.class, args, splashModule);
}

And that’s it. The framework will display the splash screen and all will work fine. Of course if you’re running on Java 6 you’d used the Java 6 version (that uses the new SplashScreen functionality). Of course if we don’t define the service in one of our modules, the framework uses the default `NullSplashScreenService`.

If MyApplicationFrame (or any other class for that matter) wanted to use the splash screen service, it just needs to inject it into it’s constructor.

public class MyApplicationFrame extends JFrame
{
   @Inject
   public MyApplicationFrame(SplashScreenService splashService)
   {
      // do stuff....
      splashService.setImageURL(nextImageURL);
   }
}

Playing with Google Guice

It’s been a long time coming but I’ve finally started dabbling in dependency injection for my swing frameworks. It’s taken me a quite a while to get a feel for where and how it can/should be used. Given the complexity of even an average Swing application I’d been loathed to convert all my UI construction and wiring over to a container, but I’d also love to create a framework environment where I can install all my standard behaviours in one line.

I’d also been wanting to consolidate my various frameworks and utilities into a single application framework (along the lines of JSR-296) but wanted to try out the dependency injection route.

Anyway, so far I’ve been very pleased with the results. I’ve been able to create services for controlling the splash screen, determining the runtime environment and providing runtime environment services, configuring Look and Feel settings and so on. With Guice you can easily create default implementations of your services so you can have the basics going with zero configuration.

So the following useless example shows what’s necessary to get a frame up and create a file in the default application data directory.

public class MyApplication
extends SingleFrameApplication
{
   public MyApplication()
   {
      super("MyApplication", MyApplicationFrame.class);
   }

   public void initialise(String[] args)
   {
      // The EnvironemntService ensures it's the correct location
      // based on the runtime platform.. i.e. `C:\AppData\MyApplication`
      // on windows and `~/Library/Application Support/MyApplication`
      // on the Mac.

      // AbstractApplication provides getters for standard services so
      // you don't have to magically discern their existence.
      EnvironmentService env = getEnvironmentServices();
      File logFile = env.getFileInAppDataDirectory("logs/my-app.log");

      // do stuff with the file...
      ....
   }
}

Then the application can be simply started using the following.

public static void main(String[] args)
{
   Launcher.launch(MyApplication.class, args);
}