]> git.mxchange.org Git - flightgear.git/blob - src/GUI/CocoaFileDialog.mm
Support for multiple data dirs.
[flightgear.git] / src / GUI / CocoaFileDialog.mm
1
2
3 #include "CocoaFileDialog.hxx"
4
5 // bring it all in!
6 #include <Cocoa/Cocoa.h>
7
8 #include <boost/foreach.hpp>
9
10 #include <osgViewer/Viewer>
11 #include <osgViewer/api/Cocoa/GraphicsWindowCocoa>
12
13 #include <simgear/debug/logstream.hxx>
14 #include <simgear/misc/strutils.hxx>
15
16 #include <Main/globals.hxx>
17 #include <Main/fg_props.hxx>
18 #include <Viewer/renderer.hxx>
19
20 static NSString* stdStringToCocoa(const std::string& s)
21 {
22     return [NSString stringWithUTF8String:s.c_str()];
23 }
24
25 static NSURL* pathToNSURL(const SGPath& aPath)
26 {
27     return [NSURL fileURLWithPath:stdStringToCocoa(aPath.str())];
28 }
29
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;
34
35 class CocoaFileDialog::CocoaFileDialogPrivate
36 {
37 public:
38     CocoaFileDialogPrivate() :
39         panel(nil)
40     {
41         
42     }
43     
44     ~CocoaFileDialogPrivate()
45     {
46         [panel release];
47     }
48     
49     NSSavePanel* panel;
50 };
51
52 CocoaFileDialog::CocoaFileDialog(FGFileDialog::Usage use) :
53     FGFileDialog(use)
54 {
55     d.reset(new CocoaFileDialogPrivate);
56     if (use == USE_SAVE_FILE) {
57         d->panel = [NSSavePanel savePanel];
58     } else {
59         NSOpenPanel* openPanel = [NSOpenPanel openPanel]; 
60         d->panel = openPanel;
61         
62         if (use == USE_CHOOSE_DIR) {
63             [openPanel setCanChooseDirectories:YES];
64         }
65     } // of USE_OPEN_FILE or USE_CHOOSE_DIR -> building NSOpenPanel
66     
67     [d->panel retain];
68 }
69
70 CocoaFileDialog::~CocoaFileDialog()
71 {
72     
73 }
74
75 void CocoaFileDialog::exec()
76 {
77 // find the native Cocoa NSWindow handle so we can parent the dialog and show
78 // it window-modal.
79     NSWindow* cocoaWindow = nil;
80     std::vector<osgViewer::GraphicsWindow*> windows;
81     globals->get_renderer()->getViewer()->getWindows(windows);
82     
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
86         // everything.
87         if (strcmp(gw->className(), "GraphicsWindowCocoa")) {
88             continue; 
89         }
90             
91         osgViewer::GraphicsWindowCocoa* gwCocoa = static_cast<osgViewer::GraphicsWindowCocoa*>(gw);
92         cocoaWindow = (NSWindow*) gwCocoa->getWindow();
93         break;
94     }
95     
96 // setup the panel fields now we have collected all the data
97     if (_usage == USE_SAVE_FILE) {
98         [d->panel setNameFieldStringValue:stdStringToCocoa(_placeholder)];
99     }
100     
101     if (_filterPatterns.empty()) {
102         [d->panel setAllowedFileTypes:nil];
103     } else {
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);
108                 continue;
109             }
110             [extensions addObject:stdStringToCocoa(ext.substr(2))];
111         }
112
113         [d->panel setAllowedFileTypes:extensions];
114     }
115     
116     [d->panel setTitle:stdStringToCocoa(_title)];
117     if (_showHidden) {
118         [d->panel setShowsHiddenFiles:YES];
119     }
120     
121     [d->panel setDirectoryURL: pathToNSURL(_initialPath)];
122     
123     [d->panel beginSheetModalForWindow:cocoaWindow completionHandler:^(NSInteger result)
124     {
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);
130         }
131     }];
132 }
133
134 void CocoaFileDialog::close()
135 {
136     [d->panel close];
137 }
138