implementation module tmdialog


import	StdBool, StdChar, StdFunc, StdList, StdMisc, StdTuple
import	StdControl, StdId, StdMenuElement, StdPSt, StdPStClass, StdSystem, StdWindow
import	showtm, tmfile, Notice


::	TmIds
	=	{	windowID		:: Id
		,	tapeWdID		:: Id
		,	fileMenuId		:: Id
		,	saveItemId		:: Id
		,	machineMenuId	:: Id
		,	stepItemId		:: Id
		,	haltItemId		:: Id
		}
::	Tm
	=	{	tmstate			:: !TmState
		,	name			:: !String
		,	delay			:: !Int
		,	saved			:: !Bool
		,	tmids			:: !TmIds
		}


HelpFile
	:== "TuringHelp"


/*	Create the necessary Ids for the turing program.
*/
openTmIds :: !*env -> (!TmIds,!*env)	| Ids env
openTmIds env
	# (ids,env)			= openIds 7 env 
	  [windowID,tapeID,fileMenuId,saveItemId,machineMenuId,stepItemId,haltItemId:_]
						= ids
	= (	{	windowID		= windowID
		,	tapeWdID		= tapeID
		,	fileMenuId		= fileMenuId
		,	saveItemId		= saveItemId
		,	machineMenuId	= machineMenuId
		,	stepItemId		= stepItemId
		,	haltItemId		= haltItemId
		}
	  ,	env
	  )


/*	The dialog to alter the contents of a tape cell.
*/
AlterCell :: Int (PSt Tm) -> PSt Tm
AlterCell pos pst=:{ls=tm=:{tmstate={turing={tape}},tmids={tapeWdID}}}
	# (ids,pst)	= accPIO (openIds 3) pst
	# pst		= appPIO (appWindowPicture tapeWdID (HiliteCell pos cell)) pst
	# (_,pst)	= openModalDialog undef (dialog ids) pst
	= pst
where
	cell		= CellContents pos tape
	
	dialog ids	= Dialog "Change Tape Cell"
					(	LayoutControl
					(	TextControl		"Write:"						[]
					:+:	EditControl		"" (PixelWidth (hmm 15.0)) 1	[ControlId celId]
					)	[ControlPos (Center,zero)]
					:+:	LayoutControl
					(	ButtonControl	"Cancel"						[ControlFunction (noLS (Cancel pos cell))]
					:+:	ButtonControl	"OK"							[ControlFunction (noLS (Ok     pos     )),ControlId okId]
					)	[ControlPos (Center,zero)]
					)
					[	WindowOk	okId
					,	WindowId	wId
					]
	where
		wId		= ids!!0
		okId	= ids!!1
		celId	= ids!!2
		
		Ok :: Int (PSt Tm) -> PSt Tm
		Ok pos pst=:{ls=tm=:{tmstate,tmids={tapeWdID}},io}
			# (maybeDialog,io)	= getWindow wId io
			  cell				= FirstChar (fromJust (snd (getControlText celId (fromJust maybeDialog))))
			  newtape			= ChangeCellContents pos cell tmstate.turing.tape
			  tm				= {tm & tmstate={tmstate & turing={tmstate.turing & tape=newtape}}}
			# io				= appWindowPicture tapeWdID (DrawTapeCell pos cell) io
			= closeWindow wId {pst & ls=tm,io=io}
		
		Cancel :: Int Char (PSt Tm) -> PSt Tm
		Cancel pos cell pst=:{ls={tmids={tapeWdID}},io}
			= closeWindow wId {pst & io=appWindowPicture tapeWdID (DrawTapeCell pos cell) io}

//	The dialog to alter a transition.
AlterTransition :: Int (PSt Tm) -> PSt Tm
AlterTransition tnr pst=:{ls=tm=:{tmstate={turing={transitions}},tmids={windowID,tapeWdID}}}
	# (ids,pst)	= accPIO (openIds 6)													pst
	# pst		= appPIO (appWindowPicture windowID (HiliteTransition tnr transition))	pst
	# pst		= appPIO (appWindowPicture tapeWdID EraseError)							pst
	# (_,pst)	= openModalDialog undef (dialog ids)									pst
	= pst
