Code: Select all
[panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result)
Code: Select all
[panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result)
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.Wolfram wrote:Can someone translate this to PB?Thanks!Code: Select all
[panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result)
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
Code: Select all
Define tmp1.s = URLDecoder(SelectedFiles, #PB_UTF8)
Define tmp2.s = ReplaceString(tmp1, "file://", "")
Debug FileSize(tmp2)
Code: Select all
Debug FileSize(tmp2)
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