One of these days I’ll make a tutorial on skinning as well as do that “uber size method” article, but till then, here are my notes I collect throughout my travels in the Flash MX 2004 framework.
Skin stuff has deep ties with UIObject. UIObject is the base component class. UIComponent helps, but UIObject is the one you should pay attention to. There are some properties n’ methods setup in him in preparation for some of the skin classes, interestingly enough. With frameworks, I’m starting to feel because your building something to help, it’s ok to cross pollenate knowledge of other classes. Everyone has a job, but that doesn’t necessarely mean each person shouldn’t have knowledge, even if a little bit, about another’s. That violates OOP, but who cares, this stuff works.
Ok, first off, all of the good stuff is in mx.skins. The main dude, SkinElement, is what you input into a skin. So, you make a movie clip, put your shiot in it, and then input mx.skins.SkinElement into the AS2 class for that symbol and your good.
There are a few other support classes in there to help with foundations, such as borders. The RectBorder is used for outlines n’ such. CustomBorder, however, operates like a window titlebar; it has 3 pieces; a left, right, and a stretchable middle. I personally haven’t found using this class directly to work. Skins, at least in CustomBorder’s case, do not have an initial width and height property, thus rendering them useless. They do, but those properties don’t have values. The size method will get called, but it won’t have any values associated with them, thereofore, it’ll fail to position the middle and right correctly. I looked at mx.controls.scrollClasses.Thumb or whatever, as he seems to use CustomBorder, but didn’t see anything that helped.
So barring that mofo, let’s get to the properties that, like SkinElement, I actually know how to get to work.
Typically, if you have a skin for, say, your background, you’d define a private variable equal to the linkageID name. So, for a window component you’d do:
private var backgroundSkin:String = "WindowBackground";
Where that is the linkageID of the movie clip that houses the WindowBackground. When you attach him, you can then call setSize on him, but he doesn’t have all the functions that UIObject has. SkinElement is a lot like UIObject, but is greatly simplified, thus reducing memory costs.
Here’s where things get fuzzy for me, but let me define some more properties first before I explain how to use that private variable.
One more note about him; since he’s defined with an initial value, he’s on the prototype of the class. Therefore, all instances will have that value by default. If you change that value for that class, only he will have the modified property. If you change the prototype value directly, all instances thus forth will have the new property’s value. This, too, helps in memory since initially, the string is only stored in one place. So, if you want one component to have a different skin, you can just set is backgroundSkin variable to something else via the initObject when creating.
This, like all of the mix-in style classes, is an array of strings. This array houses the linkageID names of all the skin elements you’ll be using. It may seem redundant because you just set all of those strings to variables, but I believe this is used for look up for the setSkin method.
Here’s mx.controls.SimpleButton’s implementation (I think it’s him):
An object where property names are skin names, and numbers are
skins’s ID; a number. They are used for depth, as well as the getSkinIDName method, which the tag is passed in and used as an an array index, from idNames, to
return the linkageID name to use in createEmptyObject, which is a simple wrapper for createClassObject creating a UIObject instance.
In my words, it’s just a simple way to house both the skin’s ID # as well as it’s linkageID name all in one object. Further redundancy, but I’m sure there’s a reason.
Use dat Shiot
The end result is, instead of using createObject, createClassObject, or attachMovie to make your skins, you do setSkin. It requires the id, linkageName, and initObject if you want one. To me, you’d do:
And I believe the end result will be that it will respond to style changes as well as other setSize events. The registration with the skin registry variables seems kind of dumb. The SkinElement register element is just a wrapper for Object.registerClass… but I wouldn’t be using that class if it wasn’t a skin… Also, I think the skinRegistry global is just to check it’s actually a registered skin. You can do the same thing with attachMovie, but it’s cleaner and better managed this way… at least, that’s the feeling I get the more I dig. No, I have no idea all of what’s going on, but this is how every other component does it, and after finding out why createLabel was cooler than createTextField, I’m using history as the best teacher.
…and the research continues…