﻿/**************************************************************************
*
*  @@@BUILDINFO@@@ 24scripts-2.jsx 3.5.0.7		08-December-2008
*  ADOBE SYSTEMS INCORPORATED
*  Copyright 2010 Adobe Systems Incorporated
*  All Rights Reserved.
* 
* NOTICE:  Adobe permits you to use,  modify, and  distribute this file in
* accordance with the terms of the Adobe license agreement accompanying it.
* If you have received this file from a source other than Adobe, then your
* use, modification, or distribution of it requires the prior written
* permission of Adobe.
*
**************************************************************************/

// Code to add to the Scripts pane
// The output field of the scripts pane is a list box. The array scriptIDs
// takes a list of all script IDs. This list is used during Document.onSave()
// to determine if a document belongs to a target app and whether that app
// should receive a PutScript message.

// Get the script IDs and populate the Scripts pane. Each line contains
// two words. The first, is the display name, while the second word is the
// script ID. The script ID must be a path name if it starts with '/' or '~'. If
// it starts with anything else but a '(' (which is reserved for new scripts),
// it is app specific, and the app will have to supply the script on request.
// Application-supplied script IDs should be system unique.

// The "info" property is an object with script IDs as property names. Each
// object has the properties displayName, scriptID, status and readOnly. If a script
// is not executable, the status is "noexec". The object is also attached to
// the list item.

scripts =   {
                pane            : null,         // the pane
                name            : 'scripts',  // unique name
                title           : '$$$/ESToolkit/Panes/Scripts/Title=Scripts',
                menu            : '$$$/ESToolkit/Menu/Window/Scripts/Title=&Scripts',
                iconDefault     : '#PScripts_N',
                iconRollover    : '#PScripts_R'
            };          
          
globalBroadcaster.registerClient( scripts, 'initPanes' );

scripts.onNotify = function( reason )
{
    if( reason == 'initPanes' )
    {
        this.init();
    }
    else if( this.pane && this.initialized )
    {
        switch( reason )
        {
		    case 'shutdown':
		    {
				prefs.scripts.favorite = this.currentFavorite;
			    this.pane.output.removeAll();
			    this.pane.targetDDL.removeAll();
			    this.pane.engineDDL.removeAll();
			    globalBroadcaster.unregisterClient( this );
		    }
		    break;
			
            case 'changeTargets':
            case 'addTarget':
                this.fillTargets();
                break;
				
		    case 'targetDied':
		    {
			    if( this.pane.targetDDL.selection &&  arguments[1] == this.pane.targetDDL.selection.target )
				    this.pane.targetDDL.selection = 0;
		    }
		    break;
		    
		    case 'changeConnectionState':
		    {
			    if( this.pane.targetDDL.selection                           &&  
			        arguments[1] == this.pane.targetDDL.selection.target    &&
			        !arguments[1].getConnected()                                )
				    this.pane.targetDDL.selection = 0;
		    }
		    break;
			
		    case 'state':
		    {
		        // TODO: set icons for engines depending on debugger state
		    }
		    break;
		    
		    case 'endConnect':
		    {
		        if( this.pendingTargetRequest && this.pendingTargetRequest == arguments[1] )
		        {			        
		            var target = this.pendingTargetRequest;
		            this.pendingTargetRequest = null;
		            
		            if( target.getConnected() )
		            {
		                // target is connected, fill engines list
		                this.fillEngines();
		                this.pane.engineDDL.selection = 0;
		                this.prevTarget = this.pane.targetDDL.selection;
		                this.setEnabled( true );
		            }
		            else
		            {
		                // target not connected, switch back
		                this.setEnabled( true );
		                this.pane.targetDDL.selection = this.prevTarget;
		            }
		        }
		    }
		    break;
		    
		    case 'initialized':
		    {
		        if( this.pendingSessionRequest && this.pendingSessionRequest == arguments[2] )
		        {
		            var session = this.pendingSessionRequest;
		            this.pendingSessionRequest = null;
		            
		            this.doFillScripts( session );
		        }
		    }
		    break;
		    
		    case 'newFavorites':
		    {
		        this.favorites = favorites;

		        if( this.pane.targetDDL.items.length > 0 )
		            this.pane.targetDDL.items[0].favorites = favorites;
		    
		        if( this.pane.targetDDL.selection && this.pane.targetDDL.selection == this.pane.targetDDL.items[0] )
		        {
		            var oldSel = this.pane.engineDDL.selection;
		            
		            this.pane.engineDDL.removeAll();
		            
		            for( var i=0; i<favorites.length; i++ )
		            {
	                    item = this.pane.engineDDL.add( 'item', favorites.items[i].name );
	                    item.favorite = favorites.items[i];
		            }
		            
		            if( oldSel )
		                this.pane.engineDDL.selection = oldSel;
		            else
		                this.pane.engineDDL.selection = 0;
    		
	                this.pane.targetGroup.fillScripts();
		        }
		    }
		    break;
        }
    }
}

