1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 //------------------------------------------------------------------------
25 // includes
26 //------------------------------------------------------------------------
27 
28 #include <com/sun/star/lang/DisposedException.hpp>
29 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
31 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
32 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
33 #include <cppuhelper/interfacecontainer.h>
34 #include <osl/diagnose.h>
35 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
36 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
37 #include <com/sun/star/uno/Any.hxx>
38 #include <FPServiceInfo.hxx>
39 #include <vos/mutex.hxx>
40 #include <vcl/svapp.hxx>
41 
42 #ifndef _TOOLS_URLOBJ_HXX
43 #include <tools/urlobj.hxx>
44 #endif
45 #include "resourceprovider.hxx"
46 
47 #ifndef _SV_RC_H
48 #include <tools/rc.hxx>
49 #endif
50 #include <osl/file.hxx>
51 #include "CFStringUtilities.hxx"
52 #include "NSString_OOoAdditions.hxx"
53 #include "NSURL_OOoAdditions.hxx"
54 
55 #include <iostream>
56 
57 #include "SalAquaFilePicker.hxx"
58 
59 
60 #pragma mark DEFINES
61 
62 #define LABEL_TOGGLE( elem ) \
63 case elem : \
64 aLabel = aResProvider.getResString( CHECKBOX_##elem ); \
65     setLabel( CHECKBOX_##elem, aLabel ); \
66     break
67 
68 #define CLASS_NAME "SalAquaFilePicker"
69 
70 //------------------------------------------------------------------------
71 // namespace directives
72 //------------------------------------------------------------------------
73 
74 using namespace ::com::sun::star;
75 using namespace ::com::sun::star::ui::dialogs;
76 using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
77 using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
78 using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
79 using namespace ::com::sun::star::lang;
80 using namespace ::com::sun::star::beans;
81 using namespace ::com::sun::star::uno;
82 
83 //------------------------------------------------------------------------
84 // helper functions
85 //------------------------------------------------------------------------
86 
87 namespace
88 {
89     // controlling event notifications
90     const bool STARTUP_SUSPENDED = true;
91     const bool STARTUP_ALIVE     = false;
92 
FilePicker_getSupportedServiceNames()93     uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames()
94     {
95         uno::Sequence<rtl::OUString> aRet(3);
96         aRet[0] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.FilePicker" );
97         aRet[1] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.SystemFilePicker" );
98         aRet[2] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.AquaFilePicker" );
99         return aRet;
100     }
101 }
102 
103 #pragma mark Constructor
104 //-----------------------------------------------------------------------------------------
105 // constructor
106 //-----------------------------------------------------------------------------------------
107 
SalAquaFilePicker(const uno::Reference<lang::XMultiServiceFactory> & xServiceMgr)108 SalAquaFilePicker::SalAquaFilePicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) :
109 cppu::WeakComponentImplHelper8<XFilterManager, XFilterGroupManager, XFilePickerControlAccess, XFilePickerNotifier,
110  lang::XInitialization, util::XCancellable, lang::XEventListener, lang::XServiceInfo>( m_rbHelperMtx )
111 , m_xServiceMgr( xServiceMgr )
112 , m_pFilterHelper( NULL )
113 {
114     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
115 
116     m_pDelegate = [[AquaFilePickerDelegate alloc] initWithFilePicker:this];
117     m_pControlHelper->setFilePickerDelegate(m_pDelegate);
118 
119     DBG_PRINT_EXIT(CLASS_NAME, __func__);
120 }
121 
~SalAquaFilePicker()122 SalAquaFilePicker::~SalAquaFilePicker()
123 {
124     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
125 
126     if (NULL != m_pFilterHelper)
127         delete m_pFilterHelper;
128 
129     [m_pDelegate release];
130 
131     DBG_PRINT_EXIT(CLASS_NAME, __func__);
132 }
133 
134 
135 #pragma mark XFilePickerNotifier
136 //------------------------------------------------------------------------------------
137 // XFilePickerNotifier
138 //------------------------------------------------------------------------------------
139 
addFilePickerListener(const uno::Reference<XFilePickerListener> & xListener)140 void SAL_CALL SalAquaFilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener )
141     throw( uno::RuntimeException )
142 {
143     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
144 
145     ::vos::OGuard aGuard( Application::GetSolarMutex() );
146     m_xListener = xListener;
147 
148     DBG_PRINT_EXIT(CLASS_NAME, __func__);
149 }
150 
removeFilePickerListener(const uno::Reference<XFilePickerListener> &)151 void SAL_CALL SalAquaFilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& )
152     throw( uno::RuntimeException )
153 {
154     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
155 
156     ::vos::OGuard aGuard( Application::GetSolarMutex() );
157     m_xListener.clear();
158 
159     DBG_PRINT_EXIT(CLASS_NAME, __func__);
160 }
161 
162 #pragma mark XAsynchronousExecutableDialog
163 //-----------------------------------------------------------------------------------------
164 // XExecutableDialog functions
165 //-----------------------------------------------------------------------------------------
setTitle(const rtl::OUString & aTitle)166 void SAL_CALL SalAquaFilePicker::setTitle( const rtl::OUString& aTitle ) throw( uno::RuntimeException )
167 {
168     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "title", aTitle);
169 
170     ::vos::OGuard aGuard( Application::GetSolarMutex() );
171     implsetTitle(aTitle);
172 
173     DBG_PRINT_EXIT(CLASS_NAME, __func__);
174 }
175 
execute()176 sal_Int16 SAL_CALL SalAquaFilePicker::execute() throw( uno::RuntimeException )
177 {
178     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
179 
180     ::vos::OGuard aGuard( Application::GetSolarMutex() );
181 
182     sal_Int16 retVal = 0;
183 
184     implInitialize();
185 
186     // if m_pDialog is nil after initialization, something must have gone wrong before
187     // or there was no initialization (see issue http://www.openoffice.org/issues/show_bug.cgi?id=100214)
188     if (m_pDialog == nil) {
189         //throw uno::RuntimeException(rtl::OUString::createFromAscii("The dialog was not properly initialized!"), static_cast< XFilePicker* >( this ));
190         m_nDialogType = NAVIGATIONSERVICES_OPEN;
191     }
192 
193     if (m_pFilterHelper) {
194         m_pFilterHelper->SetFilters();
195     }
196 
197     if (m_nDialogType == NAVIGATIONSERVICES_SAVE) {
198         if (m_sSaveFileName.getLength() == 0) {
199             //if no filename is set, NavigationServices will set the name to "untitled". We don't want this!
200             //So let's try to get the window title to get the real untitled name
201             NSWindow *frontWindow = [NSApp keyWindow];
202             if (NULL != frontWindow) {
203                 NSString *windowTitle = [frontWindow title];
204                 if (windowTitle != nil) {
205                     rtl::OUString ouName = [windowTitle OUString];
206                     //a window title will typically be something like "Untitled1 - OpenOffice.org Writer"
207                     //but we only want the "Untitled1" part of it
208                     sal_Int32 indexOfDash = ouName.indexOf(rtl::OUString::createFromAscii(" - "));
209                     if (indexOfDash > -1) {
210                         m_sSaveFileName = ouName.copy(0,indexOfDash);
211                         if (m_sSaveFileName.getLength() > 0) {
212                             setDefaultName(m_sSaveFileName);
213                         }
214                     } else {
215                         OSL_TRACE("no dash present in window title");
216                     }
217                 } else {
218                     OSL_TRACE("couldn't get window title");
219                 }
220             } else {
221                 OSL_TRACE("no front window found");
222             }
223         }
224     }
225 
226     //Set the delegate to be notified of certain events
227     [m_pDialog setDelegate:m_pDelegate];
228 
229     int nStatus = runandwaitforresult();
230 
231     [m_pDialog setDelegate:nil];
232 
233     switch( nStatus )
234     {
235         case NSOKButton:
236             OSL_TRACE("The dialog returned OK");
237             retVal = ExecutableDialogResults::OK;
238             break;
239 
240         case NSCancelButton:
241             OSL_TRACE("The dialog was cancelled by the user!");
242             retVal = ExecutableDialogResults::CANCEL;
243             break;
244 
245         default:
246             throw uno::RuntimeException(rtl::OUString::createFromAscii("The dialog returned with an unknown result!"), static_cast< XFilePicker* >( this ));
247             break;
248     }
249 
250     DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal);
251 
252     return retVal;
253 }
254 
255 
256 #pragma mark XFilePicker
257 //-----------------------------------------------------------------------------------------
258 // XFilePicker functions
259 //-----------------------------------------------------------------------------------------
260 
setMultiSelectionMode(sal_Bool bMode)261 void SAL_CALL SalAquaFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( uno::RuntimeException )
262 {
263     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "multiSelectable?", bMode);
264 
265     ::vos::OGuard aGuard( Application::GetSolarMutex() );
266 
267     if (m_nDialogType == NAVIGATIONSERVICES_OPEN) {
268         [(NSOpenPanel*)m_pDialog setAllowsMultipleSelection:YES];
269         OSL_TRACE("dialog allows multi-selection? %d", [(NSOpenPanel*)m_pDialog allowsMultipleSelection]);
270     }
271 
272     DBG_PRINT_EXIT(CLASS_NAME, __func__);
273 }
274 
setDefaultName(const rtl::OUString & aName)275 void SAL_CALL SalAquaFilePicker::setDefaultName( const rtl::OUString& aName )
276 throw( uno::RuntimeException )
277 {
278     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "name", aName);
279 
280     ::vos::OGuard aGuard( Application::GetSolarMutex() );
281 
282     m_sSaveFileName = aName;
283 
284     DBG_PRINT_EXIT(CLASS_NAME, __func__);
285 }
286 
setDisplayDirectory(const rtl::OUString & rDirectory)287 void SAL_CALL SalAquaFilePicker::setDisplayDirectory( const rtl::OUString& rDirectory )
288 throw( lang::IllegalArgumentException, uno::RuntimeException )
289 {
290     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "directory", rDirectory);
291 
292     ::vos::OGuard aGuard( Application::GetSolarMutex() );
293 
294     implsetDisplayDirectory(rDirectory);
295 
296     DBG_PRINT_EXIT(CLASS_NAME, __func__);
297 }
298 
getDisplayDirectory()299 rtl::OUString SAL_CALL SalAquaFilePicker::getDisplayDirectory() throw( uno::RuntimeException )
300 {
301     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
302 
303     rtl::OUString retVal = implgetDisplayDirectory();
304 
305     DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal);
306     return retVal;
307 }
308 
getFiles()309 uno::Sequence<rtl::OUString> SAL_CALL SalAquaFilePicker::getFiles() throw( uno::RuntimeException )
310 {
311     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
312 
313     ::vos::OGuard aGuard( Application::GetSolarMutex() );
314 
315     // OSL_TRACE("starting work");
316     /*
317      * If more than one file is selected in an OpenDialog, then the first result
318      * is the directory and the remaining results contain just the files' names
319      * without the basedir path.
320      */
321     NSArray *files = nil;
322     if (m_nDialogType == NAVIGATIONSERVICES_OPEN) {
323         files = [(NSOpenPanel*)m_pDialog URLs];
324     }
325     else if (m_nDialogType == NAVIGATIONSERVICES_SAVE) {
326         files = [NSArray arrayWithObjects:[m_pDialog URL], nil];
327     }
328 
329     long nFiles = [files count];
330     OSL_TRACE("# of items: %d", nFiles);
331 
332     uno::Sequence< rtl::OUString > aSelectedFiles(nFiles > 1 ? nFiles + 1 : nFiles);
333 
334     for(int nIndex = 0; nIndex < nFiles; nIndex += 1)
335     {
336         NSURL *url = [files objectAtIndex:nIndex];
337         OSL_TRACE("handling %s", [[url description] UTF8String]);
338         InfoType info = FULLPATH;
339         if (nFiles > 1) {
340             //just get the file's name (only in OpenDialog)
341             info = FILENAME;
342         }
343         OUString sFileOrDirURL = [url OUStringForInfo:info];
344 
345         //get the directory information, only on the first file processed
346         if (nIndex == 0) {
347             OUString sDirectoryURL = [url OUStringForInfo:PATHWITHOUTLASTCOMPONENT];
348 
349             if (nFiles > 1) {
350                 aSelectedFiles[0] = OUString(sDirectoryURL);
351             }
352         }
353 
354         short nSequenceIndex = nFiles > 1 ? nIndex + 1 : nIndex;
355         aSelectedFiles[nSequenceIndex] = sFileOrDirURL;
356 
357         OSL_TRACE("Returned file in getFiles: \"%s\".", OUStringToOString(sFileOrDirURL, RTL_TEXTENCODING_UTF8).getStr());
358     }
359 
360     DBG_PRINT_EXIT(CLASS_NAME, __func__);
361     return aSelectedFiles;
362 }
363 
364 #pragma mark XFilterManager
365 //-----------------------------------------------------------------------------------------
366 // XFilterManager functions
367 //-----------------------------------------------------------------------------------------
368 
appendFilter(const rtl::OUString & aTitle,const rtl::OUString & aFilter)369 void SAL_CALL SalAquaFilePicker::appendFilter( const rtl::OUString& aTitle, const rtl::OUString& aFilter )
370 throw( lang::IllegalArgumentException, uno::RuntimeException )
371 {
372     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
373 
374     ::vos::OGuard aGuard( Application::GetSolarMutex() );
375 
376     ensureFilterHelper();
377     m_pFilterHelper->appendFilter( aTitle, aFilter );
378     m_pControlHelper->setFilterControlNeeded(YES);
379 
380     DBG_PRINT_EXIT(CLASS_NAME, __func__);
381 }
382 
setCurrentFilter(const rtl::OUString & aTitle)383 void SAL_CALL SalAquaFilePicker::setCurrentFilter( const rtl::OUString& aTitle )
384 throw( lang::IllegalArgumentException, uno::RuntimeException )
385 {
386     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
387     OSL_TRACE( "Setting current filter to %s",
388                OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() );
389 
390     ::vos::OGuard aGuard( Application::GetSolarMutex() );
391 
392     ensureFilterHelper();
393     m_pFilterHelper->setCurrentFilter(aTitle);
394     updateFilterUI();
395 
396     updateSaveFileNameExtension();
397 
398     DBG_PRINT_EXIT(CLASS_NAME, __func__);
399 }
400 
getCurrentFilter()401 rtl::OUString SAL_CALL SalAquaFilePicker::getCurrentFilter() throw( uno::RuntimeException )
402 {
403     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
404     ::vos::OGuard aGuard( Application::GetSolarMutex() );
405 
406     ensureFilterHelper();
407 
408     DBG_PRINT_EXIT(CLASS_NAME, __func__);
409     return m_pFilterHelper->getCurrentFilter();
410 }
411 
412 #pragma mark XFilterGroupManager
413 //-----------------------------------------------------------------------------------------
414 // XFilterGroupManager functions
415 //-----------------------------------------------------------------------------------------
416 
appendFilterGroup(const rtl::OUString & sGroupTitle,const uno::Sequence<beans::StringPair> & aFilters)417 void SAL_CALL SalAquaFilePicker::appendFilterGroup( const rtl::OUString& sGroupTitle, const uno::Sequence<beans::StringPair>& aFilters )
418 throw( lang::IllegalArgumentException, uno::RuntimeException )
419 {
420     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
421     ::vos::OGuard aGuard( Application::GetSolarMutex() );
422 
423     ensureFilterHelper();
424     m_pFilterHelper->appendFilterGroup(sGroupTitle, aFilters);
425     m_pControlHelper->setFilterControlNeeded(YES);
426     DBG_PRINT_EXIT(CLASS_NAME, __func__);
427 }
428 
429 #pragma mark XFilePickerControlAccess
430 //------------------------------------------------------------------------------------
431 // XFilePickerControlAccess functions
432 //------------------------------------------------------------------------------------
433 
setValue(sal_Int16 nControlId,sal_Int16 nControlAction,const uno::Any & rValue)434 void SAL_CALL SalAquaFilePicker::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any& rValue )
435 throw( uno::RuntimeException )
436 {
437     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
438 
439     ::vos::OGuard aGuard( Application::GetSolarMutex() );
440 
441     m_pControlHelper->setValue(nControlId, nControlAction, rValue);
442 
443     if (nControlId == ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION && m_nDialogType == NAVIGATIONSERVICES_SAVE) {
444         updateSaveFileNameExtension();
445     }
446 
447     DBG_PRINT_EXIT(CLASS_NAME, __func__);
448 }
449 
getValue(sal_Int16 nControlId,sal_Int16 nControlAction)450 uno::Any SAL_CALL SalAquaFilePicker::getValue( sal_Int16 nControlId, sal_Int16 nControlAction )
451 throw( uno::RuntimeException )
452 {
453     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
454 
455     uno::Any aValue = m_pControlHelper->getValue(nControlId, nControlAction);
456 
457     DBG_PRINT_EXIT(CLASS_NAME, __func__);
458     return aValue;
459 }
460 
enableControl(sal_Int16 nControlId,sal_Bool bEnable)461 void SAL_CALL SalAquaFilePicker::enableControl( sal_Int16 nControlId, sal_Bool bEnable )
462 throw( uno::RuntimeException )
463 {
464     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
465 
466     m_pControlHelper->enableControl(nControlId, bEnable);
467 
468     DBG_PRINT_EXIT(CLASS_NAME, __func__);
469 }
470 
setLabel(sal_Int16 nControlId,const::rtl::OUString & aLabel)471 void SAL_CALL SalAquaFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString& aLabel )
472 throw( uno::RuntimeException )
473 {
474     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
475 
476     ::vos::OGuard aGuard( Application::GetSolarMutex() );
477 
478     NSString* sLabel = [NSString stringWithOUString:aLabel];
479     m_pControlHelper->setLabel( nControlId, sLabel ) ;
480 
481     DBG_PRINT_EXIT(CLASS_NAME, __func__);
482 }
483 
getLabel(sal_Int16 nControlId)484 rtl::OUString SAL_CALL SalAquaFilePicker::getLabel( sal_Int16 nControlId )
485 throw( uno::RuntimeException )
486 {
487     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
488     DBG_PRINT_EXIT(CLASS_NAME, __func__);
489 
490     return m_pControlHelper->getLabel(nControlId);
491 }
492 
493 #pragma mark XInitialization
494 //------------------------------------------------------------------------------------
495 // XInitialization
496 //------------------------------------------------------------------------------------
497 
initialize(const uno::Sequence<uno::Any> & aArguments)498 void SAL_CALL SalAquaFilePicker::initialize( const uno::Sequence<uno::Any>& aArguments )
499 throw( uno::Exception, uno::RuntimeException )
500 {
501     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "arguments size", aArguments.getLength());
502 
503     ::vos::OGuard aGuard( Application::GetSolarMutex() );
504 
505     // parameter checking
506     uno::Any aAny;
507     if( 0 == aArguments.getLength() )
508         throw lang::IllegalArgumentException(rtl::OUString::createFromAscii( "no arguments" ),
509                                              static_cast<XFilePicker*>( this ), 1 );
510 
511     aAny = aArguments[0];
512 
513     if( ( aAny.getValueType() != ::getCppuType( ( sal_Int16* )0 ) ) &&
514         (aAny.getValueType() != ::getCppuType( ( sal_Int8* )0 ) ) )
515         throw lang::IllegalArgumentException(rtl::OUString::createFromAscii( "invalid argument type" ),
516                                              static_cast<XFilePicker*>( this ), 1 );
517 
518     sal_Int16 templateId = -1;
519     aAny >>= templateId;
520 
521     switch( templateId )
522     {
523         case FILEOPEN_SIMPLE:
524             m_nDialogType = NAVIGATIONSERVICES_OPEN;
525             OSL_TRACE( "Template: FILEOPEN_SIMPLE" );
526             break;
527         case FILESAVE_SIMPLE:
528             m_nDialogType = NAVIGATIONSERVICES_SAVE;
529             OSL_TRACE( "Template: FILESAVE_SIMPLE" );
530             break;
531         case FILESAVE_AUTOEXTENSION_PASSWORD:
532             m_nDialogType = NAVIGATIONSERVICES_SAVE;
533             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_PASSWORD" );
534             break;
535         case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
536             m_nDialogType = NAVIGATIONSERVICES_SAVE;
537             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS" );
538             break;
539         case FILESAVE_AUTOEXTENSION_SELECTION:
540             m_nDialogType = NAVIGATIONSERVICES_SAVE;
541             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_SELECTION" );
542             break;
543         case FILESAVE_AUTOEXTENSION_TEMPLATE:
544             m_nDialogType = NAVIGATIONSERVICES_SAVE;
545             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_TEMPLATE" );
546             break;
547         case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
548             m_nDialogType = NAVIGATIONSERVICES_OPEN;
549             OSL_TRACE( "Template: FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE" );
550             break;
551         case FILEOPEN_PLAY:
552             m_nDialogType = NAVIGATIONSERVICES_OPEN;
553             OSL_TRACE( "Template: FILEOPEN_PLAY" );
554             break;
555         case FILEOPEN_READONLY_VERSION:
556             m_nDialogType = NAVIGATIONSERVICES_OPEN;
557             OSL_TRACE( "Template: FILEOPEN_READONLY_VERSION" );
558             break;
559         case FILEOPEN_LINK_PREVIEW:
560             m_nDialogType = NAVIGATIONSERVICES_OPEN;
561             OSL_TRACE( "Template: FILEOPEN_LINK_PREVIEW" );
562             break;
563         case FILESAVE_AUTOEXTENSION:
564             m_nDialogType = NAVIGATIONSERVICES_SAVE;
565             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION" );
566             break;
567         default:
568             throw lang::IllegalArgumentException(rtl::OUString::createFromAscii( "Unknown template" ),
569                                                  static_cast< XFilePicker* >( this ),
570                                                  1 );
571     }
572 
573     m_pControlHelper->initialize(templateId);
574 
575     implInitialize();
576 
577     DBG_PRINT_EXIT(CLASS_NAME, __func__);
578 }
579 
580 #pragma mark XCancellable
581 //------------------------------------------------------------------------------------
582 // XCancellable
583 //------------------------------------------------------------------------------------
584 
cancel()585 void SAL_CALL SalAquaFilePicker::cancel() throw( uno::RuntimeException )
586 {
587     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
588 
589     ::vos::OGuard aGuard( Application::GetSolarMutex() );
590 
591     if (m_pDialog != nil) {
592         [m_pDialog cancel:nil];
593     }
594 
595     DBG_PRINT_EXIT(CLASS_NAME, __func__);
596 }
597 
598 #pragma mark XEventListener
599 //------------------------------------------------
600 // XEventListener
601 //------------------------------------------------
602 
disposing(const lang::EventObject & aEvent)603 void SAL_CALL SalAquaFilePicker::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException )
604 {
605     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
606 
607     ::vos::OGuard aGuard( Application::GetSolarMutex() );
608 
609     uno::Reference<XFilePickerListener> xFilePickerListener( aEvent.Source, ::com::sun::star::uno::UNO_QUERY );
610 
611     if( xFilePickerListener.is() )
612         removeFilePickerListener( xFilePickerListener );
613 
614     DBG_PRINT_EXIT(CLASS_NAME, __func__);
615 }
616 
617 #pragma mark XServiceInfo
618 // -------------------------------------------------
619 // XServiceInfo
620 // -------------------------------------------------
621 
getImplementationName()622 rtl::OUString SAL_CALL SalAquaFilePicker::getImplementationName()
623 throw( uno::RuntimeException )
624 {
625     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
626 
627     rtl::OUString retVal = rtl::OUString::createFromAscii( FILE_PICKER_IMPL_NAME );
628 
629     DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal);
630 
631     return retVal;
632 }
633 
supportsService(const rtl::OUString & sServiceName)634 sal_Bool SAL_CALL SalAquaFilePicker::supportsService( const rtl::OUString& sServiceName )
635 throw( uno::RuntimeException )
636 {
637     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "service name", sServiceName);
638 
639     sal_Bool retVal = sal_False;
640 
641     uno::Sequence <rtl::OUString> supportedServicesNames = FilePicker_getSupportedServiceNames();
642 
643     for( sal_Int32 n = supportedServicesNames.getLength(); n--; ) {
644         if( supportedServicesNames[n].compareTo( sServiceName ) == 0) {
645             retVal = sal_True;
646             break;
647         }
648     }
649 
650     DBG_PRINT_EXIT(CLASS_NAME, __func__);
651 
652     return retVal;
653 }
654 
getSupportedServiceNames()655 uno::Sequence<rtl::OUString> SAL_CALL SalAquaFilePicker::getSupportedServiceNames()
656 throw( uno::RuntimeException )
657 {
658     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
659     DBG_PRINT_EXIT(CLASS_NAME, __func__);
660 
661     return FilePicker_getSupportedServiceNames();
662 }
663 
664 #pragma mark Misc/Private
665 //-----------------------------------------------------------------------------------------
666 // FilePicker Event functions
667 //-----------------------------------------------------------------------------------------
668 
fileSelectionChanged(FilePickerEvent aEvent)669 void SAL_CALL SalAquaFilePicker::fileSelectionChanged( FilePickerEvent aEvent )
670 {
671     OSL_TRACE( "file selection changed");
672     if (m_xListener.is())
673         m_xListener->fileSelectionChanged( aEvent );
674 }
675 
directoryChanged(FilePickerEvent aEvent)676 void SAL_CALL SalAquaFilePicker::directoryChanged( FilePickerEvent aEvent )
677 {
678     OSL_TRACE("directory changed");
679     if (m_xListener.is())
680         m_xListener->directoryChanged( aEvent );
681 }
682 
controlStateChanged(FilePickerEvent aEvent)683 void SAL_CALL SalAquaFilePicker::controlStateChanged( FilePickerEvent aEvent )
684 {
685     OSL_TRACE("control state changed");
686     if (m_xListener.is())
687         m_xListener->controlStateChanged( aEvent );
688 }
689 
dialogSizeChanged()690 void SAL_CALL SalAquaFilePicker::dialogSizeChanged()
691 {
692     OSL_TRACE("dialog size changed");
693     if (m_xListener.is())
694         m_xListener->dialogSizeChanged();
695 }
696 
697 //------------------------------------------------------------------------------------
698 
699 #define MAP_TOGGLE( elem ) \
700 case ExtendedFilePickerElementIds::CHECKBOX_##elem: \
701     pWidget = m_pToggles[elem]; \
702     break
703 
704 #define MAP_BUTTON( elem ) \
705 case ExtendedFilePickerElementIds::PUSHBUTTON_##elem: \
706     pWidget = m_pButtons[elem]; \
707     break
708 #undef MAP_LIST
709 #define MAP_LIST( elem ) \
710 case ExtendedFilePickerElementIds::LISTBOX_##elem: \
711     pWidget = m_pListControls[elem]; if (isAList != NULL) *isAList = sal_True; \
712     break
713 
714 #define MAP_LIST_LABEL( elem ) \
715 case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \
716     pWidget = m_pListControls[elem]; \
717     break
718 
719 //--------------------------------------------------
720 // Misc
721 //-------------------------------------------------
ensureFilterHelper()722 void SalAquaFilePicker::ensureFilterHelper() {
723     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
724 
725     ::vos::OGuard aGuard( Application::GetSolarMutex() );
726 
727     if (NULL == m_pFilterHelper) {
728         m_pFilterHelper = new FilterHelper;
729         m_pControlHelper->setFilterHelper(m_pFilterHelper);
730         [m_pDelegate setFilterHelper:m_pFilterHelper];
731     }
732 
733     DBG_PRINT_EXIT(CLASS_NAME, __func__);
734 }
735 
implInitialize()736 void SalAquaFilePicker::implInitialize()
737 {
738     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
739 
740     //call super
741     SalAquaPicker::implInitialize();
742 
743     DBG_PRINT_EXIT(CLASS_NAME, __func__);
744 }
745 
updateFilterUI()746 void SalAquaFilePicker::updateFilterUI() {
747     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
748 
749     m_pControlHelper->updateFilterUI();
750 
751     DBG_PRINT_EXIT(CLASS_NAME, __func__);
752 }
753 
updateSaveFileNameExtension()754 void SalAquaFilePicker::updateSaveFileNameExtension() {
755     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
756 
757     if (m_nDialogType != NAVIGATIONSERVICES_SAVE) {
758         return;
759     }
760 
761     // we need to set this here again because initial setting does
762     //[m_pDialog setExtensionHidden:YES];
763 
764     ::vos::OGuard aGuard( Application::GetSolarMutex() );
765 
766     if (m_pControlHelper->isAutoExtensionEnabled() == false) {
767         OSL_TRACE("allowing other file types");
768         [m_pDialog setAllowedFileTypes:nil];
769         [m_pDialog setAllowsOtherFileTypes:YES];
770     } else {
771         ensureFilterHelper();
772 
773         OUStringList aStringList = m_pFilterHelper->getCurrentFilterSuffixList();
774         if( aStringList.empty()) // #i9328#
775             return;
776 
777         rtl::OUString suffix = (*(aStringList.begin())).copy(1);
778         NSString *requiredFileType = [NSString stringWithOUString:suffix];
779 
780         [m_pDialog setRequiredFileType:requiredFileType];
781 
782         OSL_TRACE("disallowing other file types");
783         [m_pDialog setAllowsOtherFileTypes:NO];
784     }
785 
786     DBG_PRINT_EXIT(CLASS_NAME, __func__);
787 }
788 
filterControlChanged()789 void SalAquaFilePicker::filterControlChanged() {
790     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
791 
792     if (m_pDialog == nil) {
793         return;
794     }
795 
796     ::vos::OGuard aGuard( Application::GetSolarMutex() );
797 
798     updateSaveFileNameExtension();
799 
800     [m_pDialog validateVisibleColumns];
801 
802     FilePickerEvent evt;
803     evt.ElementId = LISTBOX_FILTER;
804     controlStateChanged( evt );
805 
806     DBG_PRINT_EXIT(CLASS_NAME, __func__);
807 }
808 
809