implementation module LinkOptionsDialogue

import	StdInt, StdString, StdBool, StdChar, StdArray, StdClass
import	deltaEventIO, deltaMenu, deltaWindow, deltaDialog, deltaControls
import	EdProgramState, EdProject, EdDialogs, EdWindows, EdSupport,  EdFiles,
		EdPath, EdProjectUtils, EdMyIO, EdLists

import UtilSequence

/* Link Options Dialogue */
PSPTitleID	:== 600
PSPrjPathID	:== 610	
AddObjectID		:== 620
RemoveObjectID		:== 630
ObjectsListID:== 640
PSDefPathID	:== 650
AddLibraryID		:== 660
RemoveLibraryID		:== 670
LibraryListID	:== 680
CancelID	:== 700
OkID		:== 710
UseDefaultSystemObjectsGroupID
			:== 720
UseDefaultSystemObjectsCheckboxID
			:== 721
UseDefaultLibrariesGroupID
			:== 730
UseDefaultLibrariesCheckboxID
			:== 731
ShowFullNamesGroupID
			:== 740
ShowFullNamesCheckboxID
			:== 741

::	LinkOptionsDialog =
					{
						projectSet :: Bool,
						linkOptions :: LinkOptions,
						selobject :: !Pathname,
						sellibrary :: !Pathname,
						homedir :: {#Char},
						appdir :: {#Char}
					}

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

// Device function for the Paths Command

LinkOptionsDialogue :: !ProgState !IO -> ProgIO;
LinkOptionsDialogue state=:{editor=ed=:{Editor | project, startupinfo={startupdir}}} io
	# prog
		=	state // {state & editor={Editor | ed /* & project=PR_InitProject */}};
	=	LinkDialogue project prog io;

LinkDialogue ::  !Project !ProgState !IO -> ProgIO;
LinkDialogue project prog=:{editor={startupinfo={startupdir},defaults=defaults=:{paths}}} io
	| True // projectSet
		= OpenLinkOptionsDialog2 pstateb prog2 io
		with
			pstateb	= { pstatea & 	
									homedir	= RemoveFilename project_file_name,
									linkOptions = linkOptions,
									selobject	= GetSelectedPath linkOptions.extraObjectModules,
									sellibrary	= GetSelectedPath linkOptions.libraries
					}
			(project_file_name,prog2) = GetProjectFileName prog
			linkOptions = PR_GetLinkOptions project
		= OpenLinkOptionsDialog2 pstatea prog io
	where
		pstatea			= {	projectSet	= projectSet,
							linkOptions = linkOptions,
							selobject	= GetSelectedPath linkOptions.extraObjectModules,
							sellibrary	= GetSelectedPath linkOptions.libraries,

							homedir	= EmptyPathname,
							appdir = startupdir}

		projectSet	= PR_ProjectSet project
		linkOptions = defaults.Defaults.linkOptions

OpenLinkOptionsDialog2 :: !LinkOptionsDialog !ProgState !IO -> ProgIO
OpenLinkOptionsDialog2 dialogueState=:{projectSet,homedir,appdir,linkOptions} prog io
	=  OpenModalDialog dialog prog io
	where

	dialog = CommandDialog DLinkOptionsID "Link Options" [] OkID [st1,st2,checkBoxDefaultObjects,bt1,bt2,sl1,
																	st3,checkBoxDefaultLibraries,bt3,bt4,sl2,
																	checkBoxFullNames,bt5,bt6]
	st1	= StaticText	PSPTitleID	Center "Link Options"
	st2	= StaticText	PSPrjPathID	Left "Object Modules"
	bt1	= DialogButton	AddObjectID  Left "Append..." Able (AddPath True dialogueState)
	bt2	= DialogButton 	RemoveObjectID Left "Remove" objectsable (RemPath True dialogueState)
	sl1 = ScrollingList ObjectsListID (XOffset AddObjectID (MM 10.0)) ListBoxWidth objectsable 4 remobject objectlist DFIdle
	st3	= StaticText	PSDefPathID	Left "Libraries"
	bt3	= DialogButton	AddLibraryID Left "Append..."	Able		(AddPath False dialogueState)
	bt4	= DialogButton	RemoveLibraryID Left "Remove"	libsable		(RemPath False dialogueState)
	sl2 = ScrollingList LibraryListID (XOffset AddLibraryID (MM 10.0)) ListBoxWidth libsable 4 remlibrary liblist DFIdle

	checkBoxFullNames	= CheckBoxes ShowFullNamesGroupID Left (Columns 1) [
			CheckBox ShowFullNamesCheckboxID	"Show Full Names"	Able 	NoMark	(ShowFullNames dialogueState)]

	bt5	= DialogButton	CancelID (RightTo ShowFullNamesGroupID)	"Cancel" Able (CancelLinkOptions dialogueState)
	bt6	= DialogButton	OkID (RightTo CancelID)	"OK" Able (OKLinkOptions dialogueState)

	libraries	= linkOptions.libraries
	liblist		= MakePathNameList False homedir appdir libraries
	library		= GetSelectedPath libraries
	remlibrary	= MakePathName False homedir appdir library
	libsable	= BoolToSelect (not (IsEmptyList libraries))

	objects		= linkOptions.extraObjectModules
	objectlist	= MakePathNameList False homedir appdir objects
	object		= GetSelectedPath objects
	remobject	= MakePathName False homedir appdir object
	objectsable	= BoolToSelect (not (IsEmptyList objects))

	checkBoxDefaultObjects	= CheckBoxes UseDefaultSystemObjectsGroupID (RightTo PSPrjPathID) (Columns 1) [
			CheckBox UseDefaultSystemObjectsCheckboxID	"Use Default System Objects"	Able 	(BoolToMark linkOptions.useDefaultSystemObjects)	DFIdle ]
	checkBoxDefaultLibraries	= CheckBoxes UseDefaultLibrariesGroupID (RightTo PSDefPathID) (Columns 1) [
			CheckBox UseDefaultLibrariesCheckboxID	"Use Default Libraries"	Able 	(BoolToMark linkOptions.useDefaultLibraries)  DFIdle ]

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

MakePathName	:: !Bool !Pathname !Pathname !Pathname -> String;
MakePathName full projectDir applicationDir name
	| full
		=	name
	// otherwise
		=  MakeApplicationPathName applicationDir (MakeProjectPathName projectDir name)

/* Convert a list of pathname to a long / short form to be used in a list box. */
	
MakePathNameList	:: !Bool !Pathname !Pathname !(List Pathname) -> [String];
MakePathNameList full home appl Nil
		=  [];
MakePathNameList full home appl (path:!rest)
	| path == EmptyPathname
		= MakePathNameList full home appl rest
		= [MakePathName full home appl path : MakePathNameList 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;

OKLinkOptions :: !LinkOptionsDialog !DialogInfo !ProgState !IO -> ProgIO;
OKLinkOptions pstate=:{LinkOptionsDialog | linkOptions} dinfo state=:{editor=editor=:{project}} io
	=	UpdateProjectWindowAndSaveProjectFile project` {state & editor={Editor | editor & project=project`}}
															(ActivateCurrentWindow (CloseActiveDialog io))
	where
		project`
			=	PR_SetLinkOptions project {linkOptions & useDefaultSystemObjects = CheckBoxMarked UseDefaultSystemObjectsCheckboxID dinfo,
							useDefaultLibraries = CheckBoxMarked UseDefaultLibrariesCheckboxID dinfo}

CancelLinkOptions	:: !LinkOptionsDialog !DialogInfo !ProgState !IO -> ProgIO;
CancelLinkOptions pstate dinfo state io
	=  (	state, ActivateCurrentWindow (CloseActiveDialog io) )


ShowFullNames :: !LinkOptionsDialog !DialogInfo !(DialogState ProgState (IOState ProgState)) -> DialogState ProgState (IOState ProgState)
ShowFullNames pstate=:{homedir, appdir, linkOptions={extraObjectModules, libraries}} dialogueInfo dialogueState
	=	dialogueState
	:-	ChangePaths True marked homedir appdir extraObjectModules
	:-	ChangePaths False marked homedir appdir libraries
	where
		marked
			=	CheckBoxMarked ShowFullNamesCheckboxID dialogueInfo

ChangePaths	:: 	!Bool !Bool !Pathname !Pathname !(List Pathname) !(DialogState ProgState IO)
				-> DialogState ProgState IO;
ChangePaths objects full home appl paths dstate
	=	ChangeScrollingList scrollid path` paths` dstate;
	where
		scrollid | objects	= ObjectsListID
							= LibraryListID
		path`
			=	MakePathName full home appl (GetSelectedPath paths)
		paths`
			=	MakePathNameList full home appl paths

AddPath	:: !Bool !LinkOptionsDialog !DialogInfo !ProgState IO -> ProgIO
AddPath objects pstate=:{homedir,appdir,linkOptions} dinfo ps io
	| success	= (ps`, io`)
				= (ps`, io1)