scripts.init = function()
{
    //
    // create and register pane
    //
    var res = panes.createPaneObj( this,
	                                """targetGroup : Group
                                       {
                                           alignment : ['fill','top'],
                                           orientation: 'row',
                                           margins:0,

                                           targets: DropDownList
                                           {
                                               preferredSize: [40, 20],
                                               alignment    : ['fill','fill'],
                                               helpTip      : '$$$/ESToolkit/Panes/Scripts/htTargets=Select a target application.'
                                           },
                                           engines: DropDownList
                                           {
                                               preferredSize: [40, 20],
                                               alignment    : ['fill','fill']
                                               helpTip      : '$$$/ESToolkit/Panes/Scripts/htEngine=Select an engine of the selected target application.'
                                           }
                                       },
                                       output: TreeView
                                       {
                                           preferredSize: [10, 20],
                                           alignment: ['fill', 'fill']
                                       }
                                       infogrp : Group
                                       {
                                           orientation : 'row',
                                           margins      : 0,
                                           spacing      : 0,
                                           alignment	: ['fill','bottom'],
                                           pathField: EditText
                                           {
                                               properties	: { readonly: true },
                                               alignment	: ['fill','bottom'],
                                               characters : 40
                                           },
                                           sizeBoxSpacer    : Group
                                           {
                                               alignment	: ['right','bottom'],
                                               preferredSize        : [14,1]
                                           }
                                       }""" );

    ///////////////////////////////////////////////////////////////////////////////
    //
    // shortcuts
    //
    this.pane.targetDDL   = this.pane.targetGroup.targets;
    this.pane.engineDDL   = this.pane.targetGroup.engines;
    this.pane.pathField   = this.pane.infogrp.pathField;

	this.currentFavorite = prefs.scripts.favorite.getValue( Preference.STRING );

    //
    // first fill favorites
    //
    if( !this.favorites )
        this.favorites = favorites;
        
    this.prevTarget              = null;
    this.pendingTargetRequest    = null;
    this.pendingSessionRequest   = null;
    this.blockTargetGroup        = 0;		
	this.info                    = {};
	this.initialized             = true;

    ///////////////////////////////////////////////////////////////////////////////
    //
    // register for additional broadcast messages
    //	
	globalBroadcaster.registerClient( this, 'shutdown,newFavorites' );
    targetMgr.registerClient( this, 'changeTargets,addTarget,targetDied,endConnect,changeConnectionState' );
    DebugSession.registerClient( this, 'initialized,state' );

    ///////////////////////////////////////////////////////////////////////////////
    //
    // flyout menu
    //
    this.pane.menu = new MenuElement( "popupmenu", "Flyout", undefined, "scripts/flyout" );  
    
    var item = new MenuElement( 'command', '$$$/ESToolkit/Panes/Scripts/Flyout/Refresh=Refresh', "at the end of scripts/flyout", "scripts/flyout/refresh" );

    item.onSelect = function()
    {
        scripts.pane.targetGroup.fillScripts();
    }

    item = new MenuElement( 'command', '$$$/ESToolkit/Panes/Scripts/Flyout/AddFav=Add Favorite...', "---at the end of scripts/flyout", "scripts/flyout/addfav" );
    item.onSelect = function()
    {
        var newItem = scripts.favorites.dialog();

        if( newItem )
        {
            newItem = scripts.favorites.add( newItem.name, newItem.path, false, newItem.filter, newItem.recursive, newItem.filterDot );

            if( scripts.favorites )
            {
                //
                // if the "Favorites" target is selected then
                // force updating the engines popup
                //
                var sel = scripts.pane.targetDDL.selection;
                scripts.pane.targetDDL.selection = null;
                scripts.pane.targetDDL.selection = sel;

                //
                // after that select the new added favorite
                //
				scripts.pane.engineDDL.selection = null;
				
				for( var i=0; i<scripts.pane.engineDDL.items.length; i++ )
				{
					if( newItem.equal( scripts.pane.engineDDL.items[i].favorite ) )
					{
						scripts.pane.engineDDL.selection = scripts.pane.engineDDL.items[i];
						break;
					}
				}
				
                scripts.setEnabled( true );
            }
        }
    }

    item = new MenuElement( 'command', '$$$/ESToolkit/Panes/Scripts/Flyout/ModFav=Modify Favorite', "at the end of scripts/flyout", "scripts/flyout/modfav" );
    item.onDisplay = function()
    {
        this.enabled = false;

        if( scripts.pane.engineDDL.selection                   && 
            scripts.pane.engineDDL.selection.favorite          && 
            !scripts.pane.engineDDL.selection.favorite.isDefault )
            this.enabled = true;
    }
    item.onSelect = function()
    {
        if( scripts.favorites                          && 
            scripts.pane.engineDDL.selection.favorite  && 
            !scripts.pane.engineDDL.selection.isDefault    )
        {
            var fav = scripts.favorites.dialog( scripts.pane.engineDDL.selection.favorite );
            
            if( fav )
            {
                scripts.favorites.replace( scripts.pane.engineDDL.selection.favorite, fav );
                scripts.pane.engineDDL.selection.text = fav.name;
                scripts.pane.targetGroup.fillScripts();
            }
        }
    }    

    item = new MenuElement( 'command', '$$$/ESToolkit/Panes/Scripts/Flyout/RemFav=Remove Favorite', "at the end of scripts/flyout", "scripts/flyout/remfav" );
    item.onDisplay = function()
    {
        this.enabled = false;

        if( scripts.pane.engineDDL.selection                   && 
            scripts.pane.engineDDL.selection.favorite          && 
            !scripts.pane.engineDDL.selection.favorite.isDefault   )
            this.enabled = true;
    }
    item.onSelect = function()
    {
        if( scripts.favorites                          && 
            scripts.pane.engineDDL.selection.favorite  && 
            !scripts.pane.engineDDL.selection.isDefault    )
        {
            scripts.favorites.remove( scripts.pane.engineDDL.selection.favorite );
            
            if( scripts.pane.targetDDL.selection.favorites )
            {
                //
                // if the "Favorites" target is selected then 
                // force updating the engines popup
                //
                var sel = scripts.pane.targetDDL.selection;
                scripts.pane.targetDDL.selection = null;
                scripts.pane.targetDDL.selection = sel;
                
                //
                // after that select the new added favorite
                //
                scripts.pane.engineDDL.selection = null;
                scripts.pane.engineDDL.selection = scripts.pane.engineDDL.items.length-1;
            }
        }
    }    

    ///////////////////////////////////////////////////////////////////////////////
    //
    // UI handler
    //

	// The callback for the output list box is activated when the user
	// selects a different script. The code tries to find the document.
	// If found, it brings the document to the front. If not, it asks the
	// current debugger (who filled in the list) to fetch the script.

	this.pane.output.onDoubleClick = function()
	{
		if (this.selection && this.selection.text.length)
		{
			if (this.selection.type == "item")
			{
				var info = this.selection.info;
				
				if( info )
				{
					var docCount    = documents.length;
					var target      = null;
					var session     = null;
					var scriptID    = info.scriptID;
					var doc         = docMgr.find( scriptID );
				    
					if( this.parent.parent.targetDDL.selection )
						target = this.parent.parent.targetDDL.selection.target;
					
					if( this.parent.parent.engineDDL.selection )
					{
						session = this.parent.parent.engineDDL.selection.session;
					
					    //
					    // check for invalid favorite
					    //	
						if( !this.parent.targetGroup.validateFavorite( this.parent.parent.engineDDL.selection.favorite ) )
						    return;
					}
				        
					if( !doc )
						scripts.loadScript( info, target, session );
					else
						doc.activate( true );

					if( documents.length != docCount )
					{
						//
						// a new document were opened, set target&engine at document
						//
						targetMgr.setActive( target, session );
						
						//
						// activate new document
						//
						doc = docMgr.find( scriptID );
						
						if( doc )
							docMgr.activateDocument( doc, session );
					}					
				}
			}
			else
				this.selection.expanded = !this.selection.expanded;
		}
	}

    this.pane.targetGroup.targets.onChange = function()
    {            
		scripts.setStatusText();
		
		scripts.pendingTargetRequest = null;

        if( scripts.blockTargetGroup <= 0 && this.selection )
		{
			scripts.setEnabled( false );
			
			if( this.selection.favorites )
			{
			    scripts.fillEngines();
				scripts.setCurrentFavorite();
		                
			    scripts.setEnabled( true );
			    scripts.prevTarget = this.selection;
			}
			else
			{
			    var target = this.selection.target;
			    
			    if( target )
			    {
			        if( target.getChangeConnectState() )
			        {
			            // wait for 'endConnect' notification
			            scripts.pendingTargetRequest = target;
			        }
			        else
			        {
			            if( target.getConnected() )
			            {
			                // target is connected, fill engines list
			                scripts.fillEngines();
			                scripts.pane.engineDDL.selection = 0;
			                scripts.prevTarget = this.selection;
			                scripts.setEnabled( true );
			            }
			            else
			            {
			                //
			                // target isn't connected yet, connect first
			                // and wait for 'endConnect' notification
			                //
			                scripts.pendingTargetRequest = target;

							var err = new ErrorInfo();
							var cb = new Callback( function(err){ if(err) err.display(); }, err );
							target.connect( undefined, cb, err );
							err.display();
						}
			        }
			    }
			    else
			    {
			        // no target, switch back
			        scripts.setEnabled( true );
			        this.selection = scripts.prevTarget;
			    }
            }
		}
    }
    		
    this.pane.targetGroup.engines.onChange = function()
    {
		scripts.setStatusText();

        if( scripts.blockTargetGroup <= 0 )
        {
            if( this.selection && this.parent.validateFavorite( this.selection.favorite ) )
			    this.parent.fillScripts();
		}
	}

    this.pane.output.onChange = function()
    {
	    var pathStr = '';

        if( this.parent.parent.engineDDL.selection && 
            !this.parent.targetGroup.validateFavorite( this.parent.parent.engineDDL.selection.favorite ) )
            return;
            
		if( this.selection )
		{		
		    if( this.selection.favorite )
		        pathStr = this.selection.favorite.path;
		    else if( this.selection.info )
		        pathStr = this.selection.info.scriptID;
		    else if( this.selection.folder )
		        pathStr = this.selection.folder;
		    
		    var path = new File( pathStr );

		    if( path.exists )
		        pathStr = path.fsName;
		}
		        
		scripts.setStatusText();
	    scripts.pane.pathField.textselection = pathStr;
    }
    
	this.pane.output.onExpand = function(item)
	{
	    item.icon = '#FolderOpened';
	    
	    if( item.items.length == 0 && scripts.pane.engineDDL.selection )
	    {
	        if( scripts.pane.engineDDL.selection.favorite )
	        {
	            if( this.parent.targetGroup.validateFavorite( this.rootPane.engineDDL.selection.favorite ) )
	                scripts.pane.targetGroup.populateFavoritesList( item, 
	                                                           item.folder, 
	                                                           this.rootPane.engineDDL.selection.favorite.filter, 
	                                                           this.rootPane.engineDDL.selection.favorite.recursive, 
	                                                           this.rootPane.engineDDL.selection.favorite.filterDot );
	        }
	        else
	            scripts.pane.targetGroup.populateFavoritesList( item, item.folder, "*.js?", true, true );
	    }
	}

	this.pane.output.onCollapse = function(item)
	{
	    item.icon = '#FolderClosed';
	}
	
	///////////////////////////////////////////////////////////////////////////////
	//
	// object methods
	//
		
    //-----------------------------------------------------------------------------
    // 
    // scripts.erase(...)
    // 
    // Purpose: empty list of scripts
    // 
    //-----------------------------------------------------------------------------

    this.erase = function()
    {
        scripts.pane.output.removeAll();
    }

    //-----------------------------------------------------------------------------
    // 
    // scripts.deselect(...)
    // 
    // Purpose: remove selection in script list
    // 
    //-----------------------------------------------------------------------------

    this.deselect = function()
    {
	    this.pane.output.selection = null;
    }

    //-----------------------------------------------------------------------------
    // 
    // scripts.setEnabled(...)
    // 
    // Purpose: set palettes enable state
    // 
    //-----------------------------------------------------------------------------

	this.setEnabled = function( state )
	{
		this.pane.targetGroup.enabled = state;
		this.pane.output.enabled = state;
	}
	
	//-----------------------------------------------------------------------------
	// 
	// scripts.fillTargets(...)
	// 
	// Purpose: fill targets DropDownList
	// 
	//-----------------------------------------------------------------------------
	
    this.fillTargets = function()
    {              
        //
        // remove entries
        //            
        this.pane.targetDDL.removeAll();
        
        this.blockTargetGroup++;
        
        var item = this.pane.targetDDL.add( 'item', localize('$$$/ESToolkit/ScriptFavorites/Title=Favorites') );
        item.favorites = this.favorites;
        
        //
        // fill targets
        //        
        var targets = targetMgr.getTargets();

        for( var i=0; i<targets.length; i++ )
        {
            if( !targets[i].isDefault() )
            {
                var target  = targets[i];
			    var text    = target.getTitle();
                var item    = this.pane.targetDDL.add( 'item', text );
                item.target = targets[i];
            }
        }
        
        this.blockTargetGroup--;
        
        //
        // set selection
        //
		// This loads the Favorites
	    this.pane.targetDDL.selection = 0;
    }

    this.fillEngines = function()
    {
        this.blockTargetGroup++;
        
        this.pane.engineDDL.removeAll();

        if( this.pane.targetDDL.selection )
        {
		    if( this.pane.targetDDL.selection.favorites )
		    {
		        //
		        // fill engines DDL with favorites
		        //
    		    
	            for( i=0; i<this.favorites.length; i++ )
	            {
	                var favItem = this.favorites.items[i];
    	            
	                item = this.pane.engineDDL.add( 'item', favItem.name );
	                item.favorite = favItem;
	            }
		    }
		    else
		    {
		        //
		        // fill engines DDL with sessions of selected target
		        //
    		    
		        var target = this.pane.targetDDL.selection.target;
    		    
		        if( target )
		        {
		            var sessions = target.getSessions();
    		    
	                for( i=0; i<sessions.length; i++ )
	                {
	                    var item     = this.pane.engineDDL.add( 'item', sessions[i].address.engine );
	                    item.session = sessions[i];
	                }
		        }
		    }
        }
        
        this.blockTargetGroup--;
    }

    //-----------------------------------------------------------------------------
    // 
    // scripts.targetGroup.populateFavoritesList(...)
    // 
    // Purpose: fill scripts list
    // 
    //-----------------------------------------------------------------------------

    this.pane.targetGroup.populateFavoritesList = function( node, folder, filter, recursive, filterDot )
    {
        scripts.blockTargetGroup++;
        
		var fileList = folder.getFiles( filter );

        if( recursive )
        {
            var subFolders = folder.getFiles();
            
            for( var i=0; i<subFolders.length; i++ )
            {
                var tmp = subFolders[i].resolve();
                
                tmp = ( tmp ? tmp : subFolders[i] );
                
				if( tmp instanceof Folder )
				{
					var item    = node.add( 'node', ( subFolders[i].displayName == '' ? subFolders[i].name : subFolders[i].displayName ) );
					item.icon   = '#FolderClosed';
					item.folder = tmp;
					item.info   = node.info;
				}
            }
        }
        
        for( var i=0; i<fileList.length; i++ )
        {
			var file = fileList[i];
			if (!(file instanceof File))
				continue;
			if (file.alias)
			{
				// #1461401: do not list aliases that are folders
				var file2 = file.resolve();
				if (file2 instanceof Folder)
					continue;
			}
			
			if( filterDot && file.displayName[0] == '.' )
			    continue;

            var item    = node.add( 'item', file.displayName );
            item.icon   = '#ScriptFile';
            item.info   = new ScriptInfo( file.absoluteURI, file.displayName, true, ( file.readOnly == true ) );

            if( node.info && node.info.includes )
                item.info.includes = node.info.includes;
            else
            {
                var tmp = File( item.info.scriptID );
                
                if( tmp.exists )
					item.info.includes = tmp.parent ? tmp.parent.absoluteURI : "/";
    		}
    		
            scripts.info[fileList[i].absoluteURI] = item.info;
        }
        
        scripts.blockTargetGroup--;
    }
    
    //-----------------------------------------------------------------------------
    // 
    // scripts.fillScripts(...)
    // 
    // Purpose: Request script list from target
    // 
    //-----------------------------------------------------------------------------

    this.fillScripts = function()
    {
        this.pane.targetGroup.fillScripts();
    }
    
	this.pane.targetGroup.fillScripts = function()
	{		
	    scripts.setStatusText();
		scripts.setEnabled( false );
		
		if( this.targets.selection && this.engines.selection )
		{
		    if( this.targets.selection.favorites )
		    {
		        //
		        // fill script list for favorites
		        //
		        var favorite = this.engines.selection.favorite;

		        if( favorite )
		        {
			        scripts.currentFavorite = favorite.name;
                    var folder = new Folder( favorite.path );
                    
                    scripts.erase();

                    if( this.validateFavorite( favorite ) )
                        this.populateFavoritesList( scripts.pane.output, folder, favorite.filter, favorite.recursive, favorite.filterDot );
		        }
		        
		        scripts.setEnabled( true );
		    }
		    else
		    {
		        //
		        // fill script list for target & engine
		        //
		        if( this.engines.selection.session )
		        {
		            if( !this.engines.selection.session.initialized() )
		                scripts.pendingSessionRequest = this.engines.selection.session;
		            else
		                scripts.doFillScripts( this.engines.selection.session );
		        }
		        else
		            scripts.setEnabled( true );
			}
		}
		else
		    scripts.setEnabled( true );
    }

    this.doFillScripts = function( session )
    {
		if( session && session.sessionObj && !session.sessionObj.enabled )
		{		
			addDelayedTask( this, this.doFillScripts, session );
		}
		else
		{		
			// request script list from target
			try
			{
				var job = session.sessionObj.getScripts();
				job.scriptsPane = this;
				
				job.onResult = function()
				{
					this.scriptsPane.fillScriptList( this.result );            
					this.scriptsPane.setEnabled( true );
				}
				
				job.onError = job.onTimeout = function()
				{
					this.scriptsPane.setEnabled( true );
				}
				
				job.submit();
			}
			catch( exc )
			{
				this.setEnabled( true );
			}
		}
    }
    
    //-----------------------------------------------------------------------------
    // 
    // scripts.fillScriptList(...)
    // 
    // Purpose: Fill listbox with given scripts
    // 
    //-----------------------------------------------------------------------------

    this.fillScriptList = function( scriptInfo )
    {
        // clear all lists
        this.pane.output.removeAll();
        this.info = {};
        
		// sort the table alphabetically by display name
		function sortfn( a, b )
		{
		    if( !( a instanceof ScriptInfo ) )
		        return -1;
		    if( !( b instanceof ScriptInfo ) )
		        return 1;
		        
			if( a.label < b.label )
				return -1;
			else if( a.label > b.label )
				return 1;
			else
				return 0;
		}

        scriptInfo.sort( sortfn );
        
        for( var i=0; i<scriptInfo.length; i++ )
        {
			//
			// Disk files must start with "~" or "/" (see IDEBackend::getScripts())
            //
			var icon     = "#ScriptSource";
			var nodeType = "item";
			var isFolder = false;

			if( scriptInfo[i].scriptID[0] == '/' || scriptInfo[i].scriptID[0] == '~' )
			{
				var tmp1 = File( scriptInfo[i].scriptID );
				var tmp2 = tmp1.resolve();
				tmp1 = ( tmp2 ? tmp2 : tmp1 );
				
				if( tmp1.exists )
				{
					isFolder = (tmp1 instanceof Folder);
					
					if( isFolder )
						icon = "#FolderClosed", nodeType = "node";
					else
						icon = "#ScriptFile";
				}
			}
			
			// don't display files starting with a dot
			if( nodeType == "item" && scriptInfo[i].label[0] == "." )
			    continue;
			    
			var item    = scripts.pane.output.add( nodeType, scriptInfo[i].label );
			item.info   = scriptInfo[i];
			item.folder = isFolder ? Folder (scriptInfo[i].scriptID) : null;
			item.icon   = icon;
			this.info[item.info.scriptID] = item.info;
        }
    }
    
    //-----------------------------------------------------------------------------
    // 
    // scripts.targetGroup.validateFavorite(...)
    // 
    // Purpose: Validate given favorite
    // 
    //-----------------------------------------------------------------------------

    this.pane.targetGroup.validateFavorite = function( favorite )
    {
        var ret = true;
        
        scripts.setStatusText();
        
        if( favorite && !Folder( favorite.path ).exists )
        {
            ret = false;
            addDelayedTask( scripts.erase );
            
            scripts.setStatusText( localize( '$$$/CT/ExtendScript/Errors/Err48=File or folder does not exist' ), true );
        }
        
        return ret;
    }
    
    //-----------------------------------------------------------------------------
    // 
    // scripts.setStatusText(...)
    // 
    // Purpose: Set status bar
    // 
    //-----------------------------------------------------------------------------

    this.setStatusText = function( text, error )
    {
        var winGfx = this.pane.pathField.graphics; 
        
        if( error )
        {
            var redColorPen = winGfx.newPen (winGfx.PenType.SOLID_COLOR, [1, 0, 0], 1);
            winGfx.foregroundColor = redColorPen;
        }
        else
            winGfx.foregroundColor = null;
            
        if( !text )
            text = ' ';
            
        this.pane.pathField.text = text;
    }
    			
    //-----------------------------------------------------------------------------
    // 
    // scripts.getSource(...)
    // 
    // Purpose: return script source code
    // 
    //-----------------------------------------------------------------------------
    
    this.getSource = function( scriptInfo, target, session, callback )
    {
        if( scriptInfo )
        {
		    if( scriptInfo.scriptID[0] == '(' )
		    {
		        if( callback )
		            callback.call( null, scriptInfo );
		    }
		    else if( scriptInfo.scriptID[0] == '/' || scriptInfo.scriptID[0] == '~' )
		    {
			    var file = new File( scriptInfo.scriptID );
			    var text = '';
    			
			    if( file.open( 'r' ) )
			    {
				    text = docMgr.safeRead( file );
				    file.close();
			    }
    			
			    if( text && text.length <= 0 )
				    text = null;
				    
				if( callback )
				    callback.call( text, scriptInfo );
		    }		    
		    else if( session )
		    {
		        try
		        {
		            var job     = session.sessionObj.getScriptSource( scriptInfo );
		            job.cb      = callback;
		            job.info    = scriptInfo;
		            job.target  = target;
		            job.session = session;
		            
		            job.onResult = function()
		            {
		                if( this.cb )
		                    this.cb.call( this.result[0], this.info, this.target, this.session );
		            }
		            
		            job.onError = job.onTimeout = function()
		            {
		                if( this.cb )
		                    this.cb.call( null, this.info, this.target, this.session );
		            }
		            
		            job.submit();
		        }
		        catch( exc )
		        {
		            if( callback )
		                callback.call( null, scriptInfo, target, session );
		        }
		    }
		}
    }
    
    //-----------------------------------------------------------------------------
    // 
    // scripts.loadFile(...)
    // 
    // Purpose: Load a script from file and bring that doc to the front.
    // 
    //-----------------------------------------------------------------------------

	this.loadFile = function (scriptID)
	{
		var doc;
		var file = new File (scriptID);
		var f2 = file.resolve();
		if (f2)
		{
			// this is an alias
			file = f2;
			scriptID = file.absoluteURI;
		}
		// Try to find an existing doc
		for (var i = 0; i < documents.length; i++)
		{
			doc = documents [i];
			if (doc.scriptID == scriptID)
			{
				// the doc is already present, so reload
				doc.reload();
				doc.activate();
				breakpoints.updatePane();
				return doc;
			}
		}
		// not found: create a new document
		doc = docMgr.load (file);
		if (doc)
			doc.status = "exec";
		return doc;
	}

    //-----------------------------------------------------------------------------
    // 
    // scripts.loadScript(...)
    // 
    // Purpose: Get a script from the target app. 
    // 
    //-----------------------------------------------------------------------------

	this.loadScript = function( info, target, session )
	{
		if( info.scriptID[0] != '(' )
		{
		    if( info.scriptID[0] == '/' || info.scriptID[0] == '~' )
			    this.loadFile( info.scriptID );
		    else
		        this.getSource( info, target, session, new Callback( this.onLoadScript, { scriptInfo:info, target:target, session:session } ) );
		}
	}
	
	this.onLoadScript = function( loadInfo, source)
	{
        var target      = loadInfo.target;
        var engine      = loadInfo.session;
        
        if( source )
        {
            var doc = docMgr.find( loadInfo.scriptInfo.scriptID );
            
            if( !doc )
            {
                var docWin = docMgr.create( loadInfo.scriptInfo.label, source, undefined, loadInfo.scriptInfo.scriptID );
            	
                if( docWin )
                    doc = docWin.document;
            }
            else
            {
                // make sure that the text is displayed.
                doc.setText( source, false );
                breakpoints.updatePane();
            }
            
            // set target and engine
            var info        = scripts.info[loadInfo.scriptInfo.scriptID];
            doc.target      = target;
            doc.engine      = engine;
            doc.status      = ( loadInfo.scriptInfo.executable ? 'exec' : 'noexec' );
            doc.readOnly    = loadInfo.scriptInfo.readOnly;
            doc.includePath = loadInfo.scriptInfo.includes;
            
            app.toFront();

            // this may be a reload of a doc
            if( !session.document || session.document.scriptID == doc.scriptID )
                session.setDocument(doc);
            	
			targetMgr.setActive( target, session );
                
            // reflect the script state etc
            menus.debug.reflectState();
        }
        else
        {
            if( session )
                session.stop();
                
            errorBox( localize( '$$$/ESToolkit/Alerts/CannotLoadScript=Cannot load script from target %1!', target.getTitle() ) );
        }
	}

    //-----------------------------------------------------------------------------
    // 
    // scripts.storeScript(...)
    // 
    // Purpose: Store the script into the target if appropriate. Return true if a 
    //          PutScript operation was initiated.
    // 
    //-----------------------------------------------------------------------------

	this.storeScript = function( doc )
	{
		var scriptID = doc.scriptID;
	
		if( scriptID != '(' && scriptID != '/' && scriptID != '~' )
		{
		    var session = doc.getCurrentSession();
		    
		    if( session )
		    {
		        try
		        {
		            var info        = new ScriptInfo( scriptID );
		            var job         = session.sessionObj.putScriptSource( info, doc.getText() ); 
		            job.scriptID    = scriptID;
		            job.title       = doc.title;
		            
		            job.onResult = function()
		            {
				        var doc = documents.find( this.scriptID );
				        
				        if (doc)
					        doc.setSaved();
				        // the scripts pane may have changed due to the save operation
				        scripts.fillScripts();
		            }
		            
		            job.onError = job.onTimeout = function()
		            {
		                errorBox (localize ("$$$/CT/ExtendScript/Errors/Err46=%1 is read only", this.title));
		            }
		            
		            job.submit();
		        }
		        catch( exc )
		        {
		            errorBox (localize ("$$$/CT/ExtendScript/Errors/Err46=%1 is read only", doc.title));
		        }
		            
		        return true;
		    }
		    else
		        return false;
		}
		else
		    return false;
	}    
    
    //-----------------------------------------------------------------------------
    // 
    // scripts.setCurrentFavorite(...)
    // 
    // Purpose: Set current favorite
    // 
    //-----------------------------------------------------------------------------

	this.setCurrentFavorite = function()
	{
		var items = this.pane.engineDDL.items;
		// Preset to 0 (Default). This will then take care of the favorite not being found.
		// In that case, it always reverts to Default (also covers localization)
		var sel = 0;

		for (var i = 0; i < items.length; i++)
		{
			if (items[i].text == this.currentFavorite)
			{
				sel = i; break;
			}
		}
		this.pane.engineDDL.selection = sel;
	}	
}
