// CocoaFileDialog.mm - Cocoa implementation of file-dialog interface // Copyright (C) 2013 James Turner // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // #include "CocoaFileDialog.hxx" #include #include #include #include #include #include #include #include #include
#include
#include // 10.6 compiler won't accept block-scoped locals in Objective-C++, // so making these globals. static NSString* completion_path = nil; static SGPath completion_sgpath; class CocoaFileDialog::CocoaFileDialogPrivate { public: CocoaFileDialogPrivate() : panel(nil) { } ~CocoaFileDialogPrivate() { [panel release]; } NSSavePanel* panel; }; CocoaFileDialog::CocoaFileDialog(FGFileDialog::Usage use) : FGFileDialog(use) { d.reset(new CocoaFileDialogPrivate); if (use == USE_SAVE_FILE) { d->panel = [NSSavePanel savePanel]; } else { NSOpenPanel* openPanel = [NSOpenPanel openPanel]; d->panel = openPanel; if (use == USE_CHOOSE_DIR) { [openPanel setCanChooseDirectories:YES]; } } // of USE_OPEN_FILE or USE_CHOOSE_DIR -> building NSOpenPanel [d->panel retain]; } CocoaFileDialog::~CocoaFileDialog() { } void CocoaFileDialog::exec() { // find the native Cocoa NSWindow handle so we can parent the dialog and show // it window-modal. NSWindow* cocoaWindow = nil; std::vector windows; globals->get_renderer()->getViewer()->getWindows(windows); BOOST_FOREACH(osgViewer::GraphicsWindow* gw, windows) { // OSG doesn't use RTTI, so no dynamic cast. Let's check the class type // using OSG's own system, before we blindly static_cast<> and break // everything. if (strcmp(gw->className(), "GraphicsWindowCocoa")) { continue; } osgViewer::GraphicsWindowCocoa* gwCocoa = static_cast(gw); cocoaWindow = (NSWindow*) gwCocoa->getWindow(); break; } // setup the panel fields now we have collected all the data if (_usage == USE_SAVE_FILE) { [d->panel setNameFieldStringValue:stdStringToCocoa(_placeholder)]; } if (_filterPatterns.empty()) { [d->panel setAllowedFileTypes:nil]; } else { NSMutableArray* extensions = [NSMutableArray arrayWithCapacity:0]; BOOST_FOREACH(std::string ext, _filterPatterns) { if (!simgear::strutils::starts_with(ext, "*.")) { SG_LOG(SG_GENERAL, SG_INFO, "can't use pattern on Cococa:" << ext); continue; } [extensions addObject:stdStringToCocoa(ext.substr(2))]; } [d->panel setAllowedFileTypes:extensions]; } [d->panel setTitle:stdStringToCocoa(_title)]; if (_showHidden) { [d->panel setShowsHiddenFiles:YES]; } [d->panel setDirectoryURL: pathToNSURL(_initialPath)]; [d->panel beginSheetModalForWindow:cocoaWindow completionHandler:^(NSInteger result) { if (result == NSFileHandlingPanelOKButton) { completion_path = [[d->panel URL] path]; //NSLog(@"the URL is: %@", d->panel URL]); completion_sgpath = SGPath::fromUtf8([completion_path UTF8String]); _callback->onFileDialogDone(this, completion_sgpath); } }]; } void CocoaFileDialog::close() { [d->panel close]; }