Hi Alex, You are right, I tried using Type Selector to set default skinClass for the custom SkinnableComponent, it worked.
In the constructor function of the custom SkinnableComponent (test.TestComponent): super(); //getQualifiedClassName(this) returns test::TestComponent var fullClassName:String = getQualifiedClassName(this).replace(/::/g, "."); //fullClassName is "test.TestComponent" var css:CSSStyleDeclaration = new CSSStyleDeclaration(); css.setStyle("skinClass", skin.DefaultTestComponentSkin); styleManager.setStyleDeclaration(fullClassName, css, true); These codes above will solve all the problems we discussed before, it's a little bit long, so here is the shortened one: super(); var css:CSSStyleDeclaration = new CSSStyleDeclaration(); css.setStyle("skinClass", skin.DefaultTestComponentSkin); styleManager.setStyleDeclaration(getQualifiedClassName(this).replace(/::/g, "."), css, true); So, I think we should do as you recommended in the last email, I will revert the changes I made to SkinnableComponent on the 'develop' branch of Flex SDK git, then we should update the Flex SkinnableComponent online help: http://help.adobe.com/en_US/flex/using/WS460ee381960520ad-2811830c121e9107ecb-7ff9.html#WS460ee381960520ad-2811830c121e9107ecb-7ff7 And tell developers they should use Type Selector to set default skinClass for their custom SkinnableComponent, and include the sample codes I provided above (the shortened one). DarkStone 2014-12-19 At 2014-12-18 05:02:52, "Alex Harui" <aha...@adobe.com> wrote: >Hi Darkstone, > >I would prefer 1A) which is to revert the change, prove that Type >Selectors work, and change the documentation for SkinnableComponent to >guide people to use Type Selectors. Then overriding styleName should not >be needed, and folks will build components following the same pattern as >the rest of the SDK. > >Thoughts? >-Alex > >On 12/17/14, 12:53 PM, "DarkStone" <darkst...@163.com> wrote: > >>Hi Alex, >> >>I got what you saying, I understand why you don't agree to the changes, >>you've got your point, I think you are right. >> >>But that won't prevent others from doing it in the wrong ways. >> >>There is a paragraph in SkinnableComponent online help about implementing >>the constructor: >> >>"Use the constructor to set the initial values of class properties. For >>example, you can set default values for properties and styles, or >>initialize data structures, such as Arrays. You can also set the >>skinClass style to the name of your skin class." >>http://help.adobe.com/en_US/flex/using/WS460ee381960520ad-2811830c121e9107 >>ecb-7ff9.html#WS460ee381960520ad-2811830c121e9107ecb-7ff7 >> >>It encourages developers to write setStyle("skinClass", MyDefaultSkin) to >>the constructor, if they want to set default skin for it. >> >>But doing so, set styleName on the MXML won't change the skin: >><ns:MyComponent styleName="otherSkin"/> >> >>This will cause confusion, because built in Spark components like Button, >>CheckBox, they all have their default skins, and if developers want to >>use a different skin, they do this: >><s:Button styleName="myButtonSkin"/> >> >>The confusion is: >> >><s:Button styleName="myButtonSkin"/> is working, the skin changes to >>MyButtonSkin. >> >><ns:MyComponent styleName="otherSkin"/> is not working, the skin remains >>default. >> >>They would be wondering why, and would assume this is a bug. >> >>So, the way I see it, there are two choices: >> >>1. Don't treat this as a bug, revert the changes I made, and update the >>help docs about SkinnableComponent, tell developers they have to override >>the styleName setter function by themselves, in order to make this case >>work. >> >>2. Treat this as a bug, apply the changes I made. >> >>Both are OK for me, I still prefer the 2nd one, but I fully respect other >>committers and PMC members' opinions. >> >> >>DarkStone >>2014-12-18 >> >> >>在 2014-12-18 03:28:49,"Alex Harui" <aha...@adobe.com> 写道: >>>Hi Darkstone, >>> >>>Think of the general case. Let’s say that you also call: >>> >>>myComponent.setStyle(“fontWeight", “bold"); >>> >>>myComponent.setStyle(“color", #ff0000); >>> >>> >>>When you later call: >>> >>>myComponent.styleName = “otherSkin” and you have >>> >>>.otherskin { >>> skinClass : MyOtherSkin; >>> fontWeight : “normal”; >>> color : #00FF00; >>>} >>> >>>Why should skinClass be given special treatment? There is an order to >>>the >>>CSS lookup. Styles set on an instance override other styles specified in >>>other selectors. I don’t think we should change that order, and I don’t >>>think we should try to figure out what instance styles to clear. It >>>isn’t >>>really clear to me that folks will always want those styles cleared. >>> >>>It sounds like what your friend really wants is to specify a Type >>>Selector >>>for MyComponent and specify the default skin there instead of calling >>>setStyle on each instance. Then styles set that have higher priority >>>like >>>styleName and instance styles will override with the intended result. >>> >>>CSS is expected to work a certain way. I don’t think we should change >>>it, >>>and I think your friend should be specifying a Type Selector. >>> >>>HTH, >>>-Alex >>> >>> >>>On 12/17/14, 10:06 AM, "DarkStone" <darkst...@163.com> wrote: >>> >>>>Hi Alex, >>>> >>>>Actually, this bug is reported to me by a Flex Developer, who is a >>>>friend >>>>of mine. >>>> >>>>The demand is, he wants to set a default skin class for his component >>>>(which extends SkinnableComponent), so inside the constructor of his >>>>component, he writes this: >>>>setStyle("skinClass", MyDefaultSkin); >>>>super(); >>>> >>>>Then, he wants other people to apply a different skin if they want to, >>>>other people would write this: >>>><ns:MyComponent styleName="otherSkin"/> >>>> >>>>I think his demand is very common, now the problem is, by doing so, the >>>>skin won't change. >>>> >>>>This bug only affects on custom SkinnableComponent, but it doesn't >>>>affect >>>>on any built in Flex Components like Spark Button, CheckBox, etc.. >>>> >>>>That's why I think it is a bug : ) >>>> >>>> >>>>DarkStone >>>>2014-12-18 >>>> >>>> >>>>At 2014-12-18 01:30:23, "Alex Harui" <aha...@adobe.com> wrote: >>>>>Hi Darkstone, >>>>> >>>>>By this description, this is not a bug. Any style set via setStyle >>>>>overrides styles in CSS selectors. The more common case is someone >>>>>does >>>>>want to always have myComponent use SkinA regardless of underlying >>>>>changes >>>>>to the selectors, like when style modules are loaded. If you want an >>>>>overridden style to revert to using the styles of the selectors, then >>>>>you >>>>>have to call clearStyle in your code. >>>>> >>>>>-Alex >>>>> >>>>> >>>>>On 12/17/14, 2:05 AM, "DarkStone" <darkst...@163.com> wrote: >>>>> >>>>>>Hi Alex, >>>>>> >>>>>>I've located the problem: >>>>>> >>>>>>Step 1. Using MySkinnableComponent.setStyle("skinClass", SkinA) to >>>>>>apply >>>>>>an initial skin is ok. >>>>>> >>>>>>Step 2. Then using MySkinnableComponent.styleName = "skinB" won't >>>>>>work, >>>>>>the skin won't change. >>>>>> >>>>>>When [Step 2] happens, inside the validateSkinChange() function of >>>>>>SkinnableComponent.as (line 440-443): >>>>>> >>>>>>newSkinClass = getStyle("skinClass"); >>>>>>skipReload = newSkinClass && getQualifiedClassName(newSkinClass) == >>>>>>getQualifiedClassName(_skin); >>>>>> >>>>>>The getStyle("skinClass") returns the old skin (SkinA), which should >>>>>>be >>>>>>the new skin (SkinB). >>>>>> >>>>>>As a result, the newSkinClass && getQualifiedClassName(newSkinClass) >>>>>>== >>>>>>getQualifiedClassName(_skin) returns true, which should be false. >>>>>> >>>>>>That's why the SkinnableComponent won't change the skin. >>>>>> >>>>>> >>>>>> >>>>>>I know how to fix this now. >>>>>> >>>>>>No need to override the styleName setter function in >>>>>>SkinnableComponent.as. >>>>>> >>>>>>Just add a line clearStyle("skinClass") to styleChanged() function in >>>>>>SkinnableComponent.as (add at line 552): >>>>>> >>>>>>override public function styleChanged(styleProp:String):void >>>>>>{ >>>>>> var allStyles:Boolean = styleProp == null || styleProp == >>>>>>"styleName"; >>>>>> >>>>>> if (allStyles || styleProp == "skinClass" || styleProp == >>>>>>"skinFactory") >>>>>> { >>>>>> clearStyle("skinClass"); //This will fix the bug >>>>>> skinChanged = true; >>>>>> invalidateProperties(); >>>>>> >>>>>> if (styleProp == "skinFactory") >>>>>> skinFactoryStyleChanged = true; >>>>>> } >>>>>> >>>>>> super.styleChanged(styleProp); >>>>>>} >>>>>> >>>>>>clearStyle("skinClass"); //This will fix the bug >>>>>>That's the only line needs to be added, in order to fix this bug. >>>>>> >>>>>> >>>>>>I've already updated the JIRA for this >>>>>>https://issues.apache.org/jira/browse/FLEX-34689 >>>>>> >>>>>> >>>>>>DarkStone >>>>>>2014-12-17 >>>>>> >>>>>> >>>>>>在 2014-12-17 14:12:52,"Alex Harui" <aha...@adobe.com> 写道: >>>>>>> >>>>>>> >>>>>>>On 12/16/14, 9:36 PM, "DarkStone" <darkst...@163.com> wrote: >>>>>>> >>>>>>>>Hi Alex, >>>>>>>> >>>>>>>>Why this needs to be fixed is simple: >>>>>>>> >>>>>>>>1. Using MySkinnableComponent.setStyle("skinClass", SkinA) to apply >>>>>>>>an >>>>>>>>initial skin is ok. >>>>>>>> >>>>>>>>2. Then using MySkinnableComponent.styleName = "skinB" won't work, >>>>>>>>the >>>>>>>>skin won't change. >>>>>>>> >>>>>>>>The styleChanged() function in SkinnableComponent doesn't handle >>>>>>>>this >>>>>>>>scenario correctly, that's why we need to override the styleName >>>>>>>>setter >>>>>>>>function to fix this. >>>>>>> >>>>>>>I’m wondering why the styleChanged() function can’t be changed to >>>>>>>handle >>>>>>>this scenario correctly. There are other ways to change skinClass, >>>>>>>like >>>>>>>setting it directly in a CSSStyleDeclaration or by loading a Style >>>>>>>module. >>>>>>> I would expect them all to call styleChanged() and the right thing >>>>>>>to >>>>>>>happen. >>>>>>> >>>>>>>Thanks, >>>>>>>-Alex >>>>>>> >>>>> >>> >