Implement basic visualization facilities such as primitive drawing. In
    particular, this means the implementation of
    o.e.swt.graphics.GC [#Base] class. The test example of this
    step should be able to create an SWT top window and draw some graphic
    primitives in it.
In OS/2, as opposed to Windows (at least from the API point of view),
    the client part of the frame window (the area where the custom drawing
    takes place) is the separate window with its own window class and
    procedure. SWT uses the Windows approach and therefore the frame window
    (i.e. Decorations and Shell widgets) should
    encapsulate the client window functionality to be as a whole for the user.
    To achieve this the client window, an instance of the special
    ClientArea class (which is derived from the
    Composite), is anonymously created by the
    Decorations.createHandle() method. "Anonymously" means that
    this instance is unaccessible anywhere outside the
    Decorations class. The special feature of the
    ClientArea class is that it uses its parent's (i.e. the
    Decorations) event table and, when sending or posting
    messages, sets the Event.widget field to the value of
    parent rather than this. This means that all
    events (specifically, the SWT.Paint event) generated by the
    client window look as Decorations events to the user (and
    directed to listeners registered on the Decorations
    instance).
The presentation space handle to do low level painting in the window is
    obtained via the Control.internal_new_GC() method and must be
    freed by the Control.internal_dispose_GC() method when no
    more needed. The logic of work of these two methods is as follows:
data argument is null or
      data.rcl is null then WinGetPS()
      is used to obtain the presentation space handle and
      WinReleasePS() -- to release it. Otherwise
      WinBeginPaint() obtains a handle, reusing
      data.hps (if not null) and filling
      data.rcl with the updating rectangle, and
      WinEndPaint() releases the presentation space
      obtained.WinGetPS() and WinBeginPaint() use
      data.hwnd, if it is not zero, as the window handle to
      obtain the presentation space for. Otherwise Control.handle
      is used. The latter is the normal behavior (i.e. data.hwnd
      should normally be zero), the former can be used to substitute the
      handle in subclasses when obtaining the presentation space handle (it is
      not currently used and may be removed in the future).data is not null,
      data.device is assigned to the return value of
      getDevice() and data.hdc is filled with the
      device context handle returned by GpiQueryDevice() for the
      presentation space obtained above.In the Windows version, the WM_PAINT handler uses the
    device context obtained via the BeginPaint() API call, which
    initializes it with default attributes. To setup the correct graphics
    context (a pen, brush, etc.) the GC.win32_new() method is
    called every time when the WM_PAINT message occurs. Although
    the same technique can be used in OS/2 too (and the existing code is ready
    to do it) at the present time the "long-term" presentation space is used
    to save attributes between WM_PAINT messages (and for some
    other purposes). This presentation space is allocated only once (lazily in
    the WM_PAINT handler) for every Control widget
    which has at least one SWT.Paint event listener registered,
    and it is released when the widget is being destroyed. However, the
    Composite class (and its descendants, of course) allocates
    such presentation space even if no SWT.Paint listeners are
    registered, to draw the background (this behavior may change in the
    future). This approach should lead to a better performance since no calls
    to setup attributes on every paint message (except the first one) are made
    (the GCData.doInit field is used by GC.pm_new()
    and the WM_PAINT handler to indicate the need to setup the
    presentation space). At the same time, this should not cause the increase
    of memory usage because the presentation space is obtained via the
    WinGetPS() call, which returns the cached presentation
    space.
Besides other things, the long-term presentation space is used to store
    the default view transformation matrix to do the automatic coordinate
    space flipping when using Gpi* functions for painting (see
    also here). It allows to
    update the matrix only when the window is resized instead of doing it on
    every paint message.
There is some muddle with dimensions of graphic primitives in the Win32
    version of SWT: for example, the javadoc says that
    GC.drawRoundRectangle()draws a rectangle, those left and
    right edges are at x and x + width, top and bottom
    edges are at y and y + height. But it's not the case
    -- actually, the right edge is at x + width - 1, and the bottom
    one is at y + height - 1, i.e. the horizontal and vertical size
    is one pixel smaller than it stated. Besides this, all fill*
    versions of primitives draw figures one pixel smaller in size than their
    draw* versions, i.e. the rectangle drawn by
    GC.fillRectangle(0,0,10,10) is not the same in size as by
    GC.drawRectangle(0,0,10,10) -- the size of the former is 11
    by 11 pixels while the size of the latter is 10 by 10. The docs just say
    that fill* versions fill the interior of a primitive, but we
    see no reasons for the interior to be one pixel smaller than the outline
    (although it's an expected behavior of the corresponding Win32 API calls,
    but not OS/2 ones). Also, there are errors when drawing very small figures
    (few pixels in size) and figures with the negative width and/or height
    (see the SWT003_01 example). Most of these things look just
    like bugs, so in OS/2 version we decided to fix them until any
    incompatibility issue appears. "To fix" here means that the bounding
    rectangle of all primitives in the OS/2 version of SWT always follows the
    rule stated in the javadoc for GC.drawRectangle() about the
    edges and covers an area width + 1 pixels wide by height +
    1 pixels tall.
