module Insert; from Lecture import all; from File import all; export all; object ImportDialogue is components: files:File*; operations: ImportFile; description: (* This object is responsible for importing a file and having a collection of Files to choose from. *); end ImportDialogue; operation ImportFile inputs: id:ImportDialogue, file:File, fs:FileSpace, fn:FileName; outputs: id':ImportDialogue; precondition: (* A file of a given name exists in the given file space, the file must be readable, and the file's data may contain lecture data. *) exists (file in fs) (file.name = fn) and file.file_type?html_type; postcondition: (* The result of this operation is the file is stored in the ImportDialogue's collection of files. The file must be the last object in the collection does not require saving. *) (exists (lect:Lecture) (not lect.save) and (#(id'.files) = #(id.files) +1) and (forall (i:integer | (i >= 2) and (i <= #(id.files))) id'.files[i+1] = id.files[i+1] ) ); end ImportFile; object SlideBreak is components: symbol:File, location:LinePosition, isAuto:boolean; description: (* This is the definition of a SlideBreak -- it's location on a vertical plane. *); end SlideBreak; object Topic is components: location:Location, body:string, isSub:boolean, subs:Topic*; description: (* A topic contains a body text and a boolean value dictating if it is a subtopic or a topic in the outline hierarchy. *); end Topic; object Picture inherits from File components: location:Location, dimensions:PictureDimensions; description: (* A Picture has a location and dimensions (y,x) and is essentially a file. *); end Picture; object PictureDimensions is components: xy:integer*; description: (* This specifies the length and width of a picture by a 2-size array. *); end PictureDimensions; operation PictureInsert inputs: pict:Picture, location:Location, lect:Lecture; outputs: lect':Lecture; precondition: (* In order to insert a picture that picture's location and dimensions cannot overlap with the locations of slide breaks. *) (not Overlap(location, pict, lect)); postcondition: (* The inserted picture is stored in the Lecture object's collection of pictures and the location of the picture is stored within the picture object as well. Also, because an edit operation has been performed the save flag is made true. *) forall (pict':Picture) (pict' in lect'.lectItems) iff (pict' = pict) and (pict.location = location) and (lect.save = true); end PictureInsert; function Overlap(location:Location, pict:Picture, lecture:Lecture)->boolean = exists (slide:SlideBreak | slide in lecture.lectItems) ((location.vertical.lPos < slide.location) and (slide.location < (location.vertical.lPos + pict.dimensions.xy[2]))); operation SlideInsert inputs: location:LinePosition, slide:SlideBreak, lect:Lecture; outputs: lect':Lecture; precondition: (* A slide can only be inserted if it doesnt go through a topic or a picture. *) (not OverlapToPic(location, lect)); postcondition: (* A slide is inserted into the lecture when it is entered in the lecture's collection of slide breaks. Also, the save flag is made true because inserting a slide is an edit operation to the lecture object. Also the slide's location must equal to the location specified. *) exists (sb in lect'.lectItems) (sb = slide) and (lect'.save = true) and (slide.location = location); end SlideInsert; function OverlapToPic(location:LinePosition, lecture:Lecture)->boolean = exists (topic:Topic | topic in lecture.lectItems) (location = topic.location.vertical.lPos) or exists (pi:Picture | pi in lecture.lectItems) ((location > pi.location.vertical.lPos) and (location < (pi.location.vertical.lPos + pi.dimensions.xy[2]))); object SlideIntervalFactor is integer description: (* The SlideIntervalFactor is the integer value that represents the line spacing in between each slide break as specified by the user. *); end SlideIntervalFactor; operation SpecifyAutoSlideIntervalFactor inputs: interval:integer; outputs: slidefactor:SlideIntervalFactor; precondition: (* The user specifies an integer value (in inches) that is the space in between all slide breaks that are automatically generated. It cannot be 0 or a negative number. *) (interval != nil) and (interval > 0); postcondition: (* The integer value specified by the user is now transfered to the value of a SlideIntervalFactor. *) (slidefactor = interval); end SpecifyAutoSlideIntervalFactor; operation AutoSlideInsert inputs: location:LinePosition, slide:SlideBreak, lect:Lecture, interval:SlideIntervalFactor; outputs: lect':Lecture; precondition: (* Autoslide insertion involves the same precondition as a normal slide insertion in addition to making sure that the specified slideintervalfactor (the line space in between each line) is greater than 0. *) (not OverlapToPic(location, lect)) and (interval > 0); postcondition: (* AUtoslide insertion involves the same postcondition as a normal slide insertion except the slide break also has an auto slidebreak boolean flag that must be true. This is also an edit operation thus it is necessary to save the lecture. The slide's location must also be equal to that of the location specified.*) exists (slide':SlideBreak | slide' in lect'.lectItems) (slide' = slide) and (slide'.isAuto = true) and (lect'.save = true) and (slide'.location = location) and forall(autoSlide:SlideBreak | ((autoSlide in lect'.lectItems) and (autoSlide.isAuto = true))) (autoSlide.location/interval = 0); end AutoSlideInsert; operation TopicInsert inputs: location:Location, body:string, top:Topic, lect:Lecture; outputs: lect':Lecture; precondition: (* There is no precondition for inserting a topic other than the body text cannot be nil. *) (body != nil); postcondition: (* The topic is inserted successfully when it is a part of the lecture object's collection of objects and has a body string and location as specified by the user. Adding a topic also changes the lecture object, thus it is necessary to save the lecture. *) exists (top' in lect'.lectItems) (top' = top) and (top.body = body) and (lect'.save = true) and (top.location = location); end TopicInsert; operation SubTopicInsert inputs: location:Location, body:string, topic:Topic, sTopic:Topic, lect:Lecture; outputs: lect':Lecture; precondition: (* In order to insert a subtopic there must be a topic that exists within the lecture topic collection and the topic cannot be empty. This is the topic in which the sub topic will be stored in. *) ((topic in lect.lectItems ) and (body != nil)); postcondition: (* Inserting a subtopic is the same as a topic except the isSub flag is made true and the subtopic is inserted into the topic's collection which is inserted in the lecture's topic collection. Since inserting a subtopic changes the lecture it is necessary to save the lecture as well. The subtopic's location must be equal to that of the specified location. The subtopic's body text must be equal to the text that was given. *) if(exists (topic' in lect'.lectItems) (topic' = topic)) then exists (sTopic' in topic.subs) ((sTopic' = sTopic) and (sTopic.body = body) and (sTopic'.isSub = true)) and (lect'.save = true) and (sTopic'.location = location); end SubTopicInsert; operation NoteInsert inputs: location:Location, text:StickMessage, note:StickyNote, lect:Lecture; outputs: lect':Lecture; precondition: (* In order to insert a note the message must have a string. *) (text != nil); postcondition: (* A sucessful note insertion means that the note object contains the provided body text and location and is a part of the lecture object's collection of notes. *) exists(stickynote in lect'.lectItems) (stickynote = note) and (note.location = location) and (note.text = text); end NoteInsert; object StickyNote is components: text:StickMessage, location:Location; description: (* A note object contains a message of type string and a location (y,x) on the lecture. *); end Note; object StickMessage is string; end Insert;