JawGadget
 
 


First example

Purpose: Display a semi-transparent picture, like the rose on the previous page. When the mouse cursor enters the picture it becomes completely opaque and is on top of all other windows. When the mouse cursor leaves the picture, it becomes semi-transparent again.


// GadgetEx1.java
// Transparent picture getting opaque when mouse cursor enters
// Left double click to terminate

import ch.aplu.jaw.*;

public class GadgetEx1 implements NativeMouseListener
{
  private JawGadget jg = new JawGadget();
  private final String img = "rose.gif";

  // Constructor
  public GadgetEx1()
  {
    jg.showImage(img,                 // Path to image
                 50,                  // 50% opacity
                 false,               // Not top most
                 1020);             // Position (upper left corner)

    // Select mouse events
    jg.addNativeMouseListener(this, NativeMouse.enter |
                                    NativeMouse.leave |
                                    NativeMouse.lDClick);
  }

  // Callback method
  public void mouseEvent(NativeMouse mouse)
  {
    switch (mouse.getEvent())
    {
      case NativeMouse.enter:
        jg.showImage(img, 100true);  // 100% opacity, top most
        break;

      case NativeMouse.leave:
        jg.showImage(img, 50false);  // 50% opacity, not top most
        break;

      case NativeMouse.lDClick:
        jg.destroy();  // Cleanup and terminate
        break;
    }
  }

  // main
  public static void main(String args[])
  {
    new GadgetEx1();
  }
}

Discussion: When the program starts, showImage() takes the path of the picture file, 50% of opacity and the boolean false, because we do not want the picture to be on top of all other windows.. (10, 20) is the screen position in pixels of the upper left corner. In order to get callbacks from mouse events, addNativeMouseListener() registers a NativeMouseListener and defines with an OR-combination of constants, which mouse events are really needed. This boosts the performance of the overall system, because mouse events, especially mouse moves, may be rather time consuming.

In the implementation of NativeMouseListener's method mouseEvent() , we use getEvent() to find out, which event actually occurred. When the mouse cursor enters the picture, we show it fully opaque and on top of all other windows. When the mouse cursor leaves the picture, we show it semi-transparent, so that the underlying desktop shines through. Double-clicking on the picture terminates the program.

No code is necessary to drag the picture with the left mouse button.

Special care must be taken for the location of the image file. Either it is in the same directory as the Java application class file GadgetEx1.class or you must use a fully qualified path, including drive and directory, like

String img = "c:\\temp\\rose.gif"

JawGadget uses a native DLL called jawgadget.dll . This file must either reside in the directory of the Java application class file or in the path of the Windows operating system, e.g. in c:\windows\system32 .

To create an pleasant image for JawGadget some special care must be taken. Here some recommandations:

  • For image creation use format BMP (Windows-RGB 24 bit), convert it to GIF when finished
  • Image size in pixel corresponds to screen size in pixel
  • The color parameter in JawGadget constructor determines which parts of the picture are transparent. Normally white (RGB 255x255x255) is used. In this case, to let white parts appear as white and not transparent, use a slightly different color for them, e.g. RGB 254x255x255
  • Crossovers from a non-transparent to a transparent part should be as sharp as possible to avoid frayed edges. Use a pixel editor to rework the image (good results with Pixel Editor from www.iconempire.com)

 

Second example

Purpose: Display a fully opaque picture, like a Jman with a red nose. When the mouse cursor moves over the nose, it's shown in green color and an speech balloon is displayed.

// GadgetEx2.java
// Detect hotspot area using move event

import ch.aplu.jaw.*;

public class GadgetEx2 implements NativeMouseListener
{
  private JawGadget jg = new JawGadget();
  private boolean isGreenNose = false;

  public GadgetEx2()
  {
    jg.showImage("jman.bmp",  //Red nose
                  100,        // Percentage of opacity
                  false,      // Not top most
                  1020);    // Position (upper left corner)

    jg.addNativeMouseListener(this, NativeMouse.move | NativeMouse.lDClick);
  }

  public void mouseEvent(NativeMouse mouse)
  {
    switch (mouse.getEvent())
    {
      case NativeMouse.move:
      {
        int x = mouse.getX();
        int y = mouse.getY();
        if (> 45 && x < 65 && y > 60 && y < 80)  // Nose hit
        {
          if (!isGreenNose)  // Proceed only if necessary
          {
            jg.showImage("jman1.bmp"100false)// Green nose
            isGreenNose = true;
          }
        }
        else
        {
          if (isGreenNose) // ditto
          {
            jg.showImage("jman.bmp"100false);  // Red nose
            isGreenNose = false;
          }
        }
        break;
      }

      case NativeMouse.lDClick:
        jg.destroy();
        break;
    }
  }

  public static void main(String args[])
  {
    new GadgetEx2();
  }
}

Discussion: We use two pictures jman.bmp (red nose) and jman1.bmp (green nose with speech balloon). The nose is considered as hot spot area. When the mouse cursor enters the hot spot, we show the second picture, when the cursor leaves the hot we show the first picture again. We use a boolean state variable isGreenNose, because we only want to load the new picture when the mouse enters or leaves the hot spot and not repeatedly when the cursor is inside or outside.

 

 

Third example

Purpose: Add a turning wheel as icon in the taskbar tray (animated tray icon). A left mouse button click reverses the rotation direction, a right mouse button click terminates the program. At startup a balloon tool tip is shown. Each time the mouse cursor enters the wheel, a tool tip reports the current direction.

// GadgetEx3.java
// Dynamic tray icon

