]> git.mxchange.org Git - flightgear.git/blob - src/GUI/CocoaFileDialog.mm
Make it all work with existing FileSelector API.
[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 class CocoaFileDialog::CocoaFileDialogPrivate
31 {
32 public:
33     CocoaFileDialogPrivate() :
34         panel(nil)
35     {
36         
37     }
38     
39     ~CocoaFileDialogPrivate()
40     {
41         [panel release];
42     }
43     
44     NSSavePanel* panel;
45 };
46
47 CocoaFileDialog::CocoaFileDialog(FGFileDialog::Usage use) :
48     FGFileDialog(use)
49 {
50     d.reset(new CocoaFileDialogPrivate);
51     if (use == USE_SAVE_FILE) {
52         d->panel = [NSSavePanel savePanel];
53     } else {
54         NSOpenPanel* openPanel = [NSOpenPanel openPanel]; 
55         d->panel = openPanel;
56         
57         if (use == USE_CHOOSE_DIR) {
58             [openPanel setCanChooseDirectories:YES];
59         }
60     } // of USE_OPEN_FILE or USE_CHOOSE_DIR -> building NSOpenPanel
61     
62     [d->panel retain];
63 }
64
65 CocoaFileDialog::~CocoaFileDialog()
66 {
67     
68 }
69
70 void CocoaFileDialog::exec()
71 {
72 // find the native Cocoa NSWindow handle so we can parent the dialog and show
73 // it window-modal.
74     NSWindow* cocoaWindow = nil;
75     std::vector<osgViewer::GraphicsWindow*> windows;
76     globals->get_renderer()->getViewer()->getWindows(windows);
77     BOOST_FOREACH(osgViewer::GraphicsWindow* gw, windows) {
78         // OSG doesn't use RTTI, so no dynamic cast. Let's check the class type
79         // using OSG's own system, before we blindly static_cast<> and break
80         // everything.
81         if (strcmp(gw->className(), "GraphicsWindowCocoa")) {
82             continue; 
83         }
84             
85         osgViewer::GraphicsWindowCocoa* gwCocoa = static_cast<osgViewer::GraphicsWindowCocoa*>(gw);
86         cocoaWindow = (NSWindow*) gwCocoa->getWindow();
87         break;
88     }
89     
90 // setup the panel fields now we have collected all the data
91     if (_usage == USE_SAVE_FILE) {
92         [d->panel setNameFieldStringValue:stdStringToCocoa(_placeholder)];
93     }
94     
95     if (_filterPatterns.empty()) {
96         [d->panel setAllowedFileTypes:nil];
97     } else {
98         NSMutableArray* extensions = [NSMutableArray arrayWithCapacity:0];
99         BOOST_FOREACH(std::string ext, _filterPatterns) {
100             if (!simgear::strutils::starts_with(ext, "*.")) {
101                 SG_LOG(SG_GENERAL, SG_INFO, "can't use pattern on Cococa:" << ext);
102                 continue;
103             }
104             [extensions addObject:stdStringToCocoa(ext.substr(2))];
105         }
106
107         [d->panel setAllowedFileTypes:extensions];
108     }
109     
110     [d->panel setTitle:stdStringToCocoa(_title)];
111     if (_showHidden) {
112         [d->panel setShowsHiddenFiles:YES];
113     }
114     
115     [d->panel setDirectoryURL: pathToNSURL(_initialPath)];
116     
117     [d->panel beginSheetModalForWindow:cocoaWindow completionHandler:^(NSInteger result)
118     {
119         if (result == NSFileHandlingPanelOKButton) {
120             NSString* path = [[d->panel URL] path];
121             //NSLog(@"the URL is: %@", d->panel URL]);
122             SGPath sgpath([path UTF8String]);
123             _callback->onFileDialogDone(this, sgpath);
124         }
125     }];
126 }
127
128 void CocoaFileDialog::close()
129 {
130     [d->panel close];
131 }
132