/**************************************************************************
*
*  @@@BUILDINFO@@@ 86preferences-2.jsx 2.0.1.65  24-April-2007
*  Copyright 2006-2007 Adobe Systems Incorporated
*  All Rights Reserved.
*
* NOTICE:  All information contained herein is, and remains the property of
* Adobe Systems Incorporated  and its suppliers,  if any.  The intellectual 
* and technical concepts contained herein are proprietary to  Adobe Systems 
* Incorporated  and its suppliers  and may be  covered by U.S.  and Foreign 
* Patents,patents in process,and are protected by trade secret or copyright 
* law.  Dissemination of this  information or reproduction of this material
* is strictly  forbidden  unless prior written permission is  obtained from 
* Adobe Systems Incorporated.
**************************************************************************/

var preferenceDialog = null;

var locales = [];
const cShortcutTitleLength = 35;    
scintillaPrefs = new Object;

// This object contains all color icons under the name of the color.

var colorIcons = null;

///////////////////////////////////////////////////////////////////////////////
//
// scintilla prefs
//

scintillaPrefs.init = function()
{
	if( this.xml == undefined )
	{
		this.xml = new XML( "<scintilla/>" );
		this.xml.languages = languages.copy();
		this.xml.defaults = new XML( "<defaults/>" ); 
		this.xml.defaults.languages = languages.copy();
	}
}

// Load the file scintilla.xml during app startup.

scintillaPrefs.reset = function()
{
	var loaded = false;
	
	if( !this.backup )
	{
	    var f = new File( app.prefsFolder + "/scintilla.xml" );
    	
	    if( f.exists && f.open ("r") )
	    {
		    f.encoding = "UTF-8";
		    this.xml = new XML( f.read() );
		    this.backup = this.xml;
		    f.close();
		    loaded = (this.xml.languages.length() > 0);
	    }
    }
    else
    {
        this.xml = this.backup;
        loaded = true;
    }
        
	// copy from the current languages...
	if( !loaded )
	    this.init();

	return loaded;
}

// Load the file scintilla.xml during app startup.

scintillaPrefs.load = function()
{
	var loaded = this.reset();
	if( loaded )
		languages = this.xml.languages.copy();
	
	return loaded;
}

// Create the parent folder if not yet present.

scintillaPrefs.createFolder = function()
{
	var fld = new Folder (app.prefsFolder);
	if (!fld.exists)
		fld.create();

	return fld;
}

// Save the file scintilla.xml during app shutdown.

scintillaPrefs.save = function()
{			
	// create the prefs file
	var fld = this.createFolder();
	
	var f = new File (fld + "/scintilla.xml");
	if (f.open ("w"))
	{
		f.encoding = "UTF-8";
		f.write ( this.xml.toXMLString() );
		if (!f.close())
			f.remove();
	}
}

///////////////////////////////////////////////////////////////////////////////
//
// preference dialog
//