where
	transition	= GetTransition tnr transitions
	
	ctos :: Char -> String
	ctos c		= if (c==' ') "" (toString c)
	
	dialog ids	= Dialog "Change Transition" 
					(	LayoutControl
					(	TextControl		"From:"												[	ControlPos (Left,zero)
																							,	ControlWidth (PixelWidth (hmm 20.0))
																							]
					:+:	EditControl		transition.start (PixelWidth (hmm 25.0)) 1			[	ControlId fromId
																			 				]
					:+:	TextControl		"With:"												[	ControlPos (Left,zero)
																							,	ControlWidth (PixelWidth (hmm 20.0))
																							]
					:+:	EditControl		(ctos transition.sigma) (PixelWidth (hmm 25.0)) 1	[	ControlId headId
																							]
					)	[ControlHMargin 0 0,ControlVMargin 0 0]
					:+:	LayoutControl
					(	TextControl		"To:"												[	ControlPos (Left,zero)
																							,	ControlWidth (PixelWidth (hmm 20.0))
																							]
					:+:	EditControl		transition.end (PixelWidth (hmm 25.0)) 1			[	ControlId toId
																							]
					:+:	TextControl		"Action:"											[	ControlPos (Left,zero)
																							,	ControlWidth (PixelWidth (hmm 20.0))
																							]
					:+:	EditControl		(ctos transition.move) (PixelWidth (hmm 25.0)) 1	[	ControlId moveId
																							]
					)	[ControlHMargin 0 0,ControlVMargin 0 0]
					:+:	LayoutControl
					(	ButtonControl	"Cancel"	[ControlFunction (noLS (Cancel tnr transition))]
					:+:	ButtonControl	"Remove"	[ControlFunction (noLS (Remove tnr))]
					:+:	ButtonControl	"OK"		[ControlFunction (noLS (Ok tnr)),ControlId okId]
					)	[ControlPos (Center,zero)]
					)
					[	WindowId	wId
					,	WindowOk	okId
					]
	where
		[wId,fromId,headId,toId,moveId,okId:_]
				= ids
		
		Ok :: Int (PSt Tm) -> PSt Tm
		Ok tnr pst=:{ls=tm=:{tmstate,tmids={windowID,fileMenuId,saveItemId}},io}
			# (maybeDialog,io)	= getWindow wId io
			  dialog			= fromJust maybeDialog
			  transition		= {	start	= FourCharString	(fromJust (snd (getControlText fromId dialog)))
								  ,	sigma	= FirstChar			(fromJust (snd (getControlText headId dialog)))
								  ,	end		= FourCharString	(fromJust (snd (getControlText toId   dialog)))
								  ,	move	= FirstChar			(fromJust (snd (getControlText moveId dialog)))
								  }
			  newtransitions	= ChangeTransition tnr transition turing.transitions
			# io				= appWindowPicture windowID (ShowTrans tnr transition) io
			# io				= enableMenuElements [saveItemId] io
			# pst				= {pst & ls={tm & tmstate={tmstate & turing={turing & transitions=newtransitions}},saved=False},io=io}
			# pst				= closeWindow wId pst
			= pst
		where
			turing				= tmstate.turing
		
		Cancel :: Int Transition (PSt Tm) -> PSt Tm
		Cancel tnr transition=:{start} pst=:{ls={tmids={windowID}}}
			# pst			= closeWindow wId pst
			| start==""		= appPIO (appWindowPicture windowID (EraseTrans tnr)) pst
			| otherwise		= appPIO (appWindowPicture windowID (ShowTrans  tnr transition)) pst
		
		Remove :: Int (PSt Tm) -> PSt Tm
		Remove tnr pst=:{ls=tm=:{tmstate,tmids={fileMenuId,saveItemId}}}
			# pst			= closeWindow wId pst
			# pst			= appPIO (enableMenuElements [saveItemId]) pst
			# pst			= {pst & ls={tm & tmstate = {tmstate & turing={turing & transitions=newtransitions},transition=0}
										    , saved   = False
									    }}
			= ReDraw pst
		where
			turing			= tmstate.turing
			newtransitions	= RemoveTransition tnr turing.transitions


