1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 //-----------------------------------------------------------------------------
30 //-----------------------------------------------------------------------------
32 #include "VistaFilePickerImpl.hxx"
34 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
35 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
36 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
37 #include <comphelper/sequenceasvector.hxx>
38 #include <osl/file.hxx>
39 #include <osl/mutex.hxx>
43 #include "..\misc\WinImplHelper.hxx"
45 inline bool is_current_process_window(HWND hwnd
)
48 GetWindowThreadProcessId(hwnd
, &pid
);
49 return (pid
== GetCurrentProcessId());
52 HWND
choose_parent_window()
54 HWND hwnd_parent
= GetForegroundWindow();
55 if (!is_current_process_window(hwnd_parent
))
56 hwnd_parent
= GetDesktopWindow();
60 //-----------------------------------------------------------------------------
62 //-----------------------------------------------------------------------------
68 namespace css
= ::com::sun::star
;
70 //-----------------------------------------------------------------------------
71 // types, const etcpp.
72 //-----------------------------------------------------------------------------
75 static const ::sal_Int16 INVALID_CONTROL_ID
= -1;
76 static const ::sal_Int16 INVALID_CONTROL_ACTION
= -1;
78 typedef ::comphelper::SequenceAsVector
< ::rtl::OUString
> TStringList
;
80 // Guids used for IFileDialog::SetClientGuid
81 static const GUID CLIENTID_FILEDIALOG_SIMPLE
= {0xB8628FD3, 0xA3F5, 0x4845, 0x9B, 0x62, 0xD5, 0x1E, 0xDF, 0x97, 0xC4, 0x83};
82 static const GUID CLIENTID_FILEDIALOG_OPTIONS
= {0x93ED486F, 0x0D04, 0x4807, 0x8C, 0x44, 0xAC, 0x26, 0xCB, 0x6C, 0x5D, 0x36};
83 static const GUID CLIENTID_FILESAVE
= {0x3B2E2261, 0x402D, 0x4049, 0xB0, 0xC0, 0x91, 0x13, 0xF8, 0x6E, 0x84, 0x7C};
84 static const GUID CLIENTID_FILESAVE_PASSWORD
= {0xC12D4F4C, 0x4D41, 0x4D4F, 0x97, 0xEF, 0x87, 0xF9, 0x8D, 0xB6, 0x1E, 0xA6};
85 static const GUID CLIENTID_FILESAVE_SELECTION
= {0x5B2482B3, 0x0358, 0x4E09, 0xAA, 0x64, 0x2B, 0x76, 0xB2, 0xA0, 0xDD, 0xFE};
86 static const GUID CLIENTID_FILESAVE_TEMPLATE
= {0x9996D877, 0x20D5, 0x424B, 0x9C, 0x2E, 0xD3, 0xB6, 0x31, 0xEC, 0xF7, 0xCE};
87 static const GUID CLIENTID_FILEOPEN_LINK_TEMPLATE
= {0x32237796, 0x1509, 0x49D1, 0xBB, 0x7E, 0x63, 0xAD, 0x36, 0xAE, 0x86, 0x8C};
88 static const GUID CLIENTID_FILEOPEN_PLAY
= {0x32CFB147, 0xF5AE, 0x4F90, 0xA1, 0xF1, 0x81, 0x20, 0x72, 0xBB, 0x2F, 0xC5};
89 static const GUID CLIENTID_FILEOPEN_LINK
= {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE, 0x2E, 0xF8, 0x8C, 0xB5, 0x65, 0x5E, 0x6A};
91 //-----------------------------------------------------------------------------
92 ::rtl::OUString
lcl_getURLFromShellItem (IShellItem
* pItem
)
97 SIGDN eConversion
= SIGDN_FILESYSPATH
;
98 HRESULT hr
= pItem
->GetDisplayName ( eConversion
, &pStr
);
102 eConversion
= SIGDN_URL
;
103 hr
= pItem
->GetDisplayName ( eConversion
, &pStr
);
106 return ::rtl::OUString();
108 sURL
= ::rtl::OUString(reinterpret_cast<sal_Unicode
*>(pStr
));
112 ::osl::FileBase::getFileURLFromSystemPath( reinterpret_cast<sal_Unicode
*>(pStr
), sURL
);
115 CoTaskMemFree (pStr
);
119 //-----------------------------------------------------------------------------------------
120 ::std::vector
< COMDLG_FILTERSPEC
> lcl_buildFilterList(CFilterContainer
& rContainer
)
122 const sal_Int32 c
= rContainer
.numFilter();
124 ::std::vector
< COMDLG_FILTERSPEC
> lList
;
125 CFilterContainer::FILTER_ENTRY_T aFilter
;
127 rContainer
.beginEnumFilter( );
128 while( rContainer
.getNextFilter(aFilter
) )
130 COMDLG_FILTERSPEC aSpec
;
132 aSpec
.pszName
= reinterpret_cast<LPCTSTR
>(aFilter
.first
.getStr()) ;
133 aSpec
.pszSpec
= reinterpret_cast<LPCTSTR
>(aFilter
.second
.getStr());
135 lList
.push_back(aSpec
);
141 //-----------------------------------------------------------------------------------------
142 VistaFilePickerImpl::VistaFilePickerImpl()
148 , m_iEventHandler(new VistaFilePickerEventHandler(this))
149 , m_bInExecute (sal_False
)
150 , m_bWasExecuted (sal_False
)
154 m_hParentWindow
= choose_parent_window();
157 //-------------------------------------------------------------------------------
158 VistaFilePickerImpl::~VistaFilePickerImpl()
162 //-------------------------------------------------------------------------------
163 void VistaFilePickerImpl::before()
166 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
169 // osl::Thread class initializes COm already in MTA mode because it's needed
170 // by VCL and UNO so. There is no way to change that from outside ...
171 // but we need a STA environment ...
172 // So we make it by try-and-error ...
173 // If first CoInitialize will fail .. we unitialize COM initialize it new .-)
175 m_hLastResult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
176 if ( FAILED(m_hLastResult
) )
179 m_hLastResult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
183 //-------------------------------------------------------------------------------
184 void VistaFilePickerImpl::doRequest(const RequestRef
& rRequest
)
188 switch(rRequest
->getRequest())
190 case E_ADD_PICKER_LISTENER
:
191 impl_sta_addFilePickerListener(rRequest
);
194 case E_REMOVE_PICKER_LISTENER
:
195 impl_sta_removeFilePickerListener(rRequest
);
198 case E_APPEND_FILTER
:
199 impl_sta_appendFilter(rRequest
);
202 case E_SET_CURRENT_FILTER
:
203 impl_sta_setCurrentFilter(rRequest
);
206 case E_GET_CURRENT_FILTER
:
207 impl_sta_getCurrentFilter(rRequest
);
210 case E_CREATE_OPEN_DIALOG
:
211 impl_sta_CreateOpenDialog(rRequest
);
214 case E_CREATE_SAVE_DIALOG
:
215 impl_sta_CreateSaveDialog(rRequest
);
218 case E_SET_MULTISELECTION_MODE
:
219 impl_sta_SetMultiSelectionMode(rRequest
);
223 impl_sta_SetTitle(rRequest
);
227 impl_sta_SetFileName(rRequest
);
230 case E_SET_DIRECTORY
:
231 impl_sta_SetDirectory(rRequest
);
234 case E_GET_DIRECTORY
:
235 impl_sta_GetDirectory(rRequest
);
238 case E_SET_DEFAULT_NAME
:
239 impl_sta_SetDefaultName(rRequest
);
242 case E_GET_SELECTED_FILES
:
243 impl_sta_getSelectedFiles(rRequest
);
246 case E_SHOW_DIALOG_MODAL
:
247 impl_sta_ShowDialogModal(rRequest
);
250 case E_SET_CONTROL_VALUE
:
251 impl_sta_SetControlValue(rRequest
);
254 case E_GET_CONTROL_VALUE
:
255 impl_sta_GetControlValue(rRequest
);
258 case E_SET_CONTROL_LABEL
:
259 impl_sta_SetControlLabel(rRequest
);
262 case E_GET_CONTROL_LABEL
:
263 impl_sta_GetControlLabel(rRequest
);
266 case E_ENABLE_CONTROL
:
267 impl_sta_EnableControl(rRequest
);
270 // no default: let the compiler detect changes on enum ERequest !
277 //-------------------------------------------------------------------------------
278 void VistaFilePickerImpl::after()
283 //-------------------------------------------------------------------------------
284 void VistaFilePickerImpl::impl_sta_addFilePickerListener(const RequestRef
& rRequest
)
286 // SYNCHRONIZED outside !
287 const css::uno::Reference
< css::ui::dialogs::XFilePickerListener
> xListener
= rRequest
->getArgumentOrDefault(PROP_PICKER_LISTENER
, css::uno::Reference
< css::ui::dialogs::XFilePickerListener
>());
288 if ( ! xListener
.is())
292 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
293 TFileDialogEvents iHandler
= m_iEventHandler
;
297 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
299 pHandlerImpl
->addFilePickerListener(xListener
);
302 //-------------------------------------------------------------------------------
303 void VistaFilePickerImpl::impl_sta_removeFilePickerListener(const RequestRef
& rRequest
)
305 // SYNCHRONIZED outside !
306 const css::uno::Reference
< css::ui::dialogs::XFilePickerListener
> xListener
= rRequest
->getArgumentOrDefault(PROP_PICKER_LISTENER
, css::uno::Reference
< css::ui::dialogs::XFilePickerListener
>());
307 if ( ! xListener
.is())
311 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
312 TFileDialogEvents iHandler
= m_iEventHandler
;
316 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
318 pHandlerImpl
->removeFilePickerListener(xListener
);
321 //-------------------------------------------------------------------------------
322 void VistaFilePickerImpl::impl_sta_appendFilter(const RequestRef
& rRequest
)
324 const ::rtl::OUString sTitle
= rRequest
->getArgumentOrDefault(PROP_FILTER_TITLE
, ::rtl::OUString());
325 const ::rtl::OUString sFilter
= rRequest
->getArgumentOrDefault(PROP_FILTER_VALUE
, ::rtl::OUString());
328 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
330 m_lFilters
.addFilter(sTitle
, sFilter
);
333 //-------------------------------------------------------------------------------
334 void VistaFilePickerImpl::impl_sta_setCurrentFilter(const RequestRef
& rRequest
)
336 const ::rtl::OUString sTitle
= rRequest
->getArgumentOrDefault(PROP_FILTER_TITLE
, ::rtl::OUString());
339 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
341 m_lFilters
.setCurrentFilter(sTitle
);
344 //-------------------------------------------------------------------------------
345 void VistaFilePickerImpl::impl_sta_getCurrentFilter(const RequestRef
& rRequest
)
347 TFileDialog iDialog
= impl_getBaseDialogInterface();
348 UINT nIndex
= UINT_MAX
;
349 HRESULT hResult
= iDialog
->GetFileTypeIndex(&nIndex
);
351 ( FAILED(hResult
) ) ||
352 ( nIndex
== UINT_MAX
) // COM dialog sometimes return S_OK for empty filter lists .-(
357 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
359 ::rtl::OUString sTitle
;
360 ::sal_Int32 nRealIndex
= (nIndex
-1); // COM dialog base on 1 ... filter container on 0 .-)
362 (nRealIndex
>= 0 ) &&
363 (m_lFilters
.getFilter(nRealIndex
, sTitle
))
365 rRequest
->setArgument(PROP_FILTER_TITLE
, sTitle
);
366 else if ( nRealIndex
== -1 ) // Dialog not visible yet
368 sTitle
= m_lFilters
.getCurrentFilter();
369 rRequest
->setArgument(PROP_FILTER_TITLE
, sTitle
);
376 //-------------------------------------------------------------------------------
377 void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef
& rRequest
)
380 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
382 m_hLastResult
= m_iDialogOpen
.create();
383 if (FAILED(m_hLastResult
))
388 m_iDialogOpen
->QueryInterface(IID_IFileDialog
, (void **)(&iDialog
));
390 m_iDialogOpen
.query(&iDialog
);
393 TFileDialogEvents iHandler
= m_iEventHandler
;
399 iDialog
->GetOptions ( &nFlags
);
401 nFlags
&= ~FOS_FORCESHOWHIDDEN
;
402 nFlags
|= FOS_PATHMUSTEXIST
;
403 nFlags
|= FOS_FILEMUSTEXIST
;
404 nFlags
|= FOS_OVERWRITEPROMPT
;
405 nFlags
|= FOS_DONTADDTORECENT
;
407 iDialog
->SetOptions ( nFlags
);
409 ::sal_Int32 nFeatures
= rRequest
->getArgumentOrDefault(PROP_FEATURES
, (::sal_Int32
)0);
410 ::sal_Int32 nTemplate
= rRequest
->getArgumentOrDefault(PROP_TEMPLATE_DESCR
, (::sal_Int32
)0);
411 impl_sta_enableFeatures(nFeatures
, nTemplate
);
413 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
415 pHandlerImpl
->startListening(iDialog
);
418 //-------------------------------------------------------------------------------
419 void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef
& rRequest
)
422 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
424 m_hLastResult
= m_iDialogSave
.create();
425 if (FAILED(m_hLastResult
))
428 TFileDialogEvents iHandler
= m_iEventHandler
;
431 m_iDialogSave
->QueryInterface(IID_IFileDialog
, (void **)(&iDialog
));
433 m_iDialogSave
.query(&iDialog
);
440 iDialog
->GetOptions ( &nFlags
);
442 nFlags
&= ~FOS_FORCESHOWHIDDEN
;
443 nFlags
|= FOS_PATHMUSTEXIST
;
444 nFlags
|= FOS_FILEMUSTEXIST
;
445 nFlags
|= FOS_OVERWRITEPROMPT
;
446 nFlags
|= FOS_DONTADDTORECENT
;
448 iDialog
->SetOptions ( nFlags
);
450 ::sal_Int32 nFeatures
= rRequest
->getArgumentOrDefault(PROP_FEATURES
, (::sal_Int32
)0);
451 ::sal_Int32 nTemplate
= rRequest
->getArgumentOrDefault(PROP_TEMPLATE_DESCR
, (::sal_Int32
)0);
452 impl_sta_enableFeatures(nFeatures
, nTemplate
);
454 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
456 pHandlerImpl
->startListening(iDialog
);
459 //-------------------------------------------------------------------------------
460 static const ::sal_Int32 GROUP_VERSION
= 1;
461 static const ::sal_Int32 GROUP_TEMPLATE
= 2;
462 static const ::sal_Int32 GROUP_IMAGETEMPLATE
= 3;
463 static const ::sal_Int32 GROUP_CHECKBOXES
= 4;
465 //-------------------------------------------------------------------------------
466 static void setLabelToControl(CResourceProvider
& rResourceProvider
, TFileDialogCustomize iCustom
, sal_uInt16 nControlId
)
468 ::rtl::OUString aLabel
= rResourceProvider
.getResString(nControlId
);
469 aLabel
= SOfficeToWindowsLabel(aLabel
);
470 iCustom
->SetControlLabel(nControlId
, reinterpret_cast<LPCWSTR
>(aLabel
.getStr()) );
473 //-------------------------------------------------------------------------------
474 void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures
, ::sal_Int32 nTemplate
)
479 case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE
:
480 case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE
:
481 aGUID
= CLIENTID_FILEDIALOG_SIMPLE
;
484 case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION
:
485 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
486 aGUID
= CLIENTID_FILEDIALOG_OPTIONS
;
489 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION
:
490 aGUID
= CLIENTID_FILESAVE
;
493 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
:
494 aGUID
= CLIENTID_FILESAVE_PASSWORD
;
497 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION
:
498 aGUID
= CLIENTID_FILESAVE_SELECTION
;
501 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE
:
502 aGUID
= CLIENTID_FILESAVE_TEMPLATE
;
505 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
506 aGUID
= CLIENTID_FILEOPEN_LINK_TEMPLATE
;
509 case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY
:
510 aGUID
= CLIENTID_FILEOPEN_PLAY
;
513 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW
:
514 aGUID
= CLIENTID_FILEOPEN_LINK
;
517 TFileDialog iDialog
= impl_getBaseDialogInterface();
518 iDialog
->SetClientGuid ( aGUID
);
520 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
522 if ((nFeatures
& FEATURE_VERSION
) == FEATURE_VERSION
)
524 iCustom
->StartVisualGroup (GROUP_VERSION
, L
"Version");
525 iCustom
->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION
);
526 iCustom
->EndVisualGroup ();
527 iCustom
->MakeProminent (GROUP_VERSION
);
530 if ((nFeatures
& FEATURE_TEMPLATE
) == FEATURE_TEMPLATE
)
532 iCustom
->StartVisualGroup (GROUP_TEMPLATE
, L
"Template");
533 iCustom
->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE
);
534 iCustom
->EndVisualGroup ();
535 iCustom
->MakeProminent (GROUP_TEMPLATE
);
538 if ((nFeatures
& FEATURE_IMAGETEMPLATE
) == FEATURE_IMAGETEMPLATE
)
540 iCustom
->StartVisualGroup (GROUP_IMAGETEMPLATE
, L
"Style");
541 iCustom
->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE
);
542 iCustom
->EndVisualGroup ();
543 iCustom
->MakeProminent (GROUP_IMAGETEMPLATE
);
546 iCustom
->StartVisualGroup (GROUP_CHECKBOXES
, L
"");
548 sal_uInt16
nControlId(0);
549 if ((nFeatures
& FEATURE_AUTOEXTENSION
) == FEATURE_AUTOEXTENSION
)
551 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
;
552 iCustom
->AddCheckButton (nControlId
, L
"Auto Extension", true);
553 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
556 if ((nFeatures
& FEATURE_PASSWORD
) == FEATURE_PASSWORD
)
558 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
;
559 iCustom
->AddCheckButton (nControlId
, L
"Password", false);
560 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
563 if ((nFeatures
& FEATURE_READONLY
) == FEATURE_READONLY
)
565 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY
;
566 iCustom
->AddCheckButton (nControlId
, L
"Readonly", false);
567 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
570 if ((nFeatures
& FEATURE_FILTEROPTIONS
) == FEATURE_FILTEROPTIONS
)
572 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
;
573 iCustom
->AddCheckButton (nControlId
, L
"Filter Options", false);
574 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
577 if ((nFeatures
& FEATURE_LINK
) == FEATURE_LINK
)
579 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK
;
580 iCustom
->AddCheckButton (nControlId
, L
"Link", false);
581 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
584 if ((nFeatures
& FEATURE_SELECTION
) == FEATURE_SELECTION
)
586 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION
;
587 iCustom
->AddCheckButton (nControlId
, L
"Selection", false);
588 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
591 /* can be ignored ... new COM dialog supports preview native now !
592 if ((nFeatures & FEATURE_PREVIEW) == FEATURE_PREVIEW)
593 iCustom->AddCheckButton (css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, L"Preview", false);
596 iCustom
->EndVisualGroup();
598 if ((nFeatures
& FEATURE_PLAY
) == FEATURE_PLAY
)
599 iCustom
->AddPushButton (css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY
, L
"Play");
603 //-------------------------------------------------------------------------------
604 void VistaFilePickerImpl::impl_sta_SetMultiSelectionMode(const RequestRef
& rRequest
)
606 const ::sal_Bool bMultiSelection
= rRequest
->getArgumentOrDefault(PROP_MULTISELECTION_MODE
, (::sal_Bool
)sal_True
);
609 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
610 TFileDialog iDialog
= impl_getBaseDialogInterface();
615 m_hLastResult
= iDialog
->GetOptions ( &nFlags
);
618 nFlags
|= FOS_ALLOWMULTISELECT
;
620 nFlags
&= ~FOS_ALLOWMULTISELECT
;
622 iDialog
->SetOptions ( nFlags
);
625 //-------------------------------------------------------------------------------
626 void VistaFilePickerImpl::impl_sta_SetTitle(const RequestRef
& rRequest
)
628 ::rtl::OUString sTitle
= rRequest
->getArgumentOrDefault(PROP_TITLE
, ::rtl::OUString());
631 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
632 TFileDialog iDialog
= impl_getBaseDialogInterface();
636 iDialog
->SetTitle(reinterpret_cast<LPCTSTR
>(sTitle
.getStr()));
639 //-------------------------------------------------------------------------------
640 void VistaFilePickerImpl::impl_sta_SetFileName(const RequestRef
& rRequest
)
642 ::rtl::OUString sFileName
= rRequest
->getArgumentOrDefault(PROP_FILENAME
, ::rtl::OUString());
645 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
646 TFileDialog iDialog
= impl_getBaseDialogInterface();
650 iDialog
->SetFileName(reinterpret_cast<LPCTSTR
>(sFileName
.getStr()));
653 //-------------------------------------------------------------------------------
654 void VistaFilePickerImpl::impl_sta_SetDirectory(const RequestRef
& rRequest
)
656 ::rtl::OUString sDirectory
= rRequest
->getArgumentOrDefault(PROP_DIRECTORY
, ::rtl::OUString());
657 bool bForce
= rRequest
->getArgumentOrDefault(PROP_FORCE
, false);
661 // Vista stores last used folders for file dialogs
662 // so we don't want the application to change the folder
664 // Store the requested folder in the mean time and decide later
666 m_sDirectory
= sDirectory
;
670 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
671 TFileDialog iDialog
= impl_getBaseDialogInterface();
675 ComPtr
< IShellItem
> pFolder
;
677 HRESULT hResult
= SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR
>(sDirectory
.getStr()), NULL
, IID_IShellItem
, (void**)(&pFolder
) );
679 HRESULT hResult
= SHCreateItemFromParsingName ( sDirectory
, NULL
, IID_PPV_ARGS(&pFolder
) );
681 if ( FAILED(hResult
) )
684 if ( m_bInExecute
|| bForce
)
685 iDialog
->SetFolder(pFolder
);
688 // Use set default folder as Microsoft recommends in the IFileDialog documentation.
689 iDialog
->SetDefaultFolder(pFolder
);
693 void VistaFilePickerImpl::impl_sta_GetDirectory(const RequestRef
& rRequest
)
695 TFileDialog iDialog
= impl_getBaseDialogInterface();
696 ComPtr
< IShellItem
> pFolder
;
697 HRESULT hResult
= iDialog
->GetFolder( &pFolder
);
698 if ( FAILED(hResult
) )
700 ::rtl::OUString sFolder
= lcl_getURLFromShellItem ( pFolder
);
701 if( sFolder
.getLength())
702 rRequest
->setArgument( PROP_DIRECTORY
, sFolder
);
705 //-------------------------------------------------------------------------------
706 void VistaFilePickerImpl::impl_sta_SetDefaultName(const RequestRef
& rRequest
)
708 ::rtl::OUString sFilename
= rRequest
->getArgumentOrDefault(PROP_FILENAME
, ::rtl::OUString());
709 TFileDialog iDialog
= impl_getBaseDialogInterface();
711 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
715 // if we have the autoextension check box set, remove (or change ???) the extension of the filename
716 // so that the autoextension mechanism can do its job
718 HRESULT hResult
= iCustom
->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, &bValue
);
721 sal_Int32 nSepPos
= sFilename
.lastIndexOf( '.' );
723 sFilename
= sFilename
.copy(0, nSepPos
);
726 iDialog
->SetFileName ( reinterpret_cast<LPCTSTR
>(sFilename
.getStr()));
727 m_sFilename
= sFilename
;
730 //-------------------------------------------------------------------------------
731 void VistaFilePickerImpl::impl_sta_setFiltersOnDialog()
734 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
736 ::std::vector
< COMDLG_FILTERSPEC
> lFilters
= lcl_buildFilterList(m_lFilters
);
737 ::rtl::OUString sCurrentFilter
= m_lFilters
.getCurrentFilter();
738 sal_Int32 nCurrentFilter
= m_lFilters
.getFilterPos(sCurrentFilter
);
739 TFileDialog iDialog
= impl_getBaseDialogInterface();
740 TFileDialogCustomize iCustomize
= impl_getCustomizeInterface();
745 COMDLG_FILTERSPEC
*pFilt
= &lFilters
[0];
746 iDialog
->SetFileTypes(lFilters
.size(), pFilt
/*&lFilters[0]*/);
747 iDialog
->SetFileTypeIndex(nCurrentFilter
+ 1);
750 HRESULT hResult
= iCustomize
->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, &bValue
);
754 LPCWSTR lpFilterExt
= lFilters
[0].pszSpec
;
756 lpFilterExt
= wcsrchr( lpFilterExt
, '.' );
759 iDialog
->SetDefaultExtension( lpFilterExt
);
764 //-------------------------------------------------------------------------------
765 void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef
& rRequest
)
768 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
770 TFileOpenDialog iOpen
= m_iDialogOpen
;
771 TFileSaveDialog iSave
= m_iDialogSave
;
772 ::sal_Bool bInExecute
= m_bInExecute
;
777 // ask dialog for results
778 // Note : we must differ between single/multi selection !
779 // Note further: we must react different if dialog is in execute or not .-(
780 ComPtr
< IShellItem
> iItem
;
781 ComPtr
< IShellItemArray
> iItems
;
782 HRESULT hResult
= E_FAIL
;
787 hResult
= iOpen
->GetSelectedItems(&iItems
);
790 hResult
= iOpen
->GetResults(&iItems
);
792 hResult
= iOpen
->GetResult(&iItem
);
799 hResult
= iSave
->GetCurrentSelection(&iItem
);
801 hResult
= iSave
->GetResult(&iItem
);
807 // convert and pack results
811 const ::rtl::OUString sURL
= lcl_getURLFromShellItem(iItem
);
812 if (sURL
.getLength() > 0)
813 lFiles
.push_back(sURL
);
819 hResult
= iItems
->GetCount(&nCount
);
820 if ( SUCCEEDED(hResult
) )
822 for (DWORD i
=0; i
<nCount
; ++i
)
824 hResult
= iItems
->GetItemAt(i
, &iItem
);
825 if ( SUCCEEDED(hResult
) )
827 const ::rtl::OUString sURL
= lcl_getURLFromShellItem(iItem
);
828 if (sURL
.getLength() > 0)
829 lFiles
.push_back(sURL
);
835 rRequest
->setArgument(PROP_SELECTED_FILES
, lFiles
.getAsConstList());
838 //-------------------------------------------------------------------------------
839 void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef
& rRequest
)
841 impl_sta_setFiltersOnDialog();
844 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
846 TFileDialog iDialog
= impl_getBaseDialogInterface();
847 TFileOpenDialog iOpen
= m_iDialogOpen
;
848 TFileSaveDialog iSave
= m_iDialogSave
;
850 // it's important to know if we are showing the dialog.
851 // Some dialog interface methods cant be called then or some
852 // tasks must be done differently .-) (e.g. see impl_sta_getSelectedFiles())
853 m_bInExecute
= sal_True
;
855 m_bWasExecuted
= 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
;
1098 if( m_bWasExecuted
)
1101 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
:
1102 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY
:
1103 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
:
1104 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK
:
1105 //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1106 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION
:
1108 BOOL bValue
= FALSE
;
1109 HRESULT hResult
= iCustom
->GetCheckButtonState(nId
, &bValue
);
1110 if ( SUCCEEDED(hResult
) )
1111 aValue
= css::uno::makeAny((sal_Bool
)bValue
);
1116 if (aValue
.hasValue())
1117 rRequest
->setArgument(PROP_CONTROL_VALUE
, aValue
);
1120 //-------------------------------------------------------------------------------
1121 void VistaFilePickerImpl::impl_sta_SetControlLabel(const RequestRef
& rRequest
)
1123 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1124 ::rtl::OUString sLabel
= rRequest
->getArgumentOrDefault(PROP_CONTROL_LABEL
, ::rtl::OUString() );
1126 // dont check for right values here ...
1127 // most parameters are optional !
1129 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1130 if ( ! iCustom
.is())
1132 iCustom
->SetControlLabel ( nId
, reinterpret_cast<LPCTSTR
>(sLabel
.getStr()));
1135 //-------------------------------------------------------------------------------
1136 void VistaFilePickerImpl::impl_sta_GetControlLabel(const RequestRef
& /*rRequest*/)
1140 //-------------------------------------------------------------------------------
1141 void VistaFilePickerImpl::impl_sta_EnableControl(const RequestRef
& rRequest
)
1143 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1144 ::sal_Bool bEnabled
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ENABLE
, (::sal_Bool
)sal_True
);
1146 // dont check for right values here ...
1147 // most parameters are optional !
1149 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1150 if ( ! iCustom
.is())
1153 CDCONTROLSTATEF eState
= CDCS_VISIBLE
;
1155 eState
|= CDCS_ENABLED
;
1157 eState
|= CDCS_INACTIVE
;
1159 iCustom
->SetControlState(nId
, eState
);
1161 //-------------------------------------------------------------------------------
1162 void VistaFilePickerImpl::impl_SetDefaultExtension( const rtl::OUString
& currentFilter
)
1164 TFileDialog iDialog
= impl_getBaseDialogInterface();
1165 if (currentFilter
.getLength())
1167 rtl::OUString FilterExt
;
1168 m_lFilters
.getFilter(currentFilter
, FilterExt
);
1170 sal_Int32 posOfPoint
= FilterExt
.indexOf(L
'.');
1171 const sal_Unicode
* pFirstExtStart
= FilterExt
.getStr() + posOfPoint
+ 1;
1173 sal_Int32 posOfSemiColon
= FilterExt
.indexOf(L
';') - 1;
1174 if (posOfSemiColon
< 0)
1175 posOfSemiColon
= FilterExt
.getLength() - 1;
1177 FilterExt
= rtl::OUString(pFirstExtStart
, posOfSemiColon
- posOfPoint
);
1178 iDialog
->SetDefaultExtension ( reinterpret_cast<LPCTSTR
>(FilterExt
.getStr()) );
1183 //-------------------------------------------------------------------------------
1184 void VistaFilePickerImpl::onAutoExtensionChanged (bool bChecked
)
1187 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
1189 const ::rtl::OUString sFilter
= m_lFilters
.getCurrentFilter ();
1190 ::rtl::OUString sExt
;
1191 if ( !m_lFilters
.getFilter (sFilter
, sExt
))
1194 TFileDialog iDialog
= impl_getBaseDialogInterface();
1202 pExt
= reinterpret_cast<LPCTSTR
>(sExt
.getStr());
1203 pExt
= wcsrchr( pExt
, '.' );
1207 iDialog
->SetDefaultExtension( pExt
);
1210 } // namespace vista
1211 } // namespace win32
1212 } // namespace fpicker