function PreferenceDialog()
{
    //
	// Initialize the color icons for the Fonts and Colors prefs if we don't have them yet
	//
	if (!colorIcons)
	{
		colorIcons = {};

		for (var i in colors)
			colorIcons [i] = ScriptUI.newImage ("#" + i);
	}

	/////////////////////////////////////////////////////////////////////////
    //
	// Create scintilla prefs if the user launched without prefs (see "shift" in startup.jsx).
	//
	scintillaPrefs.init();

	/////////////////////////////////////////////////////////////////////////
	//
	// The preferences dialog resource
    //
	var prefsDlgResSpec =
	"prefdialog {										\
		text			: '$$$/ESToolkit/PreferencesDlg/Title=ExtendScript Toolkit 2 Preferences', \
		orientation		: 'column',					\
		alignment		: ['fill','fill'],			\
		alignChildren	: ['fill','fill'],			\
		listAndPanels	: Group						\
		{											\
			orientation		: 'row',				\
			selector		: ListBox				\
			{										\
				preferredSize	: [155,145],		\
				alignment		: ['left','fill'],	\
				margins			: [15,20,15,15]		\
				helpTip:'$$$/ESToolkit/PreferencesDlg/htSelector=Select the preferences to change' \
			},										\
			prefs			: Group					\
			{										\
				orientation		: 'column',			\
				alignment		: ['fill','fill'],	\
				alignChildren	: ['fill','fill'],	\
				panes			: Group				\
				{									\
					minimumSize		: [380, 380],	\
					maximumSize		: [380, 380],	\
					alignment		: ['left','top'], \
					orientation		: 'stack',		\
				},									\
				divider			: Panel				\
				{									\
					orientation		: 'row',		\
					preferredSize	: [10,1],		\
					maximumSize		: [1000,1],		\
					alignment		: ['fill','bottom'],\
				}									\
			}										\
		},											\
		btns			: Group {					\
			orientation		: 'row',	        	\
			alignment		: ['right','bottom'],  	\
			defBtn			: Button				\
			{										\
				text			: '$$$/ESToolkit/PreferencesDlg/DefaultBtn=Default' }, \
				space			: Group				\
				{									\
					minimumSize		: [30,1],		\
					preferedSize	: [30,1]		\
				},					            	\
				okBtn			: Button			\
				{									\
					text			: '$$$/CT/ExtendScript/UI/OK=OK', \
					properties		: {				\
						name			:'ok'		\
					}								\
				},						        	\
				cancelBtn		: Button			\
				{									\
					text			 : '$$$/CT/ExtendScript/UI/Cancel=Cancel', \
					properties		: {				\
						name			: 'cancel'	\
					}								\
				}						        	\
			}										\
		}											\
	}";

	this.prefsDlg = new Window (prefsDlgResSpec);
	
	this.prefsDlg.currentPane = null;

	// Each Prefs object needs the following methods:
	// prefsObj.create (parentPane) - create the pane and return the Pane object.
	// pane.preProcess()			- preprocess the pane just before being shown.
	// pane.layoutDone()			- informs the pane that the initial layout is done (optional)
	// pane.postProcess()			- do any work just before the pane is being hidden.
	// pane.store()					- store the preferences. Return true if the Next Time dialog is needed.
	// pane.toDefault()				- set back to default values
	// pane.cancelled()				- Prefs dialog has been cancelled

	var parentPane = this.prefsDlg.listAndPanels.prefs.panes;

	//	Initialize the 'selector' list that chooses which preference pane to show
	this.initSelectorList(   this.prefsDlg.listAndPanels.selector, parentPane,
		                [
		                    [ "$$$/ESToolkit/PreferencesDlg/StartupTitle=Startup",				generalPrefs	],
		                    [ "$$$/ESToolkit/PreferencesDlg/textTitle=Documents",				documentPrefs	],
		                    [ "$$$/ESToolkit/PreferencesDlg/fontTitle=Font and Colors",			fontPrefs		],
	                        [ "$$$/ESToolkit/PreferencesDlg/debuggerTitle=Debugging",			debugPrefs		],
		                    [ "$$$/ESToolkit/PreferencesDlg/helpTitle=Help",			        helpPrefs		],
	                        [ "$$$/ESToolkit/PreferencesDlg/favoritesTitle=Favorites",			favoritesPrefs	],
	                        [ "$$$/ESToolkit/PreferencesDlg/shortcutTitle=Keyboard Shortcuts",	shortcutPrefs	]
		                ] );

	with( this.prefsDlg.btns ) 
	{
		//	Dialog window is 2 levels in hierarchy up from the buttons
		okBtn.onClick = function () 
		{	
			// Make sure to post-process the current pane
			if( this.window.currentPane )
				this.window.currentPane.postProcess();
		
		    // pwollek 02/09/07 should happen on shutdwon
			// Save the scintilla prefs...
			//scintillaPrefs.save();
			
			languages = scintillaPrefs.xml.languages.copy();
			
			if( documents.length > 0 )
			{
				for( var i=0; i<documents.length; i++ )
				{
					var langID          = documents[i].langID;
					documents[i].langID = null;
					documents[i].setLanguage( langID );
				}
			}
			
			// close dialog
			this.window.close(1);
		}
		
		cancelBtn.onClick = function () 
		{ 
			// load old prefs
			scintillaPrefs.reset();
			
			// close dialog
			this.window.close(2); 
		}
		
		defBtn.onClick = function()
		{
			if( this.window.currentPane )
				this.window.currentPane.toDefault();
		}
	}
}

