3 #include "CocoaFileDialog.hxx"
6 #include <Cocoa/Cocoa.h>
8 #include <boost/foreach.hpp>
10 #include <osgViewer/Viewer>
11 #include <osgViewer/api/Cocoa/GraphicsWindowCocoa>
13 #include <simgear/debug/logstream.hxx>
14 #include <simgear/misc/strutils.hxx>
16 #include <Main/globals.hxx>
17 #include <Main/fg_props.hxx>
18 #include <Viewer/renderer.hxx>
20 static NSString* stdStringToCocoa(const std::string& s)
22 return [NSString stringWithUTF8String:s.c_str()];
25 static NSURL* pathToNSURL(const SGPath& aPath)
27 return [NSURL fileURLWithPath:stdStringToCocoa(aPath.str())];
30 // 10.6 compiler won't accept block-scoped locals in Objective-C++,
31 // so making these globals.
32 static NSString* completion_path = nil;
33 static SGPath completion_sgpath;
35 class CocoaFileDialog::CocoaFileDialogPrivate
38 CocoaFileDialogPrivate() :
44 ~CocoaFileDialogPrivate()
52 CocoaFileDialog::CocoaFileDialog(FGFileDialog::Usage use) :
55 d.reset(new CocoaFileDialogPrivate);
56 if (use == USE_SAVE_FILE) {
57 d->panel = [NSSavePanel savePanel];
59 NSOpenPanel* openPanel = [NSOpenPanel openPanel];
62 if (use == USE_CHOOSE_DIR) {
63 [openPanel setCanChooseDirectories:YES];
65 } // of USE_OPEN_FILE or USE_CHOOSE_DIR -> building NSOpenPanel
70 CocoaFileDialog::~CocoaFileDialog()
75 void CocoaFileDialog::exec()
77 // find the native Cocoa NSWindow handle so we can parent the dialog and show
79 NSWindow* cocoaWindow = nil;
80 std::vector<osgViewer::GraphicsWindow*> windows;
81 globals->get_renderer()->getViewer()->getWindows(windows);
83 BOOST_FOREACH(osgViewer::GraphicsWindow* gw, windows) {
84 // OSG doesn't use RTTI, so no dynamic cast. Let's check the class type
85 // using OSG's own system, before we blindly static_cast<> and break
87 if (strcmp(gw->className(), "GraphicsWindowCocoa")) {
91 osgViewer::GraphicsWindowCocoa* gwCocoa = static_cast<osgViewer::GraphicsWindowCocoa*>(gw);
92 cocoaWindow = (NSWindow*) gwCocoa->getWindow();
96 // setup the panel fields now we have collected all the data
97 if (_usage == USE_SAVE_FILE) {
98 [d->panel setNameFieldStringValue:stdStringToCocoa(_placeholder)];
101 if (_filterPatterns.empty()) {
102 [d->panel setAllowedFileTypes:nil];
104 NSMutableArray* extensions = [NSMutableArray arrayWithCapacity:0];
105 BOOST_FOREACH(std::string ext, _filterPatterns) {
106 if (!simgear::strutils::starts_with(ext, "*.")) {
107 SG_LOG(SG_GENERAL, SG_INFO, "can't use pattern on Cococa:" << ext);
110 [extensions addObject:stdStringToCocoa(ext.substr(2))];
113 [d->panel setAllowedFileTypes:extensions];
116 [d->panel setTitle:stdStringToCocoa(_title)];
118 [d->panel setShowsHiddenFiles:YES];
121 [d->panel setDirectoryURL: pathToNSURL(_initialPath)];
123 [d->panel beginSheetModalForWindow:cocoaWindow completionHandler:^(NSInteger result)
125 if (result == NSFileHandlingPanelOKButton) {
126 completion_path = [[d->panel URL] path];
127 //NSLog(@"the URL is: %@", d->panel URL]);
128 completion_sgpath = ([completion_path UTF8String]);
129 _callback->onFileDialogDone(this, completion_sgpath);
134 void CocoaFileDialog::close()