{Sample Program demonstrating the Text Building Block} {Copyright 1984, Apple Computer Inc.} UNIT URecipes; {Yes! It's a cook book!} INTERFACE USES {$U UObject} UObject, {$U QuickDraw} QuickDraw, {$U UDraw} UDraw, {$U UABC} UABC, {$U UUnivText} UTKUniversalText, {Must use this even if you're not dealing with Universal Text} {$U UText} UText, {$U UDialog} UDialog; {$SETC debugMe := fDBGOK } CONST {Menu and phrase numbers; must match corresponding entry in PRecipes} cmdRefresh = 3000; uOneColumn = 3001; uTwoColumn = 3002; uTraceRecipe = 3003; uAddRecipe = 3004; uDeleteRecipe = 3005; uAddIngred = 3006; uInsIngred = 3007; uDeleteIngred = 3008; uRecipeDialog = 3009; uDrawRects = 3010; uCopyRecipe = 3020; uPasteRecipe = 3021; phTypeIn = 4001; TYPE TFoodTypes = (mainCourse, soup, appetizer, sandwich, dessert, noFood); {**************************************} {******** SUBCLASSES ***********} {**************************************} TRecipe = SUBCLASS OF TObject name: TString; {The recipe name (ex: "Brownies")} ingredients: TList; {of TString: one string per ingredient description} directions: TList; {of TParagraph: a multi-paragraph explanation how to prepare the recipe} {Creation} FUNCTION TRecipe.CREATE(object: TObject; heap: THeap; itsName: TString; itsIngredients: TList; itsDirections: TList): TRecipe; PROCEDURE TRecipe.Free; OVERRIDE; FUNCTION TRecipe.Clone(heap: THeap): TObject; OVERRIDE; {$IFC fDebugMethods} PROCEDURE TRecipe.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} FUNCTION TRecipe.MakeIntoImage(itsView: TView): TRecipeImage; END; {A displayable version of TRecipe; only one of these exists at a time since only one recipe is displayed at a time} TRecipeImage = SUBCLASS OF TImage name: TTextImage; ingredients: TList; {of TTextImage} twoColumn: BOOLEAN; {TRUE => two column directions; one column otherwise (NOT IMPLEMENTED)} directions: TTextImage; changed: BOOLEAN; {checked before copying to the clipboard} {Creation} FUNCTION TRecipeImage.CREATE(object: TObject; heap: THeap; itsView: TView; nameImage: TTextImage; ingredList: TList; direcImage: TTextImage): TRecipeImage; PROCEDURE TRecipeImage.Free; OVERRIDE; {$IFC fDebugMethods} PROCEDURE TRecipeImage.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} FUNCTION TRecipeImage.CursorAt(mouseLPt: LPoint): TCursorNumber; OVERRIDE; FUNCTION TRecipeImage.DismantleImage: TRecipe; PROCEDURE TRecipeImage.Draw; OVERRIDE; FUNCTION TRecipeImage.ImageAt(mouseLPt: LPoint; VAR ingredIndex: LONGINT): TTextImage; PROCEDURE TRecipeImage.MousePress(mouseLPt: LPoint); OVERRIDE; END; {This is the view of the upper left panel, the chapter titles display} TCookBookView = SUBCLASS OF TView {Variables} {This sample program has a fixed list of chapter titles. The reader may wish to make this more flexible by allowing a variable number of custom chapter titles} headings: ARRAY [mainCourse..dessert] OF TList; {array of lists of recipes} {Creation} FUNCTION TCookBookView.CREATE(object: TObject; heap: THeap; itsPanel: TPanel; itsExtent: LRect): TCookBookView; {$IFC fDebugMethods} PROCEDURE TCookBookView.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} {Display} PROCEDURE TCookBookView.Draw; OVERRIDE; {Mousing} PROCEDURE TCookBookView.MousePress(mouseLPt: LPoint); OVERRIDE; END; {This is the view of the lower left panel, the recipe titles display} TChapterView = SUBCLASS OF TView {Variables} foodType: TFoodType; {the foodType of the current displayed chapter} recipes: TList; {of TRecipe; the recipes in this chapter} editImage: TTextImage; {Used when one is editing a recipe title} {Creation} FUNCTION TChapterView.CREATE(object: TObject; heap: THeap; itsPanel: TPanel; itsExtent: LRect): TChapterView; {$IFC fDebugMethods} PROCEDURE TChapterView.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} {Display} PROCEDURE TChapterView.ChangeFood(food: TFoodTypes); FUNCTION TChapterView.CursorAt(mouseLPt: LPoint): TCursorNumber; OVERRIDE; PROCEDURE TChapterView.Draw; OVERRIDE; {Mousing} PROCEDURE TChapterView.MousePress(mouseLPt: LPoint); OVERRIDE; FUNCTION TChapterView.NewRecipe(recipeName: STR255): TRecipe; END; {This is the view of the right panel, the display of the selected recipe} TRecipeView = SUBCLASS OF TView recipeImage: TRecipeImage; {currently displayed recipe} canEdit: BOOLEAN; {TRUE => this recipe is editable (ALWAYS TRUE IN SAMPLE)} {Creation} FUNCTION TRecipeView.CREATE(object: TObject; heap: THeap; itsPanel: TPanel; itsExtent: LRect): TRecipeView; {$IFC fDebugMethods} PROCEDURE TRecipeView.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} {Display} PROCEDURE TRecipeView.ChangeRecipe(recipe: TRecipe); FUNCTION TRecipeView.CreateSecondTxtImg: TTextImage; FUNCTION TRecipeView.CursorAt(mouseLPt: LPoint): TCursorNumber; OVERRIDE; PROCEDURE TRecipeView.Draw; OVERRIDE; PROCEDURE TRecipeView.FreeRecipeImage; PROCEDURE TRecipeView.ScrollStuff(ingredIndex: LONGINT; moveDown: BOOLEAN); {Mousing} PROCEDURE TRecipeView.MousePress(mouseLPt: LPoint); OVERRIDE; END; {TRecipeClipView and TClipSelection are used when a recipe is copied to the clipboard} TRecipeClipView = SUBCLASS OF TView foodtype: TFoodType; recipe: TRecipe; {Creation} FUNCTION TRecipeClipView.CREATE(object: TObject; heap: THeap; itsPanel: TPanel; itsExtent: LRect; itsFoodType: TFoodType; itsRecipe: TRecipe): TRecipeClipView; {Display} PROCEDURE TRecipeClipView.Draw; OVERRIDE; END; TClipSelection = SUBCLASS OF TSelection {Creation} FUNCTION TClipSelection.CREATE(object: TObject; heap: THeap; itsView: TView): TClipSelection; END; {This selection is created when one clicks on a chapter title in the cookBookView} TBookSelection = SUBCLASS OF TSelection {Variables} currFood: TFoodTypes; {Creation} FUNCTION TBookSelection.CREATE(object: TObject; heap: THeap; itsView: TView; itsAnchorLPt: LPoint; whatFood: TFoodTypes): TBookSelection; {$IFC fDebugMethods} PROCEDURE TBookSelection.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} {Display} PROCEDURE TBookSelection.Deselect; OVERRIDE; PROCEDURE TBookSelection.Highlight(highTransit: THighTransit); OVERRIDE; END; {This is a general selection class for anyone who wants to use text selections as coSelections of their main selection. The coSelection mechanism is the only way to override some of the Text Building Blocks text selection behaviour since text selections cannot be subclassed. There are numerous examples of text selection overrides in this sample program. TTextCoverSelection's main purpose in this example is to intercept calls to CanDoCommand to restrict the typeStyles one can choose.} TTextCoverSelection = SUBCLASS OF TSelection {Variables} {Creation} FUNCTION TTextCoverSelection.CREATE(object: TObject; heap: THeap; itsView: TView; itsAnchorLPt: LPoint): TTextCoverSelection; FUNCTION TTextCoverSelection.CanDoCommand(cmdNumber: TCmdNumber; VAR checkIt: BOOLEAN): BOOLEAN; OVERRIDE; END; {This selection is created when one clicks on a recipe title in the chapterView. It is a subclass of TTextCoverSelection because, if the user clicks twice on a recipe title, she is allowed to edit it} TChapSelection = SUBCLASS OF TTextCoverSelection {Variables} recipeIndex: INTEGER; {Creation} FUNCTION TChapSelection.CREATE(object: TObject; heap: THeap; itsView: TView; itsAnchorLPt: LPoint): TChapSelection; PROCEDURE TChapSelection.Free; OVERRIDE; FUNCTION TChapSelection.Clone(heap: THeap): TObject; OVERRIDE; {$IFC fDebugMethods} PROCEDURE TChapSelection.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} PROCEDURE TChapSelection.AddRecipe(recipeName: STR255); PROCEDURE TChapSelection.KeyReturn; OVERRIDE; FUNCTION TChapSelection.NewCommand(cmdNumber: TCmdNumber): TCommand; OVERRIDE; {Display} PROCEDURE TChapSelection.Deselect; OVERRIDE; PROCEDURE TChapSelection.Highlight(highTransit: THighTransit); OVERRIDE; END; {This selection is created when one clicks on a recipe title in the recipeView} TNameSelection = SUBCLASS OF TTextCoverSelection {Creation} FUNCTION TNameSelection.CREATE(object: TObject; heap: THeap; itsView: TView; itsAnchorLPt: LPoint): TNameSelection; PROCEDURE TNameSelection.KeyReturn; OVERRIDE; END; {This selection is created when one clicks on an ingredient in the recipeView} TIngredSelection = SUBCLASS OF TTextCoverSelection {Variables} ingredients: TList; {list of ingredient text images} ingredIndex: INTEGER; {Index into recipeImage.ingredients} {Creation} FUNCTION TIngredSelection.CREATE(object: TObject; heap: THeap; itsView: TView; itsAnchorLPt: LPoint; itsIngredients: TList; index: INTEGER): TIngredSelection; {$IFC fDebugMethods} PROCEDURE TIngredSelection.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} FUNCTION TIngredSelection.CanDoCommand(cmdNumber: TCmdNumber; VAR checkIt: BOOLEAN) : BOOLEAN; OVERRIDE; PROCEDURE TIngredSelection.KeyReturn; OVERRIDE; PROCEDURE TIngredSelection.KeyTab(fBackward: BOOLEAN); OVERRIDE; FUNCTION TIngredSelection.NewCommand(cmdNumber: TCmdNumber): TCommand; OVERRIDE; END; {This selection is created when one clicks in the directions in the recipeView} TDirecSelection = SUBCLASS OF TTextCoverSelection {Variables} {Creation} FUNCTION TDirecSelection.CREATE(object: TObject; heap: THeap; itsView: TView; itsAnchorLPt: LPoint): TDirecSelection; FUNCTION TDirecSelection.CanDoCommand(cmdNumber: TCmdNumber; VAR checkIt: BOOLEAN): BOOLEAN; OVERRIDE; END; {These two subclasses wre here so we can do some tricks as described in the implementation} TChapTextImage = SUBCLASS OF TTextImage refCount: INTEGER; FUNCTION TChapTextImage.CREATE(object: TObject; heap: THeap; itsView: TView; itsLRect: LRect; itsText: TText; isGrowable: BOOLEAN): TChapTextImage; {$IFC fDebugMethods} PROCEDURE TChapTextImage.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} PROCEDURE TChapTextImage.ChangeRefCountBy(delta: INTEGER); PROCEDURE TChapTextImage.FilterAndDo( actualObj: TObject; PROCEDURE DoToObject(filteredObj: TObject)); OVERRIDE; FUNCTION TChapTextImage.NewParaImage(itsParagraph: TEditPara; itsLRect: LRect; lineTop: LONGINT; lineLeft: LONGINT): TParaImage; OVERRIDE; END; TChapParaImage = SUBCLASS OF TParaImage FUNCTION TChapParaImage.CREATE(object: TObject; heap: THeap; itsView: TView; itsParagraph: TEditPara; itsLRect: LRect; lineTop: LONGINT; lineLeft: LONGINT): TChapParaImage; PROCEDURE TChapParaImage.FilterAndDo( actualObj: TObject; PROCEDURE DoToObject(filteredObj: TObject)); OVERRIDE; END; {************************************* COMMANDS **********************************************} {NOTE: Some of these commands are not fully implemented} TAddIngredCmd = SUBCLASS OF TCommand ingredients: TList; ingredIndex: INTEGER; FUNCTION TAddIngredCmd.CREATE(object: TObject; heap: THeap; itsImage: TImage; cmdNumber: TCmdNumber; itsIngredients: TList; itsIndex: INTEGER): TAddIngredCmd; {$IFC fDebugMethods} PROCEDURE TAddIngredCmd.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} PROCEDURE TAddIngredCmd.Perform(cmdPhase: TCmdPhase); OVERRIDE; END; TDelIngredCmd = SUBCLASS OF TCommand ingredients: TList; ingredIndex: INTEGER; ingredSelection: TIngredSelection; saveTextImage: TTextImage; FUNCTION TDelIngredCmd.CREATE(object: TObject; heap: THeap; itsImage: TImage; itsSelection: TIngredSelection; itsIngredients: TList; itsIndex: INTEGER): TDelIngredCmd; {$IFC fDebugMethods} PROCEDURE TDelIngredCmd.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} PROCEDURE TDelIngredCmd.Commit; OVERRIDE; PROCEDURE TDelIngredCmd.Perform(cmdPhase: TCmdPhase); OVERRIDE; END; TDelRecipeCmd = SUBCLASS OF TCommand recipeIndex: INTEGER; FUNCTION TDelRecipeCmd.CREATE(object: TObject; heap: THeap; itsImage: TImage; itsIndex: INTEGER): TDelRecipeCmd; {$IFC fDebugMethods} PROCEDURE TDelRecipeCmd.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} PROCEDURE TDelRecipeCmd.Commit; OVERRIDE; PROCEDURE TDelRecipeCmd.Perform(cmdPhase: TCmdPhase); OVERRIDE; END; TCopyRecipeCmd = SUBCLASS OF TCutCopyCommand recipeIndex: INTEGER; FUNCTION TCopyRecipeCmd.CREATE(object: TObject; heap: THeap; itsImage: TImage; itsIndex: INTEGER): TCopyRecipeCmd; {$IFC fDebugMethods} PROCEDURE TCopyRecipeCmd.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} PROCEDURE TCopyRecipeCmd.DoCutCopy(clipSelection: TSelection; deleteOriginal: BOOLEAN; cmdPhase: TCmdPhase); OVERRIDE; END; TPasteRecipeCmd = SUBCLASS OF TPasteCommand FUNCTION TPasteRecipeCmd.CREATE(object: TObject; heap: THeap; itsImage: TImage): TPasteRecipeCmd; PROCEDURE TPasteRecipeCmd.DoPaste(clipSelection: TSelection; pic: PicHandle; cmdPhase: TCmdPhase); OVERRIDE; END; {Subclasses that are always required so that we operate in the application's environment rather than the ToolKit's generic environment} TMyProcess = SUBCLASS OF TProcess {Creation/Destruction} FUNCTION TMyProcess.CREATE: TMyProcess; PROCEDURE TMyProcess.Commence(phraseVersion: INTEGER); OVERRIDE; FUNCTION TMyProcess.NewDocManager(volumePrefix: TFilePath; openAsTool: BOOLEAN) : TDocManager; OVERRIDE; END; TMyDocManager = SUBCLASS OF TDocManager {Creation/Destruction} FUNCTION TMyDocManager.CREATE(object: TObject; heap: THeap; itsPathPrefix: TFilePath): TMyDocManager; FUNCTION TMyDocManager.NewWindow(heap: THeap; wmgrID: TWindowID): TWindow; OVERRIDE; END; TMyWindow = SUBCLASS OF TWindow {Variables} styleSheet: TStyleSheet; cookBookPanel: TPanel; chapterPanel: TPanel; recipePanel: TPanel; dialogWindow: TDialogWindow; dialog: TDialog; inputFrame: TInputFrame; okayToHilite: BOOLEAN; {kludge described in implementation of PerformLast} {Creation/Destruction} FUNCTION TMyWindow.CREATE(object: TObject; heap: THeap; itsWmgrID: TWindowID): TMyWindow; {$IFC fDebugMethods} PROCEDURE TMyWindow.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE; {$ENDC} {Document Creation} PROCEDURE TMyWindow.BlankStationery; OVERRIDE; {Commands} FUNCTION TMyWindow.CanDoCommand(cmdNumber: TCmdNumber; VAR checkIt: BOOLEAN): BOOLEAN; OVERRIDE; FUNCTION TMyWindow.NewCommand(cmdNumber: TCmdNumber): TCommand; OVERRIDE; PROCEDURE TMyWindow.PerformLast(cmdPhase: TCmdPhase); OVERRIDE; END; IMPLEMENTATION {$I URecipes2.text} END.