/////////////////////////////////////////////////////////////////////////
//	configureDialogFromPrefs()
//
//	Initialize dialog settings from the saved 'preferenceDialogPrefs' values.
//	Called on each 'show' of the preferences dialog.
//
PreferenceDialog.prototype.configureDialogFromPrefs = function()
{
	//	Location unknown: center over the main window
	this.prefsDlg.center();
	
	//	Show the last known preferences pane
	this.prefsDlg.listAndPanels.selector.selection = null;
	this.prefsDlg.listAndPanels.selector.selection = isNaN( parseInt(prefs.preferencesDialogPrefs.selectedPane) ) ? 0 : parseInt(prefs.preferencesDialogPrefs.selectedPane);
	this.prefsDlg.listAndPanels.selector.currPane = this.prefsDlg.listAndPanels.selector.selection.pane;
} // configureDialogFromPrefs

/////////////////////////////////////////////////////////////////////////
//	updateDialogPrefs()
//	Update the 'preferenceDialogPrefs' object with current dialog settings.
PreferenceDialog.prototype.updateDialogPrefs = function()
{		
	//	Remember what prefences pane was selected
	prefs.preferencesDialogPrefs.selectedPane = this.prefsDlg.listAndPanels.selector.selection.index;
} // updateDialogPrefs	

PreferenceDialog.prototype.show = function()
{
    return this.prefsDlg.show();
}

/////////////////////////////////////////////////////////////////////////
/*	initSelectorList
	Setup the list to show 1 pane for each list item.
	'selector' is the DropDownList that will contain names of preference panes.
	'panes' is the panel that the selector list should be positioned over
	'selections' is an array of "title, obj" pairs, where 'obj' is the
	pane object if the given 'title' is selected in the list.
*/
PreferenceDialog.prototype.initSelectorList = function(selector, panes, selections)
{
	selector.stackPane = panes;
	//	Load the list with preference pane titles
	for (var i = 0; i < selections.length; i++) 
	{
		var sel = selections [i];
		item = selector.add ("item", localize(sel [0]));
		item.prefsObject = sel [1];
		item.pane = null;
	}
	
	/*	When a list item is selected, hide the currently visible preference pane
		and show the one corresponding to the selected item. */
	selector.onChange = function ()
	{
		if (this.selection)
		{
			var created = false;
			if (!this.selection.pane)
			{
				created = true;
				app.setWaitCursor (true);
				var pane = this.selection.prefsObject.create (this.stackPane);
				this.selection.pane = pane;
				pane.preProcess();
				selector.window.layout.layout(true);
				if (pane.layoutDone)
					pane.layoutDone();
				app.setWaitCursor (false);
			}
			var paneToShow = this.selection.pane;
			if (selector.window.currentPane)
			{
				selector.window.currentPane.postProcess();
				selector.window.currentPane.hide();
			}
			if (!created)
				paneToShow.preProcess();
			paneToShow.show();
			selector.window.currentPane = paneToShow;
		}
	}
} // initSelectorList

