xref: /trunk/main/fpicker/source/aqua/SalAquaFilePicker.cxx (revision 45c5a00162811bd03b87fcb4fe9996782f2b59ec)
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 
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 
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 
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 
140 void SAL_CALL SalAquaFilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener )
141 {
142     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
143 
144     ::vos::OGuard aGuard( Application::GetSolarMutex() );
145     m_xListener = xListener;
146 
147     DBG_PRINT_EXIT(CLASS_NAME, __func__);
148 }
149 
150 void SAL_CALL SalAquaFilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& )
151 {
152     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
153 
154     ::vos::OGuard aGuard( Application::GetSolarMutex() );
155     m_xListener.clear();
156 
157     DBG_PRINT_EXIT(CLASS_NAME, __func__);
158 }
159 
160 #pragma mark XAsynchronousExecutableDialog
161 //-----------------------------------------------------------------------------------------
162 // XExecutableDialog functions
163 //-----------------------------------------------------------------------------------------
164 void SAL_CALL SalAquaFilePicker::setTitle( const rtl::OUString& aTitle )
165 {
166     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "title", aTitle);
167 
168     ::vos::OGuard aGuard( Application::GetSolarMutex() );
169     implsetTitle(aTitle);
170 
171     DBG_PRINT_EXIT(CLASS_NAME, __func__);
172 }
173 
174 sal_Int16 SAL_CALL SalAquaFilePicker::execute()
175 {
176     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
177 
178     ::vos::OGuard aGuard( Application::GetSolarMutex() );
179 
180     sal_Int16 retVal = 0;
181 
182     implInitialize();
183 
184     // if m_pDialog is nil after initialization, something must have gone wrong before
185     // or there was no initialization (see issue http://www.openoffice.org/issues/show_bug.cgi?id=100214)
186     if (m_pDialog == nil) {
187         //throw uno::RuntimeException(rtl::OUString::createFromAscii("The dialog was not properly initialized!"), static_cast< XFilePicker* >( this ));
188         m_nDialogType = NAVIGATIONSERVICES_OPEN;
189     }
190 
191     if (m_pFilterHelper) {
192         m_pFilterHelper->SetFilters();
193     }
194 
195     if (m_nDialogType == NAVIGATIONSERVICES_SAVE) {
196         if (m_sSaveFileName.getLength() == 0) {
197             //if no filename is set, NavigationServices will set the name to "untitled". We don't want this!
198             //So let's try to get the window title to get the real untitled name
199             NSWindow *frontWindow = [NSApp keyWindow];
200             if (NULL != frontWindow) {
201                 NSString *windowTitle = [frontWindow title];
202                 if (windowTitle != nil) {
203                     rtl::OUString ouName = [windowTitle OUString];
204                     //a window title will typically be something like "Untitled1 - OpenOffice.org Writer"
205                     //but we only want the "Untitled1" part of it
206                     sal_Int32 indexOfDash = ouName.indexOf(rtl::OUString::createFromAscii(" - "));
207                     if (indexOfDash > -1) {
208                         m_sSaveFileName = ouName.copy(0,indexOfDash);
209                         if (m_sSaveFileName.getLength() > 0) {
210                             setDefaultName(m_sSaveFileName);
211                         }
212                     } else {
213                         OSL_TRACE("no dash present in window title");
214                     }
215                 } else {
216                     OSL_TRACE("couldn't get window title");
217                 }
218             } else {
219                 OSL_TRACE("no front window found");
220             }
221         }
222     }
223 
224     //Set the delegate to be notified of certain events
225     [m_pDialog setDelegate:m_pDelegate];
226 
227     int nStatus = runandwaitforresult();
228 
229     [m_pDialog setDelegate:nil];
230 
231     switch( nStatus )
232     {
233         case NSOKButton:
234             OSL_TRACE("The dialog returned OK");
235             retVal = ExecutableDialogResults::OK;
236             break;
237 
238         case NSCancelButton:
239             OSL_TRACE("The dialog was cancelled by the user!");
240             retVal = ExecutableDialogResults::CANCEL;
241             break;
242 
243         default:
244             throw uno::RuntimeException(rtl::OUString::createFromAscii("The dialog returned with an unknown result!"), static_cast< XFilePicker* >( this ));
245             break;
246     }
247 
248     DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal);
249 
250     return retVal;
251 }
252 
253 
254 #pragma mark XFilePicker
255 //-----------------------------------------------------------------------------------------
256 // XFilePicker functions
257 //-----------------------------------------------------------------------------------------
258 
259 void SAL_CALL SalAquaFilePicker::setMultiSelectionMode( sal_Bool bMode )
260 {
261     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "multiSelectable?", bMode);
262 
263     ::vos::OGuard aGuard( Application::GetSolarMutex() );
264 
265     if (m_nDialogType == NAVIGATIONSERVICES_OPEN) {
266         [(NSOpenPanel*)m_pDialog setAllowsMultipleSelection:YES];
267         OSL_TRACE("dialog allows multi-selection? %d", [(NSOpenPanel*)m_pDialog allowsMultipleSelection]);
268     }
269 
270     DBG_PRINT_EXIT(CLASS_NAME, __func__);
271 }
272 
273 void SAL_CALL SalAquaFilePicker::setDefaultName( const rtl::OUString& aName )
274 {
275     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "name", aName);
276 
277     ::vos::OGuard aGuard( Application::GetSolarMutex() );
278 
279     m_sSaveFileName = aName;
280 
281     DBG_PRINT_EXIT(CLASS_NAME, __func__);
282 }
283 
284 void SAL_CALL SalAquaFilePicker::setDisplayDirectory( const rtl::OUString& rDirectory )
285 {
286     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "directory", rDirectory);
287 
288     ::vos::OGuard aGuard( Application::GetSolarMutex() );
289 
290     implsetDisplayDirectory(rDirectory);
291 
292     DBG_PRINT_EXIT(CLASS_NAME, __func__);
293 }
294 
295 rtl::OUString SAL_CALL SalAquaFilePicker::getDisplayDirectory()
296 {
297     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
298 
299     rtl::OUString retVal = implgetDisplayDirectory();
300 
301     DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal);
302     return retVal;
303 }
304 
305 uno::Sequence<rtl::OUString> SAL_CALL SalAquaFilePicker::getFiles()
306 {
307     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
308 
309     ::vos::OGuard aGuard( Application::GetSolarMutex() );
310 
311     // OSL_TRACE("starting work");
312     /*
313      * If more than one file is selected in an OpenDialog, then the first result
314      * is the directory and the remaining results contain just the files' names
315      * without the basedir path.
316      */
317     NSArray *files = nil;
318     if (m_nDialogType == NAVIGATIONSERVICES_OPEN) {
319         files = [(NSOpenPanel*)m_pDialog URLs];
320     }
321     else if (m_nDialogType == NAVIGATIONSERVICES_SAVE) {
322         files = [NSArray arrayWithObjects:[m_pDialog URL], nil];
323     }
324 
325     long nFiles = [files count];
326     OSL_TRACE("# of items: %d", nFiles);
327 
328     uno::Sequence< rtl::OUString > aSelectedFiles(nFiles > 1 ? nFiles + 1 : nFiles);
329 
330     for(int nIndex = 0; nIndex < nFiles; nIndex += 1)
331     {
332         NSURL *url = [files objectAtIndex:nIndex];
333         OSL_TRACE("handling %s", [[url description] UTF8String]);
334         InfoType info = FULLPATH;
335         if (nFiles > 1) {
336             //just get the file's name (only in OpenDialog)
337             info = FILENAME;
338         }
339         OUString sFileOrDirURL = [url OUStringForInfo:info];
340 
341         //get the directory information, only on the first file processed
342         if (nIndex == 0) {
343             OUString sDirectoryURL = [url OUStringForInfo:PATHWITHOUTLASTCOMPONENT];
344 
345             if (nFiles > 1) {
346                 aSelectedFiles[0] = OUString(sDirectoryURL);
347             }
348         }
349 
350         short nSequenceIndex = nFiles > 1 ? nIndex + 1 : nIndex;
351         aSelectedFiles[nSequenceIndex] = sFileOrDirURL;
352 
353         OSL_TRACE("Returned file in getFiles: \"%s\".", OUStringToOString(sFileOrDirURL, RTL_TEXTENCODING_UTF8).getStr());
354     }
355 
356     DBG_PRINT_EXIT(CLASS_NAME, __func__);
357     return aSelectedFiles;
358 }
359 
360 #pragma mark XFilterManager
361 //-----------------------------------------------------------------------------------------
362 // XFilterManager functions
363 //-----------------------------------------------------------------------------------------
364 
365 void SAL_CALL SalAquaFilePicker::appendFilter( const rtl::OUString& aTitle, const rtl::OUString& aFilter )
366 {
367     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
368 
369     ::vos::OGuard aGuard( Application::GetSolarMutex() );
370 
371     ensureFilterHelper();
372     m_pFilterHelper->appendFilter( aTitle, aFilter );
373     m_pControlHelper->setFilterControlNeeded(YES);
374 
375     DBG_PRINT_EXIT(CLASS_NAME, __func__);
376 }
377 
378 void SAL_CALL SalAquaFilePicker::setCurrentFilter( const rtl::OUString& aTitle )
379 {
380     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
381     OSL_TRACE( "Setting current filter to %s",
382                OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() );
383 
384     ::vos::OGuard aGuard( Application::GetSolarMutex() );
385 
386     ensureFilterHelper();
387     m_pFilterHelper->setCurrentFilter(aTitle);
388     updateFilterUI();
389 
390     updateSaveFileNameExtension();
391 
392     DBG_PRINT_EXIT(CLASS_NAME, __func__);
393 }
394 
395 rtl::OUString SAL_CALL SalAquaFilePicker::getCurrentFilter()
396 {
397     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
398     ::vos::OGuard aGuard( Application::GetSolarMutex() );
399 
400     ensureFilterHelper();
401 
402     DBG_PRINT_EXIT(CLASS_NAME, __func__);
403     return m_pFilterHelper->getCurrentFilter();
404 }
405 
406 #pragma mark XFilterGroupManager
407 //-----------------------------------------------------------------------------------------
408 // XFilterGroupManager functions
409 //-----------------------------------------------------------------------------------------
410 
411 void SAL_CALL SalAquaFilePicker::appendFilterGroup( const rtl::OUString& sGroupTitle, const uno::Sequence<beans::StringPair>& aFilters )
412 {
413     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
414     ::vos::OGuard aGuard( Application::GetSolarMutex() );
415 
416     ensureFilterHelper();
417     m_pFilterHelper->appendFilterGroup(sGroupTitle, aFilters);
418     m_pControlHelper->setFilterControlNeeded(YES);
419     DBG_PRINT_EXIT(CLASS_NAME, __func__);
420 }
421 
422 #pragma mark XFilePickerControlAccess
423 //------------------------------------------------------------------------------------
424 // XFilePickerControlAccess functions
425 //------------------------------------------------------------------------------------
426 
427 void SAL_CALL SalAquaFilePicker::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any& rValue )
428 {
429     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
430 
431     ::vos::OGuard aGuard( Application::GetSolarMutex() );
432 
433     m_pControlHelper->setValue(nControlId, nControlAction, rValue);
434 
435     if (nControlId == ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION && m_nDialogType == NAVIGATIONSERVICES_SAVE) {
436         updateSaveFileNameExtension();
437     }
438 
439     DBG_PRINT_EXIT(CLASS_NAME, __func__);
440 }
441 
442 uno::Any SAL_CALL SalAquaFilePicker::getValue( sal_Int16 nControlId, sal_Int16 nControlAction )
443 {
444     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
445 
446     uno::Any aValue = m_pControlHelper->getValue(nControlId, nControlAction);
447 
448     DBG_PRINT_EXIT(CLASS_NAME, __func__);
449     return aValue;
450 }
451 
452 void SAL_CALL SalAquaFilePicker::enableControl( sal_Int16 nControlId, sal_Bool bEnable )
453 {
454     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
455 
456     m_pControlHelper->enableControl(nControlId, bEnable);
457 
458     DBG_PRINT_EXIT(CLASS_NAME, __func__);
459 }
460 
461 void SAL_CALL SalAquaFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString& aLabel )
462 {
463     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
464 
465     ::vos::OGuard aGuard( Application::GetSolarMutex() );
466 
467     NSString* sLabel = [NSString stringWithOUString:aLabel];
468     m_pControlHelper->setLabel( nControlId, sLabel ) ;
469 
470     DBG_PRINT_EXIT(CLASS_NAME, __func__);
471 }
472 
473 rtl::OUString SAL_CALL SalAquaFilePicker::getLabel( sal_Int16 nControlId )
474 {
475     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
476     DBG_PRINT_EXIT(CLASS_NAME, __func__);
477 
478     return m_pControlHelper->getLabel(nControlId);
479 }
480 
481 #pragma mark XInitialization
482 //------------------------------------------------------------------------------------
483 // XInitialization
484 //------------------------------------------------------------------------------------
485 
486 void SAL_CALL SalAquaFilePicker::initialize( const uno::Sequence<uno::Any>& aArguments )
487 {
488     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "arguments size", aArguments.getLength());
489 
490     ::vos::OGuard aGuard( Application::GetSolarMutex() );
491 
492     // parameter checking
493     uno::Any aAny;
494     if( 0 == aArguments.getLength() )
495         throw lang::IllegalArgumentException(rtl::OUString::createFromAscii( "no arguments" ),
496                                              static_cast<XFilePicker*>( this ), 1 );
497 
498     aAny = aArguments[0];
499 
500     if( ( aAny.getValueType() != ::getCppuType( ( sal_Int16* )0 ) ) &&
501         (aAny.getValueType() != ::getCppuType( ( sal_Int8* )0 ) ) )
502         throw lang::IllegalArgumentException(rtl::OUString::createFromAscii( "invalid argument type" ),
503                                              static_cast<XFilePicker*>( this ), 1 );
504 
505     sal_Int16 templateId = -1;
506     aAny >>= templateId;
507 
508     switch( templateId )
509     {
510         case FILEOPEN_SIMPLE:
511             m_nDialogType = NAVIGATIONSERVICES_OPEN;
512             OSL_TRACE( "Template: FILEOPEN_SIMPLE" );
513             break;
514         case FILESAVE_SIMPLE:
515             m_nDialogType = NAVIGATIONSERVICES_SAVE;
516             OSL_TRACE( "Template: FILESAVE_SIMPLE" );
517             break;
518         case FILESAVE_AUTOEXTENSION_PASSWORD:
519             m_nDialogType = NAVIGATIONSERVICES_SAVE;
520             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_PASSWORD" );
521             break;
522         case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
523             m_nDialogType = NAVIGATIONSERVICES_SAVE;
524             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS" );
525             break;
526         case FILESAVE_AUTOEXTENSION_SELECTION:
527             m_nDialogType = NAVIGATIONSERVICES_SAVE;
528             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_SELECTION" );
529             break;
530         case FILESAVE_AUTOEXTENSION_TEMPLATE:
531             m_nDialogType = NAVIGATIONSERVICES_SAVE;
532             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION_TEMPLATE" );
533             break;
534         case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
535             m_nDialogType = NAVIGATIONSERVICES_OPEN;
536             OSL_TRACE( "Template: FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE" );
537             break;
538         case FILEOPEN_PLAY:
539             m_nDialogType = NAVIGATIONSERVICES_OPEN;
540             OSL_TRACE( "Template: FILEOPEN_PLAY" );
541             break;
542         case FILEOPEN_READONLY_VERSION:
543             m_nDialogType = NAVIGATIONSERVICES_OPEN;
544             OSL_TRACE( "Template: FILEOPEN_READONLY_VERSION" );
545             break;
546         case FILEOPEN_LINK_PREVIEW:
547             m_nDialogType = NAVIGATIONSERVICES_OPEN;
548             OSL_TRACE( "Template: FILEOPEN_LINK_PREVIEW" );
549             break;
550         case FILESAVE_AUTOEXTENSION:
551             m_nDialogType = NAVIGATIONSERVICES_SAVE;
552             OSL_TRACE( "Template: FILESAVE_AUTOEXTENSION" );
553             break;
554         default:
555             throw lang::IllegalArgumentException(rtl::OUString::createFromAscii( "Unknown template" ),
556                                                  static_cast< XFilePicker* >( this ),
557                                                  1 );
558     }
559 
560     m_pControlHelper->initialize(templateId);
561 
562     implInitialize();
563 
564     DBG_PRINT_EXIT(CLASS_NAME, __func__);
565 }
566 
567 #pragma mark XCancellable
568 //------------------------------------------------------------------------------------
569 // XCancellable
570 //------------------------------------------------------------------------------------
571 
572 void SAL_CALL SalAquaFilePicker::cancel()
573 {
574     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
575 
576     ::vos::OGuard aGuard( Application::GetSolarMutex() );
577 
578     if (m_pDialog != nil) {
579         [m_pDialog cancel:nil];
580     }
581 
582     DBG_PRINT_EXIT(CLASS_NAME, __func__);
583 }
584 
585 #pragma mark XEventListener
586 //------------------------------------------------
587 // XEventListener
588 //------------------------------------------------
589 
590 void SAL_CALL SalAquaFilePicker::disposing( const lang::EventObject& aEvent )
591 {
592     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
593 
594     ::vos::OGuard aGuard( Application::GetSolarMutex() );
595 
596     uno::Reference<XFilePickerListener> xFilePickerListener( aEvent.Source, ::com::sun::star::uno::UNO_QUERY );
597 
598     if( xFilePickerListener.is() )
599         removeFilePickerListener( xFilePickerListener );
600 
601     DBG_PRINT_EXIT(CLASS_NAME, __func__);
602 }
603 
604 #pragma mark XServiceInfo
605 // -------------------------------------------------
606 // XServiceInfo
607 // -------------------------------------------------
608 
609 rtl::OUString SAL_CALL SalAquaFilePicker::getImplementationName()
610 {
611     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
612 
613     rtl::OUString retVal = rtl::OUString::createFromAscii( FILE_PICKER_IMPL_NAME );
614 
615     DBG_PRINT_EXIT(CLASS_NAME, __func__, retVal);
616 
617     return retVal;
618 }
619 
620 sal_Bool SAL_CALL SalAquaFilePicker::supportsService( const rtl::OUString& sServiceName )
621 {
622     DBG_PRINT_ENTRY(CLASS_NAME, __func__, "service name", sServiceName);
623 
624     sal_Bool retVal = sal_False;
625 
626     uno::Sequence <rtl::OUString> supportedServicesNames = FilePicker_getSupportedServiceNames();
627 
628     for( sal_Int32 n = supportedServicesNames.getLength(); n--; ) {
629         if( supportedServicesNames[n].compareTo( sServiceName ) == 0) {
630             retVal = sal_True;
631             break;
632         }
633     }
634 
635     DBG_PRINT_EXIT(CLASS_NAME, __func__);
636 
637     return retVal;
638 }
639 
640 uno::Sequence<rtl::OUString> SAL_CALL SalAquaFilePicker::getSupportedServiceNames()
641 {
642     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
643     DBG_PRINT_EXIT(CLASS_NAME, __func__);
644 
645     return FilePicker_getSupportedServiceNames();
646 }
647 
648 #pragma mark Misc/Private
649 //-----------------------------------------------------------------------------------------
650 // FilePicker Event functions
651 //-----------------------------------------------------------------------------------------
652 
653 void SAL_CALL SalAquaFilePicker::fileSelectionChanged( FilePickerEvent aEvent )
654 {
655     OSL_TRACE( "file selection changed");
656     if (m_xListener.is())
657         m_xListener->fileSelectionChanged( aEvent );
658 }
659 
660 void SAL_CALL SalAquaFilePicker::directoryChanged( FilePickerEvent aEvent )
661 {
662     OSL_TRACE("directory changed");
663     if (m_xListener.is())
664         m_xListener->directoryChanged( aEvent );
665 }
666 
667 void SAL_CALL SalAquaFilePicker::controlStateChanged( FilePickerEvent aEvent )
668 {
669     OSL_TRACE("control state changed");
670     if (m_xListener.is())
671         m_xListener->controlStateChanged( aEvent );
672 }
673 
674 void SAL_CALL SalAquaFilePicker::dialogSizeChanged()
675 {
676     OSL_TRACE("dialog size changed");
677     if (m_xListener.is())
678         m_xListener->dialogSizeChanged();
679 }
680 
681 //------------------------------------------------------------------------------------
682 
683 #define MAP_TOGGLE( elem ) \
684 case ExtendedFilePickerElementIds::CHECKBOX_##elem: \
685     pWidget = m_pToggles[elem]; \
686     break
687 
688 #define MAP_BUTTON( elem ) \
689 case ExtendedFilePickerElementIds::PUSHBUTTON_##elem: \
690     pWidget = m_pButtons[elem]; \
691     break
692 #undef MAP_LIST
693 #define MAP_LIST( elem ) \
694 case ExtendedFilePickerElementIds::LISTBOX_##elem: \
695     pWidget = m_pListControls[elem]; if (isAList != NULL) *isAList = sal_True; \
696     break
697 
698 #define MAP_LIST_LABEL( elem ) \
699 case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \
700     pWidget = m_pListControls[elem]; \
701     break
702 
703 //--------------------------------------------------
704 // Misc
705 //-------------------------------------------------
706 void SalAquaFilePicker::ensureFilterHelper() {
707     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
708 
709     ::vos::OGuard aGuard( Application::GetSolarMutex() );
710 
711     if (NULL == m_pFilterHelper) {
712         m_pFilterHelper = new FilterHelper;
713         m_pControlHelper->setFilterHelper(m_pFilterHelper);
714         [m_pDelegate setFilterHelper:m_pFilterHelper];
715     }
716 
717     DBG_PRINT_EXIT(CLASS_NAME, __func__);
718 }
719 
720 void SalAquaFilePicker::implInitialize()
721 {
722     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
723 
724     //call super
725     SalAquaPicker::implInitialize();
726 
727     DBG_PRINT_EXIT(CLASS_NAME, __func__);
728 }
729 
730 void SalAquaFilePicker::updateFilterUI() {
731     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
732 
733     m_pControlHelper->updateFilterUI();
734 
735     DBG_PRINT_EXIT(CLASS_NAME, __func__);
736 }
737 
738 void SalAquaFilePicker::updateSaveFileNameExtension() {
739     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
740 
741     if (m_nDialogType != NAVIGATIONSERVICES_SAVE) {
742         return;
743     }
744 
745     // we need to set this here again because initial setting does
746     //[m_pDialog setExtensionHidden:YES];
747 
748     ::vos::OGuard aGuard( Application::GetSolarMutex() );
749 
750     if (m_pControlHelper->isAutoExtensionEnabled() == false) {
751         OSL_TRACE("allowing other file types");
752         [m_pDialog setAllowedFileTypes:nil];
753         [m_pDialog setAllowsOtherFileTypes:YES];
754     } else {
755         ensureFilterHelper();
756 
757         OUStringList aStringList = m_pFilterHelper->getCurrentFilterSuffixList();
758         if( aStringList.empty()) // #i9328#
759             return;
760 
761         rtl::OUString suffix = (*(aStringList.begin())).copy(1);
762         NSString *requiredFileType = [NSString stringWithOUString:suffix];
763 
764         [m_pDialog setRequiredFileType:requiredFileType];
765 
766         OSL_TRACE("disallowing other file types");
767         [m_pDialog setAllowsOtherFileTypes:NO];
768     }
769 
770     DBG_PRINT_EXIT(CLASS_NAME, __func__);
771 }
772 
773 void SalAquaFilePicker::filterControlChanged() {
774     DBG_PRINT_ENTRY(CLASS_NAME, __func__);
775 
776     if (m_pDialog == nil) {
777         return;
778     }
779 
780     ::vos::OGuard aGuard( Application::GetSolarMutex() );
781 
782     updateSaveFileNameExtension();
783 
784     [m_pDialog validateVisibleColumns];
785 
786     FilePickerEvent evt;
787     evt.ElementId = LISTBOX_FILTER;
788     controlStateChanged( evt );
789 
790     DBG_PRINT_EXIT(CLASS_NAME, __func__);
791 }
792