<?xml version="1.0" encoding="utf-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
      contributor license agreements.  See the NOTICE file distributed with
      this work for additional information regarding copyright ownership.
      The ASF licenses this file to You under the Apache License, Version 2.0
      (the "License"); you may not use this file except in compliance with
      the License.  You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
  -->

<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:explorer="*"
				pageTitle="{TITLE}" layout="vertical" width="100%" height="100%"
				paddingBottom="2" paddingTop="2" paddingLeft="2" paddingRight="2"
			    initialize="init()" creationComplete="checkParameters()">

     <fx:Script>
        <![CDATA[
		import mx.core.FlexGlobals;

		static protected const VERSION:String = "1.2";	
		static protected const TITLE:String = "Tour De Flex Component Explorer";
		static protected const FULL_TITLE:String = "Apache Flex® Tour De Flex Component Explorer " + VERSION;

		[Embed(source="explorer.xml", mimeType="application/octet-stream")]
		private var XMLData:Class;
			
		[Bindable]
		protected var noExamples:int = 0;
			
		private function init():void
		{
			var data:XML = XML(new XMLData());
			
            explorerTree = XML(data.node);
            compLibTree.dataProvider = explorerTree;
			
			noExamples = (explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)).length();
			
			var loader:URLLoader = new URLLoader();
			var request:URLRequest = new URLRequest("3rdparty.xml");
			loader.addEventListener(Event.COMPLETE, load3rdParty);
			loader.load(request);
		}
			
		protected function load3rdParty(event:Event):void
		{
		  var loader:URLLoader = URLLoader(event.target);
		  var newNode:XML = new XML(loader.data);
		  
		  if (newNode..node.length() > 0) {
			  explorerTree.appendChild(newNode.node);
              compLibTree.dataProvider = explorerTree;
			  noExamples += (newNode..node.(hasOwnProperty("@app") && @app.length() > 0)).length();
		  }
		}
					
		protected function checkParameters():void
		{		
			var parameters:Object = FlexGlobals.topLevelApplication.parameters;
			
			if (parameters.hasOwnProperty("app")) {
				var application:String = parameters.app;
				var source:String = explorerTree..node.(hasOwnProperty("@app") && @app == application).@src;
				loadApp(application, source, false);
				openNode(application);
			}
			else {
				loadApp("Welcome", null, false);
			}
		}

        private function treeChanged(event:Event):void
        {
            var nodeApp:String = compLibTree.selectedItem.@app;
			var link:String = compLibTree.selectedItem.@link;
			var thirdParty:Boolean = compLibTree.selectedItem.hasOwnProperty("@thirdParty")
				&& compLibTree.selectedItem.@thirdParty == "true";
			
            if (nodeApp != null && nodeApp != "")
            {
				loadApp(nodeApp, compLibTree.selectedItem.@src, thirdParty, link);
            }
            else
            {
                compLibTree.expandItem(compLibTree.selectedItem, true, true);
            }
        }
			
		private function loadApp(application:String, source:String, thirdParty:Boolean, link:String=""):void
		{
			if (application.indexOf(".swf") > 0) {
				swfLoader.loadApp(application);
			}
			else if(application.indexOf(".jpg") > 0 || application.indexOf(".png") > 0)
			{
				swfLoader.loadApp(application,link);
			}
			else {
				swfLoader.loadApp(application + ".swf");
			}
			if (thirdParty) {
				vs.thirdPartyWarning();
			}
			else {
            	vs.loadSource(application, source);
			}
		}
			
		private function gotoHome(event:Event):void
		{
			var urlRequest:URLRequest = new URLRequest("http://flex.apache.org/download-tourdeflex.html");
			navigateToURL(urlRequest);
		}
		
		private function openNode(application:String):void
		{
			var node:XML = explorerTree..node.(hasOwnProperty("@app") && @app == application)[0];
			var parent:XML;
			var nodes:Array = [];
			 
			if (!node) {
				return;
			}
			
			parent = node.parent();
			 
			while (parent != null) {
			    if (!compLibTree.isItemOpen(parent)) {
			        nodes.push(parent);
			    }
			    parent = parent.parent();
			}
			 
			for each (var expand:XML in nodes) {
			    compLibTree.expandItem(expand, true);
			}
			 
			compLibTree.selectedIndex = compLibTree.getItemIndex(node);
			compLibTree.scrollToIndex(explorerTree.selectedIndex);
		}
	
		]]>
    </fx:Script>

	<fx:Declarations>
    	<fx:XML id="explorerTree"/>
	</fx:Declarations>
	
	<mx:HBox width="100%">
		<mx:Image source="./mx/controls/assets/ApacheFlexIcon.png" useHandCursor="true" buttonMode="true" click="gotoHome(event)" />
		<mx:Label text="{FULL_TITLE}" fontSize="20" fontWeight="bold" />
		<mx:Spacer width="100%" />
		<mx:Label text="{noExamples} examples" />
	</mx:HBox>
    <mx:HDividedBox width="100%" height="100%">
        <mx:Panel width="30%" height="100%" title="{TITLE}" dropShadowVisible="false">
            <mx:Tree id="compLibTree" width="100%" height="100%" showRoot="false" labelField="@label" borderStyle="none"
                     change="treeChanged(event)"/>
        </mx:Panel>
        <mx:VDividedBox width="100%" height="100%">
            <explorer:loaderPanel id="swfLoader" width="100%" height="50%"/>
            <mx:VBox width="100%" height="50%" backgroundColor="#FFFFFF">
                <explorer:viewsource id="vs" width="100%" height="100%"/>
            </mx:VBox>
        </mx:VDividedBox>
    </mx:HDividedBox>
	<mx:HBox width="100%">
		<mx:Label fontSize="9" width="100%" text="Copyright © 2014 The Apache Software Foundation, Licensed under the Apache License, Version 2.0. Apache Flex is trademark of The Apache Software Foundation." />
	</mx:HBox>
</mx:Application>