How does one define a default style for a custom Flex component?
Asked Answered
P

6

11

I'm creating a new Flex component (Flex 3). I'd like it to have a default style. Is there a naming convention or something for my .cs file to make it the default style? Am I missing something?

Pursuance answered 30/1, 2009 at 21:41 Comment(0)
G
8

Two ways, generally. One's just by referencing the class name directly -- so for example, if you'd created a new component class MyComponent in ActionScript, or indirectly by making an MXML component extending another UIComponent called MyComponent, in both cases, the component would pick up the styles declared in your external stylesheet, provided that stylesheet's been imported into your application (e.g., via Style source):

MyComponent
{
     backgroundColor: #FFFFFF;
}

Another way is by setting the UIComponent's styleName property (as a string):

public class MyComponent
{
     // ...

     this.styleName = "myStyle";

     // ...
}

... and defining the style in the CSS file like so (note the dot notation):

.myStyle
{
     backgroundColor: #FFFFFF;
}

Make sense?

Genesisgenet answered 30/1, 2009 at 23:32 Comment(1)
I wasted a lot of time getting this all to work, so for anyone seeking additional assistance: This is a great answer, this works, but for an additional good reference, check out the answer below by Yarin. When you follow Yarin's answer, make sure the CSS file name is actually called "defaults.css" No other name will work even though you can include any css file into the project. Argh.Gastroscope
S
10

Christian's right about applying the CSS, but if you're planning on using the component in a library across projects, you're gonna want to write a default css file for that library. Here's how you do it:

  1. Create a css file called "defaults.css" (Only this file name will work!) and put it at the top level under the "src" folder of your library. If the css file references any assets, they have to be under "src" as well.
  2. (IMPORTANT!) Go to library project's Properties > Flex Library Build Path > Assets and include the css file and all assets.

That's how the Adobe team sets up all their default styles, now you can do it too. Just figured this out- huge

Superelevation answered 20/3, 2010 at 17:22 Comment(1)
Rather I should give credit where it's due: Henk and Chris in responses here: parallaxed.net/article/…Superelevation
G
8

Two ways, generally. One's just by referencing the class name directly -- so for example, if you'd created a new component class MyComponent in ActionScript, or indirectly by making an MXML component extending another UIComponent called MyComponent, in both cases, the component would pick up the styles declared in your external stylesheet, provided that stylesheet's been imported into your application (e.g., via Style source):

MyComponent
{
     backgroundColor: #FFFFFF;
}

Another way is by setting the UIComponent's styleName property (as a string):

public class MyComponent
{
     // ...

     this.styleName = "myStyle";

     // ...
}

... and defining the style in the CSS file like so (note the dot notation):

.myStyle
{
     backgroundColor: #FFFFFF;
}

Make sense?

Genesisgenet answered 30/1, 2009 at 23:32 Comment(1)
I wasted a lot of time getting this all to work, so for anyone seeking additional assistance: This is a great answer, this works, but for an additional good reference, check out the answer below by Yarin. When you follow Yarin's answer, make sure the CSS file name is actually called "defaults.css" No other name will work even though you can include any css file into the project. Argh.Gastroscope
B
6

In addition to what Christian Nunciato suggested, another option is to define a static initializer for your Flex component's styles. This allows you to set the default styles without requiring the developer to include a CSS file.

private static function initializeStyles():void
{
    var styles:CSSStyleDeclaration = StyleManager.getStyleDeclaration("ExampleComponent");
    if(!styles)
    {
        styles = new CSSStyleDeclaration();
    }

    styles.defaultFactory = function():void
    {
        this.exampleNumericStyle = 4;
        this.exampleStringStyle = "word to your mother";
        this.exampleClassStyle = DefaultItemRenderer //make sure to import it!
    }

    StyleManager.setStyleDeclaration("ExampleComponent", styles, false);
}
//call the static function immediately after the declaration
initializeStyles();
Beale answered 2/2, 2009 at 0:24 Comment(0)
P
2

A refinement of what joshtynjala suggested:

public class CustomComponent extends UIComponent {
    private static var classConstructed:Boolean = classConstruct();

