I think this screenshot speaks for itself:
Screens and windows can now be skinned, using a large number of bitmaps and the new SkinnedScreen and SkinnedWindow classes.
There are two new structs in Woopsi - ScreenSkin and WindowSkin. They contain all of the information necessary to create a skinned window or screen, such as the font to use, the bitmaps to use, the dimensions of the bitmaps, etc. Putting a skin together involves a lot of property setting but, once a skin struct has been created, it can be passed into new windows/screens via a pointer and that window/screen automatically implements all of the features of the skin.
Bitmaps necessary for screens are the title bar, and the screen depth/flip buttons in both normal and clicked states. The window requires a top-left image, top-centre image, top-right, left, right, bottom-left, bottom-centre and bottom-right (for both focused and blurred states). It also requires close and depth button bitmaps for normal and clicked states, both focused and blurred (ie. 4 bitmaps for each).
There is still some work to do - it would be nice to be able to specify on which side the various buttons appeared. The SkinnedWindow resize code doesn’t work (it’s still based on the standard gadget sizes). There are probably a few other problems that I haven’t considered.
Not too bad, though!
The skin I’ve put together illustrates one of the pitfalls with DS GUI design - the buttons are too small to click accurately. It doesn’t have separate border bitmaps for the blurred state (just re-used the pointers to the focused state), so it doesn’t appear to change when clicked.
I haven’t bothered supporting tiling. If I was putting that skin together in HTML, I’d use 1px wide background images and tile them to fill the width of an element. On the DS it’s more efficient (in terms of speed, not RAM) to just have 256px wide or 192px high images, and DMA_Copy chunks of them as needed.
I should mention that the skinning system doesn’t magically provide non-rectangular gadgets. Everything in Woopsi is a rectangle (supporting non-rectangular regions becomes exponentially more complicated), and if you put together a skin with round edges you’ll see that Woopsi just draws rectangles anyway.
Other changes are mainly fiddly. There are a few clipping fixes in the GraphicsPort. I’ve removed the SuperBitmap::newBitmapGraphicsPort() function because the GraphicsPort is inextricably linked to the DS’ physical screens (due tp top-screen y-co-ordinate calculations), so can’t really be used with the SuperBitmap. Woopsi increments its VBL counter before calling its children, as per Jeff’s request. The GraphicsPort’s text routines now handle their “colour” parameters properly. Lastly, window drag initialisation is handled by the WindowBorderTop class instead of some freaky code in the AmigaWindow class.