Opensprings.org

Open Modules – version 0.1 – Demo Release


Copyright (C) 2003 Hotsprings Inc.
Distributed under the GPL

Location: www.Opensprings.org

Description:

This file is common to all the demos. It builds the skin needed by the demo apps.

The SkinBuilder class loads the needed images, and turns them into the desired skin. The generated application skin contains all skins needed by the views in the app. The generated skin (common to all the demos) contains more skins that are required by any particular demo. This is a waste of resources but since these are just sample applications we considered it is better not to let the skin creation interfere with the actual code of the app.

The images are loaded from a folder called "Skin.rsrc". This folder is located within any of the parent folders of the application launched. This allows various apps to be deployed in separate folders but grouped together inside the same parent folder. By placing the skin resources within that same parent folder we allow for the sharing of the skin resources.

To load images we use an ImagePool object. ImagePool is an agent with the ability to sequentially load a bunch of images (PNG only at the time of this writing) and send completion notifications to its master controller. The class ImageLoader is the proxy that listens to the notifications generated by the ImagePool and resends them to the SkinBuilder class.

Once all the images have been loaded the SkinBuilder reacts to the notification "ImagesLoaded()" and starts synchronously building the needed skins.For now ImagePool loads images and stores them into a vector. Addressing each individual image can be done by the vector index only. This will change in the near future once we transfer all the functionality in this file into an XML based skin configuration file. At that point various skins and images used by it will have customizable string names.

The creation of each skin consists of 2 steps:

  1. associating a state to a particular background image "AddStateSkin()"Unless you know really well what you are doing, the default state (identified by both mask and value zero) should always be defined so that the view can always draw a background. There is one view where we commonly do not define any skin states: the label. For labels we simply do not want a background drawn, and rely on the background of the container. You may choose to think differently :-)

  2. agregating any number of skin definitions as components of a larges skin "AddPart()". If the skin is to be used on a view that does not have agregated children then there is no need to define any agregate skins. Each agregated skin part has a part-name. The part name is used by the view to identify which skin part goes to which child.

Take a look at "CreateTabSkin()" as a demo.

  1. For the tabs the states hovered, selected and default are defined. The images we draw for these states will make the tab look similar to a raised button.

  2. The tab skin is agregated with the name "tab" into the bar skin. For the bar itself only the default state is defined (an inanimate background)

  3. The bar skin is agregated with the name "bar" into the tab skin. for the entire tab page we did not define a background and rely on the content of the page to draw something or for the parent container of the tab to do it. It is frequently a good ideea to just omit assigning a background to containers (as tab page) because this will avoid drawing one background (the child) on top of another (the parent) and waste precious drawing time.

  4. Notice that for each state skin we assign an image but also add a rectangle. The purpose of the rectangle is to define a "content" region to the view. This allows the skin designer to define where the content goes instead of requiring the programer to hard code such things. Of course as of now, no XML skin configuration is available so the feature is not plainly helpfull.During the drawing of the skin the content area gets stretched to cover most of the view's bounding rectangle. The edges outside of the content area will have fixed width / height. This is all you need to draw fancy looking borders.

Once the process of building the skins is complete the SkinBuilder broadcasts the appropriate notification (SkinBuildComplete or SkinBuildFailed) to the listening application.



BACK
OpenSprings Website
Sourceforge Project Page