    private static function classConstruct():Boolean {
        if (!StyleManager.getStyleDeclaration("CustomComponent")) {
            var cssStyle:CSSStyleDeclaration = new CSSStyleDeclaration();
            cssStyle.defaultFactory = function():void {
                this.fontFamily = "Tahoma";
                this.backgroundColor = 0xFF0000;
                this.backgroundAlpha = 0.2;
            }
            StyleManager.setStyleDeclaration("CustomComponent", cssStyle, true);
        }
        return true;
    }
}

I've read this in the docs somewhere; the classContruct method gets called automatically.

Platinumblond answered 14/1, 2010 at 17:28 Comment(4)
... and here's the link livedocs.adobe.com/flex/3/html/…Platinumblond
It's fairly obvious why classConstruct gets called and it's rather unfortunate that the docs aren't more verbose on this subject. It get's called because the static variable classConstructed is set by calling the static method classConstruct. Any static variable or code block will be executed when the type is first referenced, before any instantiation has ocurred. I haven't tried this, but I'm fairly certain that just using a static block will yield the same result, with no redundant variables declared and less clutter.Pomade
Note that the full package name must be used, meaning: "com.mypackage.CustomComponent". Darren's example works if CustomComponent is in the default package. Otherwise, use the full package name.Hamford
Ha ha ha, shame shame! Yes it is obvious :-/ Also didn't know static initializers existed in AS but do now :-)Platinumblond
G
2

You may want to override default styles using the <fx:Style> tag or similar. If that's the case, a CSSStyleDeclaration may already exist by the time classConstructed is checked. Here's a solution:

private static var classConstructed:Boolean = getClassConstructed ();
private static function getClassConstructed ():Boolean {
  var defaultCSSStyles:Object = {
    backgroundColorGood: 0x87E224, 
    backgroundColorBad: 0xFF4B4B, 
    backgroundColorInactive: 0xCCCCCC, 
    borderColorGood: 0x333333, 
    borderColorBad: 0x333333, 
    borderColorInactive: 0x666666, 
    borderWeightGood: 2, 
    borderWeightBad: 2, 
    borderWeightInactive: 2
  };
  var cssStyleDeclaration:CSSStyleDeclaration = FlexGlobals.topLevelApplication.styleManager.getStyleDeclaration ("StatusIndicator");
  if (!cssStyleDeclaration) {
    cssStyleDeclaration = new CSSStyleDeclaration ("StatusIndicator", FlexGlobals.topLevelApplication.styleManager, true);
  }
  for (var i:String in defaultCSSStyles) {
    if (cssStyleDeclaration.getStyle (i) == undefined) {
      cssStyleDeclaration.setStyle (i, defaultCSSStyles [i]);
    }
  }
  return (true);
}
Gumbotil answered 10/8, 2011 at 21:15 Comment(0)
P
1

To create a default style you can also have a property in your class and override the styleChanged() function in UIComponent, eg to only draw a background color across half the width of the component:

// this metadata helps flex builder to give you auto complete when writing
// css for your CustomComponent
[Style(name="customBackgroundColor", type="uint", format="color", inherit="no")]

public class CustomComponent extends UIComponent {

    private static const DEFAULT_CUSTOM_COLOR:uint = 0x00FF00;

    private var customBackgroundColor:uint = DEFAULT_CUSTOM_COLOR;

    override public function styleChanged(styleProp:String):void
    {
        super.styleChanged(styleProp);

        var allStyles:Boolean = (!styleProp || styleProp == "styleName");

        if(allStyles || styleProp == "customBackgroundColor")
        {
            if(getStyle("customBackgroundColor") is uint);
            {
                customBackgroundColor = getStyle("customBackgroundColor");
            }
            else
            {
                customBackgroundColor = DEFAULT_CUSTOM_COLOR;
            }
            invalidateDisplayList();
        }

        // carry on setting any other properties you might like
        // check out UIComponent.styleChanged() for more examples
    }

    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);

        graphics.clear();
        graphics.beginFill(customBackgroundColor);
        graphics.drawRect(0,0,unscaledWidth/2,unscaledHeight);
    }
}

You could also create a setter for the customBackgroundColor that called invalidateDisplayList(), so you could also set the customBackgroundColor property programatically as well as through css.

Postpaid answered 23/4, 2010 at 3:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.