1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 //------------------------------------------------------------------------ 29 // includes 30 //------------------------------------------------------------------------ 31 32 #include <com/sun/star/lang/DisposedException.hpp> 33 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 34 #include <cppuhelper/interfacecontainer.h> 35 #include <osl/diagnose.h> 36 #include <com/sun/star/uno/Any.hxx> 37 #include <FPServiceInfo.hxx> 38 #include <vos/mutex.hxx> 39 #include <vcl/svapp.hxx> 40 #ifndef _SALAQUAPICKER_HXX_ 41 #include "SalAquaPicker.hxx" 42 #endif 43 #include <tools/urlobj.hxx> 44 #include <osl/file.hxx> 45 #include "CFStringUtilities.hxx" 46 #include "NSString_OOoAdditions.hxx" 47 48 #ifndef _NSURL_OOOADDITIONS_HXX_ 49 #include "NSURL_OOoAdditions.hxx" 50 #endif 51 52 #include "SalAquaFilePicker.hxx" 53 54 #include <stdio.h> 55 56 #pragma mark DEFINES 57 #define CLASS_NAME "SalAquaPicker" 58 #define kSetHideExtensionStateKey @"NSNavLastUserSetHideExtensionButtonState" 59 60 //------------------------------------------------------------------------ 61 // namespace directives 62 //------------------------------------------------------------------------ 63 64 using namespace ::rtl; 65 using namespace ::com::sun::star; 66 using namespace ::com::sun::star::lang; 67 using namespace ::com::sun::star::uno; 68 69 // constructor 70 SalAquaPicker::SalAquaPicker() 71 : m_pDialog(NULL) 72 , m_pControlHelper(new ControlHelper()) 73 { 74 DBG_PRINT_ENTRY(CLASS_NAME, __func__); 75 DBG_PRINT_EXIT(CLASS_NAME, __func__); 76 } 77 78 SalAquaPicker::~SalAquaPicker() 79 { 80 DBG_PRINT_ENTRY(CLASS_NAME, __func__); 81 82 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 83 84 NSAutoreleasePool *pool = [NSAutoreleasePool new]; 85 86 if (NULL != m_pControlHelper) 87 delete m_pControlHelper; 88 89 if (NULL != m_pDialog) 90 [m_pDialog release]; 91 92 [pool release]; 93 94 DBG_PRINT_EXIT(CLASS_NAME, __func__); 95 } 96 97 void SAL_CALL SalAquaPicker::implInitialize() 98 { 99 DBG_PRINT_ENTRY(CLASS_NAME, __func__); 100 101 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 102 103 if (m_pDialog != nil) { 104 return; 105 } 106 107 switch (m_nDialogType) 108 { 109 case NAVIGATIONSERVICES_OPEN: 110 OSL_TRACE("NAVIGATIONSERVICES_OPEN"); 111 m_pDialog = [NSOpenPanel openPanel]; 112 [(NSOpenPanel*)m_pDialog setCanChooseDirectories:NO]; 113 [(NSOpenPanel*)m_pDialog setCanChooseFiles:YES]; 114 break; 115 116 case NAVIGATIONSERVICES_SAVE: 117 OSL_TRACE("NAVIGATIONSERVICES_SAVE"); 118 m_pDialog = [NSSavePanel savePanel]; 119 [(NSSavePanel*)m_pDialog setCanSelectHiddenExtension:NO]; //changed for issue #102102 120 /* I would have loved to use 121 * [(NSSavePanel*)m_pDialog setExtensionHidden:YES]; 122 * here but unfortunately this 123 * a) only works when the dialog is already displayed because it seems to act on the corresponding checkbox (that we don't show but that doesn't matter) 124 * b) Mac OS X saves this setting on an application-based level which means that the last state is always being restored again when the app runs for the next time 125 * 126 * So the only reliable way seems to be using the NSUserDefaults object because that is where that value is stored and 127 * to just overwrite it if it has the wrong value. 128 */ 129 NSUserDefaults *pDefaults = [NSUserDefaults standardUserDefaults]; 130 NSNumber *pExtn = [pDefaults objectForKey:kSetHideExtensionStateKey]; 131 if(pExtn == nil || [pExtn boolValue] == NO) { 132 OSL_TRACE("Hiding extension"); 133 [pDefaults setBool:YES forKey:kSetHideExtensionStateKey]; 134 } 135 break; 136 137 case NAVIGATIONSERVICES_DIRECTORY: 138 OSL_TRACE("NAVIGATIONSERVICES_DIRECTORY"); 139 m_pDialog = [NSOpenPanel openPanel]; 140 [(NSOpenPanel*)m_pDialog setCanChooseDirectories:YES]; 141 [(NSOpenPanel*)m_pDialog setCanChooseFiles:NO]; 142 break; 143 144 default: 145 OSL_TRACE("m_nDialogType is UNKNOWN: %d", m_nDialogType); 146 break; 147 } 148 149 if (m_pDialog == nil) { 150 OSL_TRACE("An error occurred while creating the dialog!"); 151 } 152 else { 153 [(NSOpenPanel*)m_pDialog setCanCreateDirectories:YES]; 154 //Retain the dialog instance or it will go away immediately 155 [m_pDialog retain]; 156 } 157 158 DBG_PRINT_EXIT(CLASS_NAME, __func__); 159 } 160 161 int SalAquaPicker::run() 162 { 163 DBG_PRINT_ENTRY(CLASS_NAME, __func__); 164 165 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 166 167 NSAutoreleasePool *pool = [NSAutoreleasePool new]; 168 169 if (m_pDialog == NULL) { 170 //this is the case e.g. for the folder picker at this stage 171 implInitialize(); 172 } 173 174 NSView *userPane = m_pControlHelper->getUserPane(); 175 if (userPane != NULL) { 176 [m_pDialog setAccessoryView:userPane]; 177 } 178 179 int retVal = 0; 180 181 NSString *startDirectory; 182 if (m_sDisplayDirectory.getLength() > 0) { 183 NSString *temp = [NSString stringWithOUString:m_sDisplayDirectory]; 184 NSURL *url = [NSURL URLWithString:temp]; 185 startDirectory = [url path]; 186 187 OSL_TRACE("start dir: %s", [startDirectory UTF8String]); 188 // NSLog(@"%@", startDirectory); 189 } 190 else { 191 startDirectory = NSHomeDirectory(); 192 } 193 194 switch(m_nDialogType) { 195 case NAVIGATIONSERVICES_DIRECTORY: 196 case NAVIGATIONSERVICES_OPEN: 197 retVal = [(NSOpenPanel*)m_pDialog runModalForDirectory:startDirectory file:nil types:nil]; 198 break; 199 case NAVIGATIONSERVICES_SAVE: 200 retVal = [m_pDialog runModalForDirectory:startDirectory file:[NSString stringWithOUString:((SalAquaFilePicker*)this)->getSaveFileName()]/*[m_pDialog saveFilename]*/]; 201 break; 202 // [m_pDialog beginSheetForDirectory:startDirectory file:[m_pDialog saveFilename] modalForWindow:[NSApp keyWindow] modalDelegate:((SalAquaFilePicker*)this)->getDelegate() didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) contextInfo:nil]; 203 default: 204 break; 205 } 206 207 if (retVal == NSFileHandlingPanelOKButton) { 208 NSString* pDir = [m_pDialog directory]; 209 if (pDir) { 210 implsetDisplayDirectory([[NSURL fileURLWithPath:pDir] OUStringForInfo:FULLPATH]); 211 } 212 } 213 214 DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal); 215 216 [pool release]; 217 218 return retVal; 219 } 220 221 int SalAquaPicker::runandwaitforresult() 222 { 223 DBG_PRINT_ENTRY(CLASS_NAME, __func__); 224 225 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 226 227 int status = this->run(); 228 229 DBG_PRINT_EXIT(CLASS_NAME, __func__, status); 230 return status; 231 } 232 233 void SAL_CALL SalAquaPicker::implsetDisplayDirectory( const rtl::OUString& aDirectory ) 234 throw( lang::IllegalArgumentException, uno::RuntimeException ) 235 { 236 DBG_PRINT_ENTRY(CLASS_NAME, __func__, "directory", aDirectory); 237 238 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 239 240 if (aDirectory != m_sDisplayDirectory) { 241 m_sDisplayDirectory = aDirectory; 242 } 243 244 DBG_PRINT_EXIT(CLASS_NAME, __func__); 245 } 246 247 rtl::OUString SAL_CALL SalAquaPicker::implgetDisplayDirectory() throw( uno::RuntimeException ) 248 { 249 DBG_PRINT_ENTRY(CLASS_NAME, __func__); 250 DBG_PRINT_EXIT(CLASS_NAME, __func__, m_sDisplayDirectory); 251 252 return m_sDisplayDirectory; 253 } 254 255 void SAL_CALL SalAquaPicker::implsetTitle( const rtl::OUString& aTitle ) throw( uno::RuntimeException ) 256 { 257 DBG_PRINT_ENTRY(CLASS_NAME, __func__, "title", aTitle); 258 259 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 260 261 if (m_pDialog != nil) { 262 [m_pDialog setTitle:[NSString stringWithOUString:aTitle]]; 263 } 264 265 DBG_PRINT_EXIT(CLASS_NAME, __func__); 266 } 267 268