How to modify default spark skin classes? - actionscript-3

I just want to set one property from default class.But I could't do this successfully yet.
Why I asked this question? I wanted to set Spark List view, but when I create a new Item Renderer, some of default properties changes,e.g. seperator line is removed or height property resized for each item area.
Or, How to reference default skin class to custom one?

The default skin classes are part of the Flex SDK. So you can't really modify them unless you edit the classes in your SDK and do all necessary steps to recompile it. Obviously, this is not a good approach.
Instead you should extend the skin classes that you wish to modify. After you do that, you can use CSS to make your new skin class the default skin for a given component.
Example skin class:
package com.mycompany.skins
{
import spark.skins.spark.ButtonSkin;
public class MyButtonSkin extends ButtonSkin
{
// add new properties or set new values on existing properties
public myCustomProperty:Boolean = true;
}
}
CSS:
s|Button {
skinClass: ClassReference("com.mycompany.skins.MyButtonSkin");
}
The other approach would be to extend the skin class as above. However, instead of using CSS to make it the default skin, you would specify the skin class on each component:
<s:Button id="myButton" skinClass="com.myCompany.skins.MyButtonSkin" />
This is obviously more tedious than using CSS, but will let you selectively apply the skin where you want it.

Related

Hybris backoffice extend widget

This is the syncronization popup (com.hybris.backoffice.widgets.syncpopup.SyncPopupController) used to synchronize catalogs . I want to modify this OOTB widget in order to add multiple selection instead of one (right now , you can only select one catalog at a time).
How can I achieve this ? I don't know how to extend backoffice widgets.
The Listbox you're trying to modify has an attribute called multiple. By default at initialization this is false. The widget lists (because there are 2 lists, one for stage->online and one for online->stage) doesn't have this attribute set to true when the widget is created. The initialize() method from the SyncPopupController only fill these lists with items but nothing more.
Now that you know the root of the problem, you can read this tutorial which explains you how you can extend a widget mot-a-mot. One solution could be extending the original controller and make your custom configuration in the initialize() method.
This could look like this:
public class ExtendedSyncPopupController extends SyncPopupController
{
public void initialize(Component component){
super.initialize(component);
super.getPullList().setMultiple(true);
//etc.
}
}
And after this, you can override the widget definition ( Overriding the Widget Definition chapter from the tutorial provided above ) and pass your custom controller class in <controller class="ExtendedSyncPopupController">.

In AS3, how do I run code when a when the movie starts?

I'm making a level editor for my game, and would like to be able to access a list of all the classes included in my game. I have a static function in my Main class:
public static function register(c:Class, category:String):void {
if (classRegister[category] == null) {
classRegister[category] = new Array();
}
classRegister[category].push(c);
}
Then, in each class I want registered, I put a static initializer:
{
Main.register(prototype.constructor, "motion");
}
However, the static initializers only get called when the class first gets used. Is there a way for a class to force itself to be used right when the game starts? I'm aware that I could explicitly list all the registered classes in the Main file, but that's suboptimal in that the Main file would have to be edited whenever a new class is added that wants registration.
Thanks,
Varga
List all the class definition in the ApplicationDomain, and filter them based on a naming convention or a type (an interface?).
To achieve this, you can use ApplicationDomain.getQualifiedDefinitionNames() (docs), but only if you target FlashPlayer 11.3+.
As a side note, you MUST reference this class somewhere, as a class field so the compiler knows it must include this class in the SWF. You can also put the classes you want to reference inside a SWC library and use -compiler.include-libraries as compiler setting (in that case I wonder if your static initializers gets called?).

Add a property to a Button or other type of Objects

I always created additional property to MovieCLips using the syntax
myMC.myProperty
without any sort of declaration... But i can use this method only with MovieClips.. What about if i want to add a property to a button or any different type of object? I need to extend the class? Do you can me suggest how? Many thanks
You can add property to movieclips in runtime because MovieClip is dynamic class. If the class is not dynamic, you should extend it to create methods and properties.
Read about dynamic classes.
I tend to create custom classes for nearly everything.
I would extend the relevant class and set up a private var for your new property. You can then pass in the value to the constructor or add a getter/setter method to call externally.
private function _myProperty:int;
public function get myProperty():int
{
return _myProperty;
}
public function set myProperty(newVal:int):void
{
_myProperty = newVal;
}
Getter/setter methods add a few lines of code that may seem unnecessary but on big projects when you find a property is being set and you don't know why, you can put a break point in your set myProperty
Subclass is main solution.
Next works only with mx components (flex sdk 3).
Most components have data : Object property that you can freely use to store data.
Monkey patching sometimes is the only way to go. It allows you to add custom properties to flex sdk classes. I don't think you should use it in your case. But I used it to change core logic that is locked by private keyword in flex sdk.
Hope that helps.

