Below shows the “CheckBox.png” skin asset from the “classic” theme (blown up here for a closer look):
This single image file is used to render the various visual states of the uiCheckBox. The image will be cut up from left-to-right into equal slices representing the states of “up”, “over”, “down”, “disabled”, “selected_up”, “selected_over”, “selected_down”, and “selected_disabled” respectively1). The names of these slices are defined in the “rules.xml” file stored in the same folder as the PNG file (Line 3 below):
1: <rules theme="classic" css="text.css"> 2: <Button prefs="padding|5,7|focusPadding|4|displaceX|1|displaceY|1" slices="up,over,disabled,down,selected_up,selected_over,selected_down,selected_disabled,emphasized,emphasized_down" /> 3: <CheckBox slices="up,over,down,disabled,selected_up,selected_over,selected_down,selected_disabled" /> 4: <ComboBox clone="TextInput" /> 5: <ComboBoxButton midX="9" midY="7" slices="up,over,down,disabled" /> 6: <ComboBoxList edge="1" prefs="padding|1" /> 7: <ComboBoxListItem clone="ListBoxItem" /> 8: <FocusRect edge="1" repeat="xy" /> 9: <Frame prefs="padding|8" /> 10: <ListBox clone="TextInput" /> 11: <ListBoxItem edge="" slices="up,selected" prefs="textStyle|listitem" /> 12: <LabelButton clone="Button" /> 13: <PushButton clone="Button" /> 14: <RadioButton copy="CheckBox" /> 15: <ScrollBar edge="0" repeat="xy" slices="up,disabled,down" /> 16: <ScrollBarDown slices="up,over,down,disabled" /> 17: <ScrollBarUp copy="ScrollBarDown" /> 18: <ScrollBarThumb copy="ScrollBarDown" /> 19: <Slider edge="8,3" midY="5" slices="up,disabled,down" /> 20: <SliderThumb edge="2,7,17,2" repeat="xy" slices="up,over,down,disabled" /> 21: <StepperDown edge="2" midX="4" midY="7" slices="up,over,down,disabled" /> 22: <StepperUp copy="StepperDown" /> 23: <StepperInput clone="TextInput" /> 24: <StepperInputStepDown clone="VStepperDown" /> 25: <StepperInputStepUp clone="VStepperUp" /> 26: <TabViewBar edge="1" prefs="spacing|-4" /> 27: <TabViewBarItem edge="4" slices="up,selected" prefs="displaceX|-1|displaceY|-1|focusPadding|3,2|padding|3,6" /> 28: <TabViewBarStepperDown edge="2" midX="4" midY="7" slices="up,over,down" /> 29: <TabViewBarStepperUp copy="TabViewBarStepperDown" /> 30: <TabViewContent edge="2" prefs="padding|8" /> 31: <TextArea clone="TextInput" /> 32: <TextInput slices="up,disabled" prefs="focusPadding|2|padding|2" /> 33: <VScrollBar copy="ScrollBar" /> 34: <VScrollBarDown copy="ScrollBarDown" /> 35: <VScrollBarUp copy="ScrollBarDown" /> 36: <VScrollBarThumb copy="ScrollBarDown" /> 37: <VSlider edge="3,8" midX="5" slices="up,disabled,down" /> 38: <VSliderThumb edge="2,2,7,17" repeat="xy" slices="up,over,down,disabled" /> 39: <VStepperDown edge="2" midX="7" midY="4" slices="up,over,down,disabled" /> 40: <VStepperUp copy="VStepperDown" /> 41: </rules>
The “rules.xml” file defines the rendering rules for the various skin assets stored in the same folder, and these will be different for different themes. Each skin asset must have a corresponding entry in the “rules.xml”. If the entry is missing, the skin asset will not be loaded and will not be available for use in your application.
Let's look at the various rendering rules.
“edge”
The “edge” attribute determines the outer rim that should not be scaled when the skin is resized. When undefined, the edge is assumed to be 3 pixels for each side. You define this attribute as a comma-delimited string of integer values. You can supply one, two, three or four integer values in the string. If you specify one value, that value is applied to all sides; if you supply two values, the first is applied to top and bottom, the second applied to left and right; if you supply three values, the first is applied to top, second to left and right, third to bottom; if you supply four, each side takes their respective values.2) The purpose of this property is similar to that of the Flash Player native DisplayObject’s scale9grid property, but instead of defining a Rectangle, you define the values for each side (which are intended to stay constant when the skin is resized).
“midX”
The “midX” attribute specifies in pixels the thickness of the middle horizontal portion that should not be scaled when the skin is resized. If undefined, value of zero is assumed.
“midY”
The “midY” attribute specifies in pixels the thickness of the middle vertical portion that should not be scaled when the skin is resized. If undefined, value of zero is assumed.
“repeat”
The “repeat” attribute if defined indicates that the scaleable portion should be repeated (across the x/y axis) instead of being stretched linearly. The value of this attribute if defined should be either “x” (repeated only horizontally), “y” (repeated only vertically) or “xy” (repeatedly both horizontally and vertically). For example, in Line 15 above, the “ScrollBar” asset has “repeat” set to “xy” meaning it should repeat horizontally and vertically without scaling. The “edge” for this skin is set to zero which means there are no non-scaling sides. The image is taken “as-is” and then repeated across the x and y axis. As can be expected, repeating is more CPU-intensive than scaling linearly, so do use this feature with care.
“slices”
The “slices” attribute if defined indicates that the PNG image should be cut up equally into the indicated slices. If undefined, the entire image is cached as a single slice. When creating your own skin asset, take note of the following:
“clone”
The “clone” attribute if defined means that the skin is a clone/mirror of another skin in the theme. This can be used to point several different skins to the same PNG bitmap file. This prevents duplicate work and reduce memory usage.
“copy”
The “copy” attribute if defined means that the node should copy all the attributes defined in the specified node. The value of this attribute is the name of the node to copy from.
“prefs”
The “prefs” attribute if defined indicates the property values component instances using the skin should be set to when the instances are realized5). This is usually used to set styling properties such as focusPadding, margin, padding, textStyle, etc. The value of this attribute if defined should follow the format:
prefs=“propertyName|propertyValue|propertyName|propertyValue|…|propertyName|propertyValue”
For example, the component instances using the “Button” skin will have focusPadding set to “4”, padding set to “5,7”, displaceX set to 1 and displaceY set to 1.
2: <Button prefs="padding|5,7|focusPadding|4|displaceX|1|displaceY|1" slices="up,over,disabled,down,selected_up,selected_over,selected_down,selected_disabled,emphasized,emphasized_down" />
This attribute provides great flexibility in the customization of your Flash applications. For example, you may use this attribute to alter the textStyle property for a group of component instances (using the same skin), without having to re-compile the SWF. Using this attribute to assign property values also ensures more consistency in the look of the UI controls, without having to hard-code the values for each UI control individually in the application code.
NOTE: If you wish to override the “prefs” settings in your application code, you need to do so after the component instance(s) is/are realized. Consider the following:
1: package 2: { 3: import com.ghostwire.ui.containers.*; 4: import com.ghostwire.ui.controls.*; 5: import com.ghostwire.ui.data.*; 6: import com.ghostwire.ui.events.*; 7: import com.ghostwire.ui.enums.*; 8: import com.ghostwire.ui.managers.*; 9: 10: import flash.display.Sprite; 11: import flash.events.*; 12: 13: public class MyApplication extends Sprite 14: { 15: public function MyApplication() 16: { 17: // ** optional but recommended ** 18: stage.scaleMode = "noScale"; 19: stage.align = "TL"; 20: 21: // ** optional but recommended ** 22: // ** let assets preload before starting application ** 23: uiSkins.manager.addEventListener(Event.INIT,main); 24: 25: // ** you can start your application without waiting for uiSkins to be ready but... ** 26: var btn:uiLabelButton = new uiLabelButton("One"); 27: btn.padding = "10"; // ** no effect because padding specified in "prefs" will be applied later and override this ** 28: addChild(btn); // ** added to stage but not yet realized because the framework will automatically delay this until uiSkins is ready ** 29: btn.padding = "10"; // ** still doesn't work because padding specified in "prefs" will be applied later and override this ** 30: } 31: 32: private function main(evt:Event):void 33: { 34: // ** called after uiSkins is ready ** 35: var btn:uiLabelButton = new uiLabelButton("Two"); 36: btn.padding = "10"; // ** no effect because when instance is added to stage, padding specified in "prefs" will be applied and override this ** 37: addChild(btn); // ** instance is now realized, padding specified in "prefs" applied ** 38: btn.padding = "10"; // ** this works, overriding the padding specified in "prefs" ** 39: } 40: } 41: }
Nevertheless, it is recommended that you define preferences in the rules.xml instead of hard-coding in your application code. For example, you can clone existing skins and set up different preferences.
margin and padding properties of uiComponent instances.