Somehow, srod's underpants made it in there again, don't know why :):)
If anyone can make some nice improvements, I'd be happy with that.
Code: Select all
; Visual designer generated
;- Required Image Decoders
UsePNGImageDecoder()
Define EventID, MenuID, GadgetID, WindowID
;- Window Constants
Enumeration 1
#Window_Recipeview
EndEnumeration
#WindowIndex = #PB_Compiler_EnumerationValue
;- Gadget Constants
Enumeration 1
; Window_Recipeview
#Gadget_Recipeview_Recipenames
#Gadget_Recipeview_Recipeview
#Gadget_Recipeview_cControl
#Gadget_Recipeview_Getdirectory
#Gadget_Recipeview_cStatusbar
#Gadget_Recipeview_sStatus
#Gadget_Recipeview_Printrecipe
#Gadget_Recipeview_Showhelp
#Gadget_Recipeview_Recipedirectory
#Gadget_Recipeview_Recipecategory
#Gadget_Recipeview_Recipesubcategory
#Gadget_Recipeview_Recipesearch
#Gadget_Recipeview_Exitprogram
#Gadget_Recipeview_sMessage
#Gadget_Recipeview_sCurrent
#Gadget_Recipeview_sRecords
EndEnumeration
#GadgetIndex = #PB_Compiler_EnumerationValue
;- Image Constants
Enumeration 1
#Image_Recipeview_Getdirectory
#Image_Recipeview_Printrecipe
#Image_Recipeview_Showhelp
#Image_Recipeview_Exitprogram
EndEnumeration
#ImageIndex = #PB_Compiler_EnumerationValue
;- Load Images
CatchImage(#Image_Recipeview_Getdirectory, ?_OPT_Recipeview_Getdirectory)
CatchImage(#Image_Recipeview_Printrecipe, ?_OPT_Recipeview_Printrecipe)
CatchImage(#Image_Recipeview_Showhelp, ?_OPT_Recipeview_Showhelp)
CatchImage(#Image_Recipeview_Exitprogram, ?_OPT_Recipeview_Exitprogram)
; Data section
DataSection
_OPT_Recipeview_Getdirectory: : IncludeBinary "Images\_54x54\Open.Png"
_OPT_Recipeview_Printrecipe: : IncludeBinary "Images\_54x54\Print.png"
_OPT_Recipeview_Showhelp: : IncludeBinary "Images\_54x54\Help.Png"
_OPT_Recipeview_Exitprogram: : IncludeBinary "Images\_54x54\Exit.png"
EndDataSection
; Encapsulated window code
Procedure.i Window_Recipeview()
If OpenWindow(#Window_Recipeview, 59, 68, 1195, 785, "Simple recipe finder", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered|#PB_Window_Invisible)
ListIconGadget(#Gadget_Recipeview_Recipenames, 5, 5, 290, 670, "Recipe name", 260, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
AddGadgetColumn(#Gadget_Recipeview_Recipenames, 1, "Directory", 0)
SetGadgetFont(#Gadget_Recipeview_Recipenames, LoadFont(#Gadget_Recipeview_Recipenames, "Segoe Print", 10, 0))
WebGadget(#Gadget_Recipeview_Recipeview, 300, 5, 890, 670, "")
ContainerGadget(#Gadget_Recipeview_cControl, 5, 680, 1185, 70, #PB_Container_BorderLess)
ImageGadget(#Gadget_Recipeview_Getdirectory, 5, 5, 54, 54, ImageID(#Image_Recipeview_Getdirectory))
ImageGadget(#Gadget_Recipeview_Printrecipe, 65, 5, 54, 54, ImageID(#Image_Recipeview_Printrecipe))
ImageGadget(#Gadget_Recipeview_Showhelp, 125, 5, 54, 54, ImageID(#Image_Recipeview_Showhelp))
StringGadget(#Gadget_Recipeview_Recipedirectory, 295, 5, 815, 25, "", #PB_String_ReadOnly|#PB_String_BorderLess)
SetGadgetColor(#Gadget_Recipeview_Recipedirectory, #PB_Gadget_BackColor, $D8D8D8)
SetGadgetFont(#Gadget_Recipeview_Recipedirectory, LoadFont(#Gadget_Recipeview_Recipedirectory, "Segoe Print", 10, 0))
StringGadget(#Gadget_Recipeview_Recipecategory, 295, 35, 255, 25, "", #PB_String_ReadOnly|#PB_String_BorderLess)
SetGadgetColor(#Gadget_Recipeview_Recipecategory, #PB_Gadget_BackColor, $D8D8D8)
SetGadgetFont(#Gadget_Recipeview_Recipecategory, LoadFont(#Gadget_Recipeview_Recipecategory, "Segoe Print", 10, 0))
StringGadget(#Gadget_Recipeview_Recipesubcategory, 560, 35, 255, 25, "", #PB_String_ReadOnly|#PB_String_BorderLess)
SetGadgetColor(#Gadget_Recipeview_Recipesubcategory, #PB_Gadget_BackColor, $D8D8D8)
SetGadgetFont(#Gadget_Recipeview_Recipesubcategory, LoadFont(#Gadget_Recipeview_Recipesubcategory, "Segoe Print", 10, 0))
StringGadget(#Gadget_Recipeview_Recipesearch, 825, 35, 285, 25, "", #PB_String_BorderLess)
SetGadgetFont(#Gadget_Recipeview_Recipesearch, LoadFont(#Gadget_Recipeview_Recipesearch, "Segoe Print", 10, 0))
ImageGadget(#Gadget_Recipeview_Exitprogram, 1120, 5, 54, 54, ImageID(#Image_Recipeview_Exitprogram))
CloseGadgetList()
ContainerGadget(#Gadget_Recipeview_cStatusbar, 5, 755, 1185, 25, #PB_Container_BorderLess)
StringGadget(#Gadget_Recipeview_sStatus, 0, 5, 110, 20, "", #PB_String_ReadOnly|#PB_String_BorderLess)
SetGadgetFont(#Gadget_Recipeview_sStatus, LoadFont(#Gadget_Recipeview_sStatus, "Segoe Print", 9, 0))
StringGadget(#Gadget_Recipeview_sMessage, 115, 5, 835, 20, "", #PB_String_ReadOnly|#PB_String_BorderLess)
SetGadgetFont(#Gadget_Recipeview_sMessage, LoadFont(#Gadget_Recipeview_sMessage, "Segoe Print", 9, 0))
StringGadget(#Gadget_Recipeview_sCurrent, 955, 5, 110, 20, "", #PB_String_ReadOnly|#PB_String_BorderLess)
SetGadgetFont(#Gadget_Recipeview_sCurrent, LoadFont(#Gadget_Recipeview_sCurrent, "Segoe Print", 9, 0))
StringGadget(#Gadget_Recipeview_sRecords, 1070, 5, 110, 20, "", #PB_String_ReadOnly|#PB_String_BorderLess)
SetGadgetFont(#Gadget_Recipeview_sRecords, LoadFont(#Gadget_Recipeview_sRecords, "Segoe Print", 9, 0))
CloseGadgetList()
HideWindow(#Window_Recipeview, 0)
ProcedureReturn WindowID(#Window_Recipeview)
EndIf
EndProcedure
; My personal constants, declarations etc
Declare RemoveBorders(GadgetConstant.i) ; Remove borders from various gadgets
; Program helpers
Declare GetRecipeDirectory() ; Scan recipe directory and load filenames
Declare LoadLastDirectory() ; Load the last directory used
Declare SaveLastDirectory() ; Save the last directory scanned
Declare SetInfoBarArea(FieldName.s, FieldStatus.s = "##Error##", MessageContent.s = "0", ModuleName.s = #Empty$) ; Handle the fake statusbar area messages
;
Declare SearchEngine(Searchpath.s) ; Search and list recipes from a directory
Declare SearchRecipes() ; Search recipes in linked list and display matches
Declare ShowRecipe() ; Load the recipe into the webgadget to display it
; My personal constants
#Author = "Srod's underpants" ; Author's name
#CopyRight = "Big Smeghead productions 2018 " ; Copyright holder
#Basename = "RecipeView " ; Base name for initialisation file and database
#Version = "v0.00." ; Program version
#Program = #Basename + #Version ; Copyright string
#SystrayNote = "Hello, "+ #Program + " is hiding here" ; System tray note
;
#Fish = "<°)))o><²³ " ; Beware the fish!!
#AtTheEndOfTheList = -1 ;
#FirstItemInList = 0 ;
#NoFileCreated = 0 ;
#NoFileFound = -1 ;
#NoFileRead = 0 ;
#FileIsDirectory = -2 ;
;
Structure ProgramData ;
QuitValue.i ;
CurrentDirectory.s ;
LastSelectedRecipe.i ;
CompileCounters.s ; Compiler and build counter
; Dealing with search cues in search boxes
SearchCueFont.i ; Searchbox cue font
SearchNormalFont.i ; Searchbox normal font
SearchCueText.s ; The cue text to be passed to search windows
SearchFileMarker.s ;
EndStructure ;
;
Structure RecipeNames ;
Recipename.s ;
RecipeCategory.s ;
EndStructure ;
;
Global Program.ProgramData ;
Global NewList Recipes.RecipeNames() ;
Global NewList FoundDirectories.s() ; List of dirs found by the search engine
; Create your program directories
Program\CompileCounters = Str(#PB_Editor_CompileCount) + "." + Str(#PB_Editor_BuildCount) + "a" ; Add to program version
; Initial program window quit state
Program\QuitValue = #False ; Initial program quit value
Program\CurrentDirectory.s = GetCurrentDirectory() ;
Program\SearchFileMarker.s = Program\CurrentDirectory.s + "LastDirectorySearched.txt" ;
; Setup the search box cue fonts
Program\SearchCueFont = LoadFont(#PB_Any, "Georgia", 10, #PB_Font_Italic) ; Empty search cue font
Program\SearchNormalFont = LoadFont(#PB_Any, "Segoe Print", 10, 0) ; Filled cue box font
Program\SearchCueText.s = Space(256) ; Set the cue text buffer
PokeS(@Program\SearchCueText, "Type your search string in here", -1, #PB_Unicode) ;
; Program shortcut keys
Enumeration #GadgetIndex ;
#StartSearching ;
EndEnumeration ;
; Generic procedures
; Remove borders from various gadgets
Procedure RemoveBorders(GadgetConstant.i)
; Get the gadget type from the passed gadget constant
GadgetType.i = GadgetType(GadgetConstant.i)
; Select the gadget type
Select GadgetType.i
; Do the below if it is a ListIconGadget
Case #PB_GadgetType_ListIcon
; Remove borders from ListIconGadgets
OldStyle.i = GetWindowLongPtr_(GadgetID(GadgetConstant.i), #GWL_EXSTYLE)
NewStyle.i = OldStyle.i & ( ~ #WS_EX_CLIENTEDGE)
SetWindowLongPtr_(GadgetID(GadgetConstant.i), #GWL_EXSTYLE, NewStyle.i)
SetWindowPos_(GadgetID(GadgetConstant.i), 0, 0, 0, 0, 0, #SWP_SHOWWINDOW | #SWP_NOSIZE | #SWP_NOMOVE | #SWP_FRAMECHANGED)
Case #PB_GadgetType_Editor
; Remove border from editorgadget (comment) field. Stiil leaves a 1 pixel border but that looks good here
; SetWindowLongPtr_(GadgetID(GadgetConstant.i), #GWL_EXSTYLE, GetWindowLongPtr_(GadgetID(GadgetConstant.i), #GWL_EXSTYLE) & (~#WS_EX_CLIENTEDGE))
; SetWindowPos_(GadgetID(GadgetConstant.i), 0, 0, 0, 0, 0, #SWP_SHOWWINDOW | #SWP_NOSIZE | #SWP_NOMOVE | #SWP_FRAMECHANGED)
;
OldStyle.i = GetWindowLongPtr_(GadgetID(GadgetConstant.i), #GWL_EXSTYLE)
NewStyle.i = OldStyle.i & ( ~ #WS_EX_CLIENTEDGE)
SetWindowLongPtr_(GadgetID(GadgetConstant.i), #GWL_EXSTYLE, NewStyle.i)
SetWindowTheme_(GadgetID(GadgetConstant.i), @null.w, @null.w)
; SetWindowPos_(GadgetID(1), 0, 0, 0, 0, 0, #SWP_SHOWWINDOW | #SWP_NOSIZE | #SWP_NOMOVE | #SWP_FRAMECHANGED) ; required for this to work on my Win98
; -- End removing border from EditorGadget --
EndSelect
EndProcedure
; Program helpers
; Scan recipe directory and load filenames
Procedure GetRecipeDirectory()
; Get the pdf recipe directory that we need to scan
Recipespath.s = PathRequester("What directory to search?", "D:\smeg\Documents\Underpants (Bollocks)\Cooking & Recipes\")
If Recipespath.s <> #Empty$
ClearGadgetItems(#Gadget_Recipeview_Recipenames)
SetGadgetText(#Gadget_Recipeview_Recipedirectory, Recipespath.s)
; Add the recipe names to a linked list with their category name
SearchEngine(Recipespath.s)
; Add the directory name to the form and save it to an ini file
Else
; The user cancelled the operation
EndIf
EndProcedure
; Load the last directory used
Procedure LoadLastDirectory()
FileSeeker.i = FileSize(Program\SearchFileMarker.s)
If FileSeeker.i <> #NoFileFound Or FileSeeker.i <> #FileIsDirectory
CheckLastUsed.i = ReadFile(#PB_Any, Program\SearchFileMarker.s)
If CheckLastUsed.i <> #NoFileRead
Recipespath.s = ReadString(CheckLastUsed.i)
If Recipespath.s <> #Empty$
LastUsedDirectory.i = FileSize(Recipespath.s)
If LastUsedDirectory.i = #FileIsDirectory
SetGadgetText(#Gadget_Recipeview_Recipedirectory, Recipespath.s)
SearchEngine(Recipespath.s)
Else
; Last used recipe directory cannot be found
EndIf
Else
; The last used recipe directory is empty
EndIf
CloseFile(CheckLastUsed.i)
Else
; Can't open the last used file marker
EndIf
Else
; Can't find the last used file marker
EndIf
EndProcedure
; Save the last directory scanned
Procedure SaveLastDirectory()
Recipespath.s = GetGadgetText(#Gadget_Recipeview_Recipedirectory)
If Recipespath.s <> #Empty$
SaveFile.i = CreateFile(#PB_Any, Program\SearchFileMarker.s)
If SaveFile.i <> #NoFileCreated
WriteString(SaveFile.i, Recipespath.s)
CloseFile(SaveFile.i)
Else
; Last used recipe path marker was not created
EndIf
Else
; No recipes path to save
EndIf
EndProcedure
; Handle the fake statusbar area messages
Procedure SetInfoBarArea(FieldName.s, FieldStatus.s = "##Error##", MessageContent.s = "0", ModuleName.s = #Empty$)
; Select the name of the field to put our heading string
Select FieldName.s
; Select the correct heading by the status field
Case "Headings"
Select FieldStatus.s
Case "Welcome"
MessageHeader.s = "Welcome"
Colour.i = $615E5F
Case "Info"
MessageHeader.s = "Information"
Colour.i = $DB3D24
Case "Warn"
MessageHeader.s = "Warning"
Colour.i = $7D1F82
Case "Tool"
MessageHeader.s = "Tooltip"
Colour.i = $FF0000
EndSelect
; Send all the strings to the fake status bar area
SetGadgetText(#Gadget_Recipeview_sStatus, MessageHeader.s)
SetGadgetText(#Gadget_Recipeview_sMessage, MessageContent.s)
SetGadgetColor(#Gadget_Recipeview_sStatus, #PB_Gadget_FrontColor, Colour.i)
Case "Current"
SetGadgetText(#Gadget_Recipeview_sCurrent, "Recipe " + MessageContent.s)
Case "Records"
; Figure out the correct spelling for the record field for singles or multiples
If Val(MessageContent.s) = 0
RecordHeader.s = "Recipes"
ElseIf Val(MessageContent.s) = 1
RecordHeader.s = "Recipe"
ElseIf Val(MessageContent.s) > = 2
RecordHeader.s = "Recipes"
EndIf
; Set the record number details in the fake status bar area
SetGadgetText(#Gadget_Recipeview_sRecords, FormatNumber(ValD(MessageContent.s), 0, ".", ",") + " " + RecordHeader.s)
EndSelect
EndProcedure
; Recipe related procedures
; Search and list recipes from a directory
Procedure SearchEngine(Searchpath.s)
PseudoCounter.i = 0
ClearList(FoundDirectories.s())
If Searchpath.s <> #Empty$
If Right(Searchpath.s, 1) = "\"
Searchpath.s = Left(Searchpath.s, Len(Searchpath.s) - 1)
EndIf
AddElement(FoundDirectories.s())
FoundDirectories.s() = Searchpath.s
Index.i = 0
Repeat
SelectElement(FoundDirectories.s(), Index.i)
Directory.i = ExamineDirectory(#PB_Any, FoundDirectories.s(), "*.*")
If Directory.i
Path.s = FoundDirectories.s() + "\"
While NextDirectoryEntry(Directory.i)
Filename.s = DirectoryEntryName(Directory.i)
Select DirectoryEntryType(Directory.i)
Case #PB_DirectoryEntry_File
If LCase(GetExtensionPart(Filename.s)) = "pdf"
CurrentRecipeName.s = Left(Filename.s, Len(Filename.s) - Len(GetExtensionPart(Filename.s)) - 1)
CurrentCategory.s = Path.s
If Len(CurrentRecipeName.s) And Len(CurrentCategory.s)
AddGadgetItem(#Gadget_Recipeview_Recipenames, #AtTheEndOfTheList, CurrentRecipeName.s + #LF$ + Path.s)
PseudoCounter.i + 1
AddElement(Recipes())
Recipes()\Recipename.s = CurrentRecipeName.s
Recipes()\RecipeCategory.s = CurrentCategory.s
Else
; Recipe name or directory is empty
EndIf
;
Else
; This isn't a PDF file so ignore it
EndIf
Case #PB_DirectoryEntry_Directory
Filename.s = DirectoryEntryName(Directory.i)
If Filename.s <> ".." And Filename.s <> "."
AddElement(FoundDirectories())
FoundDirectories() = Path.s + Filename.s
EndIf
EndSelect
Wend
FinishDirectory(Directory.i)
EndIf
Index.i + 1
Until Index.i > ListSize(FoundDirectories()) -1
EndIf
If CountGadgetItems(#Gadget_Recipeview_Recipenames)
SetGadgetState(#Gadget_Recipeview_Recipenames, #FirstItemInList)
SetGadgetItemState(#Gadget_Recipeview_Recipenames, #FirstItemInList, #PB_ListIcon_Selected)
SetInfoBarArea("Records", #Empty$, Str(CountGadgetItems(#Gadget_Recipeview_Recipenames)))
PostEvent(#PB_Event_Gadget, #Window_Recipeview, #Gadget_Recipeview_Recipenames, #PB_EventType_Change)
Else
; There were no PDF recipes files found in the directory
EndIf
EndProcedure
; Search recipes in linked list and display matches
Procedure SearchRecipes()
If GetActiveGadget() = #Gadget_Recipeview_Recipesearch
PseudoCounter.i = 0
SearchText.s = LCase(GetGadgetText(#Gadget_Recipeview_Recipesearch))
If Len(SearchText.s)
ClearGadgetItems(#Gadget_Recipeview_Recipenames)
SetGadgetText(#Gadget_Recipeview_Recipesearch, #Empty$)
If Left(SearchText.s, 2) = "//"
ForEach Recipes()
SearchText.s = RemoveString(SearchText.s, "//", #PB_String_NoCase, 1)
If FindString(Recipes()\RecipeCategory.s, SearchText.s, 1, #PB_String_NoCase) <> #False
AddGadgetItem(#Gadget_Recipeview_Recipenames, #AtTheEndOfTheList, Recipes()\Recipename.s + #LF$ + Recipes()\RecipeCategory.s)
PseudoCounter.i + 1
Else
; No string match so don't display this line
EndIf
Next
Else
ForEach Recipes()
If FindString(Recipes()\Recipename.s, SearchText.s, 1, #PB_String_NoCase) <> #False
AddGadgetItem(#Gadget_Recipeview_Recipenames, #AtTheEndOfTheList, Recipes()\Recipename.s + #LF$ + Recipes()\RecipeCategory.s)
PseudoCounter.i + 1
Else
; No string match so don't display this line
EndIf
Next
EndIf
Else
; No search text so do not proceed
EndIf
Else
; Nothing to do as Returnw asn't pressed from the search bar
EndIf
If CountGadgetItems(#Gadget_Recipeview_Recipenames)
SetGadgetState(#Gadget_Recipeview_Recipenames, #FirstItemInList)
SetGadgetItemState(#Gadget_Recipeview_Recipenames, #FirstItemInList, #PB_ListIcon_Selected)
SetInfoBarArea("Records", #Empty$, Str(CountGadgetItems(#Gadget_Recipeview_Recipenames)))
PostEvent(#PB_Event_Gadget, #Window_Recipeview, #Gadget_Recipeview_Recipenames, #PB_EventType_Change)
Else
; There were no PDF recipes files found in the directory
EndIf
EndProcedure
; Load the recipe into the webgadget to display it
Procedure ShowRecipe()
CurrentLine.i = GetGadgetState(#Gadget_Recipeview_Recipenames)
If CurrentLine.i >= 0
Program\LastSelectedRecipe.i = CurrentLine.i
RecipeName.s = GetGadgetItemText(#Gadget_Recipeview_Recipenames, CurrentLine.i, 0) ;: Debug RecipeName.s
RecipePath.s = GetGadgetItemText(#Gadget_Recipeview_Recipenames, CurrentLine.i, 1) ;: Debug RecipePath.s
If RecipePath.s + RecipeName.s
SetInfoBarArea("Current", #Empty$, Str(CurrentLine.i))
NumberOfSeparators.i = CountString(RecipePath.s, "\")
If NumberOfSeparators.i > 1
SetGadgetText(#Gadget_Recipeview_Recipecategory, StringField(RecipePath.s, NumberOfSeparators.i - 1, "\"))
SetGadgetText(#Gadget_Recipeview_Recipesubcategory, StringField(RecipePath.s, NumberOfSeparators.i, "\"))
ElseIf NumberOfSeparators.i = 1
SetGadgetText(#Gadget_Recipeview_Recipecategory, StringField(RecipePath.s, NumberOfSeparators.i, "\"))
SetGadgetText(#Gadget_Recipeview_Recipesubcategory, #Empty$)
Else
SetGadgetText(#Gadget_Recipeview_Recipecategory, #Empty$)
SetGadgetText(#Gadget_Recipeview_Recipesubcategory, #Empty$)
EndIf
SetGadgetText(#Gadget_Recipeview_Recipeview, RecipePath.s + RecipeName.s + ".pdf")
SetActiveGadget(#Gadget_Recipeview_Recipenames)
SetGadgetState(#Gadget_Recipeview_Recipenames, Program\LastSelectedRecipe.i)
SetGadgetItemState(#Gadget_Recipeview_Recipenames, Program\LastSelectedRecipe.i, #PB_ListIcon_Selected)
Else
; The recipe path and recipe name were empty
EndIf
Else
; There is no current line to display
EndIf
EndProcedure
; Main event handler
If Window_Recipeview()
;//
Program\QuitValue = #False
;// Add keyboard shortcuts
AddKeyboardShortcut(#Window_Recipeview, #PB_Shortcut_Return, #StartSearching)
;// Remove the ListIconGadget borders
RemoveBorders(#Gadget_Recipeview_Recipenames)
;// Limit the number of search box characters and set the cue banner text. These variables are set in the MyStuff_Myconstants file.
SendMessage_(GadgetID(#Gadget_Recipeview_Recipesearch), #EM_SETLIMITTEXT, 67, 0)
SendMessage_(GadgetID(#Gadget_Recipeview_Recipesearch), #EM_SETCUEBANNER, 1, Program\SearchCueText)
;// Set initial search string font to be italic font
SetGadgetFont(#Gadget_Recipeview_Recipesearch, FontID(Program\SearchCueFont))
;// Load the recipes from the last used recipe directory
LoadLastDirectory()
;// Setup initial welcome dialogues in the fake statusbar area
SetInfoBarArea("Headings", "Welcome", "Welcome to " + #Fish + #Basename + #Version + Program\CompileCounters + ", Have a nice day")
SetInfoBarArea("Current", #Empty$, "0")
SetInfoBarArea("Records", #Empty$, Str(CountGadgetItems(#Gadget_Recipeview_Recipenames)))
;// Main event handler
Repeat
EventID = WaitWindowEvent()
MenuID = EventMenu()
GadgetID = EventGadget()
WindowID = EventWindow()
Select EventID
Case #PB_Event_CloseWindow
Select WindowID
Case #Window_Recipeview : Program\QuitValue = #True
EndSelect
Case #PB_Event_Menu
Select MenuID
Case #StartSearching : SearchRecipes()
EndSelect
Case #PB_Event_Gadget
Select GadgetID
Case #Gadget_Recipeview_Recipenames
Select EventType()
Case #PB_EventType_Change : ShowRecipe()
EndSelect
Case #Gadget_Recipeview_Getdirectory
Select EventType()
Case #PB_EventType_LeftClick : GetRecipeDirectory()
EndSelect
Case #Gadget_Recipeview_Printrecipe : ; PrintSelectedRecipe()
Case #Gadget_Recipeview_Showhelp : ; ShowProgramHelp()
Case #Gadget_Recipeview_Exitprogram : Program\QuitValue = #True
EndSelect
EndSelect
Until Program\QuitValue
SaveLastDirectory()
CloseWindow(#Window_Recipeview)
EndIf
End