/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include "VistaFilePickerEventHandler.hxx" #include "asyncrequests.hxx" #include #include #include #include #include #include #include // namespace directives namespace fpicker{ namespace win32{ namespace vista{ VistaFilePickerEventHandler::VistaFilePickerEventHandler(IVistaFilePickerInternalNotify* pInternalNotify) : m_nRefCount (0 ) , m_nListenerHandle (0 ) , m_pDialog ( ) , m_pInternalNotify (pInternalNotify) , m_lListener (m_aMutex) { } VistaFilePickerEventHandler::~VistaFilePickerEventHandler() { } HRESULT STDMETHODCALLTYPE VistaFilePickerEventHandler::QueryInterface(REFIID rIID , void** ppObject) { *ppObject=nullptr; if ( rIID == IID_IUnknown ) *ppObject = static_cast(static_cast(this)); if ( rIID == IID_IFileDialogEvents ) *ppObject = static_cast(this); if ( rIID == IID_IFileDialogControlEvents ) *ppObject = static_cast(this); if ( *ppObject != nullptr ) { static_cast(*ppObject)->AddRef(); return S_OK; } return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::AddRef() { return osl_atomic_increment(&m_nRefCount); } ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::Release() { ULONG nReturn = --m_nRefCount; if ( m_nRefCount == 0 ) delete this; return nReturn; } STDMETHODIMP VistaFilePickerEventHandler::OnFileOk(IFileDialog* /*pDialog*/) { return E_NOTIMPL; } STDMETHODIMP VistaFilePickerEventHandler::OnFolderChanging(IFileDialog* /*pDialog*/, IShellItem* /*pFolder*/) { return E_NOTIMPL; } STDMETHODIMP VistaFilePickerEventHandler::OnFolderChange(IFileDialog* /*pDialog*/) { impl_sendEvent(E_DIRECTORY_CHANGED, 0); m_pInternalNotify->onDirectoryChanged(); return S_OK; } STDMETHODIMP VistaFilePickerEventHandler::OnSelectionChange(IFileDialog* /*pDialog*/) { impl_sendEvent(E_FILE_SELECTION_CHANGED, 0); return S_OK; } STDMETHODIMP VistaFilePickerEventHandler::OnShareViolation(IFileDialog* /*pDialog*/ , IShellItem* /*pItem*/ , FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/) { impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER); return S_OK; } STDMETHODIMP VistaFilePickerEventHandler::OnTypeChange(IFileDialog* pDialog) { UINT nFileTypeIndex; HRESULT hResult = pDialog->GetFileTypeIndex( &nFileTypeIndex ); if ( hResult == S_OK ) { if ( m_pInternalNotify->onFileTypeChanged( nFileTypeIndex )) impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER); } return S_OK; } STDMETHODIMP VistaFilePickerEventHandler::OnOverwrite(IFileDialog* /*pDialog*/ , IShellItem* /*pItem*/ , FDE_OVERWRITE_RESPONSE* /*pResponse*/) { return E_NOTIMPL; } STDMETHODIMP VistaFilePickerEventHandler::OnItemSelected(IFileDialogCustomize* /*pCustomize*/, DWORD nIDCtl , DWORD /*nIDItem*/ ) { impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast( nIDCtl )); return S_OK; } STDMETHODIMP VistaFilePickerEventHandler::OnButtonClicked(IFileDialogCustomize* /*pCustomize*/, DWORD nIDCtl ) { impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast( nIDCtl)); return S_OK; } STDMETHODIMP VistaFilePickerEventHandler::OnCheckButtonToggled(IFileDialogCustomize* /*pCustomize*/, DWORD nIDCtl , BOOL bChecked ) { if (nIDCtl == css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION) m_pInternalNotify->onAutoExtensionChanged(bChecked); impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast( nIDCtl)); return S_OK; } STDMETHODIMP VistaFilePickerEventHandler::OnControlActivating(IFileDialogCustomize* /*pCustomize*/, DWORD nIDCtl ) { impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast( nIDCtl)); return S_OK; } void VistaFilePickerEventHandler::addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) { m_lListener.addInterface(cppu::UnoType::get(), xListener); } void VistaFilePickerEventHandler::removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) { m_lListener.removeInterface(cppu::UnoType::get(), xListener); } void VistaFilePickerEventHandler::startListening( const TFileDialog& pBroadcaster ) { if (m_pDialog.is()) return; m_pDialog = pBroadcaster; m_pDialog->Advise(this, &m_nListenerHandle); } void VistaFilePickerEventHandler::stopListening() { if (m_pDialog.is()) { m_pDialog->Unadvise(m_nListenerHandle); m_pDialog.release(); } } static const char PROP_CONTROL_ID[] = "control_id"; static const char PROP_PICKER_LISTENER[] = "picker_listener"; namespace { class AsyncPickerEvents : public RequestHandler { public: AsyncPickerEvents() {} virtual void before() override {} virtual void doRequest(const RequestRef& rRequest) override { const ::sal_Int32 nEventID = rRequest->getRequest(); const ::sal_Int16 nControlID = rRequest->getArgumentOrDefault(PROP_CONTROL_ID, ::sal_Int16(0)); const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >()); if ( ! xListener.is()) return; css::ui::dialogs::FilePickerEvent aEvent; aEvent.ElementId = nControlID; switch (nEventID) { case VistaFilePickerEventHandler::E_FILE_SELECTION_CHANGED : xListener->fileSelectionChanged(aEvent); break; case VistaFilePickerEventHandler::E_DIRECTORY_CHANGED : xListener->directoryChanged(aEvent); break; case VistaFilePickerEventHandler::E_HELP_REQUESTED : xListener->helpRequested(aEvent); break; case VistaFilePickerEventHandler::E_CONTROL_STATE_CHANGED : xListener->controlStateChanged(aEvent); break; case VistaFilePickerEventHandler::E_DIALOG_SIZE_CHANGED : xListener->dialogSizeChanged(); break; // no default here. Let compiler detect changes on enum set ! } } virtual void after() override {} }; } void VistaFilePickerEventHandler::impl_sendEvent( EEventType eEventType, ::sal_Int16 nControlID) { // See special handling in ~AsyncRequests for this static static AsyncRequests aNotify(std::make_shared()); ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer( cppu::UnoType::get()); if ( ! pContainer) return; ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); while (pIterator.hasMoreElements()) { try { css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener (pIterator.next(), css::uno::UNO_QUERY); RequestRef rRequest = std::make_shared(); rRequest->setRequest (eEventType); rRequest->setArgument(PROP_PICKER_LISTENER, xListener); if ( nControlID ) rRequest->setArgument(PROP_CONTROL_ID, nControlID); aNotify.triggerRequestDirectly(rRequest); //aNotify.triggerRequestNonBlocked(rRequest); } catch(const css::uno::RuntimeException&) { pIterator.remove(); } } } } // namespace vista } // namespace win32 } // namespace fpicker /* vim:set shiftwidth=4 softtabstop=4 expandtab: */