Persistent Recent Files Menu

Share your advanced PureBasic knowledge/code with the community.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Persistent Recent Files Menu

Post by collectordave »

There are other ways of doing this just search the forum.

Just recently opened filkes added to the menu preseved in prefs file between sessions. As demo prgramme on how to use.

Code: Select all

Global Window_0,MainMenu.i

;Declare List To Hold Recent Filenames
Global NewList RecentFiles.s()

;Add recentfiles To the menu Enumeration
Enumeration FormMenu
  #mnuOpen
  #mnuRecentFiles
  #mnuRecentFile01
  #mnuRecentFile02
  #mnuRecentFile03
  #mnuRecentFile04
  #mnuExit
EndEnumeration

Procedure WriteRecentFileList()
  
  Define iLoop.i
  
    If OpenPreferences(GetCurrentDirectory() + "MyApp") = 0
   
    CreatePreferences(GetCurrentDirectory() + "MyApp")

    PreferenceGroup("RecentFiles")
    
    ClosePreferences()
    
  Else
  
      PreferenceGroup("RecentFiles")
      iLoop = 1
      ;Delete Old Group and Values
      RemovePreferenceGroup("RecentFiles")
      PreferenceGroup("RecentFiles")     
      ForEach (RecentFiles())
        WritePreferenceString("RecentFile" + Str(iLoop), RecentFiles())
        iLoop = iLoop + 1  
      Next
  
  ClosePreferences()
  
  EndIf

EndProcedure

