module Prep;

(***** 
* The following defines the objects and operations that are available in Prep mode, namely the
* Outline, Insert menu, filtering options and SlideSetup. The Outline acts as a navigational tool and 
* also allows the instructor format the slides and insert tags. The instructor can also enter text 
* directly within the Outline window but raw tags must be edited outside of Eclass.
*)


from LectureDB import Lecture, Source, SourcePool, OutlineVisibles, SlideVisibles, SlideSetup, 
GlobalSlideSetup, HTML, TitleBlock, ParagraphBlock, LineBreak, IndentBlock, Heading1Block, 
Heading2Block, Heading3Block, Heading4Block, Heading5Block, Heading6Block, UnorderedListBlock,
OrderedListBlock, DefinitionListBlock, ListItemBlock, EmphasisBlock, ItalicsBlock, UnderlineBlock,
ImageBlock, EclassML, SlideBreak, SlideTitle, SequenceBlock, SequenceItemBlock, HideBlock,
ReplaceBlock, SubstitutionBlock, SelectBlock, StartIndex, EndIndex, StartTag, EndTag, StartPosition, 
EndPosition, Slide, SlideData;


from Edit import Clipboard, Selection, SelectionContext;


object Outline is
	components: OutlineVisibles and FilteringFlags;
	description: (* LectureOutline refers to the Lecture as it appear in the LectureOutline window. 
			The FilteringFlags determine which EclassML filtering tags are visible and 
			which aren't. *);
end Outline;


operation ShowOutline is 
	inputs: sourcePool:SourcePool, outlineVisibles:OutlineVisibles, flags:FilteringFlags;
	outputs: outlineVisibles':OutlineVisibles;
	description: (* Illustrates how filtering and expand and collapse work within the Outline 
			window. Compares OutlineVisibles with the SourcePool and checks the 
			filtering flags to see which tag blocks should be displayed. *);
			
	precondition: ;
	
	postcondition:
	(
		(if (flags.selected = true) then
		(
			forall (slct in sourcePool.eML.selectBlocks) 
				(slct in outlineVisibles'.eML.selectBlocks)
		) else 
		(		
			forall (slct in sourcePool.eML.selectBlocks) 
				(not (slct in outlineVisibles'.eML.selectBlocks))
		))
		(* Selected flag determines whether or not SelectBlocks appear in the Outline 
		   window. Selected constitutes anything that is not within EclassML hide tags. *)

				and
				
		(if (flags.hidden = true) then
		(
			forall (hb in sourcePool.eML.hideBlocks) 
				(hb in outlineVisibles'.eML.hideBlocks)
		) else 
		(		
			forall (hb in sourcePool.eML.hideBlocks) 
				(not (hb in outlineVisibles'.eML.hideBlocks))
		))
		(* Hidden flag determines whether or not HideBlocks appear in the Outline window. *)
		
				and
				
		(if (flags.replace = true) then
		(
			forall (rb in sourcePool.eML.repBlocks) 
				(rb in outlineVisibles'.eML.repBlocks)
		) else 
		(		
			forall (rb in sourcePool.eML.repBlocks) 
				(not (rb in outlineVisibles'.eML.repBlocks))
		))
		(* Replace flag determines whether or not ReplaceBlocks appear in the Outline window. *)
		
				and
				
		(if (flags.subs = true) then
		(
			forall (sub in sourcePool.eML.subsBlocks) 
				(sub in outlineVisibles'.eML.subsBlocks)
		) else 
		(		
			forall (sub in sourcePool.eML.subsBlocks) 
				(not (sub in outlineVisibles'.eML.subsBlocks))
		))
		(* Substitute flag determines whether or not SubsBlocks appear in the Outline window. *)
				
				and
				
		(seq in outlineVisibles'.eML.seqBlocks) iff (seq.expanded = true)
		(* A SequenceBlock has to be expanded to appear in outlineVisibles'. *)
			
				and
				
		(si in outlineVisibles'.eML.siBlocks) iff 
		  forall (si in outlineVisibles'.eML.siBlocks) 
		    (exists (seq in outlineVisibles'.eML.seqBlocks) 
		      ((si.startIndex >= seq.startIndex) and (si.startIndex <= seq.endIndex)) 
		    )
		(* Every visible SequenceItemBlock must be within an expanded SequenceBlock. *)
	);
end ShowOutline;


object Selection is
components: startIndex:integer and endIndex:integer and startPos:integer and endPos:integer
	    and context:string;
description: (*A selection is defined as the starting and ending character indexes in the source and 
	       starting and ending positions in the slide layout.*);
end Selection;


operation InsertHideTags is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Creates an EclassML hide block using the input selection's starting and ending 
			character indexes in the source and starting and ending positions in the slide 
			layout. Adds the start and endTags and inserts the hide block in the source file.
			The hide startTag is 6 characters long and the hide endTag is 7 characters 
			long. *);
	
	precondition: (* slct in lect.sourcePool *);
	postcondition: exists (hideBlock in lect'.sourcePool.eML.hideBlocks)
		       (
		        (hideBlock.startTag.startIndex = slct.startIndex - 6) and
		        (hideBlock.startTag.endIndex = slct.startIndex - 1) and
		        (hideBlock.endTag.startIndex = slct.endIndex + 1) and
		        (hideBlock.endTag.endIndex = slct.endIndex + 7) and
		       	(hideBlock.startIndex = slct.startIndex - 6) and
		       	(hideBlock.endIndex = slct.endIndex + 7) and
		       	(hideBlock.startPos = slct.startPos) and
		       	(hideBlock.endPos = slct.endPos) 
		        (* and hideBlock in lect'.source *)
		       );
end InsertHideTags;


operation InsertReplaceTags is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertHideTags. *);
end InsertReplaceTags;

	
operation InsertSubsTags is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertHideTags. *);
end InsertSubsTags;


operation InsertSequenceTags is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertHideTags. *);
end InsertSequenceTags;


operation InsertSequenceItemTags is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertHideTags. *);
end InsertSequenceItemTags;


operation InsertSlideBreak is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Creates a slideBreak using the input selection's starting index which is the 
			same thing as the position of the text cursor. Adds the slidebreak startTag 
			to the sourcePool and source file. Since a slidebreak consists of just a 
			single startTag the start and endIndexes for the tag and the entire slideBreak
			are the same. A slide break tag is always 12 characters long. *);
	
	precondition: (* slct in lect.sourcePool *);
	postcondition: exists (slideBreak in lect'.sourcePool.eML.slideBreaks)
		       (
		        (slideBreak.startTag.startIndex = slct.startIndex + 1) and
		        (slideBreak.startTag.endIndex = slct.startIndex + 12) and
		       	(slideBreak.startIndex = slct.startIndex + 1) and
		        (slideBreak.endIndex = slct.startIndex + 12) and
		       	(slideBreak.startPos = slct.startPos) 
		       	(* and slideBreak.endPos = startOfNextLine *)  
		        (* and slideBreak in lect'.source *)
		       );
end InsertSlideBreak;


operation InsertParagraphTags is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Creates an HTML paragraph block using the input selection's starting and ending 
			character indexes in the source and starting and ending positions in the slide 
			layout. Adds the start and endTags and inserts the paragraph block in the source 
			file. The hide startTag is 3 characters long and the hide endTag is 4 characters 
			long. *);
	
	precondition: (* slct in lect.sourcePool *);
	postcondition: exists (paragBlock in lect'.sourcePool.hML.pBlocks)
		       (
		        (paragBlock.startTag.startIndex = slct.startIndex - 3) and
		        (paragBlock.startTag.endIndex = slct.startIndex - 1) and
		        (paragBlock.endTag.startIndex = slct.endIndex + 1) and
		        (paragBlock.endTag.endIndex = slct.endIndex + 4) and
		       	(paragBlock.startIndex = slct.startIndex - 3) and
		       	(paragBlock.endIndex = slct.endIndex + 4) and
		       	(paragBlock.startPos = slct.startPos) and
		       	(paragBlock.endPos = slct.endPos) 
		        (* and paragBlock in lect'.source *)
		       );
end InsertParagraphBlock;


operation InsertLineBreak is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Creates an HTML lineBreak using the input selection's starting index which is 
			the same thing as the position of the text cursor. Adds the lineBreak startTag 
			to the sourcePool and source file. Since a lineBreak consists of just a 
			single startTag the start and endIndexes for the tag and the entire lineBreak
			are the same. A line break tag is always 4 characters long. *);
	
	precondition: (* slct in lect.sourcePool *);
	postcondition: exists (lineBreak in lect'.sourcePool.hML.lineBreaks)
		       (
		        (lineBreak.startTag.startIndex = slct.startIndex + 1) and
		        (lineBreak.startTag.endIndex = slct.startIndex + 4) and
		       	(lineBreak.startIndex = slct.startIndex + 1) and
		        (lineBreak.endIndex = slct.startIndex + 4) and
		       	(lineBreak.startPos = slct.startPos) 
		       	(* and lineBreak.endPos = endOfLine *)  
		        (* and lineBreak in lect'.source *)
		       );
end InsertLineBreak;


operation InsertIndentBlock is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertIndentBlock;


operation InsertHeading1Block is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertHeading1Block;


operation InsertHeading2Block is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertHeading2Block;


operation InsertHeading3Block is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertHeading3Block;


operation InsertHeading4Block is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertHeading4Block;


operation InsertHeading5Block is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertHeading5Block;


operation InsertHeading6Block is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertHeading6Block;


operation InsertUnorderedListBlock is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertUnorderedListBlock;


operation InsertOrderedListBlock is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertOrderedListBlock;


operation InsertDefinitionListBlock is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertDefinitionListBlock;


operation InsertListItemBlock is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertListItemBlock;


operation InsertEmphasisBlock is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertEmphasisBlock;


operation InsertItalicsBlock is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertItalicsBlock;


operation InsertUnderlineBlock is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertUnderlineBlock;


operation InsertImageBlock is
	inputs: lect:Lecture and slct:Selection;
	outputs: lect':Lecture;
	description: (* Works just like InsertParagraphTags. *);
end InsertImageBlock;


operation ApplyScopeToAll is
	inputs: lect:Lecture;
	outputs: lect':Lecture;
	description: (* Applies the current slide's setup to all the slides. *);
	
	precondition: lect.slides[lect.myCurrentPosition] in lect.slides;
	postcondition: forall (sl in lect'.slides) 
			(sl.data.slideSetup = lect.slides[lect.myCurrentPosition].data.slideSetup);  
end ApplyScopeToAll;


operation ApplyScopeToSelection is 
	inputs: lect:Lecture;
	outputs: lect':Lecture;
	description: (* Applies the changes made in the SlideSetup dialog to a selection of slides.
			A selection is a set of integers representing each slide's slide number. *);
end ApplyScopeToSelection;


operation ApplyScopeToCurrent is 
	inputs: lect:Lecture;
	outputs: lect':Lecture;	
	description: (* Applies the changes made in the SlideSetup dialog to the current slide. *);
end ApplyScopeToCurrent;


operation UpdateLectureFromSource is
	inputs: lect:Lecture;
	outputs: lect':Lecture;
	description: (* Whenever tags are manually inserted into the Source file using an external
			editor the LectureOutline and LectureSlides need to be updated. *);
end UpdateLectureFromSource;


object FilteringFlags is
	components: hidden:Hidden and selected:Selected and replace:Replace and subs:Substitute;
	description: (* A collection object for the various FilteringFlag states. *);
end ViewFlags;


object Hidden is boolean;
object Selected is boolean;	
object Replace is boolean;
object Substitute is boolean;


operation CheckUncheckHidden is
	inputs: hid:Hidden;
	outputs: hid':Hidden;
	description: (* Check or uncheck Hidden in the View menu. *);
	
	precondition: ;
	postcondition: (if hid = true then hid' = false)
			or (if hid = false then hid' = true);
end CheckUncheckHidden;


operation CheckUncheckSelected is
	inputs: slct:Selected;
	outputs: slct':Selected;
	description: (* Check or uncheck Selected in the View menu. *);
	
	precondition: ;
	postcondition: (if slct = true then slct' = false)
			or (if slct = false then slct' = true);
end CheckUncheckSelected;


operation CheckUncheckReplace is
	inputs: rep:Replace;
	outputs: rep':Replace;
	description: (* Check or uncheck Replace in the View menu. *);
	
	precondition: ;
	postcondition: (if rep = true then rep' = false)
			or (if rep = false then rep' = true);
end CheckUncheckReplace;


operation CheckUncheckSubstitute is
	inputs: subs:Substitute;
	outputs: subs':Substitute;
	description: (* Check or uncheck Substitute in the View menu. *);
	
	precondition: ;
	postcondition: (if subs = true then subs' = false)
			or (if subs = false then subs' = true);	
end CheckUncheckSubstitute;


end Prep;