LibreOffice Module fpicker (master)  1
VistaFilePickerEventHandler.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <memory>
23 
25 
26 #include "asyncrequests.hxx"
27 
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/embed/XStorage.hpp>
30 #include <com/sun/star/document/XDocumentRevisionListPersistence.hpp>
31 #include <com/sun/star/util/RevisionTag.hpp>
32 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
33 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
34 
35 #include <osl/file.hxx>
36 
37 
38 // namespace directives
39 
40 
41 namespace fpicker{
42 namespace win32{
43 namespace vista{
44 
45 
47  : m_nRefCount (0 )
48  , m_nListenerHandle (0 )
49  , m_pDialog ( )
50  , m_pInternalNotify (pInternalNotify)
51  , m_lListener (m_aMutex)
52 {
53 }
54 
55 
57 {
58 }
59 
60 
61 HRESULT STDMETHODCALLTYPE VistaFilePickerEventHandler::QueryInterface(REFIID rIID ,
62  void** ppObject)
63 {
64  *ppObject=nullptr;
65 
66  if ( rIID == IID_IUnknown )
67  *ppObject = static_cast<IUnknown*>(static_cast<IFileDialogEvents*>(this));
68 
69  if ( rIID == IID_IFileDialogEvents )
70  *ppObject = static_cast<IFileDialogEvents*>(this);
71 
72  if ( rIID == IID_IFileDialogControlEvents )
73  *ppObject = static_cast<IFileDialogControlEvents*>(this);
74 
75  if ( *ppObject != nullptr )
76  {
77  static_cast<IUnknown*>(*ppObject)->AddRef();
78  return S_OK;
79  }
80 
81  return E_NOINTERFACE;
82 }
83 
84 
85 ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::AddRef()
86 {
87  return osl_atomic_increment(&m_nRefCount);
88 }
89 
90 
91 ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::Release()
92 {
93  ULONG nReturn = --m_nRefCount;
94  if ( m_nRefCount == 0 )
95  delete this;
96 
97  return nReturn;
98 }
99 
100 
101 STDMETHODIMP VistaFilePickerEventHandler::OnFileOk(IFileDialog* /*pDialog*/)
102 {
103  return E_NOTIMPL;
104 }
105 
106 
107 STDMETHODIMP VistaFilePickerEventHandler::OnFolderChanging(IFileDialog* /*pDialog*/,
108  IShellItem* /*pFolder*/)
109 {
110  return E_NOTIMPL;
111 }
112 
113 
114 STDMETHODIMP VistaFilePickerEventHandler::OnFolderChange(IFileDialog* /*pDialog*/)
115 {
118  return S_OK;
119 }
120 
121 
122 STDMETHODIMP VistaFilePickerEventHandler::OnSelectionChange(IFileDialog* /*pDialog*/)
123 {
125  return S_OK;
126 }
127 
128 
129 STDMETHODIMP VistaFilePickerEventHandler::OnShareViolation(IFileDialog* /*pDialog*/ ,
130 
131  IShellItem* /*pItem*/ ,
132 
133  FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/)
134 {
135  impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER);
136  return S_OK;
137 }
138 
139 
140 STDMETHODIMP VistaFilePickerEventHandler::OnTypeChange(IFileDialog* pDialog)
141 {
142  UINT nFileTypeIndex;
143  HRESULT hResult = pDialog->GetFileTypeIndex( &nFileTypeIndex );
144 
145  if ( hResult == S_OK )
146  {
147  if ( m_pInternalNotify->onFileTypeChanged( nFileTypeIndex ))
148  impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER);
149  }
150 
151  return S_OK;
152 }
153 
154 
155 STDMETHODIMP VistaFilePickerEventHandler::OnOverwrite(IFileDialog* /*pDialog*/ ,
156  IShellItem* /*pItem*/ ,
157  FDE_OVERWRITE_RESPONSE* /*pResponse*/)
158 {
159  return E_NOTIMPL;
160 }
161 
162 
163 STDMETHODIMP VistaFilePickerEventHandler::OnItemSelected(IFileDialogCustomize* /*pCustomize*/,
164 
165  DWORD nIDCtl ,
166 
167  DWORD /*nIDItem*/ )
168 {
169 
170  impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl ));
171  return S_OK;
172 }
173 
174 
175 STDMETHODIMP VistaFilePickerEventHandler::OnButtonClicked(IFileDialogCustomize* /*pCustomize*/,
176  DWORD nIDCtl )
177 {
178 
179  impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl));
180  return S_OK;
181 }
182 
183 
184 STDMETHODIMP VistaFilePickerEventHandler::OnCheckButtonToggled(IFileDialogCustomize* /*pCustomize*/,
185  DWORD nIDCtl ,
186  BOOL bChecked )
187 {
188  if (nIDCtl == css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION)
190 
191  impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl));
192 
193  return S_OK;
194 }
195 
196 
197 STDMETHODIMP VistaFilePickerEventHandler::OnControlActivating(IFileDialogCustomize* /*pCustomize*/,
198  DWORD nIDCtl )
199 {
200  impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl));
201  return S_OK;
202 }
203 
204 
205 void VistaFilePickerEventHandler::addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener )
206 {
208 }
209 
210 
211 void VistaFilePickerEventHandler::removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener )
212 {
214 }
215 
216 
218 {
219  if (m_pDialog.is())
220  return;
221 
222  m_pDialog = pBroadcaster;
223  m_pDialog->Advise(this, &m_nListenerHandle);
224 }
225 
226 
228 {
229  if (m_pDialog.is())
230  {
231  m_pDialog->Unadvise(m_nListenerHandle);
232  m_pDialog.release();
233  }
234 }
235 
236 const char PROP_CONTROL_ID[] = "control_id";
237 const char PROP_PICKER_LISTENER[] = "picker_listener";
238 
239 namespace {
240 
241 class AsyncPickerEvents : public RequestHandler
242 {
243 public:
244 
245  AsyncPickerEvents()
246  {}
247 
248  virtual void before() override
249  {}
250 
251  virtual void doRequest(const RequestRef& rRequest) override
252  {
253  const ::sal_Int32 nEventID = rRequest->getRequest();
254  const ::sal_Int16 nControlID = rRequest->getArgumentOrDefault(PROP_CONTROL_ID, ::sal_Int16(0));
255  const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
256 
257  if ( ! xListener.is())
258  return;
259 
260  css::ui::dialogs::FilePickerEvent aEvent;
261  aEvent.ElementId = nControlID;
262 
263  switch (nEventID)
264  {
266  xListener->fileSelectionChanged(aEvent);
267  break;
268 
270  xListener->directoryChanged(aEvent);
271  break;
272 
274  xListener->helpRequested(aEvent);
275  break;
276 
278  xListener->controlStateChanged(aEvent);
279  break;
280 
282  xListener->dialogSizeChanged();
283  break;
284 
285  // no default here. Let compiler detect changes on enum set !
286  }
287  }
288 
289  virtual void after() override
290  {}
291 };
292 
293 }
294 
296  ::sal_Int16 nControlID)
297 {
298  // See special handling in ~AsyncRequests for this static
299  static AsyncRequests aNotify(std::make_shared<AsyncPickerEvents>());
300 
302  if ( ! pContainer)
303  return;
304 
305  ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
306  while (pIterator.hasMoreElements())
307  {
308  try
309  {
310  css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener (pIterator.next(), css::uno::UNO_QUERY);
311 
312  RequestRef rRequest = std::make_shared<Request>();
313  rRequest->setRequest (eEventType);
314  rRequest->setArgument(PROP_PICKER_LISTENER, xListener);
315  if ( nControlID )
316  rRequest->setArgument(PROP_CONTROL_ID, nControlID);
317 
318  aNotify.triggerRequestDirectly(rRequest);
319  //aNotify.triggerRequestNonBlocked(rRequest);
320  }
321  catch(const css::uno::RuntimeException&)
322  {
323  pIterator.remove();
324  }
325  }
326 }
327 
328 } // namespace vista
329 } // namespace win32
330 } // namespace fpicker
331 
332 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
TFileDialog m_pDialog
cached file dialog instance (there we listen for events)
sal_Int32 SAL_CALL removeInterface(const css::uno::Type &rKey, const css::uno::Reference< css::uno::XInterface > &rxIFace)
virtual ULONG STDMETHODCALLTYPE Release() override
oslInterlockedCount m_nRefCount
ref count for AddRef/Release()
void release()
Definition: comptr.hxx:168
css::uno::XInterface *SAL_CALL next()
void stopListening()
stop listening for file picker events on the internally cached dialog COM object. ...
STDMETHODIMP OnFolderChange(IFileDialog *pDialog) override
sal_Int32 SAL_CALL addInterface(const css::uno::Type &rKey, const css::uno::Reference< css::uno::XInterface > &r)
const wchar_t *typedef BOOL
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID rIID, void **ppObject) override
STDMETHODIMP OnFolderChanging(IFileDialog *pDialog, IShellItem *pFolder) override
bool is()
Definition: comptr.hxx:201
virtual void removeFilePickerListener(const css::uno::Reference< css::ui::dialogs::XFilePickerListener > &xListener)
STDMETHODIMP OnOverwrite(IFileDialog *pDialog, IShellItem *pItem, FDE_OVERWRITE_RESPONSE *pResponse) override
::cppu::OMultiTypeInterfaceContainerHelper m_lListener
used to inform file picker listener asynchronously.
virtual bool onFileTypeChanged(UINT nTypeIndex)=0
STDMETHODIMP OnSelectionChange(IFileDialog *pDialog) override
VistaFilePickerEventHandler(IVistaFilePickerInternalNotify *pInternalNotify)
void triggerRequestDirectly(const RequestRef &rRequest)
void impl_sendEvent(EEventType eEventType,::sal_Int16 nControlID)
virtual void onAutoExtensionChanged(bool bChecked)=0
void startListening(const TFileDialog &pBroadcaster)
start listening for file picker events on the given file open dialog COM object.
STDMETHODIMP OnTypeChange(IFileDialog *pDialog) override
STDMETHODIMP OnItemSelected(IFileDialogCustomize *pCustomize, DWORD nIDCtl, DWORD nIDItem) override
std::shared_ptr< Request > RequestRef
DWORD m_nListenerHandle
unique handle for this listener provided by the broadcaster on registration time
STDMETHODIMP OnButtonClicked(IFileDialogCustomize *pCustomize, DWORD nIDCtl) override
STDMETHODIMP OnCheckButtonToggled(IFileDialogCustomize *pCustomize, DWORD nIDCtl, BOOL bChecked) override
virtual void addFilePickerListener(const css::uno::Reference< css::ui::dialogs::XFilePickerListener > &xListener)
osl::Mutex m_aMutex
STDMETHODIMP OnShareViolation(IFileDialog *pDialog, IShellItem *pItem, FDE_SHAREVIOLATION_RESPONSE *pResponse) override
STDMETHODIMP OnFileOk(IFileDialog *pDialog) override
AnyEventRef aEvent
OInterfaceContainerHelper *SAL_CALL getContainer(const css::uno::Type &rKey) const
bool SAL_CALL hasMoreElements() const
STDMETHODIMP OnControlActivating(IFileDialogCustomize *pCustomize, DWORD nIDCtl) override