Defining a "pass-through" style in Actionscript

I have a custom component called ButtonPanel written in Actionscript. Basically it's just a panel that displays a mx:ButtonBar in the upper right of the mx:Panel title bar and responds to the clicks of the buttons in the bar.
A ButtonBar has three styles available for the buttons: buttonStyleName, firstButtonStyleName, and lastButtonStyleName. I want to write these styles for the ButtonPanel so that if it is declared as such:
<comp:ButtonPanel buttonStyleName="myButtonStyle" ... />
then the ButtonPanel will pass the style through and set the corresponding style of the ButtonBar.
I really have no clue where to start on this because I've never messed with defining styles. Can someone help?
What you refer to as "pass-through" styles are actually called inheriting styles. The solution to your question is in fact quite simple.
You use the style metadata on your custom component to declare that ButtonPanel has a stylename called 'buttonStyleName':
[Style(name="buttonStyleName", inherit="yes")]
public class ButtonPanel extends Panel {
....
}
Note the 'inherit' flag which is set to true: this will make sure that any component inside your custom Panel that has the same style will inherit the value that you've given to that style at the Panel level.
Setting this metadata will make sure that FlashBuilder will suggest buttonStyleName as a style and not as a property (as would happen with Sam's solution).
Edit: already defined styles
I didn't realize at first that you were referring to the mx ButtonBar (as it's not explicitly mentioned). The reason this is not working for you is that mx:ButtonBar already has these styles defined as not inheriting. Look at the source code:
[Style(name="firstButtonStyleName", type="String", inherit="no")]
[Style(name="buttonStyleName", type="String", inherit="no")]
[Style(name="lastButtonStyleName", type="String", inherit="no")]
Because of this the compiler will complain when you try to override that definition in your custom Panel, because it simply wouldn't know which of the contradictory instructions to pick. So we'll have to do a little more work if you want to stick with mx:ButtonBar.
First define the styles on ButtonPanel exactly as they are defined in mx:ButtonBar so they have the same signature (you can just copy/paste the three lines above). This will shut up the compiler but the styles won't be inherited anymore, right?
So we'll have to pass them on manually: in your custom Panel skin, override the updateDisplayList() method and - assuming that the ButtonBar's id is 'buttonBar' - add the following:
private const buttonStyles:Array = [
"firstButtonStyleName",
"buttonStyleName",
"lastButtonStyleName"
];
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
if (buttonBar)
for each (var buttonStyle:String in buttonStyles)
buttonBar.setStyle(buttonStyle, getStyle(buttonStyle));
//some other code
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
This will take the styles from the host Panel and pass them on to the ButtonBar.
In order to pass these styles through, you only have to store them as string variables, and then pass them to the internal ButtonBar.
<mx:ButtonBar ... buttonStyleName="{buttonStyleName}" ... />
[Bindable]public var buttonStyleName:String;
If these two lines of code don't explain it fully to you, let me know and I can flesh out my example.

Setting a skinState of a button in AS3

I want to set (manually) the skinState (for example 'disabled') of a button (that I skinned) in ActionScript.
For example:
I have a button skin with hostComponent: components.backend.btnMenuBakComp
The button skin has the default button states (up, over, down, ...), but I want to set one of this skinStates in ActionScript.
For example:
subMenu.btnDashboard.currentState = "disabled";
This doesn't work because the state "disabled" is not known in the component (it is only known in the skinState of btnDashboard).
How can I fix this?
Is there another solution then load a new skinClass?
Thanks
Quick and dirty
You can access the skin of any component and just set its state directly:
subMenu.btnDashboard.skin.currentState = "disabled";
That is however not a very clean way to do it. You are telling a Skin class directly what to do and completely bypassing the host component. Hence the host component has no idea of the changes that were made to its skin.
The proper way
A cleaner way to approach this is to expose a property on the host component and then tell the skin to adjust itself to possible changes by overriding the getCurrentSkinState() method.
You could for instance create a property 'enabled' and then tell the skin to update its state by calling invalidateSkinState() whenever 'enabled' is being set.
public function set enabled(value:Boolean):void {
_enabled = value;
invalidateSkinState();
}
Calling invalidateSkinState() will make the skin call getCurrentSkinState() in the next render cycle. This method will then look something like this:
override protected function getCurrentSkinState():String {
return _enabled ? "normal" : "disabled";
}
Do note that since you are skinning a Button (or a subclass of it) all that I've written here is already baked into that component. So the answer to your question might be as simple as : "just set the 'enabled' property to true.
subMenu.btnDashboard.enabled = true;