implementation module EdOptionsMenu2;

import	StdInt, StdString, StdBool, StdChar;
import	deltaEventIO, deltaMenu, deltaWindow, deltaDialog, deltaControls;
import	EdProgramState, EdProject, EdDialogs, EdWindows, EdSupport,  EdFiles,
		EdPath, EdProjectUtils, EdMyIO, EdLists;
		
/* Default Paths Dialog */
	PSPTitleID	:== 600;
	PSPrjPathID	:== 610;	
	PAddPID		:== 620;
	PRemPID		:== 630;
	PPrjctPathID:== 640;
	PSDefPathID	:== 650;
	PAddDID		:== 660;
	PRemDID		:== 670;
	PDefPathID	:== 680;
	PFullID		:== 690;
		BFullID	:== 691;
	PCancPID	:== 700;
	POKPID		:== 710;

/* Project Manager Options Dialog */
	PSPMTitleID	:== 800;
	PPrjID		:== 810;
		RTPrID	:== 811;
		RNPrID	:== 812;
	PSVerbID	:== 820;
	PVerbID		:== 830;
		BVerbID	:== 831;
	PCancPMID	:== 840;
	POKPMID		:== 850;
	
::	PathDialog =	{	pset	:: !Bool,
						temp	:: !Bool,
						project	:: !Project,
						appdir	:: !Pathname,
						seldef	:: !Pathname,
						defs	:: !List Pathname,
						homedir	:: !Pathname,
						selprj	:: !Pathname,
						prjs	:: !List Pathname };
	//	is project set?, temporary project?, application dir, sel. def. path, default paths,
	//	home dir, sel. proj. path,
	//	project paths

// Device function for the Paths Command

Paths :: !ProgState !IO -> ProgIO;
Paths state=:{editor=ed=:{Editor | project}} io
	= OpenPathDialog "The Clean System searches for files in:" False project prog` io;
	where {
		prog`	= {state & editor={Editor | ed & project=PR_InitProject}};
	};
	
// Asks for new paths

