COCOA translation

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

COCOA translation

Post by Wolfram »

Can someone translate this to PB?

Code: Select all

[panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result)
Thanks!
macOS Catalina 10.15.7
True29
User
User
Posts: 64
Joined: Sun Feb 03, 2013 1:50 am

Re: COCOA translation

Post by True29 »

wich Effekt has this line @ Cocoa ? so we can write the code.
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: COCOA translation

Post by Shardik »

Wolfram wrote:Can someone translate this to PB?

Code: Select all

[panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result)
Thanks!
The easiest way to implement a CompletionHandler is to use Wilbert's excellent NSBlock Module. Take a look into the following example which initializes an NSOpenPanel and opens it as a sheet in an existing window. The CompletionHandler uses an NSBlock and a callback to send the result (selected button in the panel) with PostEvent() into PB's event loop where the selected button and the selected files are evaluated and displayed.

Code: Select all

EnableExplicit

#Event_OpenFilePanel_Closed = #PB_Event_FirstCustomValue
#NSCancelButton = 0
#NSOKButton     = 1

; NSBlock module from Wilbert:
; http://www.purebasic.fr/english/viewtopic.php?p=467818#p467818

DeclareModule NSBlock
 
  Structure NSBlock
    *isa
    flags.l
    reserved.l
    *invoke
    *descriptor
  EndStructure
 
  Structure NSBlockWithPtr
    *block.NSBlock
    _block.NSBlock
  EndStructure
 
  Declare InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
 
EndDeclareModule

