1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/lang/DisposedException.hpp>
22 #include <cppuhelper/interfacecontainer.h>
23 #include <osl/diagnose.h>
25 #include "FilePicker.hxx"
26 #include "WinFileOpenImpl.hxx"
28 #include "FPServiceInfo.hxx"
29 #include "../misc/WinImplHelper.hxx"
30 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
31 #include "filepickereventnotification.hxx"
33 #include <comphelper/sequenceasvector.hxx>
35 //------------------------------------------------------------------------
36 // namespace directives
37 //------------------------------------------------------------------------
39 using namespace com::sun::star
;
41 using namespace ::com::sun::star::ui::dialogs
;
42 using namespace ::com::sun::star::ui::dialogs::TemplateDescription
;
44 #define FILE_PICKER_DLL_NAME TEXT("fps.dll")
46 //------------------------------------------------------------------------
48 //------------------------------------------------------------------------
52 // controling event notifications
53 const bool STARTUP_SUSPENDED
= true;
54 const bool STARTUP_ALIVE
= false;
56 uno::Sequence
<OUString
> SAL_CALL
FilePicker_getSupportedServiceNames()
58 uno::Sequence
<OUString
> aRet(2);
59 aRet
[0] = OUString("com.sun.star.ui.dialogs.FilePicker");
60 aRet
[1] = OUString("com.sun.star.ui.dialogs.SystemFilePicker");
65 //-----------------------------------------------------------------------------------------
67 //-----------------------------------------------------------------------------------------
69 CFilePicker::CFilePicker( const uno::Reference
<lang::XMultiServiceFactory
>& xServiceMgr
) :
70 CFilePicker_Base(m_rbHelperMtx
),
71 m_xServiceMgr(xServiceMgr
),
72 m_aAsyncEventNotifier(rBHelper
)
74 HINSTANCE hInstance
= GetModuleHandle(FILE_PICKER_DLL_NAME
);
75 OSL_POSTCOND( hInstance
, "The name of the service dll must have changed" );
77 // create a default FileOpen dialog without any additional ui elements
78 m_pImpl
= std::auto_ptr
< CWinFileOpenImpl
>(
87 //------------------------------------------------------------------------------------
88 // XFPEventListenerManager
89 //------------------------------------------------------------------------------------
91 void SAL_CALL
CFilePicker::addFilePickerListener(const uno::Reference
<XFilePickerListener
>& xListener
)
92 throw(uno::RuntimeException
)
94 if ( rBHelper
.bDisposed
)
95 throw lang::DisposedException(
96 OUString( "object is already disposed" ),
97 static_cast< XFilePicker2
* >( this ) );
99 if ( !rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
100 rBHelper
.aLC
.addInterface( getCppuType( &xListener
), xListener
);
103 //-----------------------------------------------------------------------------------------
105 //-----------------------------------------------------------------------------------------
107 void SAL_CALL
CFilePicker::removeFilePickerListener(const uno::Reference
<XFilePickerListener
>& xListener
)
108 throw(uno::RuntimeException
)
110 if ( rBHelper
.bDisposed
)
111 throw lang::DisposedException(
112 OUString( "object is already disposed" ),
113 static_cast< XFilePicker2
* >( this ) );
115 rBHelper
.aLC
.removeInterface( getCppuType( &xListener
), xListener
);
118 // -------------------------------------------------
120 // -------------------------------------------------
122 void SAL_CALL
CFilePicker::disposing(const lang::EventObject
& aEvent
) throw(uno::RuntimeException
)
124 uno::Reference
<XFilePickerListener
> xFilePickerListener(aEvent
.Source
, ::com::sun::star::uno::UNO_QUERY
);
126 if (xFilePickerListener
.is())
127 removeFilePickerListener(xFilePickerListener
);
130 //-----------------------------------------------------------------------------------------
132 //-----------------------------------------------------------------------------------------
134 void SAL_CALL
CFilePicker::fileSelectionChanged(FilePickerEvent aEvent
)
136 aEvent
.Source
= uno::Reference
<uno::XInterface
>(static_cast<XFilePickerNotifier
*>(this));
137 m_aAsyncEventNotifier
.notifyEvent(
138 new CFilePickerParamEventNotification(&XFilePickerListener::fileSelectionChanged
,aEvent
));
141 //-----------------------------------------------------------------------------------------
143 //-----------------------------------------------------------------------------------------
145 void SAL_CALL
CFilePicker::directoryChanged(FilePickerEvent aEvent
)
147 aEvent
.Source
= uno::Reference
<uno::XInterface
>(static_cast<XFilePickerNotifier
*>(this));
148 m_aAsyncEventNotifier
.notifyEvent(
149 new CFilePickerParamEventNotification(&XFilePickerListener::directoryChanged
,aEvent
));
152 //-----------------------------------------------------------------------------------------
154 //-----------------------------------------------------------------------------------------
156 void SAL_CALL
CFilePicker::controlStateChanged(FilePickerEvent aEvent
)
158 aEvent
.Source
= uno::Reference
<uno::XInterface
>(static_cast<XFilePickerNotifier
*>(this));
159 m_aAsyncEventNotifier
.notifyEvent(
160 new CFilePickerParamEventNotification(&XFilePickerListener::controlStateChanged
,aEvent
));
163 //-----------------------------------------------------------------------------------------
165 //-----------------------------------------------------------------------------------------
167 void SAL_CALL
CFilePicker::dialogSizeChanged()
169 m_aAsyncEventNotifier
.notifyEvent(
170 new CFilePickerEventNotification(&XFilePickerListener::dialogSizeChanged
));
173 //-----------------------------------------------------------------------------------------
174 // If there are more then one listener the return value of the last one wins
175 //-----------------------------------------------------------------------------------------
177 OUString SAL_CALL
CFilePicker::helpRequested(FilePickerEvent aEvent
) const
181 ::cppu::OInterfaceContainerHelper
* pICHelper
=
182 rBHelper
.getContainer( getCppuType((uno::Reference
<XFilePickerListener
>*)0));
186 ::cppu::OInterfaceIteratorHelper
iter(*pICHelper
);
188 while(iter
.hasMoreElements())
193 if there are multiple listeners responding
194 to this notification the next response
195 overwrittes the one before if it is not empty
200 uno::Reference
<XFilePickerListener
> xFPListener(iter
.next(), uno::UNO_QUERY
);
201 if (xFPListener
.is())
203 temp
= xFPListener
->helpRequested(aEvent
);
204 if (temp
.getLength())
209 catch(uno::RuntimeException
&)
211 OSL_FAIL( "RuntimeException during event dispatching" );
219 //-------------------------------------
221 //-------------------------------------
223 bool CFilePicker::startupEventNotification(bool bStartupSuspended
)
225 return m_aAsyncEventNotifier
.startup(bStartupSuspended
);
228 //-------------------------------------
230 //-------------------------------------
232 void CFilePicker::shutdownEventNotification()
234 m_aAsyncEventNotifier
.shutdown();
237 //-------------------------------------
239 //-------------------------------------
241 void CFilePicker::suspendEventNotification()
243 m_aAsyncEventNotifier
.suspend();
246 //-------------------------------------
248 //-------------------------------------
250 void CFilePicker::resumeEventNotification()
252 m_aAsyncEventNotifier
.resume();
255 //------------------------------------------------------------------------------------
256 // XFilePicker functions
257 //------------------------------------------------------------------------------------
259 void SAL_CALL
CFilePicker::setMultiSelectionMode(sal_Bool bMode
) throw(uno::RuntimeException
)
261 OSL_ASSERT(0 != m_pImpl
.get());
262 osl::MutexGuard
aGuard(m_aMutex
);
263 m_pImpl
->setMultiSelectionMode(bMode
);
266 //-----------------------------------------------------------------------------------------
268 //-----------------------------------------------------------------------------------------
270 void SAL_CALL
CFilePicker::setTitle(const OUString
& aTitle
) throw(uno::RuntimeException
)
272 OSL_ASSERT(0 != m_pImpl
.get());
273 osl::MutexGuard
aGuard(m_aMutex
);
274 m_pImpl
->setTitle(aTitle
);
277 //-----------------------------------------------------------------------------------------
279 //-----------------------------------------------------------------------------------------
281 void SAL_CALL
CFilePicker::appendFilter(const OUString
& aTitle
, const OUString
& aFilter
)
282 throw(lang::IllegalArgumentException
, uno::RuntimeException
)
284 OSL_ASSERT(0 != m_pImpl
.get());
285 osl::MutexGuard
aGuard(m_aMutex
);
286 m_pImpl
->appendFilter(aTitle
, aFilter
);
289 //-----------------------------------------------------------------------------------------
291 //-----------------------------------------------------------------------------------------
293 void SAL_CALL
CFilePicker::setCurrentFilter(const OUString
& aTitle
)
294 throw(lang::IllegalArgumentException
, uno::RuntimeException
)
296 OSL_ASSERT(0 != m_pImpl
.get());
297 osl::MutexGuard
aGuard(m_aMutex
);
298 m_pImpl
->setCurrentFilter(aTitle
);
301 //-----------------------------------------------------------------------------------------
303 //-----------------------------------------------------------------------------------------
305 OUString SAL_CALL
CFilePicker::getCurrentFilter() throw(uno::RuntimeException
)
307 OSL_ASSERT(0 != m_pImpl
.get());
308 osl::MutexGuard
aGuard(m_aMutex
);
309 return m_pImpl
->getCurrentFilter();
312 //-----------------------------------------------------------------------------------------
314 //-----------------------------------------------------------------------------------------
316 void SAL_CALL
CFilePicker::appendFilterGroup(const OUString
& sGroupTitle
, const uno::Sequence
<beans::StringPair
>& aFilters
)
317 throw (lang::IllegalArgumentException
, uno::RuntimeException
)
319 OSL_ASSERT(0 != m_pImpl
.get());
320 osl::MutexGuard
aGuard(m_aMutex
);
321 m_pImpl
->appendFilterGroup(sGroupTitle
, aFilters
);
324 //-----------------------------------------------------------------------------------------
326 //-----------------------------------------------------------------------------------------
328 void SAL_CALL
CFilePicker::setDefaultName(const OUString
& aName
)
329 throw(uno::RuntimeException
)
331 OSL_ASSERT(0 != m_pImpl
.get());
332 osl::MutexGuard
aGuard(m_aMutex
);
333 m_pImpl
->setDefaultName(aName
);
336 //-----------------------------------------------------------------------------------------
338 //-----------------------------------------------------------------------------------------
340 void SAL_CALL
CFilePicker::setDisplayDirectory(const OUString
& aDirectory
)
341 throw(lang::IllegalArgumentException
, uno::RuntimeException
)
343 OSL_ASSERT(0 != m_pImpl
.get());
344 osl::MutexGuard
aGuard(m_aMutex
);
345 m_pImpl
->setDisplayDirectory(aDirectory
);
348 //-----------------------------------------------------------------------------------------
350 //-----------------------------------------------------------------------------------------
352 OUString SAL_CALL
CFilePicker::getDisplayDirectory() throw(uno::RuntimeException
)
354 OSL_ASSERT(0 != m_pImpl
.get());
355 osl::MutexGuard
aGuard(m_aMutex
);
356 return m_pImpl
->getDisplayDirectory();
359 //-----------------------------------------------------------------------------------------
361 //-----------------------------------------------------------------------------------------
363 uno::Sequence
<OUString
> SAL_CALL
CFilePicker::getFiles() throw(uno::RuntimeException
)
365 OSL_ASSERT(0 != m_pImpl
.get());
366 osl::MutexGuard
aGuard(m_aMutex
);
367 return m_pImpl
->getFiles();
370 //-----------------------------------------------------------------------------------------
372 //-----------------------------------------------------------------------------------------
373 uno::Sequence
< OUString
> SAL_CALL
CFilePicker::getSelectedFiles() throw (uno::RuntimeException
)
375 OSL_ASSERT(0 != m_pImpl
.get());
376 osl::MutexGuard
aGuard(m_aMutex
);
378 const uno::Sequence
< OUString
> lSource
= m_pImpl
->getFiles();
379 const ::sal_Int32 c
= lSource
.getLength();
383 const OUString sPath
= lSource
[0];
384 ::comphelper::SequenceAsVector
< OUString
> lTarget
;
388 const OUString sFile
= lSource
[i
];
389 if (sFile
.indexOf ('/') > 0)
391 // a) file contains own path !
392 lTarget
.push_back(sFile
);
396 // b) file is relative to given path
397 OUStringBuffer
sFull(256);
399 sFull
.append (sPath
);
400 sFull
.appendAscii("/" );
401 sFull
.append (sFile
);
403 lTarget
.push_back(sFull
.makeStringAndClear());
407 return lTarget
.getAsConstList();
410 //-----------------------------------------------------------------------------------------
412 //-----------------------------------------------------------------------------------------
414 sal_Int16 SAL_CALL
CFilePicker::execute() throw(uno::RuntimeException
)
416 OSL_ASSERT(0 != m_pImpl
.get());
420 if (startupEventNotification(STARTUP_SUSPENDED
))
422 // we should not block in this call else
423 // in the case of an event the client can't
424 // call another function an we run into a
426 ret
= m_pImpl
->execute( );
428 shutdownEventNotification();
432 OSL_FAIL("Could not start event notifier thread!");
434 throw uno::RuntimeException(
435 OUString("Error executing dialog"),
436 static_cast<XFilePicker2
*>(this));
442 //------------------------------------------------------------------------------------
443 // XFilePicker functions
444 //------------------------------------------------------------------------------------
446 void SAL_CALL
CFilePicker::setValue(sal_Int16 aControlId
, sal_Int16 aControlAction
, const uno::Any
& aValue
)
447 throw(uno::RuntimeException
)
449 OSL_ASSERT(0 != m_pImpl
.get());
451 osl::MutexGuard
aGuard(m_aMutex
);
452 m_pImpl
->setValue(aControlId
, aControlAction
, aValue
);
455 //-----------------------------------------------------------------------------------------
457 //-----------------------------------------------------------------------------------------
459 uno::Any SAL_CALL
CFilePicker::getValue(sal_Int16 aControlId
, sal_Int16 aControlAction
)
460 throw(uno::RuntimeException
)
462 OSL_ASSERT(0 != m_pImpl
.get());
464 osl::MutexGuard
aGuard(m_aMutex
);
465 return m_pImpl
->getValue(aControlId
, aControlAction
);
468 //-----------------------------------------------------------------------------------------
470 //-----------------------------------------------------------------------------------------
472 void SAL_CALL
CFilePicker::enableControl(sal_Int16 aControlId
, sal_Bool bEnable
)
473 throw(uno::RuntimeException
)
475 OSL_ASSERT( 0 != m_pImpl
.get( ) );
477 osl::MutexGuard
aGuard( m_aMutex
);
478 m_pImpl
->enableControl( aControlId
, bEnable
);
481 //-----------------------------------------------------------------------------------------
483 //-----------------------------------------------------------------------------------------
485 void SAL_CALL
CFilePicker::setLabel(sal_Int16 aControlId
, const OUString
& aLabel
)
486 throw (uno::RuntimeException
)
488 OSL_ASSERT(0 != m_pImpl
.get());
490 osl::MutexGuard
aGuard(m_aMutex
);
491 m_pImpl
->setLabel(aControlId
, aLabel
);
494 //-----------------------------------------------------------------------------------------
496 //-----------------------------------------------------------------------------------------
498 OUString SAL_CALL
CFilePicker::getLabel(sal_Int16 aControlId
)
499 throw (uno::RuntimeException
)
501 OSL_ASSERT(0 != m_pImpl
.get());
503 osl::MutexGuard
aGuard(m_aMutex
);
504 return m_pImpl
->getLabel(aControlId
);
507 //------------------------------------------------------------------------------------
509 //------------------------------------------------------------------------------------
511 uno::Sequence
<sal_Int16
> SAL_CALL
CFilePicker::getSupportedImageFormats() throw (uno::RuntimeException
)
513 OSL_ASSERT(0 != m_pImpl
.get());
515 osl::MutexGuard
aGuard(m_aMutex
);
516 return m_pImpl
->getSupportedImageFormats();
519 //------------------------------------------------------------------------------------
521 //------------------------------------------------------------------------------------
523 sal_Int32 SAL_CALL
CFilePicker::getTargetColorDepth() throw (uno::RuntimeException
)
525 OSL_ASSERT(0 != m_pImpl
.get());
527 osl::MutexGuard
aGuard(m_aMutex
);
528 return m_pImpl
->getTargetColorDepth();
531 //------------------------------------------------------------------------------------
533 //------------------------------------------------------------------------------------
535 sal_Int32 SAL_CALL
CFilePicker::getAvailableWidth() throw (uno::RuntimeException
)
537 OSL_ASSERT(0 != m_pImpl
.get());
539 osl::MutexGuard
aGuard(m_aMutex
);
540 return m_pImpl
->getAvailableWidth();
543 //------------------------------------------------------------------------------------
545 //------------------------------------------------------------------------------------
547 sal_Int32 SAL_CALL
CFilePicker::getAvailableHeight() throw (uno::RuntimeException
)
549 OSL_ASSERT(0 != m_pImpl
.get());
551 osl::MutexGuard
aGuard(m_aMutex
);
552 return m_pImpl
->getAvailableHeight();
555 //------------------------------------------------------------------------------------
557 //------------------------------------------------------------------------------------
559 void SAL_CALL
CFilePicker::setImage(sal_Int16 aImageFormat
, const uno::Any
& aImage
)
560 throw (lang::IllegalArgumentException
, uno::RuntimeException
)
562 OSL_ASSERT(0 != m_pImpl
.get());
564 osl::MutexGuard
aGuard(m_aMutex
);
565 m_pImpl
->setImage(aImageFormat
, aImage
);
568 //------------------------------------------------------------------------------------
570 //------------------------------------------------------------------------------------
572 sal_Bool SAL_CALL
CFilePicker::setShowState(sal_Bool bShowState
) throw (uno::RuntimeException
)
574 OSL_ASSERT(0 != m_pImpl
.get());
576 osl::MutexGuard
aGuard(m_aMutex
);
577 return m_pImpl
->setShowState(bShowState
);
580 //------------------------------------------------------------------------------------
582 //------------------------------------------------------------------------------------
584 sal_Bool SAL_CALL
CFilePicker::getShowState() throw (uno::RuntimeException
)
586 OSL_ASSERT(0 != m_pImpl
.get());
588 osl::MutexGuard
aGuard(m_aMutex
);
589 return m_pImpl
->getShowState();
592 //------------------------------------------------------------------------------------
594 //------------------------------------------------------------------------------------
596 void SAL_CALL
CFilePicker::initialize(const uno::Sequence
<uno::Any
>& aArguments
)
597 throw( uno::Exception
, uno::RuntimeException
)
599 // parameter checking
601 if ( 0 == aArguments
.getLength( ) )
602 throw lang::IllegalArgumentException(
603 OUString( "no arguments" ),
604 static_cast<XFilePicker2
*>(this), 1);
606 aAny
= aArguments
[0];
608 if ( (aAny
.getValueType() != ::getCppuType((sal_Int16
*)0)) &&
609 (aAny
.getValueType() != ::getCppuType((sal_Int8
*)0)) )
610 throw lang::IllegalArgumentException(
611 OUString("invalid argument type"),
612 static_cast<XFilePicker2
*>(this), 1);
614 sal_Int16 templateId
= -1;
617 sal_Bool bFileOpenDialog
= sal_True
;
618 sal_uInt32 winResTemplateId
= 0;
620 switch ( templateId
)
622 case FILEOPEN_SIMPLE
:
623 bFileOpenDialog
= sal_True
;
626 case FILESAVE_SIMPLE
:
627 bFileOpenDialog
= sal_False
;
630 case FILESAVE_AUTOEXTENSION_PASSWORD
:
631 bFileOpenDialog
= sal_False
;
632 winResTemplateId
= TMPL2000_FILESAVE_AUTOEXT_PASSWORD_BOX_ID
;
635 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
636 bFileOpenDialog
= sal_False
;
637 winResTemplateId
= TMPL2000_AUTOEXT_PASSWORD_FILTEROPTION_BOX
;
640 case FILESAVE_AUTOEXTENSION_SELECTION
:
641 bFileOpenDialog
= sal_False
;
642 winResTemplateId
= TMPL2000_AUTOEXT_SELECTION_BOX
;
645 case FILESAVE_AUTOEXTENSION_TEMPLATE
:
646 bFileOpenDialog
= sal_False
;
647 winResTemplateId
= TMPL2000_FILEOPEN_AUTOEXT_TEMPLATE_BOX_ID
;
650 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
651 winResTemplateId
= TMPL2000_FILEOPEN_LINK_PREVIEW_BOX_ID
;
655 winResTemplateId
= TMPL2000_PLAY_PUSHBUTTON
;
658 case FILEOPEN_READONLY_VERSION
:
659 winResTemplateId
= TMPL2000_FILEOPEN_READONLY_VERSION_BOX_ID
;
662 case FILEOPEN_LINK_PREVIEW
:
663 winResTemplateId
= TMPL2000_FILEOPEN_LINK_PREVIEW_BOX_SIMPLE_ID
;
666 case FILESAVE_AUTOEXTENSION
:
667 bFileOpenDialog
= sal_False
;
668 winResTemplateId
= TMPL2000_FILESAVE_AUTOEXT
;
672 throw lang::IllegalArgumentException(
673 OUString( "Unknown template" ),
674 static_cast< XFilePicker2
* >( this ),
678 HINSTANCE hInstance
= GetModuleHandle( FILE_PICKER_DLL_NAME
);
679 OSL_POSTCOND( hInstance
, "The name of the service dll must have changed" );
681 // create a new impl-class here based on the
682 // given string, if the given string is empty
684 m_pImpl
= std::auto_ptr
< CWinFileOpenImpl
>(
685 new CWinFileOpenImpl(
693 //------------------------------------------------------------------------------------
695 //------------------------------------------------------------------------------------
697 void SAL_CALL
CFilePicker::cancel()
698 throw(uno::RuntimeException
)
700 OSL_ASSERT(m_pImpl
.get());
702 osl::MutexGuard
aGuard(m_aMutex
);
706 // -------------------------------------------------
708 // -------------------------------------------------
710 OUString SAL_CALL
CFilePicker::getImplementationName()
711 throw(uno::RuntimeException
)
713 return OUString(RTL_CONSTASCII_USTRINGPARAM(FILE_PICKER_IMPL_NAME
));
716 // -------------------------------------------------
718 // -------------------------------------------------
720 sal_Bool SAL_CALL
CFilePicker::supportsService(const OUString
& ServiceName
)
721 throw(uno::RuntimeException
)
723 uno::Sequence
<OUString
> SupportedServicesNames
= FilePicker_getSupportedServiceNames();
725 for (sal_Int32 n
= SupportedServicesNames
.getLength(); n
--;)
726 if (SupportedServicesNames
[n
] == ServiceName
)
732 // -------------------------------------------------
734 // -------------------------------------------------
736 uno::Sequence
<OUString
> SAL_CALL
CFilePicker::getSupportedServiceNames()
737 throw(uno::RuntimeException
)
739 return FilePicker_getSupportedServiceNames();
742 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */