Doing a bit of SWT custom widget development lately, I stumbled across the question why is there no such thing as a default SWT mouse click listener? As this subject raises once in a while, I thought writing a word or two about the rational ground behind – and how to implement mouse clicks in general – would not hurt.

SWT Mouse Click

Event-driven widget toolkits usually distinguish between low-level and semantic events. A low-level event represents window system occurrences or low-level input. The mouse and keyboard inputs belong basically to this group.

Semantic events in turn are the result of control specific user interaction and might be composed of one or more low-level events. A button-click for example could be specified as a mouse-down followed by a mouse-up without the mouse leaving the bounds of the control.

The point of the matter is the control specific user interaction. An image-click might be specified as a mouse-down followed by a mouse-up without leaving the bounds of particular regions of the image. Which makes a small but mighty difference.

The semantic event type SWT.Selection e.g. corresponds to the button-click specification given above for the org.eclipse.swt.widgets.Button control. But its composition is quite different on org.eclipse.swt.widgets.Slider . The latter behaves rather like the image-click definition:

It is obvious that nobody would like to add particular listeners for mouse-click events on each of the control’s regions. It is much more comfortable to have a semantic abstraction based on those low-level events that notifies observers about the crucial point of interest .

Button Click for Custom Widgets

So how can a button-click event implementation look like on a (sub-)component of a custom SWT widget? Consider for example a Composite comprised of a few labels and one of those – for whatever reason – should serve as an action trigger.

The click behavior could be accomplished with a little action wrapper working on top of the typed event abstraction of SWT. It may implement/extend org.eclipse.swt.events.MouseListener/-MouseAdapter and can be registered at controls to serve as a button-click listener:

class ClickBehavior extends MouseAdapter { private final Runnable action; ClickBehavior( Runnable action ) { this.action = action; } @Override public void mouseDown( MouseEvent event ) { // TODO: decent implementation } @Override public void mouseUp( MouseEvent event ) { // TODO: decent implementation } }

As you can see the class ClickBehavior wraps a Runnable which should be triggered by a click on the observed control. To do so the first step is to verify that a left-mouse-button-down has occured and flag the observer to be trigger ready. A simple mouseDown implementation might look like this:

public static final int LEFT_BUTTON = 1; [...] public void mouseDown( MouseEvent event ) { if( event.button == LEFT_BUTTON ) { armed = true; } }

The second step is to check whether a subsequent mouseUp event has occured within the bounds of the monitored control. If so (and armed) the semantic condition has been fulfilled and the action can be triggered :

public void mouseUp( MouseEvent event ) { if( armed && inRange( event ) ) { action.run(); } armed = false; } static boolean inRange( MouseEvent event ) { Point size = ( ( Control )event.widget ).getSize(); return event.x >= 0 && event.x <= size.x && event.y >= 0 && event.y <= size.y; }

This implementation is sufficient to be able to handle a 'button-click' event on e.g. a org.eclipse.widgets.Label as shown by the following snippet:

final Shell shell = [...]; Label label = new Label( shell, SWT.NONE ); label.setText( "Click me!" ); label.addMouseListener( new ClickBehavior( new Runnable() { @Override public void run() { MessageBox box = new MessageBox( shell ); box.setMessage( "Label was clicked." ); box.setText( "Message" ); box.open(); } } ) );

And voilà, this is how it looks like at runtime:

Wrap Up

As explained above there are good reasons for SWT to omit a general purpose mouse click implementation. And the given example showed how to implement a simple button-click semantic for custom widgets. However, there is still more to consider. Widgets often react on mouse down visually to indicate that they are trigger-ready for example.

Because of this custom widget code gets quickly blown up and tend to blur the various event related reponsibilities. For a clean separation of the event-semantic from the visual-effect code, I usually extract the first one in a little helper class. I even have a general purpose version for button-click events called ButtonClick , which is part of the SWT utility feature of the Xiliary P2 repository.

In case all this mouse click related content raised a desire for some practical application of mouse clicking: how about using the social buttons below to share the knowledge? ;-)

Title Image: © Depositphotos.com/HoldenKolf