Tuesday, January 13, 2009

JFreeChart and JXLayer Adjustable Magnifier

JXLayer is cool. I wrote about Dave Gilbert's demo applet that uses JXLayer and Piet Blok's work to show a magnifying glass over a JFreeChart. Since then Piet has updated his MagnifierUI code and I extended it into a more configurable magnifying glass. In the applet below, you should be able to use your mouse wheel to adjust the magnification factor of the magnifying glass. Also, while holding down the Control and Shift keys, the mouse wheel should adjust the size of the magnifying glass.

Note: Windows users may need to right-click on the chart to enable the mouse wheel adjustments. For some reason, the popup menu that appears after a right-click causes the applet to start listening to mouse wheel events. This is most noticeable when dragging the applet out of the browser and then closing the dragged-out applet and returning to the browser window. This problem does not occur on Linux.

The code is pretty straightforward. I created a subclass of MagnifierUI called AdjustableMagnifierUI. In it I override the processMouseWheelEvent method. If the Control and Shift keys are pressed on a mouse wheel event, the setMagnifyingFactor method in MagnifierUI is called. If no modifier keys are pressed, the setRadius method is called.

The Windows hack is in the applet class. I override setVisible as follows:
public void setVisible(boolean visible) {
  super.setVisible(visible);
  if (isShowing()) {
    // simulate right-mouse click to bring-up popup menu
    chartPanel.mousePressed(new MouseEvent(chartPanel,
        0, 0,
        java.awt.event.InputEvent.BUTTON3_DOWN_MASK,
        0, 0, 1, true));
    // immediately hide the popup menu
    chartPanel.getPopupMenu().setVisible(false);
  }
}
If the applet is showing, I simulate a right-mouse click to bring-up JFreeChart's popup menu. Then the popup is immediately hidden. This enables the mouse wheel events to be handled correctly in Windows XP SP3. This hack only works when setVisible is called. If the user has Java SE 6 Update 10 or later and he drags the applet out of the browser and then closes the dragged-out window, the applet returns to its original spot in the browser window WITHOUT calling setVisible. In this case, mouse wheel events will not cause any magnifier adjustments UNTIL the user right-clicks and shows the popup menu. Dismissing the popup will restore the desired mouse wheel behavior. Does anyone know why this is or have a better solution? This hack is not needed on Ubuntu Linux 8.04.

I ran into one other problem when posting the applet. In order to avoid an AccessControlException, I had to override the isAWTEventListenerEnabled() method to return false in AdjustableMagnifierUI:
@Override
protected boolean isAWTEventListenerEnabled() {
  return false;
}
I didn't notice any problems from overriding this method. Or perhaps this is the cause of the Windows misbehavior? I would appreciate any feedback on this.

To build the applet, you will need these:
  1. My Code: tar.gz or zip
  2. JXLayer library (I use version 3.0)
  3. JFreeChart library (I use version 1.0.12)
  4. JFree JCommon library (I use version 1.0.15)
The first code link above is a modified subset of Piet Blok's generic ZoomUI released on January 11th, 2009.


5 comments:

  1. Hi!
    I am trying to figure out how I can show JPopupMenu for the LayerUI's(for example, MagnifierUI) over my panel. I can get popup from my control, but not able to attach or bring up popup menus for each wrapped LayerUI's. Can you help, or give any example?

    Thanks in advance.

    ReplyDelete
  2. Hi Anonymous,

    The popup menus in the above applet are supplied entirely by JFreeChart, and are not part of JXLayer. So I did nothing special to enable the popup menu to function as it does. If you have a question about getting popups to show for wrapped LayerUIs, I suggest asking in the JXLayer forums here.

    There are many helpful experts on that forum who can probably answer your question. But do a search first, as the question may have already been answered.

    ReplyDelete
  3. I need a an application that could magnify the desktop or what ever underneat it. But the programmer should be launched by java webstart Do you know any such code available out there in web. Any help will be appriciated.

    thanking you.

    ReplyDelete
  4. Any ideas why yours is clean and crisp but mine is blurry under zoom? Using your example with a chart of mine.

    ReplyDelete
  5. @Flint
    I experience blurring of text when upgrading to version 1.0.13 of JFreeChart. Try downgrading to version 1.0.12 to see if that helps.

    ReplyDelete