Time for action – creating a reusable widget

Although the ClockView shows an animated clock, creating an independent widget will allow the clock to be reused in other places.

  1. Create a new class in the com.packtpub.e4.clock.ui package, called ClockWidget, that extends Canvas.
  2. Create a constructor that takes a Composite parent and an int style bits parameter, and passes them to the superclass:
    public ClockWidget(Composite parent, int style) {
      super(parent, style);
    }
  3. Move the implementation of the paintControl() method from the ClockView to the ClockWidget. Remove the PaintListener references from the ClockView class.
  4. In the ClockWidget constructor, register an anonymous PaintListener that delegates the call to the paintControl() method:
    addPaintListener(new PaintListener() {
      public void paintControl(PaintEvent e) {
        ClockWidget.this.paintControl(e);
      }
    });
  5. Move the TickTock thread from ClockView to the ClockWidget constructor; this will allow the ClockWidget to operate independently. Change any references for clock to ClockWidget.this:
    new Thread("TickTock") {
      public void run() {
        while (!ClockWidget.this.isDisposed()) {
          ClockWidget.this.getDisplay().asyncExec(
           new Runnable() {
            public void run() {
              if (!ClockWidget.this.isDisposed())
                ClockWidget.this.redraw();
            }
          });
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            return;
          }
        }
      }
    }.start();
  6. Add a computeSize() method to allow the clock to have a square appearance that is the minimum of the width and height. Note that SWT.DEFAULT may be passed in, which has the value -1, so this needs to be handled explicitly:
    public Point computeSize(int w,int h,boolean changed) {
      int size;
      if(w == SWT.DEFAULT) {
        size = h;
      } else if (h == SWT.DEFAULT) {
        size = w;
      } else {
        size = Math.min(w,h);
      }
      if(size == SWT.DEFAULT)
        size = 50;
      return new Point(size,size);
    }
  7. Finally, change ClockView to instantiate the ClockWidget instead of the Canvas in the createPartControl() method:
    final ClockWidget clock = new ClockWidget(parent,SWT.NONE);
  8. Run the test Eclipse instance and the clock should be shown as before.

What just happened?

The drawing logic was moved into its own widget, and hooked up PaintListener to a custom method in ClockWidget so that it could render itself. This allows Clock to be used standalone in any Eclipse or SWT application.

In a real application, the clocks would not have their own thread; it would either be the case that a single Thread would control updates to all Clock instances, or they would be set up with repeating Jobs using the Eclipse jobs framework. Jobs will be covered in Chapter 4, Interacting with the User.

The technique of using an anonymous class to bind a specific listener type to the instance of the class is a common pattern in SWT. The convention is to use the same method name in the enclosing class; this helps to disambiguate the use. (Remember to set the listener at startup, as otherwise it can be confusing why it's not getting called.) It's also why ClockWidget.this is used in the delegation call; directly invoking this.paintControl() or paintControl() would have ended up in an infinite loop.

It's also possible for ClockWidget to implement PaintListener directly; in this case, addPaintListener(this) would be called in the constructor. Modern JITs will optimize the calls to equivalent code paths in any case; it comes down to a style decision as to whether ClockWidget should implement the PaintListener interface or not.

Finally, compute the size based on the hints. This is called by the layout manager to determine what size the widget should be. For widgets with a fixed size (say, a text string or an image) the size can vary depending on the layout. In this case, it returns a square, based on the minimal size of the supplied width and height hints, or 50, whichever is bigger. The SWT.DEFAULT value is -1 which has to be dealt with specifically.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset