Posts Tagged ‘Java’

InfiniteProgressPanel inside a Netbeans RCP TopComponent

Saturday, January 3rd, 2009

Anyone doing some serious work with Swing must have heard about the SwingFX API. This API contains some mightily cool GUI hacks, and I am particularly fond of Romain Guy’s infinite progress panel. So as a naive Java, Swing, NetBeans RCP programmer, I set out to use InfiniteProgressPanel to decorate the lenghty operations in my thesis project, AgentSpotter, the profiler for the MASs. Unsurprisingly, it did not work out of the box and required some understanding of the UI threading issues in Java, notably because I was working inside a NetBeans RCP TopComponent. In the end I managed to get the progress panel to work correctly, and I have encapsulated the logic in the following class:

public abstract class LenghtyOperationRunner
implements Runnable
{
  Component _oldPane;

  public LenghtyOperationRunner()
  {
  }

  public void run()
  {
    startProgress();

    Thread longOp = new Thread(new Runnable()
     {
         public void run()
         {
             doFirstPart();
             SwingUtilities.invokeLater(
              new Runnable()
              {
                  public void run()
                  {
                      doFinalPart();
                      stopProgress();
                  }
              });
         }
     });
    longOp.start();
  }

  private void stopProgress()
  {
    final JFrame mainWin =
      (JFrame) WindowManager.getDefault().getMainWindow();
    final PerformanceInfiniteProgressPanel p =
      (PerformanceInfiniteProgressPanel) mainWin.getGlassPane();
    p.setVisible(false);
    mainWin.setGlassPane(_oldPane);
  }

  private void startProgress()
  {
    final JFrame mainWin =
      (JFrame) WindowManager.getDefault().getMainWindow();
    _oldPane = mainWin.getGlassPane();
    PerformanceInfiniteProgressPanel glassPane;
    mainWin.setGlassPane(glassPane =
      new PerformanceInfiniteProgressPanel());
    glassPane.setVisible(true);
  }

 // Extension points:
 // override these methods
 // with the worker code

  protected abstract void doFirstPart();

  protected abstract void doFinalPart();

}

I have used PerformanceInfiniteProgressPanel, tweaked by Henry Story, instead of the standard InfiniteProgressPanel for performance reasons (would you expect something else from a profiling tool?). The implementation introduced by Romain in his original post was quite CPU intensive but it was subsquently improved by different SwingFX contributors.

The following code (adapted from here) shows how to use the class in a TopComponent:

class CallGraphTopComponent  extends TopComponent {
  private CallGraphTopComponent()
  {
      // This will launch the lenghty operation
      SwingUtilities.invokeLater(new CallGraphLoader());
  }

  private class CallGraphLoader
    extends LenghtyOperationRunner
  {
    JComponent treeview;

    @Override
    protected void doFirstPart()
    {
     // Start the main task here

      final ProgressHandle progress =
        ProgressHandleFactory.createHandle("Call Graph");
      ProgressHandler progressHandler = new ProgressHandler()
      {
        ... BLAH ...
      };

  // This is the lenghty operation
      treeview = CallGraph.newInstance(progressHandler);
    }

    @Override
    protected void doFinalPart() throws HeadlessException
    {
      // Things to run when the first part is finished

        if (treeview == null)
            JOptionPane.showMessageDialog(null,
              "Cannot create call graph tree view.");
        add(treeview);
    }
  }
}

To summarize, here are the steps to follow:

  • Subclass the LenghtyOperationRunner class listed here.
  • Override doFirstPart() and doFinalPart().
  • SwingUtilities.invokeLater() an instance of your custom runner wherever you want to display the progress panel while doing a lenghty operation. Et voilà!

Savvy readers will have noticed the use of SwingUtilities.invokeLater() which is the standard way to interact with the Java GUI event queue. The idea is to make sure that the main task code does not hog the CPU and leaves some breathing space for the UI thread which animates the panel. To this end, we must create a thread for the main task (doFirstPart()) which in turn must run any action that interacts with the UI in a new thread (doFinalPart()).

It must be noted that I tried to follow the steps described in this article first but it didn’t work for me. However you can still refer to this article to get more details on the mechanics of the progress panel.

Ultimately, I certainly have spent more time trying to make this panel work than I would have expected in the first place, but it was worth it because the bottom line is: the infinite progress panel is damn cool!