//	The dialog to alter the state of the T.M.
AlterState :: (PSt Tm) -> PSt Tm
AlterState pst=:{ls=tm=:{tmstate={turing={state}},tmids={tapeWdID,windowID}}}
	# pst		= appPIO (appWindowPicture tapeWdID EraseError) pst
	# pst		= appPIO (appWindowPicture windowID (HiliteState state)) pst
	# (ids,pst)	= accPIO (openIds 3) pst
	# (_,pst)	= openModalDialog undef (dialog ids) pst
	= pst
where
	dialog ids	= Dialog "Change State" 
					(	TextControl		"State:"						[ControlPos (Left,zero)]
					:+:	EditControl		"" (PixelWidth (hmm 25.0)) 1	[ControlId editId]
					:+:	LayoutControl
					(	ButtonControl	"Cancel"						[ControlFunction (noLS (Cancel state))]
					:+:	ButtonControl	"OK"							[ControlId okId,ControlFunction (noLS Ok)]
					)	[ControlPos (Center,zero)]
					)
					[	WindowOk	okId
					,	WindowId	wId
					]
	where
		[wId,okId,editId:_]
				= ids
		
		Ok :: (PSt Tm) -> PSt Tm
		Ok pst=:{ls=tm=:{tmstate,tmids={windowID,machineMenuId,stepItemId,haltItemId}},io}
			# (dialog,io)	= getWindow wId io
			  dialog		= fromJust dialog
			  state			= FourCharString (fromJust (snd (getControlText editId dialog)))
			# io			= appWindowPicture windowID (ShowNextState state) io
			# io			= (if (state=="halt") disableMenuElements enableMenuElements) [stepItemId,haltItemId] io
			# pst			= {pst & io=io, ls={tm & tmstate={tmstate & turing={tmstate.turing & state=state}}}}
			# pst			= closeWindow wId pst
			= pst
		
		Cancel :: String (PSt Tm) -> PSt Tm
		Cancel state pst=:{ls={tmids={windowID}},io}
			# pst	= closeWindow wId pst
			# pst	= appPIO (appWindowPicture windowID (ShowNextState state)) pst
			= pst


//	The function to redraw the entire machine when an update event takes place.
ReDraw :: (PSt Tm) -> PSt Tm
ReDraw pst=:{ls=tm=:{tmstate={turing={transitions,tape,state}},tmids={tapeWdID,windowID}},io}
	# io	= setWindowLook tapeWdID True (True,\_ _->ShowTape tape)						io
	# io	= setWindowLook windowID True (True,\_ _->ShowTransitions transitions state)	io
	= {pst & io=io}


//	General alert dialog.
Alert :: String String (PSt Tm) -> PSt Tm
Alert mes1 mes2 pst
	= openNotice (Notice [mes1,mes2] (NoticeButton "OK" id) []) pst


//	Save before close dialog.
SaveBeforeClose :: String (IdFun (PSt Tm)) (PSt Tm) -> PSt Tm
SaveBeforeClose message action pst=:{ls=tm=:{name},io}
	= openNotice notice pst
where
	notice	= Notice
				[	"Save changes to \""+++RemovePath name+++"\""
				,	"before "+++message+++"?"
				]
				(	NoticeButton "Yes"    (noLS (action o SvBfClSave)))
				[	NoticeButton "No"     (noLS action)
				,	NoticeButton "Cancel" id
				]
	
	SvBfClSave :: (PSt Tm) -> PSt Tm
	SvBfClSave pst=:{ls=tm=:{tmstate={turing},name,tmids={saveItemId}},io}
		# pst	= {pst & ls={tm & saved=True}, io=disableMenuElements [saveItemId] io}
		= snd (WriteTuringToFile turing name pst)
