PB_Gadget_SetOpenFinderFiles() is broken

Mac OSX specific forum
Wolfram
Enthusiast
Enthusiast
Posts: 604
Joined: Thu May 30, 2013 4:39 pm

PB_Gadget_SetOpenFinderFiles() is broken

Post by Wolfram »

If I try my programs on macOS 11 (Big Sur) the PB_Gadget_SetOpenFinderFiles() function works not as on older OS versions.
Normally I can start my program by double click on a file or drop a file on the program and the programs loads the file after it is started.
On macOS 11 and later the program starts, but dose't load the file.
If the program is already started and I double click on a file it is loaded.
macOS Catalina 10.15.7
User avatar
mk-soft
Always Here
Always Here
Posts: 6201
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by mk-soft »

I had a look at this in the Purebasic IDE, where it also works.
There are some rules to be observed and entries still have to be made in the info.plist.

Example:

Code: Select all

;-TOP

#ProgramTitle = "Main Window - Drop Files"
#ProgramVersion = "v1.01.2"

ImportC ""
  PB_Gadget_SetOpenFinderFiles(*Callback)
EndImport

Enumeration Windows
  #Main
EndEnumeration

Enumeration MenuBar
  #MainMenu
EndEnumeration

Enumeration MenuItems
  #MainMenuAbout
  #MainMenuExit
EndEnumeration

Enumeration Gadgets
  #MainList
EndEnumeration

Enumeration StatusBar
  #MainStatusBar
EndEnumeration

; ----

Enumeration CustomEvent #PB_Event_FirstCustomValue
  #MyEvent_OpenFiles
EndEnumeration
  
Global NewList OpenFilesCommandLine.s()

