Page 1 of 2
API call help
Posted: Tue Aug 09, 2011 12:44 am
by spacebuddy
I am trying to call an API (NSOpenPanel) but running into problems.
I want to replace OpenFileRequester with NSOPenPanel. Any API gurus here

Re: API call help
Posted: Tue Aug 09, 2011 10:44 am
by Fred
Unfortunately, NSOPenPanel is Cocoa (objectiveC) and this is not accessible trough PB. The 'easier' is your really need it is to write a small wrapper in ObjectiveC which expose a C function and then call it from PB
Re: API call help
Posted: Tue Aug 09, 2011 4:47 pm
by wilbert
Fred is right, it's Cocoa.
Re: API call help
Posted: Tue Aug 09, 2011 5:05 pm
by Polo
By the way...
How would you convert a PB string to a NSString?
This is what I do:
Code: Select all
void function (const char* pbstring)
{
NSString string = [NSString stringWithUTF8String: string];
}
When PB is in non unicode mode, it works if there aren't any special character in the PB String (ie éèë...)
When PB is in unicode mode, it only gets the first letter of the PB string into the NSString.
Any solution?

Re: API call help
Posted: Tue Aug 09, 2011 5:12 pm
by wilbert
Polo wrote:How would you convert a PB string to a NSString?
It's easier to use
NSString * string = [NSString stringWithFormat:@"%S", pbstring];
when unicode is used and
NSString * string = [NSString stringWithFormat:@"%s", pbstring];
when unicode is not used. That way you can use a static variable you set once that contains the format ( @"%S" or @"%s" ) and use the same convert function all the time.
Re: API call help
Posted: Tue Aug 09, 2011 5:13 pm
by Polo
Using Cocoa panels in PB, that's quite easy, just link your app with cocoa
ImportC "/System/Library/Frameworks/Cocoa.framework/Cocoa"
EndImport
ImportC "/System/Library/Frameworks/AppKit.framework/AppKit"
EndImport
(last one is just in case

)
Create a static library with Xcode with the ObjC code you need, like this for instance, and import the C function in PB.
(you'd still need to handle the string conversion to make the panel customisable, which i didn't in the example below)
Code: Select all
void mOpenFileRequester()
{
NSString *title = "Requester title";
NSString *directory = "";
NSString *file = "";
NSString *extensions = "";
currentwin=[NSApp keyWindow];
if ( !currentwin ) [NSApp activateIgnoringOtherApps:YES];
NSOpenPanel *panel=[NSOpenPanel openPanel];
[panel setTitle:title];
if ( [panel runModalForDirectory:directory file:file types:extensions]==NSFileHandlingPanelOKButton )
{
NSString *fileselected=[[panel filename] UTF8String];
}
if ( currentwin ) [currentwin makeKeyWindow];
}
Re: API call help
Posted: Tue Aug 09, 2011 5:20 pm
by Polo
Cheers wilbert, works great!
Re: API call help
Posted: Wed Jan 04, 2012 8:14 pm
by Khorus
I'd like to do the same (calling a Cocoa API). I need to access CoreMIDI to do some real-time MIDI. I used the WinAPI on Windows but it looks like a different game on MacOS X. Thanks!
Re: API call help
Posted: Thu Nov 07, 2013 9:26 pm
by Wolfram
Hi,
can some give me a easy example of this code. I'm a beginner and have no experience with C.
Thanks!
Re: API call help
Posted: Fri Nov 08, 2013 7:17 am
by wilbert
Wolfram wrote:can some give me a easy example of this code. I'm a beginner and have no experience with C.
I'm not sure what your goal is.
Polo gave a small piece of Objective-C code a few posts above if that's what you are looking for.
When it comes to the question this thread started with, it's no longer relevant. At that time, PureBasic for OS X was Carbon based.
The current 5.2x LTS version is Cocoa based and allows you to interact using the CocoaMessage() command.
Re: API call help
Posted: Fri Nov 08, 2013 8:15 am
by Danilo
Wolfram wrote:can some give me a easy example of this code. I'm a beginner and have no experience with C.
PB help says:
Note: The 'Pattern$' and 'PatternPosition' parameters have no effect on Mac OSX (the requester always displays all files).
So here a version with patterns, based on Polo's Objective-C code:
Code: Select all
Macro CreateCocoaObject(objectName,withMethod="alloc")
CocoaMessage(0,0,objectName+" "+withMethod)
EndMacro
#showHiddenFiles = 1
#allowMultipleSelection = 1 << 1
#returnAbsoluteNames = 1 << 2
#NSFileHandlingPanelOKButton = 1
#NSFileHandlingPanelCancelButton = 0
Procedure OpenFileRequester_(List out.s(), title.s, defaultdirectory.s="", pattern.s="", message.s="", flags=0)
ClearList(out())
NSApp = CreateCocoaObject("NSApplication")
If NSApp
currentwin = CocoaMessage(0,NSApp,"keyWindow")
If Not currentwin
CocoaMessage(0,NSApp,"activateIgnoringOtherApps:",#YES)
EndIf
panel = CreateCocoaObject("NSOpenPanel","openPanel")
If panel
;
; set title
;
CocoaMessage(0,panel,"setTitle:$",@title)
;
; set optional message text
;
If message
CocoaMessage(0,panel,"setMessage:$",@message)
EndIf
;
; set allowed patterns, separated by '|'
;
If pattern <> ""
i = 1
nextPattern.s = StringField(pattern,i,"|")
fileTypesArray = CocoaMessage(0,0,"NSArray arrayWithObject:$", @nextPattern)
Repeat
i + 1
nextPattern = StringField(pattern,i,"|")
If nextPattern
fileTypesArray = CocoaMessage(0,fileTypesArray, "arrayByAddingObject:$", @nextPattern)
EndIf
Until nextPattern = ""
CocoaMessage(0,panel,"setAllowedFileTypes:",fileTypesArray)
EndIf
;
; show hidden files?
;
If flags & #showHiddenFiles
CocoaMessage(0,panel,"setShowsHiddenFiles:",#YES)
EndIf
;
; allow multiple selection?
;
If flags & #allowMultipleSelection
CocoaMessage(0,panel,"setAllowsMultipleSelection:",#YES)
EndIf
;
; set default directory
;
url = CocoaMessage(0,0,"NSURL URLWithString:$",@defaultdirectory)
CocoaMessage(0,panel,"setDirectoryURL:",url)
;
; run
;
If CocoaMessage(0,panel,"runModal") = #NSFileHandlingPanelOKButton
;
; get results
;
results = CocoaMessage(0,panel,"URLs")
If results
count = CocoaMessage(0, results, "count")
If count
For i = 0 To count-1
NSURL = CocoaMessage(0,results,"objectAtIndex:",i)
If NSURL
If Not flags & #returnAbsoluteNames
;
; return file names
;
string = CocoaMessage(0,NSURL,"fileSystemRepresentation")
If string
fileName.s = PeekS(string,-1,#PB_UTF8)
If AddElement(out())
out() = fileName
EndIf
EndIf
Else
;
; return absolute names
;
string = CocoaMessage(0,NSURL,"absoluteString")
If string
utf8 = CocoaMessage(0,string,"UTF8String")
If utf8
fileName.s = PeekS(utf8,-1,#PB_UTF8)
If AddElement(out())
out() = fileName
EndIf
EndIf
EndIf
EndIf
EndIf
Next i
EndIf
EndIf
EndIf
EndIf
EndIf
If currentwin
CocoaMessage(0,currentwin,"makeKeyWindow")
EndIf
ProcedureReturn count
EndProcedure
NewList files.s()
num = OpenFileRequester_( files(),
"Please choose file(s) to load",
"/users/",
"pb|pbi|prefs|rtf|txt",
"Optional message:"+#CR$+"Please open a file for loading."+#CR$+"Second message line",
#allowMultipleSelection |
#showHiddenFiles )
Debug num
ForEach files()
Debug files()
Next
Polo's example used "runModalForDirectory:file:types:" method, and it was marked deprecated in OS X v10.6.
My version uses newer methods, but I think it requires at least OS X v10.6.
Re: API call help
Posted: Fri Nov 08, 2013 10:05 pm
by Wolfram
Many Thanks!
but I get an Error if I try to load a File
Object dose not respond to method "fileSystemRepresentation"
Re: API call help
Posted: Sat Nov 09, 2013 6:59 am
by wilbert
Wolfram wrote:Object dose not respond to method "fileSystemRepresentation"
The
fileSystemRepresentation method requires OS X 10.9 (Mavericks).
Re: API call help
Posted: Sat Nov 09, 2013 8:06 am
by Danilo
Wolfram wrote:but I get an Error if I try to load a File
Object dose not respond to method "fileSystemRepresentation"
Does it work for you with flag '#returnAbsoluteNames'?
In this case you get results like "file:///users/danilo/todo.rtf", but it could
be different URL for Network files.
Re: API call help
Posted: Sat Nov 09, 2013 8:15 am
by wilbert
Here's also a simplified version of Danilo's approach returning all absolute names in one string separated by |
Minimum requirement is OS X 10.6
Code: Select all
#showHiddenFiles = 1 << 0
#allowMultipleSelection = 1 << 1
Procedure.s OpenFileRequester_(title.s, defaultdirectory.s = "", pattern.s = "", message.s = "", flags = 0)
Protected NSPanel, NSArray, NSString
NSPanel = CocoaMessage(0, 0, "NSOpenPanel openPanel")
NSArray = CocoaMessage(0, CocoaMessage(0, 0, "NSString stringWithString:$", @pattern), "componentsSeparatedByString:$", @"|")
CocoaMessage(0, NSPanel, "setTitle:$", @title)
CocoaMessage(0, NSPanel, "setDirectoryURL:", CocoaMessage(0, 0, "NSURL URLWithString:$", @defaultdirectory))
CocoaMessage(0, NSPanel, "setAllowedFileTypes:", NSArray)
CocoaMessage(0, NSPanel, "setMessage:$", @message)
If flags & #showHiddenFiles
CocoaMessage(0, NSPanel, "setShowsHiddenFiles:", #YES)
EndIf
If flags & #allowMultipleSelection
CocoaMessage(0, NSPanel, "setAllowsMultipleSelection:", #YES)
EndIf
If CocoaMessage(0, NSPanel, "runModal")
NSString = CocoaMessage(0, CocoaMessage(0, NSPanel, "URLs"), "componentsJoinedByString:$", @"|")
ProcedureReturn PeekS(CocoaMessage(0, NSString, "UTF8String"), -1, #PB_UTF8)
Else
ProcedureReturn ""
EndIf
EndProcedure
Debug OpenFileRequester_("Please choose file(s) to load",
"/users/",
"pb|pbi|prefs|rtf|txt",
"Optional message:"+#CR$+"Please open a file for loading."+#CR$+"Second message line",
#allowMultipleSelection |
#showHiddenFiles )