4 Replies Latest reply on Dec 21, 2011 11:21 AM by drkstr_1

    Extend ResourceManager Class

    jgrasmeder

      Hello,

       

      Does anyone have an example of extending the ResourceManager.toString() method?

       

      Currently getString has four parameters. I would like to add an optional fifth parameter 'fallBackValue'. This would allow me to check the localChain for the existence of the bundleName and resourceName and when one can not be found the 'fallBackValue' will be returned which I think is much better than the current 'null' value returned. I currently have a function that does this but I can't seem to get the 'CHANGE' event from the ResourceManager  to update my mxml code. I am thinking a better aproach would be to extend the actual ResourceManger and preserve the databind logic already inplace rather than using my function which loads the value only once.

       

      <mx:DataGrid>

              <mx:columns>

              <mx:DataGridColumn headerText="{getMyStringResourceFromBundle('resource','COLUMN_HEADER_NAME','Name')}" />

              <mx:DataGridColumn headerText="{getMyStringResourceFromBundle('resource','COLUMN_HEADER_ADDRESS','Address')} "/>

              <mx:DataGridColumn headerText="{getMyStringResourceFromBundle('resource','COLUMN_HEADER_FOO','Foo')}" />

              <mx:DataGridColumn headerText="{getMyStringResourceFromBundle('resource','COLUMN_HEADER_RING','Ring')}" />

              <mx:DataGridColumn headerText="{getMyStringResourceFromBundle('resource','COLUMN_HEADER_ACCESS2','Access 2')}" />

              <mx:DataGridColumn headerText="{getMyStringResourceFromBundle('resource','COLUMN_HEADER_ACCESS3','Access 3')}"/>

              <mx:DataGridColumn headerText="{getMyStringResourceFromBundle('resource','COLUMN_HEADER_WHY','Why?')}" />

              <mx:DataGridColumn headerText="{getMyStringResourceFromBundle('resource','COLUMN_HEADER_SUBADDR','Sub Addr')}" />

              <mx:DataGridColumn headerText="{getMyStringResourceFromBundle('resource','COLUMN_HEADER_TEXT','Text')}" />

              </mx:columns>

          </mx:DataGrid>

        • 1. Re: Extend ResourceManager Class
          drkstr_1 Level 4

          Don't extend, encapsulate. Just listen for a 'change' event on the internal resource manager and bubble it out externally.

          1 person found this helpful
          • 2. Re: Extend ResourceManager Class
            jgrasmeder Level 1

            Encapsulate, thats how I started off but didn't get far. I did get the change event in the applyLocaleChange function but the getStringResourceFromBundle function did not update the mxml ojects the same way that the ResourceManager would. Thats why I started down the path of extending .

             

            Hear is the code I was using.

            public class ModelLocator extends EventDispatcher

                {

                    protected static var inst:ModelLocator;

             

                    public static const MY_BUNDLE:String = "resources";

             

                    public function ModelLocator(obj:SingletonEnforcer)

                    {

                        if (inst != null || !(obj is SingletonEnforcer))

                        {

                            throw new Error("Singleton Exception: ModelLocator already exists");

                        }

                        else

                        {

                            ResourceManager.getInstance().addEventListener(Event.CHANGE, applyLocaleChange);

                        }

                    }

             

                    public static function getInstance():ModelLocator

                    {

                        if (inst == null)

                        {

                            inst = new ModelLocator(new SingletonEnforcer);

                        }

             

                        return inst;

                    }

             

                   

                    private function applyLocaleChange(e:Event):void

                    {

                        // this will fire when the locale changes

                        trace("locale has changed")

                        if (e != null && e.currentTarget != null)

                        {

                            this.dispatchEvent(e.clone());

                        }

                    }

                   

                    [Bindable(event = "change")]

                    public static function getStringResourceFromBundle(resourceBundle:String = null, resourceKey:String

                                                                                            , fallbackValue:String = null, parameters:Array = null):String

                    {

                        var rtnStr:String;

                        var myResourceKey:String;

             

                        if (resourceKey == null)

                            resourceKey = "";

                        myResourceKey = com.adobe.utils.StringUtil.trim(resourceKey);

                        if (resourceBundle == null)

                            resourceBundle = ModelLocator.MY_BUNDLE;

                        rtnStr = ResourceManager.getInstance().getString(resourceBundle, myResourceKey, parameters);

                        if (rtnStr == null)

                            trace("NOTICE: Language String Key '" + resourceKey + "' needs to be added to resourceBundle '"

                                      + resourceBundle + "' fallbackValue=" + fallbackValue);

                        if (rtnStr == null && fallbackValue != null)

                            if (parameters == null)

                            {

                                rtnStr = fallbackValue;

                            }

                            else

                            {

                                rtnStr = mx.utils.StringUtil.substitute(fallbackValue, parameters);

                            }

             

                        return rtnStr;

                    }

                }

             

            Any help would be great.

             

             

            Thanks

            • 3. Re: Extend ResourceManager Class
              jgrasmeder Level 1

              drkstr_1, are you still around?

              • 4. Re: Extend ResourceManager Class
                drkstr_1 Level 4

                Simply wrapping the function call should work just fine for the initial binding (IE. a compiled resource).

                 

                Are you trying to bind to values for a locale module loaded at runtime? If that's the case, I would probably go about it a bit differently.

                 

                 

                package managers
                {
                          import flash.events.EventDispatcher;
                          import flash.events.IEventDispatcher;
                          import flash.system.ApplicationDomain;
                          import flash.system.SecurityDomain;
                          import mx.events.ResourceEvent;
                          import mx.resources.IResourceManager;
                          import mx.resources.ResourceManager;
                          import models.MyBundle;
                
                          public class MyResourceManager
                          {
                                    /**
                                     * Signleton instance.
                                     */
                                    private static var _instance:MyResourceManager;
                
                                    public static function getInstance():MyResourceManager
                                    {
                                              if(MyResourceManager._instance == null)
                                              {
                                                        MyResourceManager._instance = new MyResourceManager();
                                              }
                
                                              return MyResourceManager._instance;
                                    }
                
                
                
                                    //--------------------------------------
                                    // Public Properties 
                                    //--------------------------------------
                
                                    private var _locale:String = "en_US";
                
                                    /**
                                     *
                                     */
                                    public function get locale():String
                                    {
                                              return _locale;
                                    }
                
                                    public function set locale(value:String):void
                                    {
                                              if(_locale == value)
                                                        return;
                
                                              _locale = value;
                
                                              //handle locale change...
                                    }
                
                
                                    //--------------------------------------
                                    //   Private Properties 
                                    //--------------------------------------
                
                                    /**
                                     * Let's use some kind of map to register and encapsulate the available bundles
                                     */
                                    private var _bundles:Object = {MyBundle: new MyBundle()};
                
                                    private var _resourceManager:IResourceManager = ResourceManager.getInstance();
                
                
                
                                    //--------------------------------------
                                    //   Public Methods 
                                    //--------------------------------------
                
                                    public function getBundle(name:String):Object
                                    {
                                              if(!_bundles.hasOwnProperty(name))
                                                        return null;
                
                                              return _bundles[name];
                                    }
                
                                    /**
                                     * This would probably work better if it were internalized with some business logic to handle changes on the locale property...
                                     */
                                    public function loadResourceModule(url:String, updateFlag:Boolean = true, applicationDomain:ApplicationDomain = null, securityDomain:SecurityDomain = null):IEventDispatcher
                                    {
                                              var eventDispatcher:IEventDispatcher = _resourceManager.loadResourceModule(url, updateFlag, applicationDomain, securityDomain);
                                              eventDispatcher.addEventListener(ResourceEvent.COMPLETE, loadResourceModule_completeHandler, false, 0, true);
                
                                              return eventDispatcher;
                                    }
                
                
                                    //--------------------------------------
                                    //   Event Handlers 
                                    //--------------------------------------
                
                                    private function loadResourceModule_completeHandler(event:ResourceEvent):void
                                    {
                                              trace("loadResourceModule_completeHandler(event)");
                
                                              _resourceManager.localeChain = [this.locale];
                                    }
                          }
                }
                
                

                 

                 

                 

                package models
                {
                          import flash.events.Event;
                          import flash.events.EventDispatcher;
                          import flash.events.IEventDispatcher;
                          import mx.resources.IResourceManager;
                          import mx.resources.ResourceManager;
                
                          [Bindable("change")]
                          public class MyBundle extends EventDispatcher
                          {
                                    public function MyBundle(target:IEventDispatcher = null)
                                    {
                                              _resourceManager = ResourceManager.getInstance();
                                              _resourceManager.addEventListener(Event.CHANGE, this.dispatchEvent, false, 0, true)
                                    }
                
                
                                    public static var NAME:String = "MyBundle";
                
                
                                    //--------------------------------------
                                    // Public Properties 
                                    //--------------------------------------
                
                                    public function get city():String
                                    {
                                              return _resourceManager.getString(NAME, 'city');
                                    }
                
                                    public function get state():String
                                    {
                                              return _resourceManager.getString(NAME, 'state');
                                    }
                
                                    //--------------------------------------
                                    //   Private Properties 
                                    //--------------------------------------
                
                                    private var _resourceManager:IResourceManager;
                          }
                }
                
                

                 

                 

                <?xml version="1.0" encoding="utf-8"?>
                <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
                                                                     xmlns:views="views.*" width="1024" height="768" creationComplete="creationCompleteHandler(event)">
                
                
                          <fx:Script>
                                    <![CDATA[
                                              import mx.events.FlexEvent;
                                              import managers.MyResourceManager;
                                              import models.MyBundle;
                
                                              [Bindable]
                                              private var _resources:MyBundle;
                
                                              private var _rm:MyResourceManager = MyResourceManager.getInstance();
                
                                              protected function creationCompleteHandler(event:FlexEvent):void
                                              {
                                                        trace("creationCompleteHandler(event)");
                
                                                        _resources = MyBundle(_rm.getBundle(MyBundle.NAME));
                                                        _rm.loadResourceModule("MyBundle_en_US.swf");
                                              }
                                    ]]>
                          </fx:Script>
                
                
                          <s:VGroup horizontalCenter="0" verticalCenter="0">
                                    <s:Label text="{_resources.city}" />
                                    <s:Label text="{_resources.state}" />
                          </s:VGroup>
                
                
                </s:WindowedApplication>
                
                

                 

                You can put in your own business logic in the model to define default value returns. You may want to also extend from some kind of AbstractBundle and use code snippets to quickly type out various bundles.

                 

                There are other ways to go about this as well, but binding works best with strong typing (and IMHO, is best practice even without binding).