In the Win32 version of SWT, if the device is in the palette mode (that
    is, when it can display only 256 distinct colors simultaneously) and we
    try to create new colors inside the paint event listener (as we draw in a
    window) these colors will not appear on the screen until the next window
    invalidation (see the SWT003_02 example). It is because new
    colors are being added to the physical palette when it's already selected
    to the device context at the beginning of the paint event handling and
    won't be selected again until the next paint event. In the OS/2 version we
    solve this problem by posting the WM_REALIZEPALETTE message
    to every Shell widget when the new color is created, which
    causes widgets to invalidate themselves.
In Windows, when drawing styled lines (dotted, dashed etc.) intervals between sytle segments are considered to be the "background" of the line and therefore are drawn by the current brush (see the SWT003_01 example). In OS/2 they are considered to be transparent and this behavior cannot be altered. Due to the inefficiency of the only possible application-level implementation of this functionality it is left as is at the present.
| Operation | Status | Remarks | 
|---|---|---|
| Implement OS.WinWindowFromID()andFID_*constants | Done [dmik] | |
| Implement the frame client window creation and the message routing for it | Done [dmik] | |
| Add OS.GpiCreateRegion(),WinQueryUpdateRegion(),WinInvalidateRegion()andRGN_*
        constants | Done [dmik] | The RECTLstructure (which is originally passed as a
        pointer) is passed as anintarray (with four elements)
        from Java to simplify access to it from the native
        implementation. | 
| Add OS.GpiQueryRegionRects(),RGNRECTclass,RECTDIR_*constants | Done [dmik] | |
| Implement WM_PAINTmessage handling andSWT.Paintevent firing | Done [dmik] | |
| Implement OS.WinGetMaxPosition() | Done [dmik] | Used to implement the Display.getClientArea()method,
        which returns the size and position of maximized windows of the
        desktop. These values can differ fromDisplay.getBounds(), e.g. when XCenter is running. Note:
        XCenter 1.0.1 has a strange feature -- it reduces the maximum height
        (reported byWinGetMaxPosition()) by the value of its own
        height plus additional 5 pixels, therefore the reported maximum height
        is 5 pixels less than the actual. Possibly, it's a bug. | 
| Implement Device.getBounds(),getClientArea()forDevice,Displayand controls that support this | Done [dmik] | Scrollable.getClientArea()code is temporary (should
        take the scrollers into account) | 
| Add OS.GpiMove,OS.GpiBox,GPI_*andDRO_*constants, implementGC.{fill|draw}[Round]Rectangle()methods | Done [dmik] | POINTLstructures are passed as arrays ofintwith two elements (x and y). | 
| Add WM_CALCVALIDRECTSmessage handling,OS.CVR_*constants | Done [dmik] | Compositeinstance returnsCVR_REDRAWonWM_CALCVALIDRECTSif it has theCANVASstate
        and noSWT.NO_REDRAW_RESIZEstyle to completely
        invalidate itself when resizing. | 
| Create the draft SWT003testcase | Done [dmik] | |
| Fix the bug of GpiBox() | Done [dmik] | GpiBox()draws the rectangle 1 pixel higher than it
        should do, when rounded corners andDRO_FILLorDRO_OUTLINEFILLare specified. | 