Procedure SetMenus()
  
  ;Separate procefure to add the menu to the application
  
  Define iLoop.i
  
  If IsMenu(MainMenu)
    FreeMenu(MainMenu)
  EndIf
  
  MainMenu = CreateMenu(#PB_Any, WindowID(Window_0))
  MenuTitle("Files")
  MenuItem(#mnuOpen,"Open")
  
  ;Add Recent file list entries to menu If There are any
  If ListSize(RecentFiles()) > 0
    OpenSubMenu("Recent Files")
    FirstElement(RecentFiles())
    MenuItem(#mnuRecentFile01, RecentFiles())
    
    If NextElement(RecentFiles())
      MenuItem(#mnuRecentFile02, RecentFiles())  
    EndIf
    
    If NextElement(RecentFiles())
      MenuItem(#mnuRecentFile03, RecentFiles())  
    EndIf
    
    If NextElement(RecentFiles())
      MenuItem(#mnuRecentFile04, RecentFiles())     
    EndIf
      
    CloseSubMenu()
  Else
    ;No recent files so add place holder and disable
    MenuItem(#mnuRecentFiles,"Recent Files")
    DisableMenuItem(MainMenu, #mnuRecentFiles, #True)
  EndIf
  MenuItem(#mnuExit,"Exit")
     
EndProcedure

Procedure AddRecentFile(FileName.s)
  
  MaxFiles = 4
  
  ;Check for and remove duplicate entries
  ForEach recentfiles()
    
    If FileName = RecentFiles()
      DeleteElement(Recentfiles())     
    EndIf
    
  Next
  
  ;;Add this new entry at the start of the list
  FirstElement(Recentfiles())
  InsertElement(Recentfiles())
  RecentFiles() = FileName
  
  ;Remove last entry if required
  If ListSize(RecentFiles()) > MaxFiles 
    LastElement(Recentfiles())
    DeleteElement(Recentfiles())
  EndIf  
  
EndProcedure

Procedure ReadRecentFileList()
  
  Define PrefRet.s
  
    If OpenPreferences(GetCurrentDirectory() + "MyApp") = 0
   
    CreatePreferences(GetCurrentDirectory() + "MyApp")

    PreferenceGroup("RecentFiles")
    
    ClosePreferences()
    
  Else
    
    PreferenceGroup("RecentFiles")

      PrefRet = ReadPreferenceString("RecentFile4", "Empty")  
      If PrefRet <> "Empty"    
        AddRecentFile(PrefRet)
      EndIf
      PrefRet = ReadPreferenceString("RecentFile3", "Empty") 
       If PrefRet <> "Empty" 
        AddRecentFile(PrefRet)
      EndIf     
      PrefRet = ReadPreferenceString("RecentFile2", "Empty")
      If PrefRet <> "Empty"
        AddRecentFile(PrefRet)
      EndIf        
      PrefRet = ReadPreferenceString("RecentFile1", "Empty")
      If PrefRet <> "Empty"
        AddRecentFile(PrefRet)
      EndIf        
    
  EndIf
  
  
  
EndProcedure

Procedure.s ChooseFile()
  
  Define FileName.s
  
  Filename = OpenFileRequester("Please choose file to load", "C:\", "All Files (*.*)|*.*;", 0)
  If Filename
    
    AddRecentfile(Filename)
    ProcedureReturn FileName
    
  Else
    
    ProcedureReturn ""
    
  EndIf
  
  
EndProcedure

  Window_0 = OpenWindow(#PB_Any, 0, 0, 600, 400, "", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  ReadRecentFileList()
  Setmenus()
  
  Repeat
      
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_CloseWindow
           
        WriteRecentFileList()
        End
  
      Case #PB_Event_Menu
        Select EventMenu()
            
          Case #mnuOpen
            ChooseFile()

          Case #mnuRecentFile01
            
            Debug GetMenuItemText(MainMenu, #mnuRecentFile01)
            
          Case #mnuRecentFile02
 
            Debug GetMenuItemText(MainMenu, #mnuRecentFile02)
                        
          Case #mnuRecentFile03

            Debug GetMenuItemText(MainMenu, #mnuRecentFile03)                       
                        
          Case #mnuRecentFile04
 
            Debug GetMenuItemText(MainMenu, #mnuRecentFile04)                       
             
          Case #mnuExit
            
            WriteRecentFileList()
            End
            
Regards

CD
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Persistent Recent Files Menu

Post by Dude »

Just a tip, the following code is prone to failure:

Code: Select all

OpenPreferences(GetCurrentDirectory()+"MyApp")
This is because GetCurrentDirectory() doesn't always return the path to your app, as it will change when another app uses the SetCurrentDirectory API (be it your app, or another third-party app on your PC).

You need to use this instead if you want the actual path to your app:

Code: Select all

Global appfolder$=GetPathPart(ProgramFilename())
OpenPreferences(appfolder$+"MyApp")
Then you can use appfolder$ everywhere in your app to point to your app's actual folder.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Persistent Recent Files Menu

Post by collectordave »

Ah!

Does that work on Linux and MAC as well? Noticed some weird behaviour on Linux when creating a link.

Regards

CD

PS Just looked in help and it says it does. Will be using in future.

Thanks
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Persistent Recent Files Menu

Post by collectordave »

Looking at recent files again came up with the following code.

I realised that EventMenu() just returns a menu item number set when creating the menu.

So after enumerating my standard menu items I just choose a number larger than this to list my recent files.

A second thought was that I am only interested in the filename not the number so when opening a file the filerequester is only used when no filename provided.

You can have as many recent files as you wish (there will be limits so be careful).

When using you just need to write a procedure to manage the recent files list.

They can still be persisted in preferences or, as I do, write the list out to a json file (seems quicker and easier to me)

Then when loading your application load the list again.

Code: Select all

Global frmMain,mnuMain

Global btnDone

Enumeration FormMenu
  #mnuNew
  #mnuOpen
  #mnuSave
  #mnuRecentFiles
  #mnuSep1
  #mnuQuit
EndEnumeration

Global NewList RecentFiles.s()

Procedure OpenThisFile(FileName.s)
  
  If FileName = ""
    
    ;OpenFileRequester()
    
  EndIf
  
  Debug FileName

EndProcedure

Procedure SetMenu()
  
  Define iLoop.i = 100
  
  If IsMenu(mnuMain)
    FreeMenu(mnuMain)
  EndIf
  
  
  mnuMain = CreateMenu(#PB_Any, WindowID(frmMain))
  MenuTitle("Files")
  MenuItem(#mnuNew, "New")
  MenuItem(#mnuOpen, "Open")
  MenuItem(#mnuSave, "Save")
  If ListSize(RecentFiles()) > 0
    OpenSubMenu("Recent Files")
    ForEach RecentFiles()
      MenuItem(iLoop, RecentFiles())
      iLoop = iLoop + 1
    Next
    CloseSubMenu()

  Else  
    MenuItem(#mnuRecentFiles, "Recent Files")
  EndIf
  MenuBar()
  MenuItem(#mnuQuit, "Quit")
  
  If ListSize(RecentFiles()) = 0
    DisableMenuItem(mnuMain,#mnuRecentFiles,#True)
  EndIf
  
  
EndProcedure

frmMain = OpenWindow(#PB_Any, 0, 0, 480, 140, "", #PB_Window_SystemMenu)
btnDone = ButtonGadget(#PB_Any, 390, 100, 80, 30, "Done")

;Just make up a few file names
For iLoop = 1 To 10

  AddElement(RecentFiles())
  RecentFiles() = "File Number " + Str(iLoop)

Next iLoop

Setmenu()

Repeat
    
  Event = WaitWindowEvent()
    
  Select Event
    Case #PB_Event_CloseWindow
      End

    Case #PB_Event_Menu
      Select EventMenu()
        Case #mnuNew
        Case #mnuOpen
          OpenThisFile("")
        Case #mnuSave
        Case #mnuRecentFiles
        Case #mnuSep1
        Case #mnuQuit
          End
        Default
          
          OpenThisFile(GetMenuItemText(mnuMain,EventMenu()))
          
      EndSelect

    Case #PB_Event_Gadget
      Select EventGadget()
      EndSelect
  EndSelect
  
ForEver
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
Post Reply