Creating Extensible Flash Tool Panels Using JSFL

To construct a custom panel interface using the Flash List component, first drag the List component from the Components panel to the library, then remove it from the stage. Assign the main document class.
package {
    import flash.display.Sprite;
    import flash.events.Event;
    import fl.controls.List;
    import fl.data.DataProvider;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.text.TextFormat;
    import adobe.utils.MMExecute;
    import fl.managers.StyleManager;
    import fl.events.ListEvent;

    public class PanelController extends Sprite {
        private var configLoader:URLLoader;
        private var configData:XML;
        private var listSource:DataProvider;
        private var coreScript:String;

        public function PanelController() {
            configLoader = new URLLoader();
            configLoader.dataFormat = URLLoaderDataFormat.TEXT;
            configLoader.addEventListener(Event.COMPLETE, handleConfigLoaded);
            configLoader.load(new URLRequest("tool_assets/panel_setup.xml"));
        }

        private function handleConfigLoaded(evt:Event):void {
            configData = XML(configLoader.data);
            coreScript = configData.baseScript;
            var versionLabel:ContextMenuHelper = new ContextMenuHelper(this, configData.buildVersion);
            var rootData:* = XML(configData.entries);
            listSource = new DataProvider(rootData);
            initializeList(listSource);
        }

        private function initializeList(source:DataProvider):void {
            var uiList:List = new List();
            addChild(uiList);
            var textFormat:TextFormat = new TextFormat("Arial", 12, 0x333333);
            StyleManager.setStyle("textFormat", textFormat);
            uiList.setStyle("cellRenderer", AlternatingRowRenderer);
            uiList.dataProvider = source;
            uiList.addEventListener(ListEvent.ITEM_CLICK, handleItemClick);
            uiList.width = 320;
            uiList.height = 420;
            uiList.rowHeight = 28;
        }

        private function handleItemClick(evt:ListEvent):void {
            var method:String = evt.item.method;
            var mode:int = evt.item.execMode;
            var scriptPath:String;

            if (mode == 0) {
                runMethod(method, "WindowSWF/tool_scripts/" + coreScript + ".jsfl");  
            } else if (mode == 1) {
                scriptPath = "WindowSWF/tool_scripts/" + evt.item.scriptFile + ".jsfl";
                runMethod(method, scriptPath);
            } else if (mode == 2) {
                scriptPath = "WindowSWF/tool_scripts/" + evt.item.scriptFile + ".jsfl";
                var rawArgs:Array = String(evt.item.args).split(",");
                var formattedArgs:String = formatArguments(rawArgs);
                runMethodWithArgs(method, scriptPath, formattedArgs);
            } else if (mode == 3) {
                scriptPath = "WindowSWF/tool_scripts/" + evt.item.scriptFile + ".jsfl";
                runScriptFile(scriptPath);
            }
        }

        private function formatArguments(args:Array):String {
            if (args.length == 1) return args[0];
            var result:String = "";
            for (var i:int = 0; i < args.length; i++) {
                if (i == 0) {
                    result += args[i] + "',";
                } else if (i == args.length - 1) {
                    result += "'" + args[i];
                } else {
                    result += "'" + args[i] + "',";
                }
            }
            return result;
        }

        private function runMethodWithArgs(method:String, path:String = "", args:String = ""):void {
            MMExecute("fl.runScript(fl.configURI + '" + path + "','" + method + "','" + args + "');");
        }

        private function runMethod(method:String, path:String = ""):void {
            MMExecute("fl.runScript(fl.configURI + '" + path + "','" + method + "');");
        }

        private function runScriptFile(path:String):void {
            MMExecute("fl.runScript(fl.configURI + '" + path + "');");
        }
    }
}

package {
    import fl.controls.listClasses.CellRenderer;
    import fl.controls.listClasses.ICellRenderer;
    import fl.controls.listClasses.ListData;
    import flash.display.Shape;

    public class AlternatingRowRenderer extends CellRenderer implements ICellRenderer {
        private var background:Shape = new Shape();

        public function AlternatingRowRenderer() {
            addChildAt(background, 0);
        }

        override public function set listData(value:ListData):void {
            super.listData = value;
            background.graphics.beginFill(0xdddddd, value.index % 2);
            background.graphics.drawRect(1, 1, width - 2, height - 2);
            background.graphics.endFill();
        }
    }
}

package {
    import flash.display.InteractiveObject;
    import flash.ui.ContextMenu;
    import flash.ui.ContextMenuItem;

    public class ContextMenuHelper {
        public function ContextMenuHelper(target:InteractiveObject, versionInfo:String) {
            var customMenu:ContextMenu = new ContextMenu();
            customMenu.hideBuiltInItems();
            try {
                var versionItem:ContextMenuItem = new ContextMenuItem(versionInfo);
                customMenu.customItems.push(versionItem);
            } catch (err:Error) {
                throw new Error(err.message);
            }
            target.contextMenu = customMenu;
        }
    }
}

Define the XML configuration file (panel_setup.xml):
<configuration>
    <baseScript>generalUtils</baseScript>
    <buildVersion>Build: CustomPanel_2.0</buildVersion>
    <entries>
        <item>
            <label>Batch Publish Directory (AS2, Player 7)</label>
            <args>2,7</args>
            <method>Init</method>
            <execMode>2</execMode>
            <scriptFile>publish_handler</scriptFile>
        </item>
        <item>
            <label>Batch Publish Directory (AS3, Player 9)</label>
            <args>3,9</args>
            <method>Init</method>
            <execMode>2</execMode>
            <scriptFile>publish_handler</scriptFile>
        </item>
        <item>
            <label>Batch Publish Directory (AS3, Player 10.3)</label>
            <args>3,10.3</args>
            <method>Init</method>
            <execMode>2</execMode>
            <scriptFile>publish_handler</scriptFile>
        </item>
        <item>
            <label>Batch Publish Directory (AS3, Player 11.1)</label>
            <args>3,11.1</args>
            <method>Init</method>
            <execMode>2</execMode>
            <scriptFile>publish_handler</scriptFile>
        </item>
        <item>
            <label>Batch Publish Directory (AS3, Player 11.2)</label>
            <args>3,11.2</args>
            <method>Init</method>
            <execMode>2</execMode>
            <scriptFile>publish_handler</scriptFile>
        </item>
        <item>
            <label>Batch Publish Directory (Custom Settings)</label>
            <args></args>
            <method>definedInit</method>
            <execMode>2</execMode>
            <scriptFile>publish_handler</scriptFile>
        </item>
    </entries>
</configuration>

Deploy the compiled SWF along with the corresponding JSFL scripts and XML configuration into the appropriate Flash configuration directory (specifically, the WindowSWF folder within the Flash installation path): C:\Users\[Username]\AppData\Local\Adobe\Flash CS6\en_US\Configuration\WindowSWF\

Tags: JSFL Flash ActionScript3 Panel XML

Posted on Fri, 08 May 2026 10:02:47 +0000 by diesel_heart