| Add the long-term presentation space creation for a Controlobject | Done [dmik] | |
| Implement OS.GpiSetDefaultViewMatrix(),TRANSFORM_*constants | Done [dmik] | Necessary for automatic coordinate space flipping. | 
| Add OS.SHORT{1|2}FROMMPpseudo macros | Done [dmik] | |
| Add the o.e.swt.widgets.ClientAreaclass | Done [dmik] | This class represents the frame client window. | 
| Implement OS.DevQueryCaps()andCAPS_*constants | Done [dmik] | Currently, constants are almost fully commented -- uncomment when needed. | 
| Overload OS.WinSendMsg()with one, that takesOS.RECTLas the first message parameter | Done [dmik] | Currently used to send WM_CALCFRAMERECTmessage. | 
| Add OS.GpiCreatePalette(),GpiDeletePalette(),LCOL_*andLCOLF_*constants,GpiQueryNearestPaletteIndex(),GpiQueryPaletteInfo(),GpiSetPaletteEntries(),GpiSelectPalette(),GpiCreateLogColorTable(),WinRealizePalette() | Done [dmik] | Note: GpiQueryNearestPaletteIndex()is undocumented.
        We hope it presents in Warp4 and earlier OS/2 versions... | 
| Add OS.GpiQueryColor(),GpiSetColor(),GpiQueryBackColor(),GpiSetBackColor(),GpiQieryMix(),GpiSetMix(),FM_*constants,GpiQueryBackMix(),GpiSetBackMix(),BM_*constants,GpiQueryPattern(),GpiSetPattern(),PATSYM_*constants | Done [dmik] | |
| Add WM_REALIZEPALETTEmessage handling, implement{get|set}{Foreground|Background}()methods ofControlandGCclasses,OS.WinQuerySysColor()andSYSCLR_*constants | Done [dmik] | |
| Add the GC.Colorclass and implement color
        handling | Done [dmik] | |
| Add OS.GpiLine(),GpiBeginArea(),GpiEndArea(),GpiPartialArc(),GpiSetArcParams(),GpiQueryCurrentPosition(), implementGC.drawLine(),{draw|fill}Arc(),{draw|fill}Oval()methods | Done [dmik] | ARCPARAMSstructure is passed toGpiSetArcParams()as an array ofint[4]. | 
| Create TestCaseandSWTTestCaseclasses
        to simplify test case writing, remove theSWT003tescase
        and createSWT003_01andSWT003_02instead,
        update theSWT004testcase | Done [dmik] | If the step requires several different testcases each with its own
        top shell window, it's possible to do so, naming them as SWTXXX_YYwhere XXX is the step number and YY is the
        number of the testcase. Such testcases can be run as usual, specifying
        the step name in the format above via the test.step
        property in the build.prp file or on the command line. | 
| Add OS.GpiPolyLine(), implementGC.getBackground(),getForeground(),drawPolyline(),drawPolygon(),fillPolygon() | Done [dmik] | |
| Add OS.Gpi{Query|Set}LineType(),LINETYPE_*constants, implementGC.{get|set}LineStyle(),drawFocus() | Done [dmik] | |
| Add OS.Gpi{Begin|End|Stoke}Path(),Gpi{Query|Set}LineWidthGeom(),GpiSetLine{End|Join}, implementGC.{get|set}LineWidth,{get|set}XORMode() | Done [dmik] | |
| Readress the Decorations.redraw()methods to the
        client window; addOS.WinEnableWindowUpdate(), implementControl.setRedraw(); addOS.WinIsWindowShowing(), implementControl.isShowing() | Done [dmik] | |
| Add OS.GpiQueryClipBox(),GpiSetClipRegion(),GpiQueryRegionBox(),GpiCombineRegion(),GpiPtInRegion()andPRGN_*constants,GpiRectInRegion()abdRRGN_*constants; implement the o.e.swt.graphics.Region
        class, implementGC.{get|set}Clipping(); add testcaseSWT003_03to test clipping | Done [dmik] | Regionclass is fully implemented. However, there's a
        potential question about using regions with other devices than the
        screen (since OS/2 requires the presentation space to be specified
        when operating regions, the screen PS is used for this purpose). | 
| Move the frame class and window procedure definition code from the Shellto theDecorationsclass | Will be done on next steps | Decorationsis logically a frame too. And if it will
        be used/subclassed directly (i.e. not by theShell) then
        we need this code in it. | 
| Try to re-enable SWT.CLIP_SIBLINGSandSWT.CLIP_CHILDRENstyles recognition inControl.widgetStyle(), and remove forcing them inComposite.WM_PAINT()andComposite.widgetStyle() | Will be done on next steps | In Windows version it is intentionally commented because: "When strict clipping was not enforced on all widgets, poorly written application code could draw outside of the control". Is it the same in OS/2? Possibly, not. |