where
	list
		| objects
			=	linkOptions.extraObjectModules
		| otherwise
			=	linkOptions.libraries
	io`					= ChangeDialog	DLinkOptionsID
							[	EnableDialogItems [scrollid,removeid],
								ChangeScrollingList scrollid path paths,
								ChangeDialog_and_ButtonFunctions pstate` ] io1
	scrollid | objects	= ObjectsListID
						= LibraryListID
	removeid | objects	= RemoveObjectID
						= RemoveLibraryID
	path				= MakePathName full homedir appdir (GetSelectedPath new)
	paths				= MakePathNameList full homedir appdir new
	pstate` | objects	= {LinkOptionsDialog | pstate & selobject = newsel, linkOptions.extraObjectModules = new}
						= {LinkOptionsDialog | pstate & sellibrary = newsel, linkOptions.libraries = new}
	new	= Append  (RemoveStringFromList newdir list) newdir
	newsel				= GetSelectedPath new
	full				= CheckBoxMarked ShowFullNamesCheckboxID dinfo
	(success,newdir,ps`,io1)= EdSelectInputFile ps io


RemPath	:: !Bool !LinkOptionsDialog !DialogInfo !ProgState !IO -> ProgIO
RemPath objects pstate=:{homedir,appdir,linkOptions,sellibrary,selobject} dinfo prog io
	| rempath == EmptyPathname	= (prog, io)
								= (prog, io`)
where
	io`						= ChangeDialog	DLinkOptionsID
								[	DisableDialogItems items,
							  		ChangeScrollingList scrollid path paths,
							  		ChangeDialog_and_ButtonFunctions pstate` ] io;
	rempath | objects		= selobject;
							= sellibrary;
	items | IsEmptyList new	= [scrollid,removeid];
							= [];
	scrollid | objects		= ObjectsListID;
							= LibraryListID;
	removeid | objects		= RemoveObjectID;
							= RemoveLibraryID;
	path					= MakePathName full homedir appdir (GetSelectedPath new);
	paths					= MakePathNameList full homedir appdir new;
	pstate` | objects		= {LinkOptionsDialog | pstate & selobject = selnew, linkOptions.extraObjectModules = new};
							= {LinkOptionsDialog | pstate & sellibrary = selnew, linkOptions.libraries = new};
	new | objects			= RemoveStringFromList rempath linkOptions.extraObjectModules;
							= RemoveStringFromList rempath linkOptions.libraries;
	selnew					= GetSelectedPath new;
	full					= CheckBoxMarked ShowFullNamesCheckboxID dinfo;

ChangeDialog_and_ButtonFunctions ::	!LinkOptionsDialog !(DialogState ProgState IO)
									-> DialogState ProgState IO;
ChangeDialog_and_ButtonFunctions pstate dialog
	= 	ChangeDialogFunction ObjectsListID	(SetRemovePaths True pstate)	(
		ChangeDialogFunction LibraryListID	(SetRemovePaths False pstate)	(
		ChangeDialogFunction ShowFullNamesCheckboxID	(ShowFullNames pstate)			(
		ChangeButtonFunction OkID			(OKLinkOptions pstate)			(
		ChangeButtonFunction AddObjectID	(AddPath True pstate)			(
		ChangeButtonFunction AddLibraryID	(AddPath False pstate)			(
		ChangeButtonFunction RemoveObjectID		(RemPath True pstate)			(
		ChangeButtonFunction RemoveLibraryID	(RemPath False pstate)			dialog)))))))



SetRemovePaths	::	!Bool !LinkOptionsDialog !DialogInfo !(DialogState ProgState IO)
					-> DialogState ProgState IO;
SetRemovePaths objects pstate=:{appdir,homedir,linkOptions} dinfo dialog
	=  ChangeDialog_and_ButtonFunctions pstate` dialog;
	where
		pstate` | objects	= {pstate & selobject = path};
							= {pstate & sellibrary = path};
		scrollid | objects	= ObjectsListID;
							= LibraryListID;
		sel					= GetScrollingListItem scrollid dinfo;	
		path | objects		= MatchDefDirName full homedir sel linkOptions.extraObjectModules;
							= MatchDefDirName full homedir sel linkOptions.libraries;
		full				= CheckBoxMarked ShowFullNamesCheckboxID dinfo;

MakeProjectPathName	:: !String !String -> String
MakeProjectPathName projectDir file
	| equal_path_prefix projectDir file
		= "{Project}" +++  DirSeparatorString +++ file % (inc (size projectDir), dec (size file))
	// otherwise
		= file

MakeApplicationPathName :: !String !String -> String
MakeApplicationPathName applicationDir file
	| equal_path_prefix applicationDir file
		= "{Application}" +++ DirSeparatorString +++ file % (inc (size applicationDir), dec (size file))
	// otherwise
		= file


equal_path_prefix	:: !String !String -> Bool;
equal_path_prefix prefix string
	| lengths<=lengthpre
		= False;
		= string.[inc lengthpre]==DirSeparator && string % (0,lengthpre)==prefix;
	where
		lengths		= dec (size string);
		lengthpre	= dec (size prefix);