ProcedureC OpenDocument(*FilesUTF8)
  Protected Files$, File$, k
  ; Files are separated by a tab
  ;
  Files$ = PeekS(*FilesUTF8, -1, #PB_UTF8)
  
  Repeat
    File$ = StringField(Files$, k+1, #TAB$) ; index is 1 based
    If File$ <> ""
      If FileSize(File$) >= 0 ; no directories here...
        Debug "passed file: "+File$
        
        ; Use the queue, as loading a document from this callback crash the IDE (probably because we do GUI operations in startup callback
        ; It will be loaded in the main loop
        LastElement(OpenFilesCommandLine())
        AddElement(OpenFilesCommandLine())  ; will cause this file to be loaded when the IDE is ready for it
        OpenFilesCommandLine() = File$
      EndIf
      k+1
    EndIf
  Until File$ = ""
  PostEvent(#MyEvent_OpenFiles)
  
EndProcedure

; ----

Procedure GetCommandLineFiles()
  Protected cnt, index, file.s
  cnt = CountProgramParameters()
  For index = 0 To cnt - 1
    file = ProgramParameter(index)
    If file <> ""
      AddElement(OpenFilesCommandLine())
      OpenFilesCommandLine() = file
    EndIf
  Next
EndProcedure

; ----

Procedure UpdateWindow()
  Protected dx, dy
  dx = WindowWidth(#Main)
  dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
  ; Resize gadgets
  ResizeGadget(#MainList, 0, 0, dx, dy)
EndProcedure

Procedure Main()
  Protected dx, dy
  
  ; Set before first OpenWindow
  PB_Gadget_SetOpenFinderFiles(@OpenDocument())
    
  #MainStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 800, 600, #ProgramTitle , #MainStyle)
    ; Menu
    CreateMenu(#MainMenu, WindowID(#Main))
    MenuTitle("&File")
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      MenuItem(#PB_Menu_About, "")
    CompilerElse
      MenuItem(#MainMenuAbout, "About")
    CompilerEndIf
    ; Menu File Items
    
    CompilerIf Not #PB_Compiler_OS = #PB_OS_MacOS
      MenuBar()
      MenuItem(#MainMenuExit, "E&xit")
    CompilerEndIf
    
    ; StatusBar
    CreateStatusBar(#MainStatusBar, WindowID(#Main))
    AddStatusBarField(#PB_Ignore)
    
    ; Gadgets
    dx = WindowWidth(#Main)
    dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
    ListViewGadget(#MainList, 0, 0, dx, dy)
    
    ; Bind Events
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #Main)
    
    ;GetCommandLineFiles()
    
    ForEach OpenFilesCommandLine()
      AddGadgetItem(#MainList, -1, OpenFilesCommandLine())
    Next
    ClearList(OpenFilesCommandLine())
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case #Main
              Break
              
          EndSelect
          
        Case #PB_Event_Menu
          Select EventMenu()
            CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
              Case #PB_Menu_About
                PostEvent(#PB_Event_Menu, #Main, #MainMenuAbout)
                
              Case #PB_Menu_Preferences
                
              Case #PB_Menu_Quit
                PostEvent(#PB_Event_CloseWindow, #Main, #Null)
                
            CompilerEndIf
              
            Case #MainMenuExit
              PostEvent(#PB_Event_CloseWindow, #Main, #Null)
              
            Case #MainMenuAbout
              MessageRequester("About", #ProgramTitle + #LF$ + #ProgramVersion, #PB_MessageRequester_Info)
              
          EndSelect
          
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #MainList
              Select EventType()
                Case #PB_EventType_Change
                  ;
              EndSelect
              
          EndSelect
          
        Case #MyEvent_OpenFiles
          ForEach OpenFilesCommandLine()
            AddGadgetItem(#MainList, -1, OpenFilesCommandLine())
          Next
          ClearList(OpenFilesCommandLine())
          
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()

info.plist

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDocumentTypes</key>
  <array>
    <dict>
      <key>CFBundleTypeExtensions</key>
      <array>
        <string>pb</string>
        <string>pbi</string>
        <string>pbp</string>
      </array>
      <key>CFBundleTypeName</key>
      <string>MyDropFiles</string>
      <key>CFBundleTypeIconFile</key>
      <string>FileIcon.icns</string>
      <key>CFBundleTypeRole</key>
      <string>Editor</string>
    </dict>
  </array>
  <key>CFBundleDevelopmentRegion</key>
  <string>English</string>
  <key>CFBundleExecutable</key>
  <string>DropFiles</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundlePackageType</key>
  <string>APPL</string>
  <key>CFBundleSignature</key>
  <string>PURE</string>
  <key>CFBundleVersion</key>
  <string>0.1</string>
  <key>CSResourcesFileMapped</key>
  <true/>
  <key>NSHighResolutionCapable</key>
  <true/>
</dict>
</plist>
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by WilliamL »

mk-soft,

I really appreciate you're looking into this. It is very interesting to see the IDE example.

I've given some of my experience in this thread viewtopic.php?t=79365

The code you posted is essentially the same as Fred's original code. The ProcedureC OpenDocument(*FilesUTF8) callback is not triggered when the file is double clicked in my programs. If the program is running, dragging the file triggers the callback.

I've looked at your examples (both code and plist) and what I am using and I can't find any significant differences. The code worked for years.. now it doesn't so I don''t think it is a case of doing it wrong.

Your code obviously works in the IDE. It's a mystery to me.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
Piero
Addict
Addict
Posts: 862
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by Piero »

This works (based on mk-soft help)

Code: Select all

ImportC ""
   PB_Gadget_SetOpenFinderFiles(*Callback)
EndImport

Enumeration CustomEvent #PB_Event_FirstCustomValue
   #MyEvent_OpenFiles
EndEnumeration

Global NewList OpenFilesCommandLine.s()

ProcedureC OpenDocument(*FilesUTF8)
   Protected Files$, File$, k
   ; Files are separated by a tab
   Files$ = PeekS(*FilesUTF8, -1, #PB_UTF8)
   
   Repeat
      File$ = StringField(Files$, k+1, #TAB$) ; index is 1 based
      If File$ <> ""
         If FileSize(File$) >= 0 ; no directories here...
            LastElement(OpenFilesCommandLine())
            AddElement(OpenFilesCommandLine()) 
            OpenFilesCommandLine() = File$
         EndIf
         k+1
      EndIf
   Until File$ = ""
   PostEvent(#MyEvent_OpenFiles)
   
EndProcedure

; Set before first OpenWindow
PB_Gadget_SetOpenFinderFiles(@OpenDocument())

; Example:

If OpenWindow(0, 0, 0, 820, 620, "OpenFinderFiles", #PB_Window_SystemMenu | #PB_Window_ScreenCentered )
   
   EditorGadget(0, 10, 10, 800, 600)
   
   Repeat
      Select WaitWindowEvent()
         Case #MyEvent_OpenFiles
            ForEach OpenFilesCommandLine()
               AddGadgetItem(0, -1, OpenFilesCommandLine())
            Next
            ClearList(OpenFilesCommandLine()) ; Remember to clear the queue
         Case #PB_Event_CloseWindow
            end
      EndSelect
   Until EventMenu() = #PB_Menu_Quit
   
EndIf
Last edited by Piero on Wed Aug 16, 2023 4:13 am, edited 1 time in total.
User avatar
mk-soft
Always Here
Always Here
Posts: 6201
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by mk-soft »

But it won't work without adjusting the info.plist.

Edit and add this to info.plist inside <dict>

Code: Select all

<key>CFBundleDocumentTypes</key>
  <array>
    <dict>
      <key>CFBundleTypeExtensions</key>
      <array>
        <string>pb</string>
        <string>pbi</string>
        <string>pbp</string>
      </array>
      <key>CFBundleTypeName</key>
      <string>FinderFiles</string>
      <key>CFBundleTypeIconFile</key>
      <string>FileIcon.icns</string>
      <key>CFBundleTypeRole</key>
      <string>Editor</string>
    </dict>
  </array>
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by WilliamL »

Ok, I've spent a few hours on this...

I put Fred's original code before any Procedures but it still didn't work.

It appears that the call is made before my procedures to load the menus and preferences. I tried all ways of getting these procedures done before the OpenFiles call but with marginal success. But, in the end, I gave up.

I modified my program using a PostEvent(). These were some of the lines I added and they are from Piero's and mk-soft examples. (see their examples)

Code: Select all

Enumeration CustomEvent #PB_Event_FirstCustomValue
  #MyEvent_OpenFiles
EndEnumeration

PostEvent(#MyEvent_OpenFiles)

Case #MyEvent_OpenFiles
	LoadFile(filename$)
[These are not complete instructions of how to add the info.]

I would guess that the PostEvent method is the way to go and that is what I will use from now on.
Last edited by WilliamL on Tue Aug 15, 2023 5:32 pm, edited 1 time in total.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
Piero
Addict
Addict
Posts: 862
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by Piero »

WilliamL wrote: Mon Aug 14, 2023 9:28 pm I would guess
It seems to me that the problem was solved with this:

Code: Select all

        ; Use the queue, as loading a document from this callback crash the IDE
        ; (probably because we do GUI operations in startup callback)
        ; It will be loaded in the main loop
        LastElement(OpenFilesCommandLine())
        AddElement(OpenFilesCommandLine())  ; will cause this file to be loaded when the IDE is ready for it
        OpenFilesCommandLine() = File$
Last edited by Piero on Wed Aug 16, 2023 4:19 am, edited 1 time in total.
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by WilliamL »

mk-soft & Piero,

We agree that the loading should be done in the event loop. :wink:

Thank you. I wouldn't have been able to fix it without your help.

PS Using a NewList and disposing of it was perfect for this use.
Last edited by WilliamL on Wed Aug 16, 2023 5:39 pm, edited 2 times in total.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
Piero
Addict
Addict
Posts: 862
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by Piero »

WilliamL wrote: Mon Aug 14, 2023 10:55 pmThank you. I wouldn't have been able to fix it out without your help.
You are very welcome!
Thanks mk-soft! I will need openfinderfiles soon... :wink:
PS:
Let's all remember that you can change the app that will open your file via Get Info in Finder ("Change all" to set the default app that will open that kind of files)
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by WilliamL »

The code to load files double-clicked works great! What I can't figure out is if I just run the app how do I (for instance) go to a load routine? Since I have to go through the event loop once to see the #MyEvent_OpenFiles event I can't just go to the Load routine when I first run the program.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
Piero
Addict
Addict
Posts: 862
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: PB_Gadget_SetOpenFinderFiles() is broken

Post by Piero »

WilliamL wrote: Tue Sep 05, 2023 11:15 pm The code to load files double-clicked works great! What I can't figure out is if I just run the app how do I (for instance) go to a load routine? Since I have to go through the event loop once to see the #MyEvent_OpenFiles event I can't just go to the Load routine when I first run the program.
Huh? Do you mean load previously-opened-but-never-closed files like on the PB IDE? (mk-soft's IDE code can help you)

Otherwise, mk-soft will probably suggest you to open threads and clean the pool
Post Reply