function openPreferencesDialog()
{
    if( !preferenceDialog )
        preferenceDialog = new PreferenceDialog();
	
	/////////////////////////////////////////////////////////////////////////
	//
	// Configure the dialog, show it, and set any changed preferences
	//
	preferenceDialog.configureDialogFromPrefs();
	Preference.clearDirty();
	var ok = preferenceDialog.show() == 1;
	preferenceDialog.updateDialogPrefs ();

	if( ok ) 
    {
		// call store() only if there actually is a loaded pane
		var nextTimeNeeded  = ( generalPrefs.pane    ? generalPrefs.store() :   false );
		nextTimeNeeded     |= ( documentPrefs.pane   ? documentPrefs.store() :  false );
		nextTimeNeeded     |= ( fontPrefs.pane       ? fontPrefs.store() :      false );
		nextTimeNeeded     |= ( helpPrefs.pane       ? helpPrefs.store() :      false );
		nextTimeNeeded     |= ( debugPrefs.pane      ? debugPrefs.store() :     false );
		nextTimeNeeded     |= ( favoritesPrefs.pane  ? favoritesPrefs.store() : false );
		nextTimeNeeded     |= ( shortcutPrefs.pane   ? shortcutPrefs.store() :  false );
		
		Preference.propagateDirty();

		if (nextTimeNeeded)
			// tell the user that the settings are delayed if needed
			messageBox ("$$$/ESToolkit/PreferencesDlg/NewSettingsNextTime=The new settings will take effect the next time the program starts.");
	}
	else
	{
		// call canceled() only if there actually is a loaded pane
		if( generalPrefs.pane    && generalPrefs.pane.cancelled ) 	generalPrefs.pane.cancelled(); 
		if( documentPrefs.pane   && documentPrefs.pane.cancelled )	documentPrefs.pane.cancelled();
		if( fontPrefs.pane       && fontPrefs.pane.cancelled )	 	fontPrefs.pane.cancelled();
		if( helpPrefs.pane       && helpPrefs.pane.cancelled )	 	helpPrefs.pane.cancelled();
		if( debugPrefs.pane      && debugPrefs.pane.cancelled )	 	debugPrefs.pane.cancelled();
		if( favoritesPrefs.pane  && favoritesPrefs.pane.cancelled )	favoritesPrefs.pane.cancelled();
		if( shortcutPrefs.pane   && shortcutPrefs.pane.cancelled )	shortcutPrefs.pane.cancelled();
	}
}

// Set the text of a list item by using two texts and a dot position for the second text

ListItem.prototype.setTabbedText = function (text1, tab, text2)
{
	// First, set the width of small and large spaces
	var list = this.parent;
	if (!list.spaceWidth)
	{
		list.smallSpace			= " ";//String.fromCharCode (" "); // Tahoma does not support small-width spaces (0x200A);
		list.ellipsis			= String.fromCharCode (0x2026);
		list.ellipsisWidth		= list.graphics.measureString (list.ellipsis)[0];
		list.spaceWidth			= list.graphics.measureString (" ")[0];
		list.smallSpaceWidth	= list.graphics.measureString (list.smallSpace)[0];
	}
	// strip trailing "..."
	var i = text1.lastIndexOf ("...");
	if (i > 0)
		text1 = text1.substr (0, i);

	var width = list.graphics.measureString (text1)[0];
	var maxWidth = tab - list.ellipsisWidth - 5 * list.smallSpaceWidth;
	var halfSpace = 0.5 * list.smallSpaceWidth;
	if (width > (maxWidth + halfSpace))
	{
		// Need to shrink
		while (width > maxWidth)
		{
			text1 = text1.substr (0, text1.length-1);
			width = list.graphics.measureString (text1)[0];
		}
		// append Unicode ellipsis string
		text1 += list.ellipsis;
		width  = list.graphics.measureString (text1)[0];
	}
	
	// First, approach with spaces
	var oldWidth = width;
	while (width < tab)
	{
		text1 += " ";
		width += list.spaceWidth;
	}
	
	// Then, fine adjust
	width = list.graphics.measureString (text1)[0];
	if (width > tab && width > (oldWidth + halfSpace))
	{
//		print (tab + " " + list.graphics.measureString (text1)[0] + " Fixing " + text1);
		text1 = text1.substr (0, text1.length-1);
		width = list.graphics.measureString (text1)[0];
	}
	while (width < (tab - halfSpace))
	{
		text1 += list.smallSpace;
		width = list.graphics.measureString (text1)[0];
	}
//	print (tab + " " + list.graphics.measureString (text1)[0] + " " + text1);
	this.text = text1 + text2;
}

