上次發表了 Flex 4 Style Module 之後
有朋友問 Flex 3 能不能用,答案當然是不行
所以我又花了一些時間作出 Flex 3 版的 Style Module
本來以為 Flex 3 CSS 不支援 class selector, descendant selector… 會比較好改
結果不是那麼一回事

Flex 3 產生的 Style Module 一初始化馬上就執行 Style 設定,沒有放在特定介面的 function 內
這樣就算我撈到所有的 Module Style 還要自己想辦法找時機執行
另一個大問題是 Module 內還用了一個靜態旗標,表示 Style 是否初始化完畢
結果造成重覆載入兩次 Module 後,旗標為 true 無法撈到 Style,卸載時也無法還原 Style
還得要自行想辦法把旗標重設為 false~

以下是 Flex 3 版的 StyleManagerProxy:

package com.ticore.style.module {
 import flash.events.TimerEvent;
 import flash.utils.Timer;
 import flash.utils.setTimeout;
 
 import mx.styles.CSSStyleDeclaration;
 import mx.styles.StyleManagerImpl;
 
 public class StyleManagerProxy extends StyleManagerImpl {
 
  protected var styleModule:Object;
  protected var timer:Timer = new Timer(0, 1);
  protected var quene:Array = [];
 
  override public function StyleManagerProxy(styleModule:Object) {
   this.styleModule = styleModule;
   timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerCompleteHandler);
  }
 
  // always return null, force style module call StyleManager.setStyleDeclaration();
  override public function getStyleDeclaration(selector:String):CSSStyleDeclaration {
   return null;
  }
 
  override public function setStyleDeclaration(selector:String,
     styleDeclaration:CSSStyleDeclaration, update:Boolean):void {
 
   // delay execute until style factory setup
   quene.push([selector, styleDeclaration, update]);
   if (!timer.running) timer.start();
  }
 
  protected function onTimerCompleteHandler(e:TimerEvent):void{
   var args:Array;
   while (args = quene.shift()) {
    styleModule.setStyleDeclaration.apply(null, args);
   }
  }
 }
}

Flex 3 版的 StyleManagerProxy:

package com.ticore.style.module {
 import flash.system.Security;
 import flash.utils.getDefinitionByName;
 import flash.utils.getQualifiedClassName;
 
 import mx.core.mx_internal;
 import mx.modules.ModuleBase;
 import mx.styles.CSSStyleDeclaration;
 import mx.styles.IStyleManager2;
 import mx.styles.IStyleModule;
 
 public class StyleModule extends ModuleBase implements IStyleModule {
 
  private static var domainsAllowed:Boolean = allowDomains();
 
  private static function allowDomains():Boolean {
   if (Security.sandboxType != "application") {
    Security.allowDomain("*");
   }
   return true;
  }
 
  //============================================================
 
  public function StyleModule() {
   // reset static flag _MyStyleMod_StylesInit_done
   var fullName:String = getQualifiedClassName(this);
   var className:String = fullName.split("::")[1];
   var Cls:Class = getDefinitionByName(fullName) as Class;
   var varName:String = "_" + className + "_StylesInit_done";
 
   var qName:QName = new QName(mx_internal, varName);
   Cls[qName] = false;
  }
 
  protected var selectors:Array = [];
  protected var overrideMap:Object = {};
  protected var effectMap:Object = {};
  protected var unloadGlobal:Boolean;
 
  protected var styleManager:IStyleManager2;
 
  //============================================================
 
  public static var StyleManagerCls:Class = mx.styles.StyleManager;
 
  // StyleManager class reference hook
  protected var StyleManager:Object = new StyleManagerProxy(this);
 
  public function getStyleDeclaration(selector:String):CSSStyleDeclaration {
   return StyleManagerCls.getStyleDeclaration(selector);
  }
 
  public function setStyleDeclaration(selector:String, style:CSSStyleDeclaration, update:Boolean):void {
 
   var newStyle:CSSStyleDeclaration = StyleManagerCls.getStyleDeclaration(selector);
 
   if (!newStyle) {
    newStyle = new CSSStyleDeclaration();
   }
 
   // register override map and keys
   var factory:Function = style.factory;
 
   if (!(factory)) return;
 
   var dumpObj:Object = {};
   factory.apply(dumpObj);
 
   var keys:Array = overrideMap[selector];
   keys ||= [];
   overrideMap[selector] ||= keys;
 
   for (var key:* in dumpObj) {
    newStyle.mx_internal::setStyle(key, dumpObj[key]);
    keys.push(key);
   }
 
   // register effects map
   var addedEffects:Array;
 
   style.mx_internal::effects = style.mx_internal::effects || [];
   newStyle.mx_internal::effects = newStyle.mx_internal::effects || style.mx_internal::effects;
 
   addedEffects = style.mx_internal::effects.concat();
   effectMap[selector] = addedEffects;
 
   // update style
   StyleManagerCls.setStyleDeclaration(selector, newStyle, true);
  }
 
  //============================================================
  // original external style module functions
 
  public function unload():void {
   // (trace)("StyleModule.unload();");
   unloadOverrides();
   unloadStyleDeclarations();
   if (unloadGlobal) {
    styleManager.stylesRoot = null;
    styleManager.initProtoChainRoots();
   }
  }
 
  private function unloadOverrides():void {
   // (trace)("StyleModule.unloadOverrides();");
   for (var selector:String in overrideMap) {
    // (trace)("selector:", selector);
    var style:CSSStyleDeclaration = StyleManagerCls.getStyleDeclaration(selector);
    if (style != null) {
     var keys:Array = overrideMap[selector];
     var numKeys:int;
     var i:uint;
     if (keys != null) {
      numKeys = keys.length;
      for (i = 0; i < numKeys; i++) {
       // (trace)("clearOverride:", keys[i], style.getStyle(keys[i]));
       style.mx_internal::clearOverride(keys[i]);
      }
     }
     keys = effectMap[selector];
     if (keys != null) {
      numKeys = keys.length;
      var index:uint;
      var effects:Array = style.mx_internal::effects;
      for (i = 0; i < numKeys; i++) {
       // ReferenceError: Error #1069: Number 上找不到屬性 0,而且沒有預設值。
       // index = effects.indexOf(numKeys[i]);
       index = effects.indexOf(keys[i]);
       if (index >= 0) {
        effects.splice(index, 1);
       }
      }
     }
    }
   }
   overrideMap = null;
   effectMap = null;
  }
 
  private function unloadStyleDeclarations():void {
   // (trace)("StyleModule.unloadStyleDeclarations();");
   var numSelectors:int = selectors.length;
   for (var i:int = 0; i < numSelectors; i++) {
    var selector:String = selectors[i];
    styleManager.clearStyleDeclaration(selector, false);
   }
   selectors = null;
  }
 
  //============================================================
 }
}

GitHub 上我也作了分支 Flex 3.x StyleModule