NewPathsDialog :: !String !Pathname !Project !ProgState !IO -> (!ProgIO, !Project, !Bool);
NewPathsDialog module_name path project state=:{editor=ed=:{defaults={paths=defpaths}}} io
	= check_new_paths prog` io`;
	where {
	prog1		= {state & editor={Editor | ed & project=PR_InitProject}};
	(prog`,io`)	= OpenPathDialog line True project prog1 io;
	prjpaths	= PR_GetPaths project;
	line		= "Where is '" +++ path +++ "' imported by '" +++ module_name +++ "'";

	check_new_paths :: !ProgState !IO -> (!ProgIO,!Project,!Bool);
	check_new_paths prog=:{editor=ed=:{project,defaults={paths=defpaths`}}} io
			= ((prog`,io),project,newpaths);
		where {
			prog`		= {prog  & editor={Editor | ed & project=PR_InitProject}};
			prjpaths`	= PR_GetPaths project;
			newpaths	= not (EQStrings (SortStrings defpaths) (SortStrings defpaths`)) ||
							not (EQStrings (SortStrings prjpaths) (SortStrings prjpaths`));
		};
	};

get_project_file_name :: !ProgState -> (!Pathname,!ProgState);
get_project_file_name prog=:{editor={editwindows}}
	= (MakeProjectPathname (GetWindow ProjectWdID editwindows).wstate.pathname,prog);

OpenPathDialog :: !String !Bool !Project !ProgState !IO -> ProgIO;
OpenPathDialog title temp project prog=:{editor={startupinfo={startupdir},defaults={paths}}} io
	| prsnt
		= OpenPathDialog2 title pstateb prog2 io;
		{
			pstateb	= { pstatea & 	homedir	= RemoveFilename project_file_name, // modinfo.dir,
									selprj	= GetSelectedPath prjct,
									prjs	= prjct,
									project	= project };
			(project_file_name,prog2) = get_project_file_name prog;
			prjct		= PR_GetPaths project;
		}
		= OpenPathDialog2 title pstatea prog io;
	where {
		pstatea			= {	pset	= prsnt,
							temp	= temp,
							project	= PR_InitProject,
							appdir	= startupdir,
							seldef	= GetSelectedPath paths,
							defs	= paths,
							homedir	= EmptyPathname,
							selprj	= EmptyPathname,
							prjs	= Nil };
		prsnt			= PR_ProjectSet project;
	};
	
OpenPathDialog2 :: !String !PathDialog !ProgState !IO -> ProgIO;
OpenPathDialog2 title pstate=:{pset,homedir,appdir,defs,prjs} prog io
	=  OpenModalDialog dialog prog io;
	where {
	dialog = CommandDialog DPathsID "Paths" [] POKPID [st1,st2,bt1,bt2,sl1,st3,bt3,bt4,sl2,cb1,bt5,bt6];
	st1	= StaticText	PSPTitleID	Center				title;
	st2	= StaticText	PSPrjPathID	Left				"Project Paths";
	bt1	= DialogButton	PAddPID		Left				"Append..."	prjctable	(AddPath True pstate);
	bt2	= DialogButton 	PRemPID		Left				"Remove"	prjctable	(RemPath True pstate);
	sl1 = ScrollingList PPrjctPathID (XOffset PAddPID (MM 10.0)) ListBoxWidth prjctable 4 remprjct prjctlist (SetRemovePaths True pstate);	
	st3	= StaticText	PSDefPathID	Left				"Default Paths";
	bt3	= DialogButton	PAddDID		Left				"Append..."	Able		(AddPath False pstate);
	bt4	= DialogButton	PRemDID		Left				"Remove"	defable		(RemPath False pstate);
	sl2 = ScrollingList PDefPathID (XOffset PAddDID (MM 10.0)) ListBoxWidth defable 4 remdef deflist (SetRemovePaths False pstate);	
	cb1	= CheckBoxes	PFullID Left (Columns 1) [
			CheckBox BFullID "Full Names" Able NoMark (ShowFullNames pstate) ];
	bt5	= DialogButton	PCancPID	(RightTo PFullID)	"Cancel"	Able		(CancelPaths pstate);
	bt6	= DialogButton	POKPID		(RightTo PCancPID)	"OK"		Able		(SetPaths pstate);
	remprjct	= MakeDirName True False homedir appdir prjct;
	prjctlist	= MakeDirNameList True False homedir appdir prjs;
	remdef		= MakeDirName False False homedir appdir def;
	deflist		= MakeDirNameList False False homedir appdir defs;
	prjct		= GetSelectedPath prjs;
	def			= GetSelectedPath defs;
	defable		= BoolToSelect (not (IsEmptyList defs));
	prjctable	= BoolToSelect (pset && (not (IsEmptyList prjs)));
	};
	
ChangeDialog_and_ButtonFunctions ::	!PathDialog !(DialogState ProgState IO)
									-> DialogState ProgState IO;
ChangeDialog_and_ButtonFunctions pstate dialog
	= 	ChangeDialogFunction PPrjctPathID	(SetRemovePaths True pstate)	(
		ChangeDialogFunction PDefPathID		(SetRemovePaths False pstate)	(
		ChangeDialogFunction BFullID		(ShowFullNames pstate)			(
		ChangeButtonFunction POKPID			(SetPaths pstate)				(
		ChangeButtonFunction PAddPID		(AddPath True pstate)			(
		ChangeButtonFunction PAddDID		(AddPath False pstate)			(
		ChangeButtonFunction PRemPID		(RemPath True pstate)			(
		ChangeButtonFunction PRemDID		(RemPath False pstate)			dialog)))))));
	
ShowFullNames	:: !PathDialog !DialogInfo !(DialogState ProgState IO) -> DialogState ProgState IO;
ShowFullNames pstate=:{homedir,appdir,prjs,defs} dinfo dstate
	=  dstate``;
	where {
		dstate``	= ChangePaths True marked homedir appdir prjs dstate`;
		dstate`		= ChangePaths False marked homedir appdir defs dstate;
		marked		= CheckBoxMarked BFullID dinfo;
	};
	
AddPath	:: !Bool !PathDialog !DialogInfo !ProgState IO -> ProgIO;
AddPath project pstate=:{homedir,appdir,defs,prjs} dinfo ps io
	| success	= (ps`, io`);
				= (ps`, io1); 
	where {
	io`					= ChangeDialog	DPathsID
							[	EnableDialogItems [scrollid,removeid],
								ChangeScrollingList scrollid path paths,
								ChangeDialog_and_ButtonFunctions pstate` ] io1;
	scrollid | project	= PPrjctPathID;
						= PDefPathID;
	removeid | project	= PRemPID;
						= PRemDID;
	path				= MakeDirName project full homedir appdir (GetSelectedPath new);
	paths				= MakeDirNameList project full homedir appdir new;
	pstate` | project	= {pstate & selprj = newsel, prjs = new};
						= {pstate & seldef = newsel, defs = new};
/* RWS don't sort path list ...
	new	| project		= InsertStringInList newdir prjs;
						= InsertStringInList newdir defs;
*/
	new	| project		= Append (RemoveStringFromList newdir prjs) newdir;
						= Append (RemoveStringFromList newdir defs) newdir;
/* ... RWS */
	newsel				= GetSelectedPath new;
	full				= CheckBoxMarked BFullID dinfo;
	(success,newdir,ps`,io1)= EdSelectDir ps io;
	};
	
RemPath	:: !Bool !PathDialog !DialogInfo !ProgState !IO -> ProgIO;
RemPath project pstate=:{homedir,appdir,defs,prjs,selprj,seldef} dinfo prog io
	| rempath == EmptyPathname	= (prog, io);
								= (prog, io`);
	where {
	io`						= ChangeDialog	DPathsID
								[	DisableDialogItems items,
							  		ChangeScrollingList scrollid path paths,
							  		ChangeDialog_and_ButtonFunctions pstate` ] io;
	rempath | project		= selprj;
							= seldef;
	items | IsEmptyList new	= [scrollid,removeid];
							= [];
	scrollid | project		= PPrjctPathID;
							= PDefPathID;
	removeid | project		= PRemPID;
							= PRemDID;
	path					= MakeDirName project full homedir appdir (GetSelectedPath new);
	paths					= MakeDirNameList project full homedir appdir new;
	pstate` | project		= {pstate & selprj = selnew, prjs = new};
							= {pstate & seldef = selnew, defs = new};
	new | project			= RemoveStringFromList rempath prjs;
							= RemoveStringFromList rempath defs;
	selnew					= GetSelectedPath new;
	full					= CheckBoxMarked BFullID dinfo;
	};
	
SetRemovePaths	::	!Bool !PathDialog !DialogInfo !(DialogState ProgState IO)
					-> DialogState ProgState IO;
SetRemovePaths project pstate=:{appdir,homedir,defs,prjs} dinfo dialog
	=  ChangeDialog_and_ButtonFunctions pstate` dialog;
	where {
	pstate` | project	= {pstate & selprj = path};
						= {pstate & seldef = path};
	scrollid | project	= PPrjctPathID;
						= PDefPathID;
	sel					= GetScrollingListItem scrollid dinfo;
	path | project		= MatchDirName project full homedir appdir sel prjs;
						= MatchDirName project full homedir appdir sel defs;
	full				= CheckBoxMarked BFullID dinfo;
	};
	
CancelPaths	:: !PathDialog !DialogInfo ProgState IO -> ProgIO;
CancelPaths pstate=:{PathDialog | project} dinfo state=:{editor} io
	=  (	{state & editor={Editor | editor & project=project}},
			ActivateCurrentWindow (CloseActiveDialog io) );
	
SetPaths :: !PathDialog !DialogInfo !ProgState IO -> ProgIO;
SetPaths pstate=:{pset,temp,project,prjs,defs} dinfo prog=:{editor=ed=:{defaults}} io
	| no_project	= (proga,io`);
					= (progb,iob);
	where {
	io`						= ActivateCurrentWindow (CloseActiveDialog io);
	no_project				= not pset || temp;
	project` | pset			= PR_SetPaths False defs prjs project;
							= project;
/* RWS ... don't sort	proga					= {prog & editor={ed & project=project`,defaults={defaults & paths=SortStrings defs}}}; */
	proga					= {prog & editor={ed & project=project`,defaults={defaults & paths=defs}}};
/* ... RWS */
	(progb,iob)				= UpdateProjectWindowAndSaveProjectFile project` proga io`;
	};

ChangePaths	:: 	!Bool !Bool !Pathname !Pathname !(List Pathname) !(DialogState ProgState IO)
				-> DialogState ProgState IO;
ChangePaths project full home appl paths dstate
	=  ChangeScrollingList scrollid path` paths` dstate;
	where {
	scrollid | project		= PPrjctPathID;
							= PDefPathID;
	path`				= MakeDirName project full home appl (GetSelectedPath paths);
	paths`				= MakeDirNameList project full home appl paths;
	};
	
/* determine selected directory name. */

MatchDirName :: !Bool !Bool !Pathname !Pathname !String !(List Pathname) -> Pathname;
MatchDirName True	full home appl sel paths =  MatchProjectDirName full home appl sel paths;
MatchDirName false	full home appl sel paths =  MatchDefDirName full appl sel paths;

/* Convert pathname to a long / short form to be used in a list box. */

MakeDirName	:: !Bool !Bool !Pathname !Pathname !Pathname -> String;
MakeDirName True	full home appl name	=  MakeProjectDirName full home appl name;
MakeDirName false	full home appl name	=  MakeDefDirName full appl name;

/* Convert a list of pathname to a long / short form to be used in a list box. */
	
MakeDirNameList	:: !Bool !Bool !Pathname !Pathname !(List Pathname) -> [String];
MakeDirNameList project full home appl Nil
		=  [];
MakeDirNameList project full home appl (path:!rest)
	| path == EmptyPathname
		= MakeDirNameList project full home appl rest;
		= [MakeDirName project full home appl path : MakeDirNameList project full home appl rest];

/* Select first element of a list of string, if the list is empty, EmptyPathname is returned. */
	
GetSelectedPath	:: !(List String) -> String;
GetSelectedPath Nil				=  EmptyPathname;
GetSelectedPath (path:!rest)	=  path;

// Device function for the Project Options Command

ProjectManager :: !ProgState !IO -> ProgIO;
ProjectManager prog=:{editor={defaults={po},project}} io
  	=  OpenModalDialog dialog prog io;
  	where {
  	dialog = CommandDialog DProjectOptionsID "Project Manager" [] POKPMID
                          [st1,rb1,st2,rb2,bt1,bt2];
    st1= StaticText		PSPMTitleID Center "Project Manager Options";
    rb1= RadioButtons	PPrjID Left (Columns 2) thisornew [
    		RadioItem	RTPrID			"This Project"		thisenabled	(SetProjectOpt RTPrID RNPrID prjopt),
			RadioItem	RNPrID			"New Projects"		Able		(SetProjectOpt RNPrID RTPrID defopt)];
   	st2= StaticText		PSVerbID Left "Diagnostics";
   	rb2= CheckBoxes	PVerbID (Below PSVerbID) (Columns 1) [
			CheckBox 	BVerbID 		"Be Verbose"			Able	mark	DFIdle ];
	bt1= DialogButton	PCancPMID Left	"Cancel" 				Able 	Cancel;
	bt2= DialogButton	POKPMID (RightTo PCancPMID)	"OK" 		Able 	SetProjectOptions;
	thisornew | projectset			= RTPrID;
									= RNPrID;
	thisenabled						= BoolToSelect projectset;
	mark							= BoolToMark prjopt.ProjectOptions.verbose;
	(projectset,opt,defopt,prjopt)	= SelectProjectOptions po project;
  	};

SelectProjectOptions ::	!ProjectOptions !Project
						-> (!Bool,!ProjectOptions,!ProjectOptions,!ProjectOptions);
SelectProjectOptions defaultopt project
	| not projectset	= (False, defaultopt, defaultopt, defaultopt);
						= (True	, projectopt, defaultopt, projectopt);
	where {
	projectset	= PR_ProjectSet project;
	projectopt	= PR_GetProjectOptions project;
	};
	
SetProjectOpt ::	!Int !Int !ProjectOptions DialogInfo (DialogState ProgState IO)
					-> DialogState ProgState IO;
SetProjectOpt myid otherid {ProjectOptions | verbose} dinfo dstate
	= 	ChangeDialogFunction otherid (SetProjectOpt otherid myid old) (
		MarkCheckBoxes mark (
		UnmarkCheckBoxes unmark dstate));
	where {
	old						= GetProjectDialogInfo dinfo;
	mark | verbose			= [BVerbID];
							= [];
	unmark | verbose		= [];
							= [BVerbID];
	};
	
GetProjectDialogInfo :: !DialogInfo -> ProjectOptions;
GetProjectDialogInfo dialog
	=  {ProjectOptions | verbose = CheckBoxMarked BVerbID dialog};

SetProjectOptions :: !DialogInfo !ProgState !IO -> ProgIO;
SetProjectOptions dialog prog=:{editor=ed=:{defaults,project}} io
	| usedefault	= (proga, io`);
					= (progb,iob);
	where {
	proga		= {prog & editor={ed & defaults={defaults & po=opt}}};
	prog1		= {prog & editor={Editor | ed & project=projectb}};
	(progb,iob)	= UpdateProjectWindowAndSaveProjectFile projectb prog1 io`;
	projectb	= PR_SetProjectOptions opt project;
	opt			= GetProjectDialogInfo dialog;
	usedefault	= GetSelectedRadioItemId PPrjID dialog == RNPrID;
	io`			= ActivateCurrentWindow (CloseActiveDialog io);
	};