<french>

Le code présenté dans cet article décrit comment utiliser InfiniteProgressPanel dans une application NetBeans. Le secret est d’enchaîner correctement les appels à SwingUtilities.invokeLater() pour ne pas interférer avec le thread principal.

</french>

AgentSpotter alpha is out!

Tuesday, September 23rd, 2008

Despite my rusty Java skills I managed to produce the first version of AgentSpotter my Master’s project which is a profiler for the MASses (multi-agent systems).

The deadly combination of SQLite, Netbeans Platforms and Piccolo has allowed me to create a first useful version of my tool with a cool zoomable UI and a professional touch lent by the Netbeans application framework.

Bragging rights

I am aware that this profiler thingy is a little bit obscure for most people including my wife Stéphanie. But this is, as far a I know, the first occurence of such a tool. There are gazillions of MAS visualisation tools out there but AgentSpotter is the first to display performance data: flat profiles, call graphs, space-time diagram. You name it, we have it! So that’s doubly cool and that’s something I can boast about at the watercooler.

Java Love

Smalltalk is by far my favourite OOP language, then Ruby, then C# and C++. I have used Java for some university assignments in 1998 and it was OK but I wasn’t impressed, C++ was far more interesting or OCAML. These last 2 years I have used Java again and AgentSpotter is my first major project in Java. Actually I like Java as much as C#. Nifty stuff like inner classes make it quite fun to use and the new C# language constructs are cool. I don’t like the generics implementation though, it feels less natural than the C# one. Anyway, this is a great opportunity for me to discover for myself why 90% of my Master’s colleagues are Java programmers.

At the end of day, Smalltalk is the best OOP system and language ever, but that’s another story!

Downloading AgentSpotter Station

You can download it from here. NOTE: you need the JDK or JRE 1.6 to be able to run it. MacOS users will want to try the mac version.

To be able to test the application, you will need a sample snapshot file. Download this one and save it somewhere on your hard drive so that you can load it into the AgentSpotter Station.

Building From Source

The full code is available from sourceforge.

Projects under trunk:

  • AFBenchmark — test application used to generate sample snapshots
  • AF-RTE — local copy of the runtime (SVN “cheap” copy)
  • AgentSpotterFile — snapshot file handling and querying library
  • AgentSpotterVisualisation — main UI library (space time diagram implementation)
  • AgentSpotterStation — main netbeans platform based application

The code should build out of the box using Netbeans 6.1+ (it works on my 2 machines :-) Just open the AgentSpotterStation project folder inside Netbeans and build it.

If you use Netbeans 6.5 beta, you have to change agentspotter/trunk/src/AgentSpotterStation/nbproject/platform.properties so that “enabled.clusters” contains “platform9″ instead of “platform”.

Pictures

This is a picture of the first concept dated from May 2008:

Here’s a screenshot of the actual application:

The realisation is much better than the idea. The zoomable UI is lots of fun to use, holding the mouse allows you pan or zoom (right button). I even added a “Bird’s Eye” view.

And here is the final touch, the cheesy logo! (I will ask my friend Stan to design a better one…)

Quick User Guide

After the first startup two windows will be open on the left hand side:

  • The Snapshot Explorer
  • The Bird’s Eye View

To load an existing snapshot file, right click on the “AgentSpotter Snapshots” root folder in the Snapshot Explorer and select “Add”. Use the displayed dialog to select “profile.aspot” for example.

Once the the snapshot is loaded you will have access to the different recorded sessions.

For each session the context menu contains the following options:

  • Open: display the Summary Window.
  • View: display the Space-Time Diagram.

The Summary Window contains a bunch of JTables that provide synthetised information about the session. The most interesting of course is the flat profile which reports the most CPU hungry agents.

The Space-Time diagram is a Zoomable User Interface:

  • Double clicking with the left mouse button will zoom into a component.
  • Double clicking with the right mouse button will zoom back to the parent or container of a component.
  • Right clicking and holding the button while moving the mouse will zoom in or out.
  • Left clicking and holding the button while moving the mouse will pan the view.
  • Hovering over a component (message send/receive, message line, agent name etc.) will popup a yellow tooltip.
  • Click in the Bird’s View Window and move the viewport to navigate in the diagram. You may have to move/resize the window to get the desired effect!