]> git.mxchange.org Git - flightgear.git/blob - src/GUI/CocoaFileDialog.mm
Launcher: Maintain aircraft selection better
[flightgear.git] / src / GUI / CocoaFileDialog.mm
1 // CocoaFileDialog.mm - Cocoa implementation of file-dialog interface
2
3 // Copyright (C) 2013 James Turner <zakalawe@mac.com>
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 //
19
20
21 #include "CocoaFileDialog.hxx"
22
23 #include <AppKit/NSSavePanel.h>
24 #include <AppKit/NSOpenPanel.h>
25
26 #include <boost/foreach.hpp>
27
28 #include <osgViewer/Viewer>
29 #include <osgViewer/api/Cocoa/GraphicsWindowCocoa>
30
31 #include <simgear/debug/logstream.hxx>
32 #include <simgear/misc/strutils.hxx>
33
34 #include <GUI/CocoaHelpers_private.h>
35 #include <Main/globals.hxx>
36 #include <Main/fg_props.hxx>
37 #include <Viewer/renderer.hxx>
38
39 // 10.6 compiler won't accept block-scoped locals in Objective-C++,
40 // so making these globals.
41 static NSString* completion_path = nil;
42 static SGPath completion_sgpath;
43
44 class CocoaFileDialog::CocoaFileDialogPrivate
45 {
46 public:
47     CocoaFileDialogPrivate() :
48         panel(nil)
49     {
50         
51     }
52     
53     ~CocoaFileDialogPrivate()
54     {
55         [panel release];
56     }
57     
58     NSSavePanel* panel;
59 };
60
61 CocoaFileDialog::CocoaFileDialog(FGFileDialog::Usage use) :
62     FGFileDialog(use)
63 {
64     d.reset(new CocoaFileDialogPrivate);
65     if (use == USE_SAVE_FILE) {
66         d->panel = [NSSavePanel savePanel];
67     } else {
68         NSOpenPanel* openPanel = [NSOpenPanel openPanel]; 
69         d->panel = openPanel;
70         
71         if (use == USE_CHOOSE_DIR) {
72             [openPanel setCanChooseDirectories:YES];
73         }
74     } // of USE_OPEN_FILE or USE_CHOOSE_DIR -> building NSOpenPanel
75     
76     [d->panel retain];
77 }
78
79 CocoaFileDialog::~CocoaFileDialog()
80 {
81     
82 }
83
84 void CocoaFileDialog::exec()
85 {
86 // find the native Cocoa NSWindow handle so we can parent the dialog and show
87 // it window-modal.
88     NSWindow* cocoaWindow = nil;
89     std::vector<osgViewer::GraphicsWindow*> windows;
90     globals->get_renderer()->getViewer()->getWindows(windows);
91     
92     BOOST_FOREACH(osgViewer::GraphicsWindow* gw, windows) {
93         // OSG doesn't use RTTI, so no dynamic cast. Let's check the class type
94         // using OSG's own system, before we blindly static_cast<> and break
95         // everything.
96         if (strcmp(gw->className(), "GraphicsWindowCocoa")) {
97             continue; 
98         }
99             
100         osgViewer::GraphicsWindowCocoa* gwCocoa = static_cast<osgViewer::GraphicsWindowCocoa*>(gw);
101         cocoaWindow = (NSWindow*) gwCocoa->getWindow();
102         break;
103     }
104     
105 // setup the panel fields now we have collected all the data
106     if (_usage == USE_SAVE_FILE) {
107         [d->panel setNameFieldStringValue:stdStringToCocoa(_placeholder)];
108     }
109     
110     if (_filterPatterns.empty()) {
111         [d->panel setAllowedFileTypes:nil];
112     } else {
113         NSMutableArray* extensions = [NSMutableArray arrayWithCapacity:0];
114         BOOST_FOREACH(std::string ext, _filterPatterns) {
115             if (!simgear::strutils::starts_with(ext, "*.")) {
116                 SG_LOG(SG_GENERAL, SG_INFO, "can't use pattern on Cococa:" << ext);
117                 continue;
118             }
119             [extensions addObject:stdStringToCocoa(ext.substr(2))];
120         }
121
122         [d->panel setAllowedFileTypes:extensions];
123     }
124     
125     [d->panel setTitle:stdStringToCocoa(_title)];
126     if (_showHidden) {
127         [d->panel setShowsHiddenFiles:YES];
128     }
129     
130     [d->panel setDirectoryURL: pathToNSURL(_initialPath)];
131     
132     [d->panel beginSheetModalForWindow:cocoaWindow completionHandler:^(NSInteger result)
133     {
134         if (result == NSFileHandlingPanelOKButton) {
135             completion_path = [[d->panel URL] path];
136             //NSLog(@"the URL is: %@", d->panel URL]);
137             completion_sgpath = ([completion_path UTF8String]);
138             _callback->onFileDialogDone(this, completion_sgpath);
139         }
140     }];
141 }
142
143 void CocoaFileDialog::close()
144 {
145     [d->panel close];
146 }
147