Module NSBlock
 
  Global.i NSConcreteGlobalBlock, NSConcreteStackBlock, DyLib
 
  DyLib = OpenLibrary(#PB_Any, "libSystem.dylib")
  If DyLib
    NSConcreteGlobalBlock = GetFunction(DyLib, "_NSConcreteGlobalBlock")
    NSConcreteStackBlock = GetFunction(DyLib, "_NSConcreteStackBlock")   
    CloseLibrary(DyLib)
  EndIf
 
  If Not NSConcreteGlobalBlock
    MessageRequester("Error", "Unable to access _NSConcreteGlobalBlock symbol")
    End
  EndIf
 
  DataSection
    NSBlockDescriptor:
    Data.i 0, SizeOf(NSBlock), 0, 0
  EndDataSection
 
  Procedure InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
    *NSBlockWithPtr\block = @*NSBlockWithPtr\_block
    With *NSBlockWithPtr\_block
      If IsGlobal
        \isa = NSConcreteGlobalBlock
        \flags = $30000000
      Else
        \isa = NSConcreteStackBlock
        \flags = $20000000
      EndIf
      \invoke = *Invoke
      \descriptor = ?NSBlockDescriptor
    EndWith
  EndProcedure
 
EndModule

; *** End of NSBlock module ***

; ----- Use NSBlock module from Wilbert
UseModule NSBlock

ProcedureC BlockHandler(*Block.NSBlock, Result.I)
  PostEvent(#Event_OpenFilePanel_Closed, 0, 0, 0, Result)
EndProcedure

Define AllowedFileTypes.S = "pb|pbi|txt"
Define DirPath.S = "/Users"
Define i.I
Define Message.S = "Please select one or multiple files:"
Define MyBlockWithPtr.NSBlockWithPtr
Define OpenFilePanel.I
Define SelectedFiles.S
Define URLArray.I

; ----- Initialize NSBlock and set callback for BlockHandler
InitNSBlockWithPtr(@MyBlockWithPtr.NSBlockWithPtr, @BlockHandler())

OpenWindow(0, 0, 0, 370, 120, "Demo of sheet with CompletionHandler",
  #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

; ----- Initialize NSOpenPanel
OpenFilePanel = CocoaMessage(0, 0, "NSOpenPanel openPanel")
CocoaMessage(0, OpenFilePanel, "setMessage:$", @Message)
CocoaMessage(0, OpenFilePanel, "setAllowedFileTypes:", CocoaMessage(0,
  CocoaMessage(0, 0, "NSString stringWithString:$", @AllowedFileTypes),
  "componentsSeparatedByString:$", @"|"))
CocoaMessage(0, OpenFilePanel,
  "setDirectoryURL:", CocoaMessage(0, 0, "NSURL fileURLWithPath:$", @DirPath))
CocoaMessage(0, OpenFilePanel, "setAllowsMultipleSelection:", #YES)

; ----- Set CompletionHandler to NSBlock
CocoaMessage(0, OpenFilePanel,
  "beginSheetModalForWindow:", WindowID(0),
  "completionHandler:@", @MyBlockWithPtr)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #Event_OpenFilePanel_Closed
      Select EventData()
        Case #NSCancelButton
          MessageRequester("Info", "File selection was cancelled!")
        Case #NSOKButton
          URLArray = CocoaMessage(0, OpenFilePanel, "URLs")

          For i = 0 To CocoaMessage(0, URLArray, "count") - 1
            SelectedFiles + #CR$ + PeekS(CocoaMessage(0, CocoaMessage(0,
              CocoaMessage(0, URLArray, "objectAtIndex:", i),
              "absoluteString"), "UTF8String"), -1, #PB_UTF8)
          Next i

          MessageRequester("Info", "The following files were selected:" + #CR$ +
            SelectedFiles)
      EndSelect
  EndSelect
ForEver
User avatar
fsw
Addict
Addict
Posts: 1572
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: COCOA translation

Post by fsw »

Hello,
wanted to use this great code but somehow it doesn't work right.

The file name is reported correctly, but the file can't be found if used with PureBasic commands that take a file name.
This issue is with local files or network files and the error message is that the file doesn't exist.
(but I selected it, so it does exist...)

Even added:

Code: Select all

          Define tmp1.s = URLDecoder(SelectedFiles, #PB_UTF8)
          Define tmp2.s = ReplaceString(tmp1, "file://", "")
          Debug FileSize(tmp2)
after the message requester in case it's a network file.

Used the following to test the "existence" of the file

Code: Select all

          Debug FileSize(tmp2) 
If the result is -1 it's not an existing file.

The same file passes as a file when selected with an OpenFileRequester.

Any help is truly appreciated.

I'm flabbergasted
:?

I am to provide the public with beneficial shocks.
Alfred Hitshock
Wolfram
Enthusiast
Enthusiast
Posts: 568
Joined: Thu May 30, 2013 4:39 pm

Re: COCOA translation

Post by Wolfram »

Try this…

Code: Select all

DeclareModule NSBlock
  
  Structure NSBlock
    *isa
    flags.l
    reserved.l
    *invoke
    *descriptor
  EndStructure
  
  Structure NSBlockWithPtr
    *block.NSBlock
    _block.NSBlock
  EndStructure
  
  Declare InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
  
EndDeclareModule


Module NSBlock
  
  Global.i NSConcreteGlobalBlock, NSConcreteStackBlock, DyLib
  
  DyLib = OpenLibrary(#PB_Any, "libSystem.dylib")
  If DyLib
    NSConcreteGlobalBlock = GetFunction(DyLib, "_NSConcreteGlobalBlock")
    NSConcreteStackBlock = GetFunction(DyLib, "_NSConcreteStackBlock")    
    CloseLibrary(DyLib)
  EndIf
  
  If Not NSConcreteGlobalBlock
    MessageRequester("Error", "Unable to access _NSConcreteGlobalBlock symbol")
    End
  EndIf
  
  DataSection
    NSBlockDescriptor:
    Data.i 0, SizeOf(NSBlock), 0, 0
  EndDataSection
  
  Procedure InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
    *NSBlockWithPtr\block = @*NSBlockWithPtr\_block
    With *NSBlockWithPtr\_block
      If IsGlobal
        \isa = NSConcreteGlobalBlock
        \flags = $30000000
      Else
        \isa = NSConcreteStackBlock
        \flags = $20000000
      EndIf
      \invoke = *Invoke
      \descriptor = ?NSBlockDescriptor
    EndWith
  EndProcedure
  
EndModule


UseModule NSBlock

Global MyBlockWithPtr.NSBlockWithPtr, NSPanel

ProcedureC ModalSheetCallback(*Block.NSBlock, ReturnCode)
  
  Protected Result.s, NSEnumerator, NSURL
  
  NSEnumerator = CocoaMessage(0, CocoaMessage(0, NSPanel, "URLs"), "objectEnumerator")
  NSURL = CocoaMessage(0, NSEnumerator, "nextObject")
  If NSURL
    
    While NSURL
      Result = PeekS(CocoaMessage(0, CocoaMessage(0, NSURL, "path"), "fileSystemRepresentation"), -1, #PB_Ascii)
      NSURL = CocoaMessage(0, NSEnumerator, "nextObject")
      Debug FileSize(Result)
    Wend
  EndIf
  
  
 
  
EndProcedure

InitNSBlockWithPtr(@MyBlockWithPtr, @ModalSheetCallback())



#RequesterTypeOpen = 0
#RequesterTypeSave = 1
#showFilesExtension = 1 << 1


Global Window_0

Procedure OSXFileRequester(RequesterType, Title.s, DefaultFile.s = "", AllowedFileTypes.s = "", Message.s = "", Flags = 0)
  Protected Result.s, Path.s
  
  
  If RequesterType = #RequesterTypeSave
    NSPanel = CocoaMessage(0, 0, "NSSavePanel savePanel")
    
    If flags & #showFilesExtension
      CocoaMessage(0,NSPanel,"setCanSelectHiddenExtension:",#YES)
      CocoaMessage(0,NSPanel,"setExtensionHidden:",#NO)
    EndIf
    
  Else
    NSPanel = CocoaMessage(Window, 0, "NSOpenPanel openPanel")
    
    If Flags & #PB_Requester_MultiSelection
      CocoaMessage(0, NSPanel, "setAllowsMultipleSelection:", #YES)
      
    EndIf    
  EndIf
  
  Path = GetPathPart(DefaultFile)
  DefaultFile = GetFilePart(DefaultFile)
  
  CocoaMessage(0, NSPanel, "setDelegate:", NSPanel)
  
  CocoaMessage(0, NSPanel, "setTitle:$", @Title)
  CocoaMessage(0, NSPanel, "setMessage:$", @Message)
  If AllowedFileTypes <> ""
    CocoaMessage(0, NSPanel, "setAllowedFileTypes:", CocoaMessage(0, CocoaMessage(0, 0, "NSString stringWithString:$", @AllowedFileTypes), "componentsSeparatedByString:$", @"|"))
  EndIf
  CocoaMessage(0, NSPanel, "setDirectoryURL:", CocoaMessage(0, 0, "NSURL fileURLWithPath:$", @Path))
  CocoaMessage(0, NSPanel, "setNameFieldStringValue:$", @DefaultFile)

  CocoaMessage(0, NSPanel, "beginSheetModalForWindow:", WindowID(Window_0), "completionHandler:@", @MyBlockWithPtr)
  
EndProcedure


Procedure Window_0_Events(event)
  Protected Result.s, Path.s
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False
      
    Case #PB_Event_Menu
      Select EventMenu()
          
      EndSelect

  EndSelect
  
  ProcedureReturn #True
EndProcedure

Window_0 = OpenWindow(#PB_Any, 0, 0, 370, 120, "Hallo Welt", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

OSXFileRequester(#RequesterTypeOpen,
                 "Please choose file to open", ;Fenster Name
                 "/users/MyFile",              ;DefaultDirectori / File
                 "pb|pbi|txt|doc",                 ;Extension
                 "Optional message",
                 #PB_Requester_MultiSelection | #showFilesExtension)


Repeat
  event = WaitWindowEvent()
 
Until Window_0_Events(event) = #False
macOS Catalina 10.15.7
User avatar
fsw
Addict
Addict
Posts: 1572
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: COCOA translation

Post by fsw »

Wow, didn't expect getting help that fast :!:

Wolfram,
Thank you for sharing your code, works as advertised :wink:

Thank you very much, your help gets me going.

8)

BTW:
Still flabbergasted why the old code didn't work.
The file name was the same as the OpenFileRequester was returning...

One thing for sure:
...never stop learning new tricks :mrgreen:

I am to provide the public with beneficial shocks.
Alfred Hitshock
Wolfram
Enthusiast
Enthusiast
Posts: 568
Joined: Thu May 30, 2013 4:39 pm

Re: COCOA translation

Post by Wolfram »

The first example retuned a URL. You can see it if you look on the beginning, it starts with "file://localhost/...".
Also the some character a showed in a different way, for example " " is "%20" or "#" is "%23".

Maybe someone else can explain it more professionally.
macOS Catalina 10.15.7
Post Reply