import ch.aplu.jaw.*;

public class GadgetEx3 implements TrayIconListener
{
  private JawGadget jg = new JawGadget();
  boolean volatile isRunning = true;
  private int start = 0;

  public GadgetEx3()
  {
    int iconEventMask = NativeMouse.lRelease | NativeMouse.rRelease;
    jg.addTrayIconListener(this, iconEventMask);
    boolean first = true;

    while (isRunning)
    {
      for (int i = 0; i < 4; i++)
      {
        String ico = "wheel" + Math.abs(start - i) + ".ico";
        String msg = (start == 0) ?
          "Now turning clockwise" : "Now turning anti-clockwise";
        jg.showIcon(ico, msg);

        if (first)
        {
          jg.showBalloonTooltip("Turning wheel",
                                "Left click to change direction\n" +
                                "Right click to quit");
          first = false;
        }

        jg.sleep(200);
      }
    }
    jg.destroy();
  }

  public void iconEvent(TrayIcon icon)
  {
    switch (icon.getEvent())
    {
      case NativeMouse.lRelease:
        if (start == 0)
          start = 3;
        else
          start = 0;
        break;

      case NativeMouse.rRelease:
         isRunning = false;
         break;
    }
  }

  public static void main(String args[])
  {
    new GadgetEx3();
  }
}
 

Discussion: We use 4 pictures wheel0.ico, .. wheel3.ico for the different positions of the wheel. In order to generate the sequence 0,1,2,3,0,... or 3,2,1,0,3,... it's a trick to take abs(start - i), using an integer direction flag start. While i runs from 0 to 3, the first sequence is generated with start = 0, the second with start = 3. It's better to register the mouse release event, especially for terminating the program, because another tray icon may take over the place of the wheel and get the release event.

To conform to the Java guidelines we declare isRunning volatile, because it is modified by the callback method, which runs in another thread.

Because of the importance of tray icons, quite a few other implementations of tray icons are known, among them

  • JTrayIcon (www.javaapis.com)
  • TrayIcon written by Jan Struyf (http://jeans.studentenweb.org/java/trayicon/trayicon.html).

Tray icons are also supposed to be included in the next release of the Java Platform (Edition 6). A beta-release is already available at Sun's website.

Forth example

Purpose: Create a sample datebook with daily appointments in semi-transparent window that can be moved on the desktop. On entry of the mouse cursor, the windows becomes fully opaque. Clicking the left mouse button advances the appointment view for one hour, clicking right terminates the program (improvement: iconize it as tray icon).

// GadgetEx4.java
// Sample datebook

import ch.aplu.jaw.*;
import javax.swing.*;
import java.awt.*;
import java.io.*;

public class GadgetEx4 implements NativeMouseListener
{
  private final String[][] datebook =
     {{"8 h" , "Brush teeth"   },
      {"9 h" , "Breakfast"     },
      {"10 h""Coffee time"   },
      {"11 h""Mr. President" },
      {"12 h""Lunch"         }};

  private final String bmp = "datebook.bmp";
  private JTable table;
  private JComponent c;
  private JawGadget jg = new JawGadget();
  private int n = 0// Start index

  public GadgetEx4()
  {
    JTable table = createTable(new Dimension(20048));
    table.setBackground(Color.lightGray);
    c = new JScrollPane(table);
    packComponent(c);  // Need to write component to image file
    JawGadget.writeBMP(c, bmp);

    jg.showImage(bmp, 50false1010)// 50% opacity,not top most

    jg.addNativeMouseListener(this, NativeMouse.lClick |
                                    NativeMouse.enter |
                                    NativeMouse.leave |
                                    NativeMouse.rClick);
  }

  public void mouseEvent(NativeMouse mouse)
  {
    switch (mouse.getEvent())
    {
      case NativeMouse.lClick:
        n++;
        if (== 3)
          n = 0;
        updateTable(n);
        JawGadget.writeBMP(c, bmp);
        jg.showImage(bmp, 100false);
        break;

      case NativeMouse.enter:
        jg.showImage(bmp, 100true);
        break;

      case NativeMouse.leave:
        jg.showImage(bmp, 50false);
        break;

      case NativeMouse.rClick:
        new File(bmp).delete();
        jg.destroy();
        System.exit(0);
        break;
    }
  }

  private JTable createTable(Dimension dim)
  {
    String[] colNames = {"Time""Task"};
    Object data[][] = new Object[3][2];
    table = new JTable(data, colNames);
    updateTable(0);
    table.setPreferredScrollableViewportSize(dim);
    return table;
  }

  void updateTable(int n)
  {
    for (int i = 0; i < 3; i++)
    {
      table.setValueAt(datebook[+ n][0], i, 0);
      table.setValueAt(datebook[+ n][1], i, 1);
    }
  }

  private void packComponent(JComponent component)
  {
    JFrame f = new JFrame();
    f.getContentPane().add(component);
    f.pack();
  }

  public static void main(String args[])
  {
    new GadgetEx4();
  }
}

 


Discussion: It is appropriate to use a JTable, a very sophisticated Java component, to display the datebook. In order to get a view of the table we must proceed as if we would display the table in a JFrame: We create a JScrollPane, add this component to a JFrame and pack the JFrame. It's not evident that only now the component is ready to be transformed to a BMP file. showImage() is called to display the table. We must paint the background in light gray, unless we want it transparent.

Each time we want another look in the datebook by clicking on the picture, we must create a new BMP and redisplay it as GadGadget. Obviously the BMP file serves as data link between Java and the native code.