1 // CocoaFileDialog.mm - Cocoa implementation of file-dialog interface
3 // Copyright (C) 2013 James Turner <zakalawe@mac.com>
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.
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.
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.
21 #include "CocoaFileDialog.hxx"
24 #include <Cocoa/Cocoa.h>
26 #include <boost/foreach.hpp>
28 #include <osgViewer/Viewer>
29 #include <osgViewer/api/Cocoa/GraphicsWindowCocoa>
31 #include <simgear/debug/logstream.hxx>
32 #include <simgear/misc/strutils.hxx>
34 #include <GUI/CocoaHelpers_private.h>
35 #include <Main/globals.hxx>
36 #include <Main/fg_props.hxx>
37 #include <Viewer/renderer.hxx>
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;
44 class CocoaFileDialog::CocoaFileDialogPrivate
47 CocoaFileDialogPrivate() :
53 ~CocoaFileDialogPrivate()
61 CocoaFileDialog::CocoaFileDialog(FGFileDialog::Usage use) :
64 d.reset(new CocoaFileDialogPrivate);
65 if (use == USE_SAVE_FILE) {
66 d->panel = [NSSavePanel savePanel];
68 NSOpenPanel* openPanel = [NSOpenPanel openPanel];
71 if (use == USE_CHOOSE_DIR) {
72 [openPanel setCanChooseDirectories:YES];
74 } // of USE_OPEN_FILE or USE_CHOOSE_DIR -> building NSOpenPanel
79 CocoaFileDialog::~CocoaFileDialog()
84 void CocoaFileDialog::exec()
86 // find the native Cocoa NSWindow handle so we can parent the dialog and show
88 NSWindow* cocoaWindow = nil;
89 std::vector<osgViewer::GraphicsWindow*> windows;
90 globals->get_renderer()->getViewer()->getWindows(windows);
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
96 if (strcmp(gw->className(), "GraphicsWindowCocoa")) {
100 osgViewer::GraphicsWindowCocoa* gwCocoa = static_cast<osgViewer::GraphicsWindowCocoa*>(gw);
101 cocoaWindow = (NSWindow*) gwCocoa->getWindow();
105 // setup the panel fields now we have collected all the data
106 if (_usage == USE_SAVE_FILE) {
107 [d->panel setNameFieldStringValue:stdStringToCocoa(_placeholder)];
110 if (_filterPatterns.empty()) {
111 [d->panel setAllowedFileTypes:nil];
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);
119 [extensions addObject:stdStringToCocoa(ext.substr(2))];
122 [d->panel setAllowedFileTypes:extensions];
125 [d->panel setTitle:stdStringToCocoa(_title)];
127 [d->panel setShowsHiddenFiles:YES];
130 [d->panel setDirectoryURL: pathToNSURL(_initialPath)];
132 [d->panel beginSheetModalForWindow:cocoaWindow completionHandler:^(NSInteger result)
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);
143 void CocoaFileDialog::close()