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 .
20 #include "VistaFilePickerImpl.hxx"
22 // Without IFileDialogCustomize we can't do much
23 #ifdef __IFileDialogCustomize_INTERFACE_DEFINED__
25 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
26 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
27 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
28 #include <com/sun/star/beans/StringPair.hpp>
29 #include <comphelper/sequenceasvector.hxx>
30 #include <osl/file.hxx>
31 #include <osl/mutex.hxx>
35 #include "../misc/WinImplHelper.hxx"
39 inline bool is_current_process_window(HWND hwnd
)
42 GetWindowThreadProcessId(hwnd
, &pid
);
43 return (pid
== GetCurrentProcessId());
46 HWND
choose_parent_window()
48 HWND hwnd_parent
= GetForegroundWindow();
49 if (!is_current_process_window(hwnd_parent
))
50 hwnd_parent
= GetDesktopWindow();
58 //-----------------------------------------------------------------------------
59 // types, const etcpp.
60 //-----------------------------------------------------------------------------
63 static const ::sal_Int16 INVALID_CONTROL_ID
= -1;
64 static const ::sal_Int16 INVALID_CONTROL_ACTION
= -1;
66 typedef ::comphelper::SequenceAsVector
< OUString
> TStringList
;
68 // Guids used for IFileDialog::SetClientGuid
69 static const GUID CLIENTID_FILEDIALOG_SIMPLE
= {0xB8628FD3, 0xA3F5, 0x4845, 0x9B, 0x62, 0xD5, 0x1E, 0xDF, 0x97, 0xC4, 0x83};
70 static const GUID CLIENTID_FILEDIALOG_OPTIONS
= {0x93ED486F, 0x0D04, 0x4807, 0x8C, 0x44, 0xAC, 0x26, 0xCB, 0x6C, 0x5D, 0x36};
71 static const GUID CLIENTID_FILESAVE_PASSWORD
= {0xC12D4F4C, 0x4D41, 0x4D4F, 0x97, 0xEF, 0x87, 0xF9, 0x8D, 0xB6, 0x1E, 0xA6};
72 static const GUID CLIENTID_FILESAVE_SELECTION
= {0x5B2482B3, 0x0358, 0x4E09, 0xAA, 0x64, 0x2B, 0x76, 0xB2, 0xA0, 0xDD, 0xFE};
73 static const GUID CLIENTID_FILESAVE_TEMPLATE
= {0x9996D877, 0x20D5, 0x424B, 0x9C, 0x2E, 0xD3, 0xB6, 0x31, 0xEC, 0xF7, 0xCE};
74 static const GUID CLIENTID_FILEOPEN_LINK_TEMPLATE
= {0x32237796, 0x1509, 0x49D1, 0xBB, 0x7E, 0x63, 0xAD, 0x36, 0xAE, 0x86, 0x8C};
75 static const GUID CLIENTID_FILEOPEN_PLAY
= {0x32CFB147, 0xF5AE, 0x4F90, 0xA1, 0xF1, 0x81, 0x20, 0x72, 0xBB, 0x2F, 0xC5};
76 static const GUID CLIENTID_FILEOPEN_LINK
= {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE, 0x2E, 0xF8, 0x8C, 0xB5, 0x65, 0x5E, 0x6A};
78 //-----------------------------------------------------------------------------
79 OUString
lcl_getURLFromShellItem (IShellItem
* pItem
)
84 SIGDN eConversion
= SIGDN_FILESYSPATH
;
85 HRESULT hr
= pItem
->GetDisplayName ( eConversion
, &pStr
);
89 eConversion
= SIGDN_URL
;
90 hr
= pItem
->GetDisplayName ( eConversion
, &pStr
);
95 sURL
= OUString(reinterpret_cast<sal_Unicode
*>(pStr
));
99 ::osl::FileBase::getFileURLFromSystemPath( reinterpret_cast<sal_Unicode
*>(pStr
), sURL
);
102 CoTaskMemFree (pStr
);
106 //-----------------------------------------------------------------------------------------
107 ::std::vector
< COMDLG_FILTERSPEC
> lcl_buildFilterList(CFilterContainer
& rContainer
)
109 const sal_Int32 c
= rContainer
.numFilter();
111 ::std::vector
< COMDLG_FILTERSPEC
> lList
;
112 CFilterContainer::FILTER_ENTRY_T aFilter
;
114 rContainer
.beginEnumFilter( );
115 while( rContainer
.getNextFilter(aFilter
) )
117 COMDLG_FILTERSPEC aSpec
;
119 aSpec
.pszName
= reinterpret_cast<LPCTSTR
>(aFilter
.first
.getStr()) ;
120 aSpec
.pszSpec
= reinterpret_cast<LPCTSTR
>(aFilter
.second
.getStr());
122 lList
.push_back(aSpec
);
128 //-----------------------------------------------------------------------------------------
129 VistaFilePickerImpl::VistaFilePickerImpl()
135 , m_iEventHandler(new VistaFilePickerEventHandler(this))
136 , m_bInExecute (sal_False
)
137 , m_bWasExecuted (sal_False
)
141 m_hParentWindow
= choose_parent_window();
144 //-------------------------------------------------------------------------------
145 VistaFilePickerImpl::~VistaFilePickerImpl()
149 //-------------------------------------------------------------------------------
150 void VistaFilePickerImpl::before()
153 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
156 // osl::Thread class initializes COm already in MTA mode because it's needed
157 // by VCL and UNO so. There is no way to change that from outside ...
158 // but we need a STA environment ...
159 // So we make it by try-and-error ...
160 // If first CoInitialize will fail .. we unitialize COM initialize it new .-)
162 m_hLastResult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
163 if ( FAILED(m_hLastResult
) )
166 m_hLastResult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
170 //-------------------------------------------------------------------------------
171 void VistaFilePickerImpl::doRequest(const RequestRef
& rRequest
)
175 switch(rRequest
->getRequest())
177 case E_ADD_PICKER_LISTENER
:
178 impl_sta_addFilePickerListener(rRequest
);
181 case E_REMOVE_PICKER_LISTENER
:
182 impl_sta_removeFilePickerListener(rRequest
);
185 case E_APPEND_FILTER
:
186 impl_sta_appendFilter(rRequest
);
189 case E_APPEND_FILTERGROUP
:
190 impl_sta_appendFilterGroup(rRequest
);
193 case E_SET_CURRENT_FILTER
:
194 impl_sta_setCurrentFilter(rRequest
);
197 case E_GET_CURRENT_FILTER
:
198 impl_sta_getCurrentFilter(rRequest
);
201 case E_CREATE_OPEN_DIALOG
:
202 impl_sta_CreateOpenDialog(rRequest
);
205 case E_CREATE_SAVE_DIALOG
:
206 impl_sta_CreateSaveDialog(rRequest
);
209 case E_SET_MULTISELECTION_MODE
:
210 impl_sta_SetMultiSelectionMode(rRequest
);
214 impl_sta_SetTitle(rRequest
);
218 impl_sta_SetFileName(rRequest
);
221 case E_SET_DIRECTORY
:
222 impl_sta_SetDirectory(rRequest
);
225 case E_GET_DIRECTORY
:
226 impl_sta_GetDirectory(rRequest
);
229 case E_SET_DEFAULT_NAME
:
230 impl_sta_SetDefaultName(rRequest
);
233 case E_GET_SELECTED_FILES
:
234 impl_sta_getSelectedFiles(rRequest
);
237 case E_SHOW_DIALOG_MODAL
:
238 impl_sta_ShowDialogModal(rRequest
);
241 case E_SET_CONTROL_VALUE
:
242 impl_sta_SetControlValue(rRequest
);
245 case E_GET_CONTROL_VALUE
:
246 impl_sta_GetControlValue(rRequest
);
249 case E_SET_CONTROL_LABEL
:
250 impl_sta_SetControlLabel(rRequest
);
253 case E_GET_CONTROL_LABEL
:
254 impl_sta_GetControlLabel(rRequest
);
257 case E_ENABLE_CONTROL
:
258 impl_sta_EnableControl(rRequest
);
261 // no default: let the compiler detect changes on enum ERequest !
268 //-------------------------------------------------------------------------------
269 void VistaFilePickerImpl::after()
274 //-------------------------------------------------------------------------------
275 void VistaFilePickerImpl::impl_sta_addFilePickerListener(const RequestRef
& rRequest
)
277 // SYNCHRONIZED outside !
278 const css::uno::Reference
< css::ui::dialogs::XFilePickerListener
> xListener
= rRequest
->getArgumentOrDefault(PROP_PICKER_LISTENER
, css::uno::Reference
< css::ui::dialogs::XFilePickerListener
>());
279 if ( ! xListener
.is())
283 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
284 TFileDialogEvents iHandler
= m_iEventHandler
;
288 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
290 pHandlerImpl
->addFilePickerListener(xListener
);
293 //-------------------------------------------------------------------------------
294 void VistaFilePickerImpl::impl_sta_removeFilePickerListener(const RequestRef
& rRequest
)
296 // SYNCHRONIZED outside !
297 const css::uno::Reference
< css::ui::dialogs::XFilePickerListener
> xListener
= rRequest
->getArgumentOrDefault(PROP_PICKER_LISTENER
, css::uno::Reference
< css::ui::dialogs::XFilePickerListener
>());
298 if ( ! xListener
.is())
302 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
303 TFileDialogEvents iHandler
= m_iEventHandler
;
307 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
309 pHandlerImpl
->removeFilePickerListener(xListener
);
312 //-------------------------------------------------------------------------------
313 void VistaFilePickerImpl::impl_sta_appendFilter(const RequestRef
& rRequest
)
315 const OUString sTitle
= rRequest
->getArgumentOrDefault(PROP_FILTER_TITLE
, OUString());
316 const OUString sFilter
= rRequest
->getArgumentOrDefault(PROP_FILTER_VALUE
, OUString());
319 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
321 m_lFilters
.addFilter(sTitle
, sFilter
);
324 //-------------------------------------------------------------------------------
325 void VistaFilePickerImpl::impl_sta_appendFilterGroup(const RequestRef
& rRequest
)
327 const css::uno::Sequence
< css::beans::StringPair
> aFilterGroup
=
328 rRequest
->getArgumentOrDefault(PROP_FILTER_GROUP
, css::uno::Sequence
< css::beans::StringPair
>());
332 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
334 if ( m_lFilters
.numFilter() > 0 && aFilterGroup
.getLength() > 0 )
335 m_lFilters
.addFilter( STRING_SEPARATOR
, aEmpty
, sal_True
);
337 ::sal_Int32 c
= aFilterGroup
.getLength();
341 const css::beans::StringPair
& rFilter
= aFilterGroup
[i
];
342 m_lFilters
.addFilter(rFilter
.First
, rFilter
.Second
);
346 //-------------------------------------------------------------------------------
347 void VistaFilePickerImpl::impl_sta_setCurrentFilter(const RequestRef
& rRequest
)
349 const OUString sTitle
= rRequest
->getArgumentOrDefault(PROP_FILTER_TITLE
, OUString());
352 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
354 m_lFilters
.setCurrentFilter(sTitle
);
357 //-------------------------------------------------------------------------------
358 void VistaFilePickerImpl::impl_sta_getCurrentFilter(const RequestRef
& rRequest
)
360 TFileDialog iDialog
= impl_getBaseDialogInterface();
361 UINT nIndex
= UINT_MAX
;
362 HRESULT hResult
= iDialog
->GetFileTypeIndex(&nIndex
);
364 ( FAILED(hResult
) ) ||
365 ( nIndex
== UINT_MAX
) // COM dialog sometimes return S_OK for empty filter lists .-(
370 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
373 ::sal_Int32 nRealIndex
= (nIndex
-1); // COM dialog base on 1 ... filter container on 0 .-)
375 (nRealIndex
>= 0 ) &&
376 (m_lFilters
.getFilter(nRealIndex
, sTitle
))
378 rRequest
->setArgument(PROP_FILTER_TITLE
, sTitle
);
379 else if ( nRealIndex
== -1 ) // Dialog not visible yet
381 sTitle
= m_lFilters
.getCurrentFilter();
382 rRequest
->setArgument(PROP_FILTER_TITLE
, sTitle
);
389 //-------------------------------------------------------------------------------
390 void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef
& rRequest
)
393 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
395 m_hLastResult
= m_iDialogOpen
.create();
396 if (FAILED(m_hLastResult
))
401 m_iDialogOpen
->QueryInterface(IID_IFileDialog
, (void **)(&iDialog
));
403 m_iDialogOpen
.query(&iDialog
);
406 TFileDialogEvents iHandler
= m_iEventHandler
;
412 iDialog
->GetOptions ( &nFlags
);
414 nFlags
&= ~FOS_FORCESHOWHIDDEN
;
415 nFlags
|= FOS_PATHMUSTEXIST
;
416 nFlags
|= FOS_FILEMUSTEXIST
;
417 nFlags
|= FOS_OVERWRITEPROMPT
;
418 nFlags
|= FOS_DONTADDTORECENT
;
420 iDialog
->SetOptions ( nFlags
);
422 ::sal_Int32 nFeatures
= rRequest
->getArgumentOrDefault(PROP_FEATURES
, (::sal_Int32
)0);
423 ::sal_Int32 nTemplate
= rRequest
->getArgumentOrDefault(PROP_TEMPLATE_DESCR
, (::sal_Int32
)0);
424 impl_sta_enableFeatures(nFeatures
, nTemplate
);
426 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
428 pHandlerImpl
->startListening(iDialog
);
431 //-------------------------------------------------------------------------------
432 void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef
& rRequest
)
435 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
437 m_hLastResult
= m_iDialogSave
.create();
438 if (FAILED(m_hLastResult
))
441 TFileDialogEvents iHandler
= m_iEventHandler
;
444 m_iDialogSave
->QueryInterface(IID_IFileDialog
, (void **)(&iDialog
));
446 m_iDialogSave
.query(&iDialog
);
453 iDialog
->GetOptions ( &nFlags
);
455 nFlags
&= ~FOS_FORCESHOWHIDDEN
;
456 nFlags
|= FOS_PATHMUSTEXIST
;
457 nFlags
|= FOS_FILEMUSTEXIST
;
458 nFlags
|= FOS_OVERWRITEPROMPT
;
459 nFlags
|= FOS_DONTADDTORECENT
;
461 iDialog
->SetOptions ( nFlags
);
463 ::sal_Int32 nFeatures
= rRequest
->getArgumentOrDefault(PROP_FEATURES
, (::sal_Int32
)0);
464 ::sal_Int32 nTemplate
= rRequest
->getArgumentOrDefault(PROP_TEMPLATE_DESCR
, (::sal_Int32
)0);
465 impl_sta_enableFeatures(nFeatures
, nTemplate
);
467 VistaFilePickerEventHandler
* pHandlerImpl
= (VistaFilePickerEventHandler
*)iHandler
.get();
469 pHandlerImpl
->startListening(iDialog
);
472 //-------------------------------------------------------------------------------
473 static const ::sal_Int32 GROUP_VERSION
= 1;
474 static const ::sal_Int32 GROUP_TEMPLATE
= 2;
475 static const ::sal_Int32 GROUP_IMAGETEMPLATE
= 3;
476 static const ::sal_Int32 GROUP_CHECKBOXES
= 4;
478 //-------------------------------------------------------------------------------
479 static void setLabelToControl(CResourceProvider
& rResourceProvider
, TFileDialogCustomize iCustom
, sal_uInt16 nControlId
)
481 OUString aLabel
= rResourceProvider
.getResString(nControlId
);
482 aLabel
= SOfficeToWindowsLabel(aLabel
);
483 iCustom
->SetControlLabel(nControlId
, reinterpret_cast<LPCWSTR
>(aLabel
.getStr()) );
486 //-------------------------------------------------------------------------------
487 void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures
, ::sal_Int32 nTemplate
)
492 case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE
:
493 case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE
:
494 aGUID
= CLIENTID_FILEDIALOG_SIMPLE
;
497 case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION
:
498 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS
:
499 aGUID
= CLIENTID_FILEDIALOG_OPTIONS
;
502 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
:
503 aGUID
= CLIENTID_FILESAVE_PASSWORD
;
506 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION
:
507 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION
:
508 aGUID
= CLIENTID_FILESAVE_SELECTION
;
511 case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE
:
512 aGUID
= CLIENTID_FILESAVE_TEMPLATE
;
515 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE
:
516 aGUID
= CLIENTID_FILEOPEN_LINK_TEMPLATE
;
519 case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY
:
520 aGUID
= CLIENTID_FILEOPEN_PLAY
;
523 case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW
:
524 aGUID
= CLIENTID_FILEOPEN_LINK
;
527 TFileDialog iDialog
= impl_getBaseDialogInterface();
528 iDialog
->SetClientGuid ( aGUID
);
530 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
532 if ((nFeatures
& FEATURE_VERSION
) == FEATURE_VERSION
)
534 iCustom
->StartVisualGroup (GROUP_VERSION
, L
"Version");
535 iCustom
->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION
);
536 iCustom
->EndVisualGroup ();
537 iCustom
->MakeProminent (GROUP_VERSION
);
540 if ((nFeatures
& FEATURE_TEMPLATE
) == FEATURE_TEMPLATE
)
542 iCustom
->StartVisualGroup (GROUP_TEMPLATE
, L
"Template");
543 iCustom
->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE
);
544 iCustom
->EndVisualGroup ();
545 iCustom
->MakeProminent (GROUP_TEMPLATE
);
548 if ((nFeatures
& FEATURE_IMAGETEMPLATE
) == FEATURE_IMAGETEMPLATE
)
550 iCustom
->StartVisualGroup (GROUP_IMAGETEMPLATE
, L
"Style");
551 iCustom
->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE
);
552 iCustom
->EndVisualGroup ();
553 iCustom
->MakeProminent (GROUP_IMAGETEMPLATE
);
556 iCustom
->StartVisualGroup (GROUP_CHECKBOXES
, L
"");
558 sal_uInt16
nControlId(0);
559 if ((nFeatures
& FEATURE_AUTOEXTENSION
) == FEATURE_AUTOEXTENSION
)
561 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
;
562 iCustom
->AddCheckButton (nControlId
, L
"Auto Extension", true);
563 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
566 if ((nFeatures
& FEATURE_PASSWORD
) == FEATURE_PASSWORD
)
568 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
;
569 iCustom
->AddCheckButton (nControlId
, L
"Password", false);
570 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
573 if ((nFeatures
& FEATURE_READONLY
) == FEATURE_READONLY
)
575 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY
;
576 iCustom
->AddCheckButton (nControlId
, L
"Readonly", false);
577 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
580 if ((nFeatures
& FEATURE_FILTEROPTIONS
) == FEATURE_FILTEROPTIONS
)
582 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
;
583 iCustom
->AddCheckButton (nControlId
, L
"Filter Options", false);
584 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
587 if ((nFeatures
& FEATURE_LINK
) == FEATURE_LINK
)
589 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK
;
590 iCustom
->AddCheckButton (nControlId
, L
"Link", false);
591 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
594 if ((nFeatures
& FEATURE_SELECTION
) == FEATURE_SELECTION
)
596 nControlId
= css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION
;
597 iCustom
->AddCheckButton (nControlId
, L
"Selection", false);
598 setLabelToControl(m_ResProvider
, iCustom
, nControlId
);
601 /* can be ignored ... new COM dialog supports preview native now !
602 if ((nFeatures & FEATURE_PREVIEW) == FEATURE_PREVIEW)
603 iCustom->AddCheckButton (css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, L"Preview", false);
606 iCustom
->EndVisualGroup();
608 if ((nFeatures
& FEATURE_PLAY
) == FEATURE_PLAY
)
609 iCustom
->AddPushButton (css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY
, L
"Play");
613 //-------------------------------------------------------------------------------
614 void VistaFilePickerImpl::impl_sta_SetMultiSelectionMode(const RequestRef
& rRequest
)
616 const ::sal_Bool bMultiSelection
= rRequest
->getArgumentOrDefault(PROP_MULTISELECTION_MODE
, (::sal_Bool
)sal_True
);
619 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
620 TFileDialog iDialog
= impl_getBaseDialogInterface();
625 m_hLastResult
= iDialog
->GetOptions ( &nFlags
);
628 nFlags
|= FOS_ALLOWMULTISELECT
;
630 nFlags
&= ~FOS_ALLOWMULTISELECT
;
632 iDialog
->SetOptions ( nFlags
);
635 //-------------------------------------------------------------------------------
636 void VistaFilePickerImpl::impl_sta_SetTitle(const RequestRef
& rRequest
)
638 OUString sTitle
= rRequest
->getArgumentOrDefault(PROP_TITLE
, OUString());
641 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
642 TFileDialog iDialog
= impl_getBaseDialogInterface();
646 iDialog
->SetTitle(reinterpret_cast<LPCTSTR
>(sTitle
.getStr()));
649 //-------------------------------------------------------------------------------
650 void VistaFilePickerImpl::impl_sta_SetFileName(const RequestRef
& rRequest
)
652 OUString sFileName
= rRequest
->getArgumentOrDefault(PROP_FILENAME
, OUString());
655 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
656 TFileDialog iDialog
= impl_getBaseDialogInterface();
660 iDialog
->SetFileName(reinterpret_cast<LPCTSTR
>(sFileName
.getStr()));
663 //-------------------------------------------------------------------------------
664 void VistaFilePickerImpl::impl_sta_SetDirectory(const RequestRef
& rRequest
)
666 OUString sDirectory
= rRequest
->getArgumentOrDefault(PROP_DIRECTORY
, OUString());
667 bool bForce
= rRequest
->getArgumentOrDefault(PROP_FORCE
, false);
671 // Vista stores last used folders for file dialogs
672 // so we don't want the application to change the folder
674 // Store the requested folder in the mean time and decide later
676 m_sDirectory
= sDirectory
;
680 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
681 TFileDialog iDialog
= impl_getBaseDialogInterface();
685 ComPtr
< IShellItem
> pFolder
;
687 HRESULT hResult
= SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR
>(sDirectory
.getStr()), NULL
, IID_IShellItem
, reinterpret_cast<void**>(&pFolder
) );
689 HRESULT hResult
= SHCreateItemFromParsingName ( sDirectory
.getStr(), NULL
, IID_PPV_ARGS(&pFolder
) );
691 if ( FAILED(hResult
) )
694 if ( m_bInExecute
|| bForce
)
695 iDialog
->SetFolder(pFolder
);
698 // Use set default folder as Microsoft recommends in the IFileDialog documentation.
699 iDialog
->SetDefaultFolder(pFolder
);
703 void VistaFilePickerImpl::impl_sta_GetDirectory(const RequestRef
& rRequest
)
705 TFileDialog iDialog
= impl_getBaseDialogInterface();
706 ComPtr
< IShellItem
> pFolder
;
707 HRESULT hResult
= iDialog
->GetFolder( &pFolder
);
708 if ( FAILED(hResult
) )
710 OUString sFolder
= lcl_getURLFromShellItem ( pFolder
);
711 if( sFolder
.getLength())
712 rRequest
->setArgument( PROP_DIRECTORY
, sFolder
);
715 //-------------------------------------------------------------------------------
716 void VistaFilePickerImpl::impl_sta_SetDefaultName(const RequestRef
& rRequest
)
718 OUString sFilename
= rRequest
->getArgumentOrDefault(PROP_FILENAME
, OUString());
719 TFileDialog iDialog
= impl_getBaseDialogInterface();
721 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
725 // if we have the autoextension check box set, remove (or change ???) the extension of the filename
726 // so that the autoextension mechanism can do its job
728 HRESULT hResult
= iCustom
->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, &bValue
);
731 sal_Int32 nSepPos
= sFilename
.lastIndexOf( '.' );
733 sFilename
= sFilename
.copy(0, nSepPos
);
736 iDialog
->SetFileName ( reinterpret_cast<LPCTSTR
>(sFilename
.getStr()));
737 m_sFilename
= sFilename
;
740 //-------------------------------------------------------------------------------
741 void VistaFilePickerImpl::impl_sta_setFiltersOnDialog()
744 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
746 ::std::vector
< COMDLG_FILTERSPEC
> lFilters
= lcl_buildFilterList(m_lFilters
);
747 OUString sCurrentFilter
= m_lFilters
.getCurrentFilter();
748 sal_Int32 nCurrentFilter
= m_lFilters
.getFilterPos(sCurrentFilter
);
749 TFileDialog iDialog
= impl_getBaseDialogInterface();
750 TFileDialogCustomize iCustomize
= impl_getCustomizeInterface();
755 if (lFilters
.empty())
758 COMDLG_FILTERSPEC
*pFilt
= &lFilters
[0];
759 iDialog
->SetFileTypes(lFilters
.size(), pFilt
/*&lFilters[0]*/);
760 iDialog
->SetFileTypeIndex(nCurrentFilter
+ 1);
763 HRESULT hResult
= iCustomize
->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, &bValue
);
767 LPCWSTR lpFilterExt
= lFilters
[0].pszSpec
;
769 lpFilterExt
= wcsrchr( lpFilterExt
, '.' );
772 iDialog
->SetDefaultExtension( lpFilterExt
);
777 //-------------------------------------------------------------------------------
778 void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef
& rRequest
)
781 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
783 TFileOpenDialog iOpen
= m_iDialogOpen
;
784 TFileSaveDialog iSave
= m_iDialogSave
;
785 ::sal_Bool bInExecute
= m_bInExecute
;
790 // ask dialog for results
791 // Note : we must differ between single/multi selection !
792 // Note further: we must react different if dialog is in execute or not .-(
793 ComPtr
< IShellItem
> iItem
;
794 ComPtr
< IShellItemArray
> iItems
;
795 HRESULT hResult
= E_FAIL
;
800 hResult
= iOpen
->GetSelectedItems(&iItems
);
803 hResult
= iOpen
->GetResults(&iItems
);
805 hResult
= iOpen
->GetResult(&iItem
);
812 hResult
= iSave
->GetCurrentSelection(&iItem
);
814 hResult
= iSave
->GetResult(&iItem
);
820 // convert and pack results
824 const OUString sURL
= lcl_getURLFromShellItem(iItem
);
825 if (sURL
.getLength() > 0)
826 lFiles
.push_back(sURL
);
832 hResult
= iItems
->GetCount(&nCount
);
833 if ( SUCCEEDED(hResult
) )
835 for (DWORD i
=0; i
<nCount
; ++i
)
837 hResult
= iItems
->GetItemAt(i
, &iItem
);
838 if ( SUCCEEDED(hResult
) )
840 const OUString sURL
= lcl_getURLFromShellItem(iItem
);
841 if (sURL
.getLength() > 0)
842 lFiles
.push_back(sURL
);
848 rRequest
->setArgument(PROP_SELECTED_FILES
, lFiles
.getAsConstList());
851 //-------------------------------------------------------------------------------
852 void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef
& rRequest
)
854 impl_sta_setFiltersOnDialog();
857 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
859 TFileDialog iDialog
= impl_getBaseDialogInterface();
860 TFileOpenDialog iOpen
= m_iDialogOpen
;
861 TFileSaveDialog iSave
= m_iDialogSave
;
863 // it's important to know if we are showing the dialog.
864 // Some dialog interface methods cant be called then or some
865 // tasks must be done differently .-) (e.g. see impl_sta_getSelectedFiles())
866 m_bInExecute
= sal_True
;
868 m_bWasExecuted
= sal_True
;
873 // we set the directory only if we have a save dialog and a filename
874 // for the other cases, the file dialog remembers its last location
875 // according to its client guid.
876 if( m_sDirectory
.getLength())
878 ComPtr
< IShellItem
> pFolder
;
880 HRESULT hResult
= SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR
>(m_sDirectory
.getStr()), NULL
, IID_IShellItem
, reinterpret_cast<void**>(&pFolder
) );
882 HRESULT hResult
= SHCreateItemFromParsingName ( m_sDirectory
.getStr(), NULL
, IID_PPV_ARGS(&pFolder
) );
884 if ( SUCCEEDED(hResult
) )
886 if (m_sFilename
.getLength())
888 OUString
aFileURL(m_sDirectory
);
889 sal_Int32 nIndex
= aFileURL
.lastIndexOf('/');
890 if (nIndex
!= aFileURL
.getLength()-1)
891 aFileURL
+= OUString("/");
892 aFileURL
+= m_sFilename
;
894 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
897 HRESULT hResult
= iCustom
->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, &bValue
);
901 hResult
= iDialog
->GetFileTypeIndex(&nFileType
);
902 if ( SUCCEEDED(hResult
) )
904 ::sal_Int32 nRealIndex
= (nFileType
-1); // COM dialog base on 1 ... filter container on 0 .-)
905 ::std::vector
< COMDLG_FILTERSPEC
> lFilters
= lcl_buildFilterList(m_lFilters
);
906 LPCWSTR lpFilterExt
= lFilters
[nRealIndex
].pszSpec
;
908 lpFilterExt
= wcsrchr( lpFilterExt
, '.' );
910 aFileURL
+= reinterpret_cast<const sal_Unicode
*>(lpFilterExt
);
914 // Check existence of file. Set folder only for this special case
915 OUString aSystemPath
;
916 osl_getSystemPathFromFileURL( aFileURL
.pData
, &aSystemPath
.pData
);
918 WIN32_FIND_DATA aFindFileData
;
919 HANDLE hFind
= FindFirstFile( reinterpret_cast<LPCWSTR
>(aSystemPath
.getStr()), &aFindFileData
);
920 if (hFind
!= INVALID_HANDLE_VALUE
)
921 iDialog
->SetFolder(pFolder
);
923 hResult
= iDialog
->AddPlace(pFolder
, FDAP_TOP
);
928 hResult
= iDialog
->AddPlace(pFolder
, FDAP_TOP
);
933 HRESULT hResult
= E_FAIL
;
936 // show dialog and wait for user decision
938 hResult
= iOpen
->Show( m_hParentWindow
); // parent window needed
941 hResult
= iSave
->Show( m_hParentWindow
); // parent window needed
948 m_bInExecute
= sal_False
;
952 if ( FAILED(hResult
) )
955 impl_sta_getSelectedFiles(rRequest
);
956 rRequest
->setArgument(PROP_DIALOG_SHOW_RESULT
, sal_True
);
959 //-------------------------------------------------------------------------------
960 TFileDialog
VistaFilePickerImpl::impl_getBaseDialogInterface()
965 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
967 if (m_iDialogOpen
.is())
969 m_iDialogOpen
->QueryInterface(IID_IFileDialog
, (void**)(&iDialog
));
971 m_iDialogOpen
.query(&iDialog
);
973 if (m_iDialogSave
.is())
975 m_iDialogSave
->QueryInterface(IID_IFileDialog
, (void**)(&iDialog
));
977 m_iDialogSave
.query(&iDialog
);
983 //-------------------------------------------------------------------------------
984 TFileDialogCustomize
VistaFilePickerImpl::impl_getCustomizeInterface()
986 TFileDialogCustomize iCustom
;
989 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
991 if (m_iDialogOpen
.is())
993 m_iDialogOpen
->QueryInterface(IID_IFileDialogCustomize
, (void**)(&iCustom
));
995 m_iDialogOpen
.query(&iCustom
);
998 if (m_iDialogSave
.is())
1000 m_iDialogSave
->QueryInterface(IID_IFileDialogCustomize
, (void**)(&iCustom
));
1002 m_iDialogSave
.query(&iCustom
);
1008 //-------------------------------------------------------------------------------
1009 void lcl_removeControlItemsWorkaround(const TFileDialogCustomize
& iCustom
,
1010 ::sal_Int16 nControlId
)
1015 hResult
= iCustom
->SetSelectedControlItem(nControlId
, 1000);
1017 while ( SUCCEEDED(hResult
) )
1018 hResult
= iCustom
->RemoveControlItem(nControlId
, i
++);
1021 //-------------------------------------------------------------------------------
1022 void VistaFilePickerImpl::impl_sta_SetControlValue(const RequestRef
& rRequest
)
1024 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1025 ::sal_Int16 nAction
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ACTION
, INVALID_CONTROL_ACTION
);
1026 css::uno::Any aValue
= rRequest
->getArgumentOrDefault(PROP_CONTROL_VALUE
, css::uno::Any() );
1028 // dont check for right values here ...
1029 // most parameters are optional !
1031 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1032 if ( ! iCustom
.is())
1037 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
:
1038 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
:
1039 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY
:
1040 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
:
1041 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK
:
1042 //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1043 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION
:
1045 ::sal_Bool bValue
= sal_False
;
1047 iCustom
->SetCheckButtonState(nId
, bValue
);
1051 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION
:
1052 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE
:
1053 case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE
:
1058 case css::ui::dialogs::ControlActions::DELETE_ITEMS
:
1060 hResult
= iCustom
->RemoveAllControlItems(nId
);
1061 if ( FAILED(hResult
) )
1062 lcl_removeControlItemsWorkaround(iCustom
, nId
);
1066 case css::ui::dialogs::ControlActions::ADD_ITEMS
:
1068 css::uno::Sequence
< OUString
> lItems
;
1070 for (::sal_Int32 i
=0; i
<lItems
.getLength(); ++i
)
1072 const OUString
& sItem
= lItems
[i
];
1073 hResult
= iCustom
->AddControlItem(nId
, i
, reinterpret_cast<LPCTSTR
>(sItem
.getStr()));
1078 case css::ui::dialogs::ControlActions::SET_SELECT_ITEM
:
1080 ::sal_Int32 nItem
= 0;
1082 hResult
= iCustom
->SetSelectedControlItem(nId
, nItem
);
1089 case css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY
:
1096 //-------------------------------------------------------------------------------
1097 void VistaFilePickerImpl::impl_sta_GetControlValue(const RequestRef
& rRequest
)
1099 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1100 ::sal_Int16 nAction
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ACTION
, INVALID_CONTROL_ACTION
);
1102 // dont check for right values here ...
1103 // most parameters are optional !
1105 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1106 if ( ! iCustom
.is())
1109 css::uno::Any aValue
;
1110 if( m_bWasExecuted
)
1113 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
:
1114 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY
:
1115 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS
:
1116 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK
:
1117 //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1118 case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION
:
1120 BOOL bValue
= FALSE
;
1121 HRESULT hResult
= iCustom
->GetCheckButtonState(nId
, &bValue
);
1122 if ( SUCCEEDED(hResult
) )
1123 aValue
= css::uno::makeAny((sal_Bool
)bValue
);
1128 if (aValue
.hasValue())
1129 rRequest
->setArgument(PROP_CONTROL_VALUE
, aValue
);
1132 //-------------------------------------------------------------------------------
1133 void VistaFilePickerImpl::impl_sta_SetControlLabel(const RequestRef
& rRequest
)
1135 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1136 OUString sLabel
= rRequest
->getArgumentOrDefault(PROP_CONTROL_LABEL
, OUString() );
1138 // dont check for right values here ...
1139 // most parameters are optional !
1141 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1142 if ( ! iCustom
.is())
1144 iCustom
->SetControlLabel ( nId
, reinterpret_cast<LPCTSTR
>(sLabel
.getStr()));
1147 //-------------------------------------------------------------------------------
1148 void VistaFilePickerImpl::impl_sta_GetControlLabel(const RequestRef
& /*rRequest*/)
1152 //-------------------------------------------------------------------------------
1153 void VistaFilePickerImpl::impl_sta_EnableControl(const RequestRef
& rRequest
)
1155 ::sal_Int16 nId
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ID
, INVALID_CONTROL_ID
);
1156 ::sal_Bool bEnabled
= rRequest
->getArgumentOrDefault(PROP_CONTROL_ENABLE
, (::sal_Bool
)sal_True
);
1158 // dont check for right values here ...
1159 // most parameters are optional !
1161 TFileDialogCustomize iCustom
= impl_getCustomizeInterface();
1162 if ( ! iCustom
.is())
1165 CDCONTROLSTATEF eState
= CDCS_VISIBLE
;
1167 eState
|= CDCS_ENABLED
;
1169 eState
|= CDCS_INACTIVE
;
1171 iCustom
->SetControlState(nId
, eState
);
1173 //-------------------------------------------------------------------------------
1174 void VistaFilePickerImpl::impl_SetDefaultExtension( const OUString
& currentFilter
)
1176 TFileDialog iDialog
= impl_getBaseDialogInterface();
1177 if (currentFilter
.getLength())
1180 m_lFilters
.getFilter(currentFilter
, FilterExt
);
1182 sal_Int32 posOfPoint
= FilterExt
.indexOf(L
'.');
1183 const sal_Unicode
* pFirstExtStart
= FilterExt
.getStr() + posOfPoint
+ 1;
1185 sal_Int32 posOfSemiColon
= FilterExt
.indexOf(L
';') - 1;
1186 if (posOfSemiColon
< 0)
1187 posOfSemiColon
= FilterExt
.getLength() - 1;
1189 FilterExt
= OUString(pFirstExtStart
, posOfSemiColon
- posOfPoint
);
1190 iDialog
->SetDefaultExtension ( reinterpret_cast<LPCTSTR
>(FilterExt
.getStr()) );
1194 static void impl_refreshFileDialog( TFileDialog iDialog
)
1196 if ( SUCCEEDED(iDialog
->SetFileName(L
"")) &&
1197 SUCCEEDED(iDialog
->SetFileName(L
"*.*")) )
1199 IOleWindow
* iOleWindow
;
1201 if (SUCCEEDED(iDialog
->QueryInterface(IID_IOleWindow
, reinterpret_cast<void**>(&iOleWindow
))))
1203 if (SUCCEEDED(iDialog
->QueryInterface(IID_PPV_ARGS(&iOleWindow
))))
1207 if (SUCCEEDED(iOleWindow
->GetWindow(&hwnd
)))
1209 PostMessage(hwnd
, WM_COMMAND
, IDOK
, 0);
1211 iOleWindow
->Release();
1216 //-------------------------------------------------------------------------------
1217 void VistaFilePickerImpl::onAutoExtensionChanged (bool bChecked
)
1220 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
1222 const OUString sFilter
= m_lFilters
.getCurrentFilter ();
1224 if ( !m_lFilters
.getFilter (sFilter
, sExt
))
1227 TFileDialog iDialog
= impl_getBaseDialogInterface();
1235 pExt
= reinterpret_cast<LPCTSTR
>(sExt
.getStr());
1236 pExt
= wcsrchr( pExt
, '.' );
1240 iDialog
->SetDefaultExtension( pExt
);
1243 bool VistaFilePickerImpl::onFileTypeChanged( UINT
/*nTypeIndex*/ )
1248 } // namespace vista
1249 } // namespace win32
1250 } // namespace fpicker
1252 #endif // __IFileDialogCustomize_INTERFACE_DEFINED__
1254 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */