1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: VistaFilePickerImpl.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 //-----------------------------------------------------------------------------
33 //-----------------------------------------------------------------------------
35 #include "VistaFilePickerImpl.hxx"
37 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
38 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
39 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
40 #include <comphelper/sequenceasvector.hxx>
41 #include <osl/file.hxx>
42 #include <osl/mutex.hxx>
46 #include "..\misc\WinImplHelper.hxx"
48 inline bool is_current_process_window(HWND hwnd
)
51 GetWindowThreadProcessId(hwnd
, &pid
);
52 return (pid
== GetCurrentProcessId());
55 HWND
choose_parent_window()
57 HWND hwnd_parent
= GetForegroundWindow();
58 if (!is_current_process_window(hwnd_parent
))
59 hwnd_parent
= GetDesktopWindow();
63 //-----------------------------------------------------------------------------
65 //-----------------------------------------------------------------------------
71 namespace css
= ::com::sun::star
;
73 //-----------------------------------------------------------------------------
74 // types, const etcpp.
75 //-----------------------------------------------------------------------------
78 static const ::sal_Int16 INVALID_CONTROL_ID
= -1;
79 static const ::sal_Int16 INVALID_CONTROL_ACTION
= -1;
81 typedef ::comphelper::SequenceAsVector
< ::rtl::OUString
> TStringList
;
83 // Guids used for IFileDialog::SetClientGuid
84 static const GUID CLIENTID_FILEDIALOG_SIMPLE
= {0xB8628FD3, 0xA3F5, 0x4845, 0x9B, 0x62, 0xD5, 0x1E, 0xDF, 0x97, 0xC4, 0x83};
85 static const GUID CLIENTID_FILEDIALOG_OPTIONS
= {0x93ED486F, 0x0D04, 0x4807, 0x8C, 0x44, 0xAC, 0x26, 0xCB, 0x6C, 0x5D, 0x36};
86 static const GUID CLIENTID_FILESAVE
= {0x3B2E2261, 0x402D, 0x4049, 0xB0, 0xC0, 0x91, 0x13, 0xF8, 0x6E, 0x84, 0x7C};
87 static const GUID CLIENTID_FILESAVE_PASSWORD
= {0xC12D4F4C, 0x4D41, 0x4D4F, 0x97, 0xEF, 0x87, 0xF9, 0x8D, 0xB6, 0x1E, 0xA6};
88 static const GUID CLIENTID_FILESAVE_SELECTION
= {0x5B2482B3, 0x0358, 0x4E09, 0xAA, 0x64, 0x2B, 0x76, 0xB2, 0xA0, 0xDD, 0xFE};
89 static const GUID CLIENTID_FILESAVE_TEMPLATE
= {0x9996D877, 0x20D5, 0x424B, 0x9C, 0x2E, 0xD3, 0xB6, 0x31, 0xEC, 0xF7, 0xCE};
90 static const GUID CLIENTID_FILEOPEN_LINK_TEMPLATE
= {0x32237796, 0x1509, 0x49D1, 0xBB, 0x7E, 0x63, 0xAD, 0x36, 0xAE, 0x86, 0x8C};
91 static const GUID CLIENTID_FILEOPEN_PLAY
= {0x32CFB147, 0xF5AE, 0x4F90, 0xA1, 0xF1, 0x81, 0x20, 0x72, 0xBB, 0x2F, 0xC5};
92 static const GUID CLIENTID_FILEOPEN_LINK
= {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE, 0x2E, 0xF8, 0x8C, 0xB5, 0x65, 0x5E, 0x6A};
94 //-----------------------------------------------------------------------------
95 ::rtl::OUString
lcl_getURLFromShellItem (IShellItem
* pItem
)
100 SIGDN eConversion
= SIGDN_FILESYSPATH
;
101 HRESULT hr
= pItem
->GetDisplayName ( eConversion
, &pStr
);
105 eConversion
= SIGDN_URL
;
106 hr
= pItem
->GetDisplayName ( eConversion
, &pStr
);
109 return ::rtl::OUString();
111 sURL
= ::rtl::OUString(reinterpret_cast<sal_Unicode
*>(pStr
));
115 ::osl::FileBase::getFileURLFromSystemPath( reinterpret_cast<sal_Unicode
*>(pStr
), sURL
);
118 CoTaskMemFree (pStr
);
122 //-----------------------------------------------------------------------------------------
123 ::std::vector
< COMDLG_FILTERSPEC
> lcl_buildFilterList(CFilterContainer
& rContainer
)
125 const sal_Int32 c
= rContainer
.numFilter();
127 ::std::vector
< COMDLG_FILTERSPEC
> lList
;
128 CFilterContainer::FILTER_ENTRY_T aFilter
;
130 rContainer
.beginEnumFilter( );
131 while( rContainer
.getNextFilter(aFilter
) )
133 COMDLG_FILTERSPEC aSpec
;
135 aSpec
.pszName
= reinterpret_cast<LPCTSTR
>(aFilter
.first
.getStr()) ;
136 aSpec
.pszSpec
= reinterpret_cast<LPCTSTR
>(aFilter
.second
.getStr());
138 lList
.push_back(aSpec
);
144 //-----------------------------------------------------------------------------------------
145 VistaFilePickerImpl::VistaFilePickerImpl()
151 , m_iEventHandler(new VistaFilePickerEventHandler(this))
152 , m_bInExecute (sal_False
)
156 m_hParentWindow
= choose_parent_window();
159 //-------------------------------------------------------------------------------
160 VistaFilePickerImpl::~VistaFilePickerImpl()
164 //-------------------------------------------------------------------------------
165 void VistaFilePickerImpl::before()
168 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
171 // osl::Thread class initializes COm already in MTA mode because it's needed
172 // by VCL and UNO so. There is no way to change that from outside ...
173 // but we need a STA environment ...
174 // So we make it by try-and-error ...
175 // If first CoInitialize will fail .. we unitialize COM initialize it new .-)
177 m_hLastResult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
178 if ( FAILED(m_hLastResult
) )
181 m_hLastResult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
185 //-------------------------------------------------------------------------------
186 void VistaFilePickerImpl::doRequest(const RequestRef
& rRequest
)
190 switch(rRequest
->getRequest())
192 case E_ADD_PICKER_LISTENER
:
193 impl_sta_addFilePickerListener(rRequest
);
196 case E_REMOVE_PICKER_LISTENER
:
197 impl_sta_removeFilePickerListener(rRequest
);
200 case E_APPEND_FILTER
:
201 impl_sta_appendFilter(rRequest
);
204 case E_SET_CURRENT_FILTER
:
205 impl_sta_setCurrentFilter(rRequest
);
208 case E_GET_CURRENT_FILTER
:
209 impl_sta_getCurrentFilter(rRequest
);
212 case E_CREATE_OPEN_DIALOG
:
213 impl_sta_CreateOpenDialog(rRequest
);
216 case E_CREATE_SAVE_DIALOG
:
217 impl_sta_CreateSaveDialog(rRequest
);
220 case E_SET_MULTISELECTION_MODE
:
221 impl_sta_SetMultiSelectionMode(rRequest
);
225 impl_sta_SetTitle(rRequest
);
229 impl_sta_SetFileName(rRequest
);
232 case E_SET_DIRECTORY
:
233 impl_sta_SetDirectory(rRequest
);
236 case E_GET_DIRECTORY
:
237 impl_sta_GetDirectory(rRequest
);
240 case E_SET_DEFAULT_NAME
:
241 impl_sta_SetDefaultName(rRequest
);
244 case E_GET_SELECTED_FILES
:
245 impl_sta_getSelectedFiles(rRequest
);
248 case E_SHOW_DIALOG_MODAL
:
249 impl_sta_ShowDialogModal(rRequest
);
252 case E_SET_CONTROL_VALUE
:
253 impl_sta_SetControlValue(rRequest
);
256 case E_GET_CONTROL_VALUE
:
257 impl_sta_GetControlValue(rRequest
);
260 case E_SET_CONTROL_LABEL
:
261 impl_sta_SetControlLabel(rRequest
);
264 case E_GET_CONTROL_LABEL
:
265 impl_sta_GetControlLabel(rRequest
);
268 case E_ENABLE_CONTROL
:
269 impl_sta_EnableControl(rRequest
);
272 // no default: let the compiler detect changes on enum ERequest !
279 //-------------------------------------------------------------------------------
280 void VistaFilePickerImpl::after()
285 //-------------------------------------------------------------------------------
286 void VistaFilePickerImpl::impl_sta_addFilePickerListener(const RequestRef
& rRequest
)
288 // SYNCHRONIZED outside !
289 const css::uno::Reference
< css::ui::dialogs::XFilePickerListener
> xListener
= rRequest
->getArgumentOrDefault(PROP_PICKER_LISTENER
, css::uno::Reference
< css::ui::dialogs::XFilePickerListener
>());
290 if ( ! xListener
.is())
294 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
295 TFileDialogEvents iHandler
= m_iEventHandler
;
299 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
301 pHandlerImpl
->addFilePickerListener(xListener
);
304 //-------------------------------------------------------------------------------
305 void VistaFilePickerImpl::impl_sta_removeFilePickerListener(const RequestRef
& rRequest
)
307 // SYNCHRONIZED outside !
308 const css::uno::Reference
< css::ui::dialogs::XFilePickerListener
> xListener
= rRequest
->getArgumentOrDefault(PROP_PICKER_LISTENER
, css::uno::Reference
< css::ui::dialogs::XFilePickerListener
>());
309 if ( ! xListener
.is())
313 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
314 TFileDialogEvents iHandler
= m_iEventHandler
;
318 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
320 pHandlerImpl
->removeFilePickerListener(xListener
);
323 //-------------------------------------------------------------------------------
324 void VistaFilePickerImpl::impl_sta_appendFilter(const RequestRef
& rRequest
)
326 const ::rtl::OUString sTitle
= rRequest
->getArgumentOrDefault(PROP_FILTER_TITLE
, ::rtl::OUString());
327 const ::rtl::OUString sFilter
= rRequest
->getArgumentOrDefault(PROP_FILTER_VALUE
, ::rtl::OUString());
330 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
332 m_lFilters
.addFilter(sTitle
, sFilter
);
335 //-------------------------------------------------------------------------------
336 void VistaFilePickerImpl::impl_sta_setCurrentFilter(const RequestRef
& rRequest
)
338 const ::rtl::OUString sTitle
= rRequest
->getArgumentOrDefault(PROP_FILTER_TITLE
, ::rtl::OUString());
341 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
343 m_lFilters
.setCurrentFilter(sTitle
);
346 //-------------------------------------------------------------------------------
347 void VistaFilePickerImpl::impl_sta_getCurrentFilter(const RequestRef
& rRequest
)
349 TFileDialog iDialog
= impl_getBaseDialogInterface();
350 UINT nIndex
= UINT_MAX
;
351 HRESULT hResult
= iDialog
->GetFileTypeIndex(&nIndex
);
353 ( FAILED(hResult
) ) ||
354 ( nIndex
== UINT_MAX
) // COM dialog sometimes return S_OK for empty filter lists .-(
359 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
361 ::rtl::OUString sTitle
;
362 ::sal_Int32 nRealIndex
= (nIndex
-1); // COM dialog base on 1 ... filter container on 0 .-)
364 (nRealIndex
>= 0 ) &&
365 (m_lFilters
.getFilter(nRealIndex
, sTitle
))
367 rRequest
->setArgument(PROP_FILTER_TITLE
, sTitle
);
368 else if ( nRealIndex
== -1 ) // Dialog not visible yet
370 sTitle
= m_lFilters
.getCurrentFilter();
371 rRequest
->setArgument(PROP_FILTER_TITLE
, sTitle
);
378 //-------------------------------------------------------------------------------
379 void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef
& rRequest
)
382 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
384 m_hLastResult
= m_iDialogOpen
.create();
385 if (FAILED(m_hLastResult
))
390 m_iDialogOpen
->QueryInterface(IID_IFileDialog
, (void **)(&iDialog
));
392 m_iDialogOpen
.query(&iDialog
);
395 TFileDialogEvents iHandler
= m_iEventHandler
;
401 iDialog
->GetOptions ( &nFlags
);
403 nFlags
&= ~FOS_FORCESHOWHIDDEN
;
404 nFlags
|= FOS_PATHMUSTEXIST
;
405 nFlags
|= FOS_FILEMUSTEXIST
;
406 nFlags
|= FOS_OVERWRITEPROMPT
;
407 nFlags
|= FOS_DONTADDTORECENT
;
409 iDialog
->SetOptions ( nFlags
);
411 ::sal_Int32 nFeatures
= rRequest
->getArgumentOrDefault(PROP_FEATURES
, (::sal_Int32
)0);
412 ::sal_Int32 nTemplate
= rRequest
->getArgumentOrDefault(PROP_TEMPLATE_DESCR
, (::sal_Int32
)0);
413 impl_sta_enableFeatures(nFeatures
, nTemplate
);
415 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
417 pHandlerImpl
->startListening(iDialog
);
420 //-------------------------------------------------------------------------------
421 void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef
& rRequest
)
424 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
426 m_hLastResult
= m_iDialogSave
.create();
427 if (FAILED(m_hLastResult
))
430 TFileDialogEvents iHandler
= m_iEventHandler
;
433 m_iDialogSave
->QueryInterface(IID_IFileDialog
, (void **)(&iDialog
));
435 m_iDialogSave
.query(&iDialog
);
442 iDialog
->GetOptions ( &nFlags
);
444 nFlags
&= ~FOS_FORCESHOWHIDDEN
;
445 nFlags
|= FOS_PATHMUSTEXIST
;
446 nFlags
|= FOS_FILEMUSTEXIST
;
447 nFlags
|= FOS_OVERWRITEPROMPT
;
448 nFlags
|= FOS_DONTADDTORECENT
;
450 iDialog
->SetOptions ( nFlags
);
452 ::sal_Int32 nFeatures
= rRequest
->getArgumentOrDefault(PROP_FEATURES
, (::sal_Int32
)0);
453 ::sal_Int32 nTemplate
= rRequest
->getArgumentOrDefault(PROP_TEMPLATE_DESCR
, (::sal_Int32
)0);
454 impl_sta_enableFeatures(nFeatures
, nTemplate
);
456 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
458 pHandlerImpl
->startListening(iDialog
);
461 //-------------------------------------------------------------------------------
462 static const ::sal_Int32 GROUP_VERSION
= 1;
463 static const ::sal_Int32 GROUP_TEMPLATE
= 2;
464 static const ::sal_Int32 GROUP_IMAGETEMPLATE
= 3;
465 static const ::sal_Int32 GROUP_CHECKBOXES
= 4;
467 //-------------------------------------------------------------------------------
468 static void setLabelToControl(CResourceProvider
& rResourceProvider
, TFileDialogCustomize iCustom
, sal_uInt16 nControlId
)
470 ::rtl::OUString aLabel
= rResourceProvider
.getResString(nControlId
);
471 aLabel
= SOfficeToWindowsLabel(aLabel
);
472 iCustom
->SetControlLabel(nControlId
, reinterpret_cast<LPCWSTR
>(aLabel
.getStr()) );
475 //-------------------------------------------------------------------------------
476 void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures
, ::sal_Int32 nTemplate
)
481 case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE
:
482 case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE
:
483 aGUID
= CLIENTID_FILEDIALOG_SIMPLE
;
486 case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION
:
487 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
488 aGUID
= CLIENTID_FILEDIALOG_OPTIONS
;
491 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION
:
492 aGUID
= CLIENTID_FILESAVE
;
495 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
:
496 aGUID
= CLIENTID_FILESAVE_PASSWORD
;
499 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION
:
500 aGUID
= CLIENTID_FILESAVE_SELECTION
;
503 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE
:
504 aGUID
= CLIENTID_FILESAVE_TEMPLATE
;
507 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
508 aGUID
= CLIENTID_FILEOPEN_LINK_TEMPLATE
;
511 case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY
:
512 aGUID
= CLIENTID_FILEOPEN_PLAY
;
515 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW
:
516 aGUID
= CLIENTID_FILEOPEN_LINK
;
519 TFileDialog iDialog
= impl_getBaseDialogInterface();
520 iDialog
->SetClientGuid ( aGUID
);
522 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
524 if ((nFeatures
& FEATURE_VERSION
) == FEATURE_VERSION
)
526 iCustom
->StartVisualGroup (GROUP_VERSION
, L
"Version");
527 iCustom
->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION
);
528 iCustom
->EndVisualGroup ();
529 iCustom
->MakeProminent (GROUP_VERSION
);
532 if ((nFeatures
& FEATURE_TEMPLATE
) == FEATURE_TEMPLATE
)
534 iCustom
->StartVisualGroup (GROUP_TEMPLATE
, L
"Template");
535 iCustom
->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE
);
536 iCustom
->EndVisualGroup ();
537 iCustom
->MakeProminent (GROUP_TEMPLATE
);
540 if ((nFeatures
& FEATURE_IMAGETEMPLATE
) == FEATURE_IMAGETEMPLATE
)
542 iCustom
->StartVisualGroup (GROUP_IMAGETEMPLATE
, L
"Style");
543 iCustom
->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE
);
544 iCustom
->EndVisualGroup ();
545 iCustom
->MakeProminent (GROUP_IMAGETEMPLATE
);
548 iCustom
->StartVisualGroup (GROUP_CHECKBOXES
, L
"");
550 sal_uInt16
nControlId(0);
551 if ((nFeatures
& FEATURE_AUTOEXTENSION
) == FEATURE_AUTOEXTENSION
)
553 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
;
554 iCustom
->AddCheckButton (nControlId
, L
"Auto Extension", true);
555 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
558 if ((nFeatures
& FEATURE_PASSWORD
) == FEATURE_PASSWORD
)
560 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
;
561 iCustom
->AddCheckButton (nControlId
, L
"Password", false);
562 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
565 if ((nFeatures
& FEATURE_READONLY
) == FEATURE_READONLY
)
567 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY
;
568 iCustom
->AddCheckButton (nControlId
, L
"Readonly", false);
569 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
572 if ((nFeatures
& FEATURE_FILTEROPTIONS
) == FEATURE_FILTEROPTIONS
)
574 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
;
575 iCustom
->AddCheckButton (nControlId
, L
"Filter Options", false);
576 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
579 if ((nFeatures
& FEATURE_LINK
) == FEATURE_LINK
)
581 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK
;
582 iCustom
->AddCheckButton (nControlId
, L
"Link", false);
583 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
586 if ((nFeatures
& FEATURE_SELECTION
) == FEATURE_SELECTION
)
588 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION
;
589 iCustom
->AddCheckButton (nControlId
, L
"Selection", false);
590 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
593 /* can be ignored ... new COM dialog supports preview native now !
594 if ((nFeatures & FEATURE_PREVIEW) == FEATURE_PREVIEW)
595 iCustom->AddCheckButton (css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, L"Preview", false);
598 iCustom
->EndVisualGroup();
600 if ((nFeatures
& FEATURE_PLAY
) == FEATURE_PLAY
)
601 iCustom
->AddPushButton (css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY
, L
"Play");
605 //-------------------------------------------------------------------------------
606 void VistaFilePickerImpl::impl_sta_SetMultiSelectionMode(const RequestRef
& rRequest
)
608 const ::sal_Bool bMultiSelection
= rRequest
->getArgumentOrDefault(PROP_MULTISELECTION_MODE
, (::sal_Bool
)sal_True
);
611 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
612 TFileDialog iDialog
= impl_getBaseDialogInterface();
617 m_hLastResult
= iDialog
->GetOptions ( &nFlags
);
620 nFlags
|= FOS_ALLOWMULTISELECT
;
622 nFlags
&= ~FOS_ALLOWMULTISELECT
;
624 iDialog
->SetOptions ( nFlags
);
627 //-------------------------------------------------------------------------------
628 void VistaFilePickerImpl::impl_sta_SetTitle(const RequestRef
& rRequest
)
630 ::rtl::OUString sTitle
= rRequest
->getArgumentOrDefault(PROP_TITLE
, ::rtl::OUString());
633 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
634 TFileDialog iDialog
= impl_getBaseDialogInterface();
638 iDialog
->SetTitle(reinterpret_cast<LPCTSTR
>(sTitle
.getStr()));
641 //-------------------------------------------------------------------------------
642 void VistaFilePickerImpl::impl_sta_SetFileName(const RequestRef
& rRequest
)
644 ::rtl::OUString sFileName
= rRequest
->getArgumentOrDefault(PROP_FILENAME
, ::rtl::OUString());
647 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
648 TFileDialog iDialog
= impl_getBaseDialogInterface();
652 iDialog
->SetFileName(reinterpret_cast<LPCTSTR
>(sFileName
.getStr()));
655 //-------------------------------------------------------------------------------
656 void VistaFilePickerImpl::impl_sta_SetDirectory(const RequestRef
& rRequest
)
658 ::rtl::OUString sDirectory
= rRequest
->getArgumentOrDefault(PROP_DIRECTORY
, ::rtl::OUString());
659 bool bForce
= rRequest
->getArgumentOrDefault(PROP_FORCE
, false);
663 // Vista stores last used folders for file dialogs
664 // so we don't want the application to change the folder
666 // Store the requested folder in the mean time and decide later
668 m_sDirectory
= sDirectory
;
672 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
673 TFileDialog iDialog
= impl_getBaseDialogInterface();
677 ComPtr
< IShellItem
> pFolder
;
679 HRESULT hResult
= SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR
>(sDirectory
.getStr()), NULL
, IID_IShellItem
, (void**)(&pFolder
) );
681 HRESULT hResult
= SHCreateItemFromParsingName ( sDirectory
, NULL
, IID_PPV_ARGS(&pFolder
) );
683 if ( FAILED(hResult
) )
686 if ( m_bInExecute
|| bForce
)
687 iDialog
->SetFolder(pFolder
);
690 // Use set default folder as Microsoft recommends in the IFileDialog documentation.
691 iDialog
->SetDefaultFolder(pFolder
);
695 void VistaFilePickerImpl::impl_sta_GetDirectory(const RequestRef
& rRequest
)
697 TFileDialog iDialog
= impl_getBaseDialogInterface();
698 ComPtr
< IShellItem
> pFolder
;
699 HRESULT hResult
= iDialog
->GetFolder( &pFolder
);
700 if ( FAILED(hResult
) )
702 ::rtl::OUString sFolder
= lcl_getURLFromShellItem ( pFolder
);
703 if( sFolder
.getLength())
704 rRequest
->setArgument( PROP_DIRECTORY
, sFolder
);
707 //-------------------------------------------------------------------------------
708 void VistaFilePickerImpl::impl_sta_SetDefaultName(const RequestRef
& rRequest
)
710 ::rtl::OUString sFilename
= rRequest
->getArgumentOrDefault(PROP_FILENAME
, ::rtl::OUString());
711 TFileDialog iDialog
= impl_getBaseDialogInterface();
713 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
717 // if we have the autoextension check box set, remove (or change ???) the extension of the filename
718 // so that the autoextension mechanism can do its job
720 HRESULT hResult
= iCustom
->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, &bValue
);
723 sal_Int32 nSepPos
= sFilename
.lastIndexOf( '.' );
725 sFilename
= sFilename
.copy(0, nSepPos
);
728 iDialog
->SetFileName ( reinterpret_cast<LPCTSTR
>(sFilename
.getStr()));
729 m_sFilename
= sFilename
;
732 //-------------------------------------------------------------------------------
733 void VistaFilePickerImpl::impl_sta_setFiltersOnDialog()
736 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
738 ::std::vector
< COMDLG_FILTERSPEC
> lFilters
= lcl_buildFilterList(m_lFilters
);
739 ::rtl::OUString sCurrentFilter
= m_lFilters
.getCurrentFilter();
740 sal_Int32 nCurrentFilter
= m_lFilters
.getFilterPos(sCurrentFilter
);
741 TFileDialog iDialog
= impl_getBaseDialogInterface();
742 TFileDialogCustomize iCustomize
= impl_getCustomizeInterface();
747 COMDLG_FILTERSPEC
*pFilt
= &lFilters
[0];
748 iDialog
->SetFileTypes(lFilters
.size(), pFilt
/*&lFilters[0]*/);
749 iDialog
->SetFileTypeIndex(nCurrentFilter
+ 1);
752 HRESULT hResult
= iCustomize
->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, &bValue
);
756 LPCWSTR lpFilterExt
= lFilters
[0].pszSpec
;
758 lpFilterExt
= wcsrchr( lpFilterExt
, '.' );
761 iDialog
->SetDefaultExtension( lpFilterExt
);
766 //-------------------------------------------------------------------------------
767 void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef
& rRequest
)
770 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
772 TFileOpenDialog iOpen
= m_iDialogOpen
;
773 TFileSaveDialog iSave
= m_iDialogSave
;
774 ::sal_Bool bInExecute
= m_bInExecute
;
779 // ask dialog for results
780 // Note : we must differ between single/multi selection !
781 // Note further: we must react different if dialog is in execute or not .-(
782 ComPtr
< IShellItem
> iItem
;
783 ComPtr
< IShellItemArray
> iItems
;
784 HRESULT hResult
= E_FAIL
;
789 hResult
= iOpen
->GetSelectedItems(&iItems
);
792 hResult
= iOpen
->GetResults(&iItems
);
794 hResult
= iOpen
->GetResult(&iItem
);
801 hResult
= iSave
->GetCurrentSelection(&iItem
);
803 hResult
= iSave
->GetResult(&iItem
);
809 // convert and pack results
813 const ::rtl::OUString sURL
= lcl_getURLFromShellItem(iItem
);
814 if (sURL
.getLength() > 0)
815 lFiles
.push_back(sURL
);
821 hResult
= iItems
->GetCount(&nCount
);
822 if ( SUCCEEDED(hResult
) )
824 for (DWORD i
=0; i
<nCount
; ++i
)
826 hResult
= iItems
->GetItemAt(i
, &iItem
);
827 if ( SUCCEEDED(hResult
) )
829 const ::rtl::OUString sURL
= lcl_getURLFromShellItem(iItem
);
830 if (sURL
.getLength() > 0)
831 lFiles
.push_back(sURL
);
837 rRequest
->setArgument(PROP_SELECTED_FILES
, lFiles
.getAsConstList());
840 //-------------------------------------------------------------------------------
841 void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef
& rRequest
)
843 impl_sta_setFiltersOnDialog();
846 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
848 TFileDialog iDialog
= impl_getBaseDialogInterface();
849 TFileOpenDialog iOpen
= m_iDialogOpen
;
850 TFileSaveDialog iSave
= m_iDialogSave
;
852 // it's important to know if we are showing the dialog.
853 // Some dialog interface methods cant be called then or some
854 // tasks must be done differently .-) (e.g. see impl_sta_getSelectedFiles())
855 m_bInExecute
= sal_True
;
860 // we set the directory only if we have a save dialog and a filename
861 // for the other cases, the file dialog remembers its last location
862 // according to its client guid.
863 if( m_sDirectory
.getLength())
865 ComPtr
< IShellItem
> pFolder
;
867 HRESULT hResult
= SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR
>(m_sDirectory
.getStr()), NULL
, IID_IShellItem
, (void**)(&pFolder
) );
869 HRESULT hResult
= SHCreateItemFromParsingName ( m_sDirectory
, NULL
, IID_PPV_ARGS(&pFolder
) );
871 if ( SUCCEEDED(hResult
) )
873 if (m_sFilename
.getLength())
875 ::rtl::OUString
aFileURL(m_sDirectory
);
876 sal_Int32 nIndex
= aFileURL
.lastIndexOf('/');
877 if (nIndex
!= aFileURL
.getLength()-1)
878 aFileURL
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/"));
879 aFileURL
+= m_sFilename
;
881 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
884 HRESULT hResult
= iCustom
->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, &bValue
);
887 ::rtl::OUString aExt
;
889 hResult
= iDialog
->GetFileTypeIndex(&nFileType
);
890 if ( SUCCEEDED(hResult
) )
892 ::sal_Int32 nRealIndex
= (nFileType
-1); // COM dialog base on 1 ... filter container on 0 .-)
893 ::std::vector
< COMDLG_FILTERSPEC
> lFilters
= lcl_buildFilterList(m_lFilters
);
894 LPCWSTR lpFilterExt
= lFilters
[nRealIndex
].pszSpec
;
896 lpFilterExt
= wcsrchr( lpFilterExt
, '.' );
898 aFileURL
+= reinterpret_cast<const sal_Unicode
*>(lpFilterExt
);
902 // Check existence of file. Set folder only for this special case
903 ::rtl::OUString aSystemPath
;
904 osl_getSystemPathFromFileURL( aFileURL
.pData
, &aSystemPath
.pData
);
906 WIN32_FIND_DATA aFindFileData
;
907 HANDLE hFind
= FindFirstFile( reinterpret_cast<LPCWSTR
>(aSystemPath
.getStr()), &aFindFileData
);
908 if (hFind
!= INVALID_HANDLE_VALUE
)
909 iDialog
->SetFolder(pFolder
);
911 hResult
= iDialog
->AddPlace(pFolder
, FDAP_TOP
);
916 hResult
= iDialog
->AddPlace(pFolder
, FDAP_TOP
);
921 HRESULT hResult
= E_FAIL
;
924 // show dialog and wait for user decision
926 hResult
= iOpen
->Show( m_hParentWindow
); // parent window needed
929 hResult
= iSave
->Show( m_hParentWindow
); // parent window needed
936 m_bInExecute
= sal_False
;
940 if ( FAILED(hResult
) )
943 impl_sta_getSelectedFiles(rRequest
);
944 rRequest
->setArgument(PROP_DIALOG_SHOW_RESULT
, (::sal_Bool
)sal_True
);
947 //-------------------------------------------------------------------------------
948 TFileDialog
VistaFilePickerImpl::impl_getBaseDialogInterface()
953 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
955 if (m_iDialogOpen
.is())
957 m_iDialogOpen
->QueryInterface(IID_IFileDialog
, (void**)(&iDialog
));
959 m_iDialogOpen
.query(&iDialog
);
961 if (m_iDialogSave
.is())
963 m_iDialogSave
->QueryInterface(IID_IFileDialog
, (void**)(&iDialog
));
965 m_iDialogSave
.query(&iDialog
);
971 //-------------------------------------------------------------------------------
972 TFileDialogCustomize
VistaFilePickerImpl::impl_getCustomizeInterface()
974 TFileDialogCustomize iCustom
;
977 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
979 if (m_iDialogOpen
.is())
981 m_iDialogOpen
->QueryInterface(IID_IFileDialogCustomize
, (void**)(&iCustom
));
983 m_iDialogOpen
.query(&iCustom
);
986 if (m_iDialogSave
.is())
988 m_iDialogSave
->QueryInterface(IID_IFileDialogCustomize
, (void**)(&iCustom
));
990 m_iDialogSave
.query(&iCustom
);
996 //-------------------------------------------------------------------------------
997 void lcl_removeControlItemsWorkaround(const TFileDialogCustomize
& iCustom
,
998 ::sal_Int16 nControlId
)
1003 hResult
= iCustom
->SetSelectedControlItem(nControlId
, 1000);
1005 while ( SUCCEEDED(hResult
) )
1006 hResult
= iCustom
->RemoveControlItem(nControlId
, i
++);
1009 //-------------------------------------------------------------------------------
1010 void VistaFilePickerImpl::impl_sta_SetControlValue(const RequestRef
& rRequest
)
1012 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1013 ::sal_Int16 nAction
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ACTION
, INVALID_CONTROL_ACTION
);
1014 css::uno::Any aValue
= rRequest
->getArgumentOrDefault(PROP_CONTROL_VALUE
, css::uno::Any() );
1016 // dont check for right values here ...
1017 // most parameters are optional !
1019 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1020 if ( ! iCustom
.is())
1025 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
:
1026 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
:
1027 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY
:
1028 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
:
1029 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK
:
1030 //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1031 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION
:
1033 ::sal_Bool bValue
= sal_False
;
1035 iCustom
->SetCheckButtonState(nId
, bValue
);
1039 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION
:
1040 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE
:
1041 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE
:
1046 case css::ui::dialogs::ControlActions::DELETE_ITEMS
:
1048 hResult
= iCustom
->RemoveAllControlItems(nId
);
1049 if ( FAILED(hResult
) )
1050 lcl_removeControlItemsWorkaround(iCustom
, nId
);
1054 case css::ui::dialogs::ControlActions::ADD_ITEMS
:
1056 css::uno::Sequence
< ::rtl::OUString
> lItems
;
1058 for (::sal_Int32 i
=0; i
<lItems
.getLength(); ++i
)
1060 const ::rtl::OUString
& sItem
= lItems
[i
];
1061 hResult
= iCustom
->AddControlItem(nId
, i
, reinterpret_cast<LPCTSTR
>(sItem
.getStr()));
1066 case css::ui::dialogs::ControlActions::SET_SELECT_ITEM
:
1068 ::sal_Int32 nItem
= 0;
1070 hResult
= iCustom
->SetSelectedControlItem(nId
, nItem
);
1077 case css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY
:
1084 //-------------------------------------------------------------------------------
1085 void VistaFilePickerImpl::impl_sta_GetControlValue(const RequestRef
& rRequest
)
1087 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1088 ::sal_Int16 nAction
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ACTION
, INVALID_CONTROL_ACTION
);
1090 // dont check for right values here ...
1091 // most parameters are optional !
1093 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1094 if ( ! iCustom
.is())
1097 css::uno::Any aValue
;
1100 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
:
1101 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY
:
1102 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
:
1103 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK
:
1104 //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1105 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION
:
1107 BOOL bValue
= sal_False
;
1108 HRESULT hResult
= iCustom
->GetCheckButtonState(nId
, &bValue
);
1109 if ( SUCCEEDED(hResult
) )
1110 aValue
= css::uno::makeAny((sal_Bool
)bValue
);
1115 if (aValue
.hasValue())
1116 rRequest
->setArgument(PROP_CONTROL_VALUE
, aValue
);
1119 //-------------------------------------------------------------------------------
1120 void VistaFilePickerImpl::impl_sta_SetControlLabel(const RequestRef
& rRequest
)
1122 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1123 ::rtl::OUString sLabel
= rRequest
->getArgumentOrDefault(PROP_CONTROL_LABEL
, ::rtl::OUString() );
1125 // dont check for right values here ...
1126 // most parameters are optional !
1128 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1129 if ( ! iCustom
.is())
1131 iCustom
->SetControlLabel ( nId
, reinterpret_cast<LPCTSTR
>(sLabel
.getStr()));
1134 //-------------------------------------------------------------------------------
1135 void VistaFilePickerImpl::impl_sta_GetControlLabel(const RequestRef
& /*rRequest*/)
1139 //-------------------------------------------------------------------------------
1140 void VistaFilePickerImpl::impl_sta_EnableControl(const RequestRef
& rRequest
)
1142 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1143 ::sal_Bool bEnabled
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ENABLE
, (::sal_Bool
)sal_True
);
1145 // dont check for right values here ...
1146 // most parameters are optional !
1148 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1149 if ( ! iCustom
.is())
1152 CDCONTROLSTATEF eState
= CDCS_VISIBLE
;
1154 eState
|= CDCS_ENABLED
;
1156 eState
|= CDCS_INACTIVE
;
1158 iCustom
->SetControlState(nId
, eState
);
1160 //-------------------------------------------------------------------------------
1161 void VistaFilePickerImpl::impl_SetDefaultExtension( const rtl::OUString
& currentFilter
)
1163 TFileDialog iDialog
= impl_getBaseDialogInterface();
1164 if (currentFilter
.getLength())
1166 rtl::OUString FilterExt
;
1167 m_lFilters
.getFilter(currentFilter
, FilterExt
);
1169 sal_Int32 posOfPoint
= FilterExt
.indexOf(L
'.');
1170 const sal_Unicode
* pFirstExtStart
= FilterExt
.getStr() + posOfPoint
+ 1;
1172 sal_Int32 posOfSemiColon
= FilterExt
.indexOf(L
';') - 1;
1173 if (posOfSemiColon
< 0)
1174 posOfSemiColon
= FilterExt
.getLength() - 1;
1176 FilterExt
= rtl::OUString(pFirstExtStart
, posOfSemiColon
- posOfPoint
);
1177 iDialog
->SetDefaultExtension ( reinterpret_cast<LPCTSTR
>(FilterExt
.getStr()) );
1182 //-------------------------------------------------------------------------------
1183 void VistaFilePickerImpl::onAutoExtensionChanged (bool bChecked
)
1186 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
1188 const ::rtl::OUString sFilter
= m_lFilters
.getCurrentFilter ();
1189 ::rtl::OUString sExt
;
1190 if ( !m_lFilters
.getFilter (sFilter
, sExt
))
1193 TFileDialog iDialog
= impl_getBaseDialogInterface();
1201 pExt
= reinterpret_cast<LPCTSTR
>(sExt
.getStr());
1202 pExt
= wcsrchr( pExt
, '.' );
1206 iDialog
->SetDefaultExtension( pExt
);
1209 } // namespace vista
1210 } // namespace win32
1211 } // namespace fpicker