SWT Step 7. Buttons

Objective

Complete the implementation of the o.e.swt.widgets.Button widget. The test example should demonstrate all types of buttons that exist in SWT.

Task notes

Button text and icon alignment styles (SWT.LEFT, SWT.RIGHT, SWT.CENTER) are not currently supported. I personally see no need in these styles at all. Besides this, supporting them will make it impossible to keep the system look and feel for SWT.PUSH buttons (for example, provided by eStyler).

However, SWT.TOGGLE buttons currently lose the pushbutton L&F provided by eStyler in any case, since they are completely drawn by hand due to lack of this type of buttons in OS/2. We're in contact with the eStyler author and hope this will be worked around later.

When implementing this step, it turned out that some other functionality has to be implemented within it, and something needs to be changed. In particular, the following has been additionally implemented:

Also, it became necessary to change the Decorations implementation.

The following subsections provide some further details.

keyboard handling

The current implementation of keyboard events is very simple: OS/2 virtual keys supported by Eclipse are reported as Eclipse virtual keys (KeyEvent::keyCode) with KeyEvent::character set to zero. All other events have keyCode set to zero and character equal to what OS/2 reports in the usch parameter of the WM_CHAR message (converted to unicode according to the curent locale), except the situation when both keyCode and character are zero (no KeyEvent is generated in this case).

This differs a bit from how Eclipse/Win32 generates key events. For example, when we press Ctrl and then press and release the A key, Eclipse/OS2 reports a (0x71) in the character field of the key press event and the control code 0x11 in the same field of the key release event (i.e. key press character doesn't match key release character); Win32 reports 0x11 in both cases. Another example is Alt plus letter. Eclipse/OS2 doesn't generate the key release event for the letter at all, since usch in WM_CHAR is zero in this case (Win32 reports both).

The reason why I left the OS/2 behavior as is for now (i.e. not fully compatible with Win32) is simple: currently, I don't get the logic how keyboard messages are handled in Win32. For example, if you press Alt there, then press some letter, then release Alt and finally release the letter you get three events: a press event with keyCode=SWT.ALT and character=0, a press event with keyCode=0 and character=<letter>, and a combined release event with keyCode=SWT.ALT and character=<letter> (i.e. we also get press/release pair mismatch) -- that seems strage to me. But all this is related to the pretty outdated SWT version 2.01, and I think things have changed in recent SWT/Win32 releases, so the keyboard handling in Eclipse/OS2 will be improved later, when we move the whole project to one of current Eclipse releases.

Decorations reimplementation

The previous Decorations implementation involved a special internal SWT widget (ClientArea) to represent the client area of any top-level window. This caused lots of problems related (not only) to focus traversal because of the explicitly expressed parent-child relationship (on SWT level) between the frame and client window (ClientArea was created as a child of Decorations, both in OS/2 and in SWT terms). This broke the children-related functionality in SWT and led to some other issues.

So, I chose a bit different solution. Instead of having a special SWT class for the client area, Decorations now maintains two window handles directly -- one is a regular Control::handle field that now holds a handle to the client window (not a frame window handle as before), and another one is a separate field, Decorations::frameHandle, to hold the frame window (WC_FRAME) handle. Both windows are created by Decorations::createHandle(). The majority of new or overriden Decorations methods use the frameHandle field, while methods derived from Composite, Control etc. continue to use the handle field. Also, PM message handling was explicitely separated: Decorations has an additional window procedure, windowFrameProc(), that delivers messages addressed to the WC_FRAME window to Decoration's methods. These methods are named FRAME_WM_* to differ from regular WM_* messages processed by windowProc() as usual.

The ClientArea class has been completely removed.