diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /toolkit/source/helper | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | toolkit/source/helper/accessibilityclient.cxx | 232 | ||||
-rw-r--r-- | toolkit/source/helper/btndlg.cxx | 304 | ||||
-rw-r--r-- | toolkit/source/helper/formpdfexport.cxx | 789 | ||||
-rw-r--r-- | toolkit/source/helper/imagealign.cxx | 128 | ||||
-rw-r--r-- | toolkit/source/helper/listenermultiplexer.cxx | 242 | ||||
-rw-r--r-- | toolkit/source/helper/property.cxx | 380 | ||||
-rw-r--r-- | toolkit/source/helper/servicenames.cxx | 24 | ||||
-rw-r--r-- | toolkit/source/helper/tkresmgr.cxx | 57 | ||||
-rw-r--r-- | toolkit/source/helper/unopropertyarrayhelper.cxx | 148 | ||||
-rw-r--r-- | toolkit/source/helper/unowrapper.cxx | 314 | ||||
-rw-r--r-- | toolkit/source/helper/vclunohelper.cxx | 608 |
11 files changed, 3226 insertions, 0 deletions
diff --git a/toolkit/source/helper/accessibilityclient.cxx b/toolkit/source/helper/accessibilityclient.cxx new file mode 100644 index 000000000..773bc9bfb --- /dev/null +++ b/toolkit/source/helper/accessibilityclient.cxx @@ -0,0 +1,232 @@ +/* -*- 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 <config_feature_desktop.h> +#include <config_wasm_strip.h> + +#include <sal/config.h> + +#include <toolkit/helper/accessiblefactory.hxx> +#include <osl/module.h> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <rtl/ref.hxx> +#include <tools/svlibrary.h> + +#include <helper/accessibilityclient.hxx> + +namespace toolkit +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::accessibility; + + namespace + { +#ifndef DISABLE_DYNLOADING + oslModule s_hAccessibleImplementationModule = nullptr; +#endif +#if HAVE_FEATURE_DESKTOP +#if !ENABLE_WASM_STRIP_ACCESSIBILITY + GetStandardAccComponentFactory s_pAccessibleFactoryFunc = nullptr; +#endif +#endif + ::rtl::Reference< IAccessibleFactory > s_pFactory; + } + + + //= AccessibleDummyFactory + + namespace { + + class AccessibleDummyFactory: + public IAccessibleFactory + { + public: + AccessibleDummyFactory(); + AccessibleDummyFactory(const AccessibleDummyFactory&) = delete; + AccessibleDummyFactory& operator=(const AccessibleDummyFactory&) = delete; + + protected: + virtual ~AccessibleDummyFactory() override; + + public: + // IAccessibleFactory + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXButton* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXCheckBox* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXRadioButton* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXListBox* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXFixedHyperlink* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXFixedText* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXScrollBar* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXEdit* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXComboBox* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXToolBox* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXHeaderBar* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( SVTXNumericField* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessibleContext > + createAccessibleContext( VCLXWindow* /*_pXWindow*/ ) override + { + return nullptr; + } + css::uno::Reference< css::accessibility::XAccessible > + createAccessible( Menu* /*_pMenu*/, bool /*_bIsMenuBar*/ ) override + { + return nullptr; + } + }; + + } + + AccessibleDummyFactory::AccessibleDummyFactory() + { + } + + + AccessibleDummyFactory::~AccessibleDummyFactory() + { + } + + + //= AccessibilityClient + + + AccessibilityClient::AccessibilityClient() + :m_bInitialized( false ) + { + } + +#if !ENABLE_WASM_STRIP_ACCESSIBILITY +#if HAVE_FEATURE_DESKTOP +#ifndef DISABLE_DYNLOADING + extern "C" { static void thisModule() {} } +#else + extern "C" void *getStandardAccessibleFactory(); +#endif +#endif // HAVE_FEATURE_DESKTOP +#endif // ENABLE_WASM_STRIP_ACCESSIBILITY + + void AccessibilityClient::ensureInitialized() + { + if ( m_bInitialized ) + return; + + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + +#if !ENABLE_WASM_STRIP_ACCESSIBILITY +#if HAVE_FEATURE_DESKTOP + // load the library implementing the factory + if (!s_pFactory) + { +#ifndef DISABLE_DYNLOADING + const OUString sModuleName( SVLIBRARY( "acc" ) ); + s_hAccessibleImplementationModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, 0 ); + if ( s_hAccessibleImplementationModule != nullptr ) + { + const OUString sFactoryCreationFunc("getStandardAccessibleFactory"); + s_pAccessibleFactoryFunc = reinterpret_cast<GetStandardAccComponentFactory>( + osl_getFunctionSymbol( s_hAccessibleImplementationModule, sFactoryCreationFunc.pData )); + + } + OSL_ENSURE( s_pAccessibleFactoryFunc, "AccessibilityClient::ensureInitialized: could not load the library, or not retrieve the needed symbol!" ); +#else + s_pAccessibleFactoryFunc = getStandardAccessibleFactory; +#endif // DISABLE_DYNLOADING + + // get a factory instance + if ( s_pAccessibleFactoryFunc ) + { + IAccessibleFactory* pFactory = static_cast< IAccessibleFactory* >( (*s_pAccessibleFactoryFunc)() ); + OSL_ENSURE( pFactory, "AccessibilityClient::ensureInitialized: no factory provided by the A11Y lib!" ); + if ( pFactory ) + { + s_pFactory = pFactory; + pFactory->release(); + } + } + } +#endif // HAVE_FEATURE_DESKTOP +#endif // ENABLE_WASM_STRIP_ACCESSIBILITY + + if (!s_pFactory) + // the attempt to load the lib, or to create the factory, failed + // -> fall back to a dummy factory + s_pFactory = new AccessibleDummyFactory; + + m_bInitialized = true; + } + + IAccessibleFactory& AccessibilityClient::getFactory() + { + ensureInitialized(); + OSL_ENSURE( s_pFactory.is(), "AccessibilityClient::getFactory: at least a dummy factory should have been created!" ); + return *s_pFactory; + } + + +} // namespace toolkit + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/btndlg.cxx b/toolkit/source/helper/btndlg.cxx new file mode 100644 index 000000000..a2471c3f9 --- /dev/null +++ b/toolkit/source/helper/btndlg.cxx @@ -0,0 +1,304 @@ +/* -*- 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 <vcl/toolkit/button.hxx> +#include <vcl/stdtext.hxx> +#include <helper/btndlg.hxx> +#include <sal/log.hxx> +#include <map> +#include <memory> + +struct ImplBtnDlgItem +{ + sal_uInt16 mnId; + bool mbOwnButton; + tools::Long mnSepSize; + VclPtr<PushButton> mpPushButton; + + ImplBtnDlgItem() : mnId(0), mbOwnButton(false), mnSepSize(0) {} +}; + +void ButtonDialog::ImplInitButtonDialogData() +{ + mnButtonSize = 0; + mnCurButtonId = 0; + mnFocusButtonId = BUTTONDIALOG_BUTTON_NOTFOUND; + mbFormat = true; +} + +ButtonDialog::ButtonDialog( WindowType nType ) : + Dialog( nType ) +{ + ImplInitButtonDialogData(); +} + +ButtonDialog::~ButtonDialog() +{ + disposeOnce(); +} + +void ButtonDialog::dispose() +{ + for (auto & it : m_ItemList) + { + if ( it->mbOwnButton ) + it->mpPushButton.disposeAndClear(); + } + m_ItemList.clear(); + Dialog::dispose(); +} + +VclPtr<PushButton> ButtonDialog::ImplCreatePushButton( ButtonDialogFlags nBtnFlags ) +{ + VclPtr<PushButton> pBtn; + WinBits nStyle = 0; + + if ( nBtnFlags & ButtonDialogFlags::Default ) + nStyle |= WB_DEFBUTTON; + if ( nBtnFlags & ButtonDialogFlags::Cancel ) + pBtn = VclPtr<CancelButton>::Create( this, nStyle ); + else if ( nBtnFlags & ButtonDialogFlags::OK ) + pBtn = VclPtr<OKButton>::Create( this, nStyle ); + else if ( nBtnFlags & ButtonDialogFlags::Help ) + pBtn = VclPtr<HelpButton>::Create( this, nStyle ); + else + pBtn = VclPtr<PushButton>::Create( this, nStyle ); + + if ( !(nBtnFlags & ButtonDialogFlags::Help) ) + pBtn->SetClickHdl( LINK( this, ButtonDialog, ImplClickHdl ) ); + + return pBtn; +} + +tools::Long ButtonDialog::ImplGetButtonSize() +{ + if ( !mbFormat ) + return mnButtonSize; + + // Calculate ButtonSize + tools::Long nLastSepSize = 0; + tools::Long nSepSize = 0; + maCtrlSize = Size( IMPL_MINSIZE_BUTTON_WIDTH, IMPL_MINSIZE_BUTTON_HEIGHT ); + + for (const auto & it : m_ItemList) + { + nSepSize += nLastSepSize; + + tools::Long nTxtWidth = it->mpPushButton->GetOutDev()->GetCtrlTextWidth(it->mpPushButton->GetText()); + nTxtWidth += IMPL_EXTRA_BUTTON_WIDTH; + + if ( nTxtWidth > maCtrlSize.Width() ) + maCtrlSize.setWidth( nTxtWidth ); + + tools::Long nTxtHeight = it->mpPushButton->GetTextHeight(); + nTxtHeight += IMPL_EXTRA_BUTTON_HEIGHT; + + if ( nTxtHeight > maCtrlSize.Height() ) + maCtrlSize.setHeight( nTxtHeight ); + + nSepSize += it->mnSepSize; + + if ( GetStyle() & WB_HORZ ) + nLastSepSize = IMPL_SEP_BUTTON_X; + else + nLastSepSize = IMPL_SEP_BUTTON_Y; + } + + size_t const nButtonCount = m_ItemList.size(); + + if ( GetStyle() & WB_HORZ ) + mnButtonSize = nSepSize + (nButtonCount*maCtrlSize.Width()); + else + mnButtonSize = nSepSize + (nButtonCount*maCtrlSize.Height()); + + return mnButtonSize; +} + +void ButtonDialog::ImplPosControls() +{ + if ( !mbFormat ) + return; + + // Create PushButtons and determine Sizes + ImplGetButtonSize(); + + // determine dialog size + Size aDlgSize = maPageSize; + tools::Long nX; + tools::Long nY; + if ( GetStyle() & WB_HORZ ) + { + if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Width() ) + aDlgSize.setWidth( mnButtonSize+(IMPL_DIALOG_OFFSET*2) ); + if ( GetStyle() & WB_LEFT ) + nX = IMPL_DIALOG_OFFSET; + else if ( GetStyle() & WB_RIGHT ) + nX = aDlgSize.Width()-mnButtonSize-IMPL_DIALOG_OFFSET; + else + nX = (aDlgSize.Width()-mnButtonSize)/2; + + aDlgSize.AdjustHeight(IMPL_DIALOG_OFFSET+maCtrlSize.Height() ); + nY = aDlgSize.Height()-maCtrlSize.Height()-IMPL_DIALOG_OFFSET; + } + else + { + if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Height() ) + aDlgSize.setHeight( mnButtonSize+(IMPL_DIALOG_OFFSET*2) ); + if ( GetStyle() & WB_BOTTOM ) + nY = aDlgSize.Height()-mnButtonSize-IMPL_DIALOG_OFFSET; + else if ( GetStyle() & WB_VCENTER ) + nY = (aDlgSize.Height()-mnButtonSize)/2; + else + nY = IMPL_DIALOG_OFFSET; + + aDlgSize.AdjustWidth(IMPL_DIALOG_OFFSET+maCtrlSize.Width() ); + nX = aDlgSize.Width()-maCtrlSize.Width()-IMPL_DIALOG_OFFSET; + } + + // Arrange PushButtons + for (auto & it : m_ItemList) + { + if ( GetStyle() & WB_HORZ ) + nX += it->mnSepSize; + else + nY += it->mnSepSize; + + it->mpPushButton->SetPosSizePixel( Point( nX, nY ), maCtrlSize ); + it->mpPushButton->Show(); + + if ( GetStyle() & WB_HORZ ) + nX += maCtrlSize.Width()+IMPL_SEP_BUTTON_X; + else + nY += maCtrlSize.Height()+IMPL_SEP_BUTTON_Y; + } + + SetOutputSizePixel(aDlgSize); + SetMinOutputSizePixel(aDlgSize); + + mbFormat = false; +} + +IMPL_LINK( ButtonDialog, ImplClickHdl, Button*, pBtn, void ) +{ + for (const auto & it : m_ItemList) + { + if ( it->mpPushButton == pBtn ) + { + mnCurButtonId = it->mnId; + if ( IsInExecute() ) + EndDialog( mnCurButtonId ); + break; + } + } +} + +void ButtonDialog::Resize() +{ +} + +void ButtonDialog::StateChanged( StateChangedType nType ) +{ + if ( nType == StateChangedType::InitShow ) + { + ImplPosControls(); + for (auto & it : m_ItemList) + { + if ( it->mpPushButton && it->mbOwnButton ) + it->mpPushButton->SetZOrder(nullptr, ZOrderFlags::Last); + } + + // Set focus on default button. + if ( mnFocusButtonId != BUTTONDIALOG_BUTTON_NOTFOUND ) + { + for (auto & it : m_ItemList) + { + if (it->mnId == mnFocusButtonId ) + { + if (it->mpPushButton->IsVisible()) + it->mpPushButton->GrabFocus(); + + break; + } + } + } + } + + Dialog::StateChanged( nType ); +} + +void ButtonDialog::AddButton( StandardButtonType eType, sal_uInt16 nId, + ButtonDialogFlags nBtnFlags, tools::Long nSepPixel ) +{ + // PageItem anlegen + std::unique_ptr<ImplBtnDlgItem> pItem(new ImplBtnDlgItem); + pItem->mnId = nId; + pItem->mbOwnButton = true; + pItem->mnSepSize = nSepPixel; + + if ( eType == StandardButtonType::OK ) + nBtnFlags |= ButtonDialogFlags::OK; + else if ( eType == StandardButtonType::Help ) + nBtnFlags |= ButtonDialogFlags::Help; + else if ( (eType == StandardButtonType::Cancel) || (eType == StandardButtonType::Close) ) + nBtnFlags |= ButtonDialogFlags::Cancel; + pItem->mpPushButton = ImplCreatePushButton( nBtnFlags ); + + // Standard-Buttons have the right text already + if ( !((eType == StandardButtonType::OK && pItem->mpPushButton->GetType() == WindowType::OKBUTTON) || + (eType == StandardButtonType::Cancel && pItem->mpPushButton->GetType() == WindowType::CANCELBUTTON) || + (eType == StandardButtonType::Help && pItem->mpPushButton->GetType() == WindowType::HELPBUTTON)) ) + { + std::map<StandardButtonType, OUString> mapButtonTypeToID = {{StandardButtonType::Yes, "yes"}, + {StandardButtonType::No, "no"}, {StandardButtonType::Retry, "retry"}, + {StandardButtonType::Close, "close"}, {StandardButtonType::More, "more"}, + {StandardButtonType::Ignore, "ignore"}, {StandardButtonType::Abort, "abort"}, + {StandardButtonType::Less, "less"}, {StandardButtonType::Count, "count"}}; + auto itr = mapButtonTypeToID.find(eType); + if (itr != mapButtonTypeToID.end()) + pItem->mpPushButton->set_id(itr->second); + pItem->mpPushButton->SetText( GetStandardText( eType ) ); + } + + if ( nBtnFlags & ButtonDialogFlags::Focus ) + mnFocusButtonId = nId; + + m_ItemList.push_back(std::move(pItem)); + + mbFormat = true; +} + +void ButtonDialog::RemoveButton( sal_uInt16 nId ) +{ + auto it = std::find_if(m_ItemList.begin(), m_ItemList.end(), + [&nId](const std::unique_ptr<ImplBtnDlgItem>& rItem) { return rItem->mnId == nId; }); + if (it != m_ItemList.end()) + { + (*it)->mpPushButton->Hide(); + if ((*it)->mbOwnButton) + (*it)->mpPushButton.disposeAndClear(); + else + (*it)->mpPushButton.clear(); + m_ItemList.erase(it); + return; + } + + SAL_WARN( "vcl.window", "ButtonDialog::RemoveButton(): ButtonId invalid" ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/formpdfexport.cxx b/toolkit/source/helper/formpdfexport.cxx new file mode 100644 index 000000000..1c001cd9e --- /dev/null +++ b/toolkit/source/helper/formpdfexport.cxx @@ -0,0 +1,789 @@ +/* -*- 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 <memory> +#include <toolkit/helper/formpdfexport.hxx> +#include <tools/diagnose_ex.h> +#include <tools/lineend.hxx> +#include <unordered_map> +#include <sal/log.hxx> + +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/awt/TextAlign.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/style/VerticalAlignment.hpp> +#include <com/sun/star/form/FormButtonType.hpp> +#include <com/sun/star/form/FormSubmitMethod.hpp> + +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/pdfextoutdevdata.hxx> + +#include <algorithm> +#include <iterator> + + +namespace toolkitform +{ + + + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::style; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::container; + + constexpr OUStringLiteral FM_PROP_NAME = u"Name"; + + namespace + { + + /** determines the FormComponentType of a form control + */ + sal_Int16 classifyFormControl( const Reference< XPropertySet >& _rxModel ) + { + static constexpr OUStringLiteral FM_PROP_CLASSID = u"ClassId"; + sal_Int16 nControlType = FormComponentType::CONTROL; + + Reference< XPropertySetInfo > xPSI; + if ( _rxModel.is() ) + xPSI = _rxModel->getPropertySetInfo(); + if ( xPSI.is() && xPSI->hasPropertyByName( FM_PROP_CLASSID ) ) + { + if( ! (_rxModel->getPropertyValue( FM_PROP_CLASSID ) >>= nControlType) ) { + SAL_WARN("toolkit.helper", "classifyFormControl: unable to get property " << FM_PROP_CLASSID); + } + } + + return nControlType; + } + + + /** (default-)creates a PDF widget according to a given FormComponentType + */ + std::unique_ptr<vcl::PDFWriter::AnyWidget> createDefaultWidget( sal_Int16 _nFormComponentType ) + { + switch ( _nFormComponentType ) + { + case FormComponentType::COMMANDBUTTON: + return std::make_unique<vcl::PDFWriter::PushButtonWidget>(); + case FormComponentType::CHECKBOX: + return std::make_unique<vcl::PDFWriter::CheckBoxWidget>(); + case FormComponentType::RADIOBUTTON: + return std::make_unique<vcl::PDFWriter::RadioButtonWidget>(); + case FormComponentType::LISTBOX: + return std::make_unique<vcl::PDFWriter::ListBoxWidget>(); + case FormComponentType::COMBOBOX: + return std::make_unique<vcl::PDFWriter::ComboBoxWidget>(); + + case FormComponentType::TEXTFIELD: + case FormComponentType::FILECONTROL: + case FormComponentType::DATEFIELD: + case FormComponentType::TIMEFIELD: + case FormComponentType::NUMERICFIELD: + case FormComponentType::CURRENCYFIELD: + case FormComponentType::PATTERNFIELD: + return std::make_unique<vcl::PDFWriter::EditWidget>(); + } + return nullptr; + } + + + /** determines a unique number for the radio group which the given radio + button model belongs to + + The number is guaranteed to be + <ul><li>unique within the document in which the button lives</li> + <li>the same for subsequent calls with other radio button models, + which live in the same document, and belong to the same group</li> + </ul> + + @precond + the model must be part of the form component hierarchy in a document + */ + sal_Int32 determineRadioGroupId( const Reference< XPropertySet >& _rxRadioModel ) + { + OSL_ENSURE( classifyFormControl( _rxRadioModel ) == FormComponentType::RADIOBUTTON, + "determineRadioGroupId: this *is* no radio button model!" ); + // The fact that radio button groups need to be unique within the complete + // host document makes it somewhat difficult ... + // Problem is that two form radio buttons belong to the same group if + // - they have the same parent + // - AND they have the same name or group name + // This implies that we need some knowledge about (potentially) *all* radio button + // groups in the document. + + // get the root-level container + Reference< XChild > xChild( _rxRadioModel, UNO_QUERY ); + Reference< XForm > xParentForm( xChild.is() ? xChild->getParent() : Reference< XInterface >(), UNO_QUERY ); + OSL_ENSURE( xParentForm.is(), "determineRadioGroupId: no parent form -> group id!" ); + if ( !xParentForm.is() ) + return -1; + + while ( xParentForm.is() ) + { + xChild = xParentForm.get(); + xParentForm.set(xChild->getParent(), css::uno::UNO_QUERY); + } + Reference< XIndexAccess > xRoot( xChild->getParent(), UNO_QUERY ); + OSL_ENSURE( xRoot.is(), "determineRadioGroupId: unable to determine the root of the form component hierarchy!" ); + if ( !xRoot.is() ) + return -1; + + // count the leafs in the hierarchy, until we encounter radio button + ::std::vector< Reference< XIndexAccess > > aAncestors; + ::std::vector< sal_Int32 > aPath; + + Reference< XInterface > xNormalizedLookup( _rxRadioModel, UNO_QUERY ); + Reference< XIndexAccess > xCurrentContainer( xRoot ); + sal_Int32 nStartWithChild = 0; + sal_Int32 nGroupsEncountered = 0; + do + { + std::unordered_map<OUString,sal_Int32> GroupNameMap; + std::unordered_map<OUString,sal_Int32> SharedNameMap; + sal_Int32 nCount = xCurrentContainer->getCount(); + sal_Int32 i; + for ( i = nStartWithChild; i < nCount; ++i ) + { + Reference< XInterface > xElement( xCurrentContainer->getByIndex( i ), UNO_QUERY ); + if ( !xElement.is() ) + { + OSL_FAIL( "determineRadioGroupId: very suspicious!" ); + continue; + } + + Reference< XIndexAccess > xNewContainer( xElement, UNO_QUERY ); + if ( xNewContainer.is() ) + { + // step down the hierarchy + aAncestors.push_back( xCurrentContainer ); + xCurrentContainer = xNewContainer; + aPath.push_back( i ); + nStartWithChild = 0; + break; + // out of the inner loop, but continue with the outer loop + } + + if ( xElement.get() == xNormalizedLookup.get() ) + { + // Our radio button is in this container. + // Now take the time to ID this container's groups and return the button's groupId + for ( i = 0; i < nCount; ++i ) + { + try + { + xElement.set( xCurrentContainer->getByIndex( i ), UNO_QUERY_THROW ); + Reference< XServiceInfo > xModelSI( xElement, UNO_QUERY_THROW ); + if ( xModelSI->supportsService("com.sun.star.awt.UnoControlRadioButtonModel") ) + { + Reference< XPropertySet > aProps( xElement, UNO_QUERY_THROW ); + + OUString sGroupName; + aProps->getPropertyValue("GroupName") >>= sGroupName; + if ( !sGroupName.isEmpty() ) + { + // map: unique key is the group name, so attempts to add a different ID value + // for an existing group are ignored - keeping the first ID - perfect for this scenario. + GroupNameMap.emplace( sGroupName, nGroupsEncountered + i ); + + if ( xElement.get() == xNormalizedLookup.get() ) + return GroupNameMap[sGroupName]; + } + else + { + // Old implementation didn't have a GroupName, just identical Control names. + aProps->getPropertyValue( FM_PROP_NAME ) >>= sGroupName; + SharedNameMap.emplace( sGroupName, nGroupsEncountered + i ); + + if ( xElement.get() == xNormalizedLookup.get() ) + return SharedNameMap[sGroupName]; + } + + } + } + catch( uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("toolkit"); + } + } + SAL_WARN("toolkit.helper","determineRadioGroupId: did not find the radios element's group!" ); + } + } + + // we encounter this container the first time. In particular, we did not just step up + if ( nStartWithChild == 0 ) + { + // Our control wasn't in this container, so consider every item to be a possible unique group. + // This is way too much: Not all of the elements in the current container will form groups. + // But anyway, this number is sufficient for our purpose, since sequential group ids are not required. + // Ultimately, the container contains *at most* this many groups. + nGroupsEncountered += nCount; + } + + if ( i >= nCount ) + { + // the loop terminated because there were no more elements + // -> step up, if possible + if ( aAncestors.empty() ) + break; + + xCurrentContainer = aAncestors.back(); aAncestors.pop_back(); + nStartWithChild = aPath.back() + 1; aPath.pop_back(); + } + } + while ( true ); + return -1; + } + + + /** copies a StringItemList to a PDF widget's list + */ + void getStringItemVector( const Reference< XPropertySet >& _rxModel, ::std::vector< OUString >& _rVector ) + { + Sequence< OUString > aListEntries; + if( ! (_rxModel->getPropertyValue( "StringItemList" ) >>= aListEntries) ) { + SAL_WARN("toolkit.helper", "getStringItemVector: unable to get property StringItemList"); + } + _rVector.insert( _rVector.end(), std::cbegin(aListEntries), std::cend(aListEntries) ); + } + } + + + /** creates a PDF compatible control descriptor for the given control + */ + std::unique_ptr<vcl::PDFWriter::AnyWidget> describePDFControl( const Reference< XControl >& _rxControl, + vcl::PDFExtOutDevData& i_pdfExportData ) + { + std::unique_ptr<vcl::PDFWriter::AnyWidget> Descriptor; + OSL_ENSURE( _rxControl.is(), "describePDFControl: invalid (NULL) control!" ); + if ( !_rxControl.is() ) + return Descriptor; + + try + { + Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY ); + sal_Int16 nControlType = classifyFormControl( xModelProps ); + Descriptor = createDefaultWidget( nControlType ); + if (!Descriptor) + // no PDF widget available for this + return Descriptor; + + Reference< XPropertySetInfo > xPSI( xModelProps->getPropertySetInfo() ); + Reference< XServiceInfo > xSI( xModelProps, UNO_QUERY ); + OSL_ENSURE( xSI.is(), "describePDFControl: no service info!" ); + // if we survived classifyFormControl, then it's a real form control, and they all have + // service infos + + + // set the common widget properties + + + // Name, Description, Text + if( ! (xModelProps->getPropertyValue( FM_PROP_NAME ) >>= Descriptor->Name) ) { + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_NAME); + } + if( ! (xModelProps->getPropertyValue( "HelpText" ) >>= Descriptor->Description) ) { + SAL_INFO("toolkit.helper", "describePDFControl: unable to get property HelpText"); + } + Any aText; + static constexpr OUStringLiteral FM_PROP_TEXT = u"Text"; + static constexpr OUStringLiteral FM_PROP_LABEL = u"Label"; + static constexpr OUStringLiteral FM_PROP_VALUE = u"Value"; + if ( xPSI->hasPropertyByName( FM_PROP_TEXT ) ) + aText = xModelProps->getPropertyValue( FM_PROP_TEXT ); + else if ( xPSI->hasPropertyByName( FM_PROP_LABEL ) ) + aText = xModelProps->getPropertyValue( FM_PROP_LABEL ); + else if ( xPSI->hasPropertyByName( FM_PROP_VALUE ) ) + { + double aValue; + if (xModelProps->getPropertyValue( FM_PROP_VALUE ) >>= aValue) + aText <<= OUString::number(aValue); + } + + if ( aText.hasValue() ) { + if( ! (aText >>= Descriptor->Text) ) { + SAL_WARN("toolkit.helper", "describePDFControl: unable to assign aText to Descriptor->Text"); + } + } + + + // readonly + static constexpr OUStringLiteral FM_PROP_READONLY = u"ReadOnly"; + if ( xPSI->hasPropertyByName( FM_PROP_READONLY ) ) + if( ! (xModelProps->getPropertyValue( FM_PROP_READONLY ) >>= Descriptor->ReadOnly) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_READONLY); + + + // border + { + static constexpr OUStringLiteral FM_PROP_BORDER = u"Border"; + if ( xPSI->hasPropertyByName( FM_PROP_BORDER ) ) + { + sal_Int16 nBorderType = 0; + if( ! (xModelProps->getPropertyValue( FM_PROP_BORDER ) >>= nBorderType) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_BORDER); + Descriptor->Border = ( nBorderType != 0 ); + + OUString sBorderColorPropertyName( "BorderColor" ); + if ( xPSI->hasPropertyByName( sBorderColorPropertyName ) ) + { + Color nBorderColor = COL_TRANSPARENT; + if ( xModelProps->getPropertyValue( sBorderColorPropertyName ) >>= nBorderColor ) + Descriptor->BorderColor = nBorderColor; + else + Descriptor->BorderColor = COL_BLACK; + } + } + } + + + // background color + static constexpr OUStringLiteral FM_PROP_BACKGROUNDCOLOR = u"BackgroundColor"; + if ( xPSI->hasPropertyByName( FM_PROP_BACKGROUNDCOLOR ) ) + { + Color nBackColor = COL_TRANSPARENT; + xModelProps->getPropertyValue( FM_PROP_BACKGROUNDCOLOR ) >>= nBackColor; + Descriptor->Background = true; + Descriptor->BackgroundColor = nBackColor; + } + + + // text color + static constexpr OUStringLiteral FM_PROP_TEXTCOLOR = u"TextColor"; + if ( xPSI->hasPropertyByName( FM_PROP_TEXTCOLOR ) ) + { + Color nTextColor = COL_TRANSPARENT; + xModelProps->getPropertyValue( FM_PROP_TEXTCOLOR ) >>= nTextColor; + Descriptor->TextColor = nTextColor; + } + + + // text style + Descriptor->TextStyle = DrawTextFlags::NONE; + + // multi line and word break + // The MultiLine property of the control is mapped to both the "MULTILINE" and + // "WORDBREAK" style flags + static constexpr OUStringLiteral FM_PROP_MULTILINE = u"MultiLine"; + if ( xPSI->hasPropertyByName( FM_PROP_MULTILINE ) ) + { + bool bMultiLine = false; + if( ! (xModelProps->getPropertyValue( FM_PROP_MULTILINE ) >>= bMultiLine) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_MULTILINE); + if ( bMultiLine ) + Descriptor->TextStyle |= DrawTextFlags::MultiLine | DrawTextFlags::WordBreak; + } + + // horizontal alignment + static constexpr OUStringLiteral FM_PROP_ALIGN = u"Align"; + if ( xPSI->hasPropertyByName( FM_PROP_ALIGN ) ) + { + sal_Int16 nAlign = awt::TextAlign::LEFT; + xModelProps->getPropertyValue( FM_PROP_ALIGN ) >>= nAlign; + // TODO: when the property is VOID - are there situations/UIs where this + // means something else than LEFT? + switch ( nAlign ) + { + case awt::TextAlign::LEFT: Descriptor->TextStyle |= DrawTextFlags::Left; break; + case awt::TextAlign::CENTER: Descriptor->TextStyle |= DrawTextFlags::Center; break; + case awt::TextAlign::RIGHT: Descriptor->TextStyle |= DrawTextFlags::Right; break; + default: + OSL_FAIL( "describePDFControl: invalid text align!" ); + } + } + + // vertical alignment + { + OUString sVertAlignPropertyName( "VerticalAlign" ); + if ( xPSI->hasPropertyByName( sVertAlignPropertyName ) ) + { + VerticalAlignment nAlign = VerticalAlignment_MIDDLE; + xModelProps->getPropertyValue( sVertAlignPropertyName ) >>= nAlign; + switch ( nAlign ) + { + case VerticalAlignment_TOP: Descriptor->TextStyle |= DrawTextFlags::Top; break; + case VerticalAlignment_MIDDLE: Descriptor->TextStyle |= DrawTextFlags::VCenter; break; + case VerticalAlignment_BOTTOM: Descriptor->TextStyle |= DrawTextFlags::Bottom; break; + default: + OSL_FAIL( "describePDFControl: invalid vertical text align!" ); + } + } + } + + // font + static constexpr OUStringLiteral FM_PROP_FONT = u"FontDescriptor"; + if ( xPSI->hasPropertyByName( FM_PROP_FONT ) ) + { + FontDescriptor aUNOFont; + if( ! (xModelProps->getPropertyValue( FM_PROP_FONT ) >>= aUNOFont) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_FONT); + Descriptor->TextFont = VCLUnoHelper::CreateFont( aUNOFont, vcl::Font() ); + } + + // tab order + OUString aTabIndexString( "TabIndex" ); + if ( xPSI->hasPropertyByName( aTabIndexString ) ) + { + sal_Int16 nIndex = -1; + if( ! (xModelProps->getPropertyValue( aTabIndexString ) >>= nIndex) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << aTabIndexString); + Descriptor->TabOrder = nIndex; + } + + + // special widget properties + + // edits + if ( Descriptor->getType() == vcl::PDFWriter::Edit ) + { + vcl::PDFWriter::EditWidget* pEditWidget = static_cast< vcl::PDFWriter::EditWidget* >( Descriptor.get() ); + + // multiline (already flagged in the TextStyle) + pEditWidget->MultiLine = bool( Descriptor->TextStyle & DrawTextFlags::MultiLine ); + + // password input + OUString sEchoCharPropName( "EchoChar" ); + if ( xPSI->hasPropertyByName( sEchoCharPropName ) ) + { + sal_Int16 nEchoChar = 0; + if ( ( xModelProps->getPropertyValue( sEchoCharPropName ) >>= nEchoChar ) && ( nEchoChar != 0 ) ) + pEditWidget->Password = true; + } + + // file select + if ( xSI->supportsService( "com.sun.star.form.component.FileControl" ) ) + pEditWidget->FileSelect = true; + + // maximum text length + static constexpr OUStringLiteral FM_PROP_MAXTEXTLEN = u"MaxTextLen"; + if ( xPSI->hasPropertyByName( FM_PROP_MAXTEXTLEN ) ) + { + sal_Int16 nMaxTextLength = 0; + if( ! (xModelProps->getPropertyValue( FM_PROP_MAXTEXTLEN ) >>= nMaxTextLength) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_MAXTEXTLEN); + if ( nMaxTextLength <= 0 ) + // "-1" has a special meaning for database-bound controls + nMaxTextLength = 0; + pEditWidget->MaxLen = nMaxTextLength; + } + + switch ( nControlType ) + { + case FormComponentType::CURRENCYFIELD: + case FormComponentType::NUMERICFIELD: + { + + pEditWidget->Format = vcl::PDFWriter::Number; + + static constexpr OUStringLiteral FM_PROP_CURRENCYSYMBOL = u"CurrencySymbol"; + if ( xPSI->hasPropertyByName( FM_PROP_CURRENCYSYMBOL ) ) + { + OUString sCurrencySymbol; + if( ! (xModelProps->getPropertyValue( FM_PROP_CURRENCYSYMBOL ) >>= sCurrencySymbol) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_CURRENCYSYMBOL); + pEditWidget->CurrencySymbol = sCurrencySymbol; + } + + static constexpr OUStringLiteral FM_PROP_DECIMALACCURACY = u"DecimalAccuracy"; + if ( xPSI->hasPropertyByName( FM_PROP_DECIMALACCURACY ) ) + { + sal_Int32 nDecimalAccuracy = 0; + if( ! (xModelProps->getPropertyValue( FM_PROP_DECIMALACCURACY ) >>= nDecimalAccuracy) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_DECIMALACCURACY); + pEditWidget->DecimalAccuracy = nDecimalAccuracy; + } + + static constexpr OUStringLiteral FM_PROP_PREPENDCURRENCYSYMBOL = u"PrependCurrencySymbol"; + if ( xPSI->hasPropertyByName( FM_PROP_PREPENDCURRENCYSYMBOL ) ) + { + bool bPrependCurrencySymbol = true; + if( ! (xModelProps->getPropertyValue( FM_PROP_PREPENDCURRENCYSYMBOL ) >>= bPrependCurrencySymbol) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_PREPENDCURRENCYSYMBOL); + pEditWidget->PrependCurrencySymbol = bPrependCurrencySymbol; + } + } break; + case FormComponentType::TIMEFIELD: + { + pEditWidget->Format = vcl::PDFWriter::Time; + + static constexpr OUStringLiteral FM_PROP_TIMEFORMAT = u"TimeFormat"; + if ( xPSI->hasPropertyByName( FM_PROP_TIMEFORMAT ) ) + { + sal_Int32 nTimeFormat = 0; + if( ! (xModelProps->getPropertyValue( FM_PROP_TIMEFORMAT ) >>= nTimeFormat) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_TIMEFORMAT); + + switch ( nTimeFormat ) + { + case 0: + pEditWidget->TimeFormat = "HH:MM"; //13:45 + break; + case 1: + pEditWidget->TimeFormat = "HH:MM:ss"; //13:45:00 + break; + case 2: + pEditWidget->TimeFormat = "h:MMtt"; //01:45 PM + break; + case 3: + pEditWidget->TimeFormat = "h:MM:sstt"; //01:45:00 PM + break; + } + } + } break; + case FormComponentType::DATEFIELD: + { + pEditWidget->Format = vcl::PDFWriter::Date; + + static constexpr OUStringLiteral FM_PROP_DATEFORMAT = u"DateFormat"; + if ( xPSI->hasPropertyByName( FM_PROP_DATEFORMAT ) ) + { + sal_Int32 nDateFormat = 0; + if( ! (xModelProps->getPropertyValue( FM_PROP_DATEFORMAT ) >>= nDateFormat) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_DATEFORMAT); + + switch ( nDateFormat ) + { + case 0: + case 1: + pEditWidget->DateFormat = "mm/dd/yy"; // Standard (short) + break; + case 2: + case 3: + pEditWidget->DateFormat = "mm/dd/yyyy"; // Standard (long) + break; + case 4: + pEditWidget->DateFormat = "dd/mm/yy"; // DD/MM/YY + break; + case 5: + pEditWidget->DateFormat = "mm/dd/yy"; // MM/DD/YY + break; + case 6: + pEditWidget->DateFormat = "yy/mm/dd"; // YY/MM/DD + break; + case 7: + pEditWidget->DateFormat = "dd/mm/yyyy"; // DD/MM/YYYY + break; + case 8: + pEditWidget->DateFormat = "mm/dd/yyyy"; // MM/DD/YYYY + break; + case 9: + pEditWidget->DateFormat = "yyyy/mm/dd"; // YYYY/MM/DD + break; + case 10: + pEditWidget->DateFormat = "yy-mm-dd"; // YY-MM-DD + break; + case 11: + pEditWidget->DateFormat = "yyyy-mm-dd"; // YYYY-MM-DD + break; + } + } + } break; + } + } + + // buttons + if ( Descriptor->getType() == vcl::PDFWriter::PushButton ) + { + vcl::PDFWriter::PushButtonWidget* pButtonWidget = static_cast< vcl::PDFWriter::PushButtonWidget* >( Descriptor.get() ); + FormButtonType eButtonType = FormButtonType_PUSH; + if( ! (xModelProps->getPropertyValue("ButtonType") >>= eButtonType) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property ButtonType"); + static constexpr OUStringLiteral FM_PROP_TARGET_URL = u"TargetURL"; + if ( eButtonType == FormButtonType_SUBMIT ) + { + // if a button is a submit button, then it uses the URL at its parent form + Reference< XChild > xChild( xModelProps, UNO_QUERY ); + Reference < XPropertySet > xParentProps; + if ( xChild.is() ) + xParentProps.set(xChild->getParent(), css::uno::UNO_QUERY); + if ( xParentProps.is() ) + { + Reference< XServiceInfo > xParentSI( xParentProps, UNO_QUERY ); + if ( xParentSI.is() && xParentSI->supportsService("com.sun.star.form.component.HTMLForm") ) + { + if( ! (xParentProps->getPropertyValue( FM_PROP_TARGET_URL ) >>= pButtonWidget->URL) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_TARGET_URL); + pButtonWidget->Submit = true; + FormSubmitMethod eMethod = FormSubmitMethod_POST; + if( ! (xParentProps->getPropertyValue("SubmitMethod") >>= eMethod) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_TARGET_URL); + pButtonWidget->SubmitGet = (eMethod == FormSubmitMethod_GET); + } + } + } + else if ( eButtonType == FormButtonType_URL ) + { + OUString sURL; + if( ! (xModelProps->getPropertyValue( FM_PROP_TARGET_URL ) >>= sURL) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_TARGET_URL); + const bool bDocumentLocalTarget = sURL.startsWith("#"); + if ( bDocumentLocalTarget ) + { + // Register the destination for future handling ... + pButtonWidget->Dest = i_pdfExportData.RegisterDest(); + + // and put it into the bookmarks, to ensure the future handling really happens + ::std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks( i_pdfExportData.GetBookmarks() ); + vcl::PDFExtOutDevBookmarkEntry aBookmark; + aBookmark.nDestId = pButtonWidget->Dest; + aBookmark.aBookmark = sURL; + rBookmarks.push_back( aBookmark ); + } + else + pButtonWidget->URL = sURL; + + pButtonWidget->Submit = false; + } + + // TODO: + // In PDF files, buttons are either reset, url or submit buttons. So if we have a simple PUSH button + // in a document, then this means that we do not export a SubmitToURL, which means that in PDF, + // the button is used as reset button. + // Is this desired? If no, we would have to reset Descriptor to NULL here, in case eButtonType + // != FormButtonType_SUBMIT && != FormButtonType_RESET + + // the PDF exporter defaults the text style, if 0. To prevent this, we have to transfer the UNO + // defaults to the PDF widget + if ( pButtonWidget->TextStyle == DrawTextFlags::NONE ) + pButtonWidget->TextStyle = DrawTextFlags::Center | DrawTextFlags::VCenter; + } + + + // check boxes + static constexpr OUStringLiteral FM_PROP_STATE = u"State"; + if ( Descriptor->getType() == vcl::PDFWriter::CheckBox ) + { + vcl::PDFWriter::CheckBoxWidget* pCheckBoxWidget = static_cast< vcl::PDFWriter::CheckBoxWidget* >( Descriptor.get() ); + sal_Int16 nState = 0; + if( ! (xModelProps->getPropertyValue( FM_PROP_STATE ) >>= nState) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_STATE); + pCheckBoxWidget->Checked = ( nState != 0 ); + + try + { + xModelProps->getPropertyValue( "RefValue" ) >>= pCheckBoxWidget->OnValue; + } + catch(...) + { + } + + try + { + xModelProps->getPropertyValue( "SecondaryRefValue" ) >>= pCheckBoxWidget->OffValue; + } + catch(...) + { + } + } + + + // radio buttons + if ( Descriptor->getType() == vcl::PDFWriter::RadioButton ) + { + vcl::PDFWriter::RadioButtonWidget* pRadioWidget = static_cast< vcl::PDFWriter::RadioButtonWidget* >( Descriptor.get() ); + sal_Int16 nState = 0; + if( ! (xModelProps->getPropertyValue( FM_PROP_STATE ) >>= nState) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property " << FM_PROP_STATE); + pRadioWidget->Selected = ( nState != 0 ); + pRadioWidget->RadioGroup = determineRadioGroupId( xModelProps ); + try + { + xModelProps->getPropertyValue( "RefValue" ) >>= pRadioWidget->OnValue; + } + catch(...) + { + } + + try + { + xModelProps->getPropertyValue( "SecondaryRefValue" ) >>= pRadioWidget->OffValue; + } + catch(...) + { + } + } + + + // list boxes + if ( Descriptor->getType() == vcl::PDFWriter::ListBox ) + { + vcl::PDFWriter::ListBoxWidget* pListWidget = static_cast< vcl::PDFWriter::ListBoxWidget* >( Descriptor.get() ); + + // drop down + if( ! (xModelProps->getPropertyValue( "Dropdown" ) >>= pListWidget->DropDown) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property Dropdown"); + + // multi selection + if( ! (xModelProps->getPropertyValue("MultiSelection") >>= pListWidget->MultiSelect) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property MultiSelection"); + + // entries + getStringItemVector( xModelProps, pListWidget->Entries ); + + // get selected items + Sequence< sal_Int16 > aSelectIndices; + if( ! (xModelProps->getPropertyValue("SelectedItems") >>= aSelectIndices) ) + SAL_WARN("toolkit.helper", "describePDFControl: unable to get property SelectedItems"); + if( aSelectIndices.hasElements() ) + { + pListWidget->SelectedEntries.resize( 0 ); + auto nEntriesSize = static_cast<sal_Int16>(pListWidget->Entries.size()); + std::copy_if(std::cbegin(aSelectIndices), std::cend(aSelectIndices), std::back_inserter(pListWidget->SelectedEntries), + [&nEntriesSize](const sal_Int16 nIndex) { return nIndex >= 0 && nIndex < nEntriesSize; }); + } + } + + + // combo boxes + if ( Descriptor->getType() == vcl::PDFWriter::ComboBox ) + { + vcl::PDFWriter::ComboBoxWidget* pComboWidget = static_cast< vcl::PDFWriter::ComboBoxWidget* >( Descriptor.get() ); + + // entries + getStringItemVector( xModelProps, pComboWidget->Entries ); + } + + + // some post-processing + + // text line ends + // some controls may (always or dependent on other settings) return UNIX line ends + Descriptor->Text = convertLineEnd(Descriptor->Text, LINEEND_CRLF); + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "toolkit", "describePDFControl" ); + } + return Descriptor; + } + + +} // namespace toolkitform + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/imagealign.cxx b/toolkit/source/helper/imagealign.cxx new file mode 100644 index 000000000..43e7cb012 --- /dev/null +++ b/toolkit/source/helper/imagealign.cxx @@ -0,0 +1,128 @@ +/* -*- 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 <com/sun/star/awt/ImagePosition.hpp> +#include <com/sun/star/awt/ImageAlign.hpp> + +#include <helper/imagealign.hxx> +#include <osl/diagnose.h> + +namespace toolkit +{ + + + using namespace ::com::sun::star::awt::ImagePosition; + using namespace ::com::sun::star::awt::ImageAlign; + + sal_Int16 translateImagePosition( ImageAlign _eVCLAlign ) + { + sal_Int16 nReturn = AboveCenter; + switch ( _eVCLAlign ) + { + case ImageAlign::Left: nReturn = LeftCenter; break; + case ImageAlign::Top: nReturn = AboveCenter; break; + case ImageAlign::Right: nReturn = RightCenter; break; + case ImageAlign::Bottom: nReturn = BelowCenter; break; + case ImageAlign::LeftTop: nReturn = LeftTop; break; + case ImageAlign::LeftBottom: nReturn = LeftBottom; break; + case ImageAlign::TopLeft: nReturn = AboveLeft; break; + case ImageAlign::TopRight: nReturn = AboveRight; break; + case ImageAlign::RightTop: nReturn = RightTop; break; + case ImageAlign::RightBottom: nReturn = RightBottom; break; + case ImageAlign::BottomLeft: nReturn = BelowLeft; break; + case ImageAlign::BottomRight: nReturn = BelowRight; break; + case ImageAlign::Center: nReturn = Centered; break; + default: + OSL_FAIL( "translateImagePosition: unknown IMAGEALIGN value!" ); + } + return nReturn; + } + + ImageAlign translateImagePosition( sal_Int16 _eUNOAlign ) + { + ImageAlign nReturn = ImageAlign::Top; + switch ( _eUNOAlign ) + { + case LeftCenter: nReturn = ImageAlign::Left; break; + case AboveCenter: nReturn = ImageAlign::Top; break; + case RightCenter: nReturn = ImageAlign::Right; break; + case BelowCenter: nReturn = ImageAlign::Bottom; break; + case LeftTop: nReturn = ImageAlign::LeftTop; break; + case LeftBottom: nReturn = ImageAlign::LeftBottom; break; + case AboveLeft: nReturn = ImageAlign::TopLeft; break; + case AboveRight: nReturn = ImageAlign::TopRight; break; + case RightTop: nReturn = ImageAlign::RightTop; break; + case RightBottom: nReturn = ImageAlign::RightBottom; break; + case BelowLeft: nReturn = ImageAlign::BottomLeft; break; + case BelowRight: nReturn = ImageAlign::BottomRight; break; + case Centered: nReturn = ImageAlign::Center; break; + default: + OSL_FAIL( "translateImagePosition: unknown css.awt.ImagePosition value!" ); + } + return nReturn; + } + + sal_Int16 getCompatibleImageAlign( ImageAlign _eAlign ) + { + sal_Int16 nReturn = TOP; + switch ( _eAlign ) + { + case ImageAlign::LeftTop: + case ImageAlign::Left: + case ImageAlign::LeftBottom: nReturn = LEFT; break; + + case ImageAlign::TopLeft: + case ImageAlign::Top: + case ImageAlign::TopRight: nReturn = TOP; break; + + case ImageAlign::RightTop: + case ImageAlign::Right: + case ImageAlign::RightBottom: nReturn = RIGHT; break; + + case ImageAlign::BottomLeft: + case ImageAlign::Bottom: + case ImageAlign::BottomRight: nReturn = BOTTOM; break; + + case ImageAlign::Center: nReturn = TOP; break; + default: + OSL_FAIL( "getCompatibleImageAlign: unknown IMAGEALIGN value!" ); + } + return nReturn; + } + + sal_Int16 getExtendedImagePosition( sal_Int16 _nImageAlign ) + { + sal_Int16 nReturn = AboveCenter; + switch ( _nImageAlign ) + { + case LEFT: nReturn = LeftCenter; break; + case TOP: nReturn = AboveCenter; break; + case RIGHT: nReturn = RightCenter; break; + case BOTTOM: nReturn = BelowCenter; break; + default: + OSL_FAIL( "getExtendedImagePosition: unknown ImageAlign value!" ); + } + return nReturn; + } + + +} // namespace toolkit + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/listenermultiplexer.cxx b/toolkit/source/helper/listenermultiplexer.cxx new file mode 100644 index 000000000..eeed767ff --- /dev/null +++ b/toolkit/source/helper/listenermultiplexer.cxx @@ -0,0 +1,242 @@ +/* -*- 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 <toolkit/helper/listenermultiplexer.hxx> +#include <toolkit/helper/macros.hxx> +#include <com/sun/star/lang/DisposedException.hpp> + +// class EventListenerMultiplexer + +EventListenerMultiplexer::EventListenerMultiplexer( ::cppu::OWeakObject& rSource ) + : ListenerMultiplexerBase( rSource ) +{ +} + +void SAL_CALL EventListenerMultiplexer::acquire() noexcept +{ + return ListenerMultiplexerBase::acquire(); +} + +void SAL_CALL EventListenerMultiplexer::release() noexcept +{ + return ListenerMultiplexerBase::release(); +} + +// css::uno::XInterface +css::uno::Any EventListenerMultiplexer::queryInterface( const css::uno::Type & rType ) +{ + css::uno::Any aRet = ::cppu::queryInterface( rType, + static_cast< css::lang::XEventListener* >(this) ); + return (aRet.hasValue() ? aRet : ListenerMultiplexerBase::queryInterface( rType )); +} + +// css::lang::XEventListener +void EventListenerMultiplexer::disposing( const css::lang::EventObject& ) +{ +} + + +// class FocusListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( FocusListenerMultiplexer, css::awt::XFocusListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( FocusListenerMultiplexer, css::awt::XFocusListener, focusGained, css::awt::FocusEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( FocusListenerMultiplexer, css::awt::XFocusListener, focusLost, css::awt::FocusEvent ) + + +// class WindowListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( WindowListenerMultiplexer, css::awt::XWindowListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( WindowListenerMultiplexer, css::awt::XWindowListener, windowResized, css::awt::WindowEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( WindowListenerMultiplexer, css::awt::XWindowListener, windowMoved, css::awt::WindowEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( WindowListenerMultiplexer, css::awt::XWindowListener, windowShown, css::lang::EventObject ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( WindowListenerMultiplexer, css::awt::XWindowListener, windowHidden, css::lang::EventObject ) + + +// class VclContainerListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( VclContainerListenerMultiplexer, css::awt::XVclContainerListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( VclContainerListenerMultiplexer, css::awt::XVclContainerListener, windowAdded, css::awt::VclContainerEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( VclContainerListenerMultiplexer, css::awt::XVclContainerListener, windowRemoved, css::awt::VclContainerEvent ) + + +// class KeyListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( KeyListenerMultiplexer, css::awt::XKeyListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( KeyListenerMultiplexer, css::awt::XKeyListener, keyPressed, css::awt::KeyEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( KeyListenerMultiplexer, css::awt::XKeyListener, keyReleased, css::awt::KeyEvent ) + + +// class MouseListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( MouseListenerMultiplexer, css::awt::XMouseListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseListenerMultiplexer, css::awt::XMouseListener, mousePressed, css::awt::MouseEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseListenerMultiplexer, css::awt::XMouseListener, mouseReleased, css::awt::MouseEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseListenerMultiplexer, css::awt::XMouseListener, mouseEntered, css::awt::MouseEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseListenerMultiplexer, css::awt::XMouseListener, mouseExited, css::awt::MouseEvent ) + + +// class MouseMotionListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( MouseMotionListenerMultiplexer, css::awt::XMouseMotionListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseMotionListenerMultiplexer, css::awt::XMouseMotionListener, mouseDragged, css::awt::MouseEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseMotionListenerMultiplexer, css::awt::XMouseMotionListener, mouseMoved, css::awt::MouseEvent ) + + +// class PaintListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( PaintListenerMultiplexer, css::awt::XPaintListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( PaintListenerMultiplexer, css::awt::XPaintListener, windowPaint, css::awt::PaintEvent ) + + +// class TopWindowListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TopWindowListenerMultiplexer, css::awt::XTopWindowListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowOpened, css::lang::EventObject ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowClosing, css::lang::EventObject ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowClosed, css::lang::EventObject ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowMinimized, css::lang::EventObject ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowNormalized, css::lang::EventObject ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowActivated, css::lang::EventObject ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowDeactivated, css::lang::EventObject ) + + +// class TextListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TextListenerMultiplexer, css::awt::XTextListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TextListenerMultiplexer, css::awt::XTextListener, textChanged, css::awt::TextEvent ) + + +// class ActionListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( ActionListenerMultiplexer, css::awt::XActionListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ActionListenerMultiplexer, css::awt::XActionListener, actionPerformed, css::awt::ActionEvent ) + + +// class ItemListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( ItemListenerMultiplexer, css::awt::XItemListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ItemListenerMultiplexer, css::awt::XItemListener, itemStateChanged, css::awt::ItemEvent ) + + +// class TabListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TabListenerMultiplexer, css::awt::XTabListener ) + +void TabListenerMultiplexer::inserted( sal_Int32 evt ) +IMPL_TABLISTENERMULTIPLEXER_LISTENERMETHOD_BODY_1PARAM( TabListenerMultiplexer, css::awt::XTabListener, inserted, ::sal_Int32 ) + +void TabListenerMultiplexer::removed( sal_Int32 evt ) +IMPL_TABLISTENERMULTIPLEXER_LISTENERMETHOD_BODY_1PARAM( TabListenerMultiplexer, css::awt::XTabListener, removed, ::sal_Int32 ) + +void TabListenerMultiplexer::changed( sal_Int32 evt, const css::uno::Sequence< css::beans::NamedValue >& evt2 ) +{ + sal_Int32 aMulti( evt ); + ::comphelper::OInterfaceIteratorHelper3 aIt(*this); + while( aIt.hasMoreElements() ) + { + css::uno::Reference<css::awt::XTabListener> xListener(aIt.next()); + try + { + xListener->changed( aMulti, evt2 ); + } + catch(const css::lang::DisposedException& e) + { + OSL_ENSURE( e.Context.is(), "caught DisposedException with empty Context field" ); + if ( e.Context == xListener || !e.Context.is() ) + aIt.remove(); + } + catch(const css::uno::RuntimeException&) + { + DISPLAY_EXCEPTION( TabListenerMultiplexer, changed ) + } + } +} + + +void TabListenerMultiplexer::activated( sal_Int32 evt ) +IMPL_TABLISTENERMULTIPLEXER_LISTENERMETHOD_BODY_1PARAM( TabListenerMultiplexer, css::awt::XTabListener, activated, ::sal_Int32 ) + +void TabListenerMultiplexer::deactivated( sal_Int32 evt ) +IMPL_TABLISTENERMULTIPLEXER_LISTENERMETHOD_BODY_1PARAM( TabListenerMultiplexer, css::awt::XTabListener, deactivated, ::sal_Int32 ) + + +// class ContainerListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( ContainerListenerMultiplexer, css::container::XContainerListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ContainerListenerMultiplexer, css::container::XContainerListener, elementInserted, css::container::ContainerEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ContainerListenerMultiplexer, css::container::XContainerListener, elementRemoved, css::container::ContainerEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ContainerListenerMultiplexer, css::container::XContainerListener, elementReplaced, css::container::ContainerEvent ) + + +// class SpinListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( SpinListenerMultiplexer, css::awt::XSpinListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SpinListenerMultiplexer, css::awt::XSpinListener, up, css::awt::SpinEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SpinListenerMultiplexer, css::awt::XSpinListener, down, css::awt::SpinEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SpinListenerMultiplexer, css::awt::XSpinListener, first, css::awt::SpinEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SpinListenerMultiplexer, css::awt::XSpinListener, last, css::awt::SpinEvent ) + + +// class AdjustmentListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( AdjustmentListenerMultiplexer, css::awt::XAdjustmentListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( AdjustmentListenerMultiplexer, css::awt::XAdjustmentListener, adjustmentValueChanged, css::awt::AdjustmentEvent ) + + +// class MenuListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( MenuListenerMultiplexer, css::awt::XMenuListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MenuListenerMultiplexer, css::awt::XMenuListener, itemHighlighted, css::awt::MenuEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MenuListenerMultiplexer, css::awt::XMenuListener, itemSelected, css::awt::MenuEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MenuListenerMultiplexer, css::awt::XMenuListener, itemActivated, css::awt::MenuEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MenuListenerMultiplexer, css::awt::XMenuListener, itemDeactivated, css::awt::MenuEvent ) + + +// class TreeSelectionListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TreeSelectionListenerMultiplexer, css::view::XSelectionChangeListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TreeSelectionListenerMultiplexer, css::view::XSelectionChangeListener, selectionChanged, css::lang::EventObject ) + + +// class TreeSelectionListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, requestChildNodes, css::awt::tree::TreeExpansionEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD_EXCEPTION( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, treeExpanding, css::awt::tree::TreeExpansionEvent, css::awt::tree::ExpandVetoException ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD_EXCEPTION( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, treeCollapsing, css::awt::tree::TreeExpansionEvent, css::awt::tree::ExpandVetoException ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, treeExpanded, css::awt::tree::TreeExpansionEvent ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, treeCollapsed, css::awt::tree::TreeExpansionEvent ) + + +// class TreeEditListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TreeEditListenerMultiplexer, css::awt::tree::XTreeEditListener ) + + +// class SelectionListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( SelectionListenerMultiplexer, css::awt::grid::XGridSelectionListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SelectionListenerMultiplexer, css::awt::grid::XGridSelectionListener, selectionChanged, css::awt::grid::GridSelectionEvent ) + + +// class SelectionListenerMultiplexer + +IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TabPageListenerMultiplexer, css::awt::tab::XTabPageContainerListener ) +IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TabPageListenerMultiplexer, css::awt::tab::XTabPageContainerListener, tabPageActivated, css::awt::tab::TabPageActivatedEvent ) +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/property.cxx b/toolkit/source/helper/property.cxx new file mode 100644 index 000000000..cdcba6f2d --- /dev/null +++ b/toolkit/source/helper/property.cxx @@ -0,0 +1,380 @@ +/* -*- 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 <toolkit/helper/property.hxx> + +#include <tools/debug.hxx> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/awt/tree/XTreeDataModel.hpp> +#include <com/sun/star/awt/grid/XGridDataModel.hpp> +#include <com/sun/star/awt/grid/XGridColumnModel.hpp> +#include <com/sun/star/view/SelectionType.hpp> +#include <com/sun/star/style/VerticalAlignment.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <algorithm> +#include <string_view> + +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::awt::XDevice; +using ::com::sun::star::awt::FontDescriptor; +using ::com::sun::star::style::VerticalAlignment; +using ::com::sun::star::graphic::XGraphic; + +using namespace com::sun::star; + +namespace { + +struct ImplPropertyInfo +{ + OUString aName; + sal_uInt16 nPropId; + css::uno::Type aType; + sal_Int16 nAttribs; + bool bDependsOnOthers; // eg. VALUE depends on MIN/MAX and must be set after MIN/MAX. + + ImplPropertyInfo( OUString const & theName, sal_uInt16 nId, const css::uno::Type& rType, + sal_Int16 nAttrs, bool bDepends = false ) + : aName(theName) + , nPropId(nId) + , aType(rType) + , nAttribs(nAttrs) + , bDependsOnOthers(bDepends) + { + } + +}; + +} + +#define DECL_PROP_1( asciiname, id, type, attrib1 ) \ + ImplPropertyInfo( asciiname, BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 ) +#define DECL_PROP_2( asciiname, id, type, attrib1, attrib2 ) \ + ImplPropertyInfo( asciiname, BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 | css::beans::PropertyAttribute::attrib2 ) +#define DECL_PROP_3( asciiname, id, type, attrib1, attrib2, attrib3 ) \ + ImplPropertyInfo( asciiname, BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 | css::beans::PropertyAttribute::attrib2 | css::beans::PropertyAttribute::attrib3 ) + +#define DECL_DEP_PROP_2( asciiname, id, type, attrib1, attrib2 ) \ + ImplPropertyInfo( asciiname, BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 | css::beans::PropertyAttribute::attrib2, true ) +#define DECL_DEP_PROP_3( asciiname, id, type, attrib1, attrib2, attrib3 ) \ + ImplPropertyInfo( asciiname, BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 | css::beans::PropertyAttribute::attrib2 | css::beans::PropertyAttribute::attrib3, true ) + +static ImplPropertyInfo* ImplGetPropertyInfos( sal_uInt16& rElementCount ) +{ + static ImplPropertyInfo aImplPropertyInfos [] = { + DECL_PROP_2 ( "AccessibleName", ACCESSIBLENAME, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "Align", ALIGN, sal_Int16, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "Autocomplete", AUTOCOMPLETE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "AutoHScroll", AUTOHSCROLL, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_1 ( "AutoMnemonics", AUTOMNEMONICS, bool, BOUND ), + DECL_PROP_2 ( "AutoToggle", AUTOTOGGLE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "AutoVScroll", AUTOVSCROLL, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "BackgroundColor", BACKGROUNDCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_DEP_PROP_2 ( "BlockIncrement", BLOCKINCREMENT, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "Border", BORDER, sal_Int16, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_DEP_PROP_3 ( "BorderColor", BORDERCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "Closeable", CLOSEABLE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "CurrencySymbol", CURRENCYSYMBOL, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "CustomUnitText", CUSTOMUNITTEXT, OUString, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_3 ( "Date", DATE, util::Date, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "DateFormat", EXTDATEFORMAT, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "DateMax", DATEMAX, util::Date, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "DateMin", DATEMIN, util::Date, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "DateShowCentury", DATESHOWCENTURY, bool, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "DecimalAccuracy", DECIMALACCURACY, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "DefaultButton", DEFAULTBUTTON, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "DefaultControl", DEFAULTCONTROL, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "DesktopAsParent", DESKTOP_AS_PARENT, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "DisplayBackgroundColor", DISPLAYBACKGROUNDCOLOR, sal_Int32, BOUND, MAYBEVOID ), + DECL_PROP_2 ( "Dropdown", DROPDOWN, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "EchoChar", ECHOCHAR, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "EditMask", EDITMASK, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "EffectiveDefault", EFFECTIVE_DEFAULT, Any, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "EffectiveMax", EFFECTIVE_MAX, double, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "EffectiveMin", EFFECTIVE_MIN, double, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_DEP_PROP_3 ( "EffectiveValue", EFFECTIVE_VALUE, Any, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "Enabled", ENABLED, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "EnforceFormat", ENFORCE_FORMAT, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "FillColor", FILLCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "FocusOnClick", FOCUSONCLICK, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontRelief", FONTRELIEF, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontEmphasisMark", FONTEMPHASISMARK, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontDescriptor", FONTDESCRIPTOR, FontDescriptor, BOUND, MAYBEDEFAULT ), + + // parts of css::awt::FontDescriptor + DECL_PROP_2 ( "FontName", FONTDESCRIPTORPART_NAME, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontStyleName", FONTDESCRIPTORPART_STYLENAME, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontFamily", FONTDESCRIPTORPART_FAMILY, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontCharset", FONTDESCRIPTORPART_CHARSET, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontHeight", FONTDESCRIPTORPART_HEIGHT, float, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontWidth", FONTDESCRIPTORPART_WIDTH, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontPitch", FONTDESCRIPTORPART_PITCH, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontWeight", FONTDESCRIPTORPART_WEIGHT, float, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontCharWidth", FONTDESCRIPTORPART_CHARWIDTH, float, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontOrientation", FONTDESCRIPTORPART_ORIENTATION, float, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontSlant", FONTDESCRIPTORPART_SLANT, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontUnderline", FONTDESCRIPTORPART_UNDERLINE, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontStrikeout", FONTDESCRIPTORPART_STRIKEOUT, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontKerning", FONTDESCRIPTORPART_KERNING, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontWordLineMode", FONTDESCRIPTORPART_WORDLINEMODE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "FontType", FONTDESCRIPTORPART_TYPE, sal_Int16, BOUND, MAYBEDEFAULT ), + + DECL_PROP_3 ( "FormatKey", FORMATKEY, sal_Int32, BOUND, MAYBEVOID, TRANSIENT ), + DECL_PROP_3 ( "FormatsSupplier", FORMATSSUPPLIER, Reference< css::util::XNumberFormatsSupplier >, BOUND, MAYBEVOID, TRANSIENT ), + + DECL_PROP_2 ( "Graphic", GRAPHIC, Reference< XGraphic >, BOUND, TRANSIENT ), + DECL_PROP_2 ( "GroupName", GROUPNAME, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "HelpText", HELPTEXT, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "HelpURL", HELPURL, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "HideInactiveSelection", HIDEINACTIVESELECTION, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "HighContrastMode", HIGHCONTRASTMODE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "HScroll", HSCROLL, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "HardLineBreaks", HARDLINEBREAKS, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ImageAlign", IMAGEALIGN, sal_Int16, BOUND, MAYBEDEFAULT), + DECL_PROP_2 ( "ImagePosition", IMAGEPOSITION, sal_Int16, BOUND, MAYBEDEFAULT), + DECL_PROP_2 ( "ImageURL", IMAGEURL, css::uno::Any, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "ItemSeparatorPos", ITEM_SEPARATOR_POS, sal_Int16, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "Label", LABEL, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "LineColor", LINECOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "LineCount", LINECOUNT, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "LineEndFormat", LINE_END_FORMAT, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_2 ( "LineIncrement", LINEINCREMENT, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "LiteralMask", LITERALMASK, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "LiveScroll", LIVE_SCROLL, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "MaxTextLen", MAXTEXTLEN, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Moveable", MOVEABLE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_1 ( "MouseTransparent", MOUSETRANSPARENT, bool, BOUND ), + DECL_PROP_2 ( "MultiLine", MULTILINE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "MultiSelection", MULTISELECTION, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "MultiSelectionSimpleMode", MULTISELECTION_SIMPLEMODE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "NativeWidgetLook", NATIVE_WIDGET_LOOK, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "NoLabel", NOLABEL, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Orientation", ORIENTATION, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "PaintTransparent", PAINTTRANSPARENT, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "PluginParent", PLUGINPARENT, sal_Int64, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "PrependCurrencySymbol", CURSYM_POSITION, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Printable", PRINTABLE, bool, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_3 ( "ProgressValue", PROGRESSVALUE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "ProgressValueMax", PROGRESSVALUE_MAX, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ProgressValueMin", PROGRESSVALUE_MIN, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "PushButtonType", PUSHBUTTONTYPE, sal_Int16, BOUND, MAYBEDEFAULT), + DECL_PROP_2 ( "ReadOnly", READONLY, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Repeat", REPEAT, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "AutoRepeat", AUTO_REPEAT, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "RepeatDelay", REPEAT_DELAY, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ScaleImage", SCALEIMAGE, bool, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_2 ( "ScaleMode", IMAGE_SCALE_MODE, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_3 ( "ScrollValue", SCROLLVALUE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "ScrollValueMax", SCROLLVALUE_MAX, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ScrollValueMin", SCROLLVALUE_MIN, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ScrollWidth", SCROLLWIDTH, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ScrollHeight", SCROLLHEIGHT, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ScrollTop", SCROLLTOP, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ScrollLeft", SCROLLLEFT, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_2 ( "SelectedItems", SELECTEDITEMS, Sequence<sal_Int16>, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ShowThousandsSeparator", NUMSHOWTHOUSANDSEP, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Sizeable", SIZEABLE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Spin", SPIN, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "SpinIncrement", SPININCREMENT, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_2 ( "SpinValue", SPINVALUE, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "SpinValueMax", SPINVALUE_MAX, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "SpinValueMin", SPINVALUE_MIN, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_2 ( "State", STATE, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "StrictFormat", STRICTFORMAT, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "StringItemList", STRINGITEMLIST, Sequence< OUString >, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "TypedItemList", TYPEDITEMLIST, Sequence< Any >, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "VisualEffect", VISUALEFFECT, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "SymbolColor", SYMBOL_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "Tabstop", TABSTOP, bool, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "Text", TEXT, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "TextColor", TEXTCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "TextLineColor", TEXTLINECOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_DEP_PROP_3 ( "Time", TIME, util::Time, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "TimeFormat", EXTTIMEFORMAT, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "TimeMax", TIMEMAX, util::Time, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "TimeMin", TIMEMIN, util::Time, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Title", TITLE, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Toggle", TOGGLE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "TreatAsNumber", TREATASNUMBER, bool, BOUND, MAYBEDEFAULT,TRANSIENT ), + DECL_PROP_2 ( "TriState", TRISTATE, bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Unit", UNIT, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "VScroll", VSCROLL, bool, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_3 ( "Value", VALUE_DOUBLE, double, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "ValueMax", VALUEMAX_DOUBLE, double, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ValueMin", VALUEMIN_DOUBLE, double, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ValueStep", VALUESTEP_DOUBLE, double, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "VerticalAlign", VERTICALALIGN, VerticalAlignment, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_DEP_PROP_3 ( "VisibleSize", VISIBLESIZE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "Activated", ACTIVATED, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Complete", COMPLETE, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "CurrentItemID", CURRENTITEMID, sal_Int16, BOUND, MAYBEDEFAULT ), + + DECL_PROP_2 ( "MouseWheelBehavior", MOUSE_WHEEL_BEHAVIOUR, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "StepTime", STEP_TIME, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Decoration", DECORATION, sal_Bool, BOUND, MAYBEDEFAULT ), + + DECL_PROP_2 ( "SelectionType", TREE_SELECTIONTYPE, css::view::SelectionType, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "Editable", TREE_EDITABLE, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "DataModel", TREE_DATAMODEL, Reference< css::awt::tree::XTreeDataModel >,BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "RootDisplayed", TREE_ROOTDISPLAYED, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ShowsHandles", TREE_SHOWSHANDLES, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ShowsRootHandles", TREE_SHOWSROOTHANDLES, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "RowHeight", ROW_HEIGHT, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "InvokesStopNodeEditing", TREE_INVOKESSTOPNODEEDITING, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "DialogSourceURL", DIALOGSOURCEURL, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "URL", URL, OUString, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "WritingMode", WRITING_MODE, sal_Int16, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "ContextWritingMode", CONTEXT_WRITING_MODE, sal_Int16, BOUND, MAYBEDEFAULT, TRANSIENT ), + DECL_PROP_2 ( "ShowRowHeader", GRID_SHOWROWHEADER, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "RowHeaderWidth", ROW_HEADER_WIDTH, sal_Int32, BOUND, MAYBEDEFAULT ), + DECL_PROP_2 ( "ShowColumnHeader", GRID_SHOWCOLUMNHEADER, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "ColumnHeaderHeight", COLUMN_HEADER_HEIGHT, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_1 ( "GridDataModel", GRID_DATAMODEL, Reference< css::awt::grid::XGridDataModel >, BOUND ), + DECL_PROP_1 ( "ColumnModel", GRID_COLUMNMODEL, Reference< css::awt::grid::XGridColumnModel >, BOUND ), + DECL_PROP_3 ( "SelectionModel", GRID_SELECTIONMODE, css::view::SelectionType, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "EnableVisible", ENABLEVISIBLE, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_PROP_3 ( "ReferenceDevice", REFERENCE_DEVICE, Reference< XDevice >,BOUND, MAYBEDEFAULT, TRANSIENT ), + DECL_PROP_3 ( "HeaderBackgroundColor", GRID_HEADER_BACKGROUND, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "HeaderTextColor", GRID_HEADER_TEXT_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "GridLineColor", GRID_LINE_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "RowBackgroundColors", GRID_ROW_BACKGROUND_COLORS, Sequence< sal_Int32 >, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_2 ( "UseGridLines", USE_GRID_LINES, sal_Bool, BOUND, MAYBEDEFAULT ), + DECL_DEP_PROP_3 ( "MultiPageValue", MULTIPAGEVALUE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "AllDialogChildren", USERFORMCONTAINEES, Reference< css::container::XNameContainer >, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "ActiveSelectionBackgroundColor", ACTIVE_SEL_BACKGROUND_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "InactiveSelectionBackgroundColor", INACTIVE_SEL_BACKGROUND_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "ActiveSelectionTextColor", ACTIVE_SEL_TEXT_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + DECL_PROP_3 ( "InactiveSelectionTextColor", INACTIVE_SEL_TEXT_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ), + }; + rElementCount = SAL_N_ELEMENTS(aImplPropertyInfos); + return aImplPropertyInfos; +} + +namespace { + +struct ImplPropertyInfoCompareFunctor +{ + bool operator()(const ImplPropertyInfo& lhs,const ImplPropertyInfo& rhs) const + { + return lhs.aName.compareTo(rhs.aName) < 0; + } + bool operator()(const ImplPropertyInfo& lhs,std::u16string_view rhs) const + { + return lhs.aName.compareTo(rhs) < 0; + } +}; + +} + +static void ImplAssertValidPropertyArray() +{ + static bool bSorted = false; + if( !bSorted ) + { + sal_uInt16 nElements; + ImplPropertyInfo* pInfo = ImplGetPropertyInfos( nElements ); + ::std::sort(pInfo, pInfo+nElements,ImplPropertyInfoCompareFunctor()); + bSorted = true; + } +} + +sal_uInt16 GetPropertyId( const OUString& rPropertyName ) +{ + ImplAssertValidPropertyArray(); + + sal_uInt16 nElements; + ImplPropertyInfo* pInfo = ImplGetPropertyInfos( nElements ); + ImplPropertyInfo* pInf = ::std::lower_bound(pInfo,pInfo+nElements,rPropertyName,ImplPropertyInfoCompareFunctor()); +/* + (ImplPropertyInfo*) + bsearch( &aSearch, pInfo, nElements, sizeof( ImplPropertyInfo ), ImplPropertyInfoCompare ); +*/ + + return ( pInf && pInf != (pInfo+nElements) && pInf->aName == rPropertyName) ? pInf->nPropId: 0; +} + +static const ImplPropertyInfo* ImplGetImplPropertyInfo( sal_uInt16 nPropertyId ) +{ + ImplAssertValidPropertyArray(); + + sal_uInt16 nElements; + ImplPropertyInfo* pInfo = ImplGetPropertyInfos( nElements ); + sal_uInt16 n; + for ( n = 0; n < nElements && pInfo[n].nPropId != nPropertyId; ++n) + ; + + return (n < nElements) ? &pInfo[n] : nullptr; +} + +sal_uInt16 GetPropertyOrderNr( sal_uInt16 nPropertyId ) +{ + ImplAssertValidPropertyArray(); + + sal_uInt16 nElements; + ImplPropertyInfo* pInfo = ImplGetPropertyInfos( nElements ); + for ( sal_uInt16 n = nElements; n; ) + { + if ( pInfo[--n].nPropId == nPropertyId ) + return n; + } + return 0xFFFF; +} + +const OUString& GetPropertyName( sal_uInt16 nPropertyId ) +{ + const ImplPropertyInfo* pImplPropertyInfo = ImplGetImplPropertyInfo( nPropertyId ); + assert(pImplPropertyInfo && "Invalid PropertyId!"); + return pImplPropertyInfo->aName; +} + +const css::uno::Type* GetPropertyType( sal_uInt16 nPropertyId ) +{ + const ImplPropertyInfo* pImplPropertyInfo = ImplGetImplPropertyInfo( nPropertyId ); + DBG_ASSERT( pImplPropertyInfo, "Invalid PropertyId!" ); + return pImplPropertyInfo ? &pImplPropertyInfo->aType : nullptr; +} + +sal_Int16 GetPropertyAttribs( sal_uInt16 nPropertyId ) +{ + const ImplPropertyInfo* pImplPropertyInfo = ImplGetImplPropertyInfo( nPropertyId ); + DBG_ASSERT( pImplPropertyInfo, "Invalid PropertyId!" ); + return pImplPropertyInfo ? pImplPropertyInfo->nAttribs : 0; +} + +bool DoesDependOnOthers( sal_uInt16 nPropertyId ) +{ + const ImplPropertyInfo* pImplPropertyInfo = ImplGetImplPropertyInfo( nPropertyId ); + DBG_ASSERT( pImplPropertyInfo, "Invalid PropertyId!" ); + return pImplPropertyInfo && pImplPropertyInfo->bDependsOnOthers; +} + +bool CompareProperties( const css::uno::Any& r1, const css::uno::Any& r2 ) +{ + return r1 == r2; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/servicenames.cxx b/toolkit/source/helper/servicenames.cxx new file mode 100644 index 000000000..825672fd2 --- /dev/null +++ b/toolkit/source/helper/servicenames.cxx @@ -0,0 +1,24 @@ +/* -*- 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 <helper/servicenames.hxx> + +const char szServiceName_UnoControlDialog[] = "stardiv.vcl.control.Dialog"; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/tkresmgr.cxx b/toolkit/source/helper/tkresmgr.cxx new file mode 100644 index 000000000..418c489f0 --- /dev/null +++ b/toolkit/source/helper/tkresmgr.cxx @@ -0,0 +1,57 @@ +/* -*- 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 <comphelper/processfactory.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <com/sun/star/graphic/GraphicProvider.hpp> +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <tools/diagnose_ex.h> + +#include <vcl/image.hxx> + +#include <helper/tkresmgr.hxx> + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::graphic::XGraphic; +using ::com::sun::star::graphic::XGraphicProvider; +using namespace ::com::sun::star; + +Image TkResMgr::getImageFromURL(const OUString& i_rImageURL) +{ + if (i_rImageURL.isEmpty()) + return Image(); + + try + { + Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext()); + Reference<XGraphicProvider> xProvider(graphic::GraphicProvider::create(xContext)); + ::comphelper::NamedValueCollection aMediaProperties; + aMediaProperties.put("URL", i_rImageURL); + Reference<XGraphic> xGraphic + = xProvider->queryGraphic(aMediaProperties.getPropertyValues()); + return Image(xGraphic); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("toolkit"); + } + return Image(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/unopropertyarrayhelper.cxx b/toolkit/source/helper/unopropertyarrayhelper.cxx new file mode 100644 index 000000000..0a36f4bf3 --- /dev/null +++ b/toolkit/source/helper/unopropertyarrayhelper.cxx @@ -0,0 +1,148 @@ +/* -*- 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 <toolkit/helper/property.hxx> +#include <map> + +#include <helper/unopropertyarrayhelper.hxx> + + + +UnoPropertyArrayHelper::UnoPropertyArrayHelper( const css::uno::Sequence<sal_Int32>& rIDs ) +{ + for ( const sal_Int32 nID : rIDs ) + maIDs.insert( nID ); +} + +UnoPropertyArrayHelper::UnoPropertyArrayHelper( const std::vector< sal_uInt16 > &rIDs ) +{ + for (const auto& rId : rIDs) + maIDs.insert( rId ); +} + +bool UnoPropertyArrayHelper::ImplHasProperty( sal_uInt16 nPropId ) const +{ + if ( ( nPropId >= BASEPROPERTY_FONTDESCRIPTORPART_START ) && ( nPropId <= BASEPROPERTY_FONTDESCRIPTORPART_END ) ) + nPropId = BASEPROPERTY_FONTDESCRIPTOR; + + return maIDs.find( nPropId ) != maIDs.end(); +} + +// ::cppu::IPropertyArrayHelper +sal_Bool UnoPropertyArrayHelper::fillPropertyMembersByHandle( OUString * pPropName, sal_Int16 * pAttributes, sal_Int32 nPropId ) +{ + sal_uInt16 id = sal::static_int_cast< sal_uInt16 >(nPropId); + bool bValid = ImplHasProperty( id ); + if ( bValid ) + { + if ( pPropName ) + *pPropName = GetPropertyName( id ); + if ( pAttributes ) + *pAttributes = GetPropertyAttribs( id ); + } + return bValid; +} + +css::uno::Sequence< css::beans::Property > UnoPropertyArrayHelper::getProperties() +{ + // Sort by names ... + + std::map<sal_Int32, sal_uInt16> aSortedPropsIds; + for (const auto& rId : maIDs) + { + sal_uInt16 nId = sal::static_int_cast< sal_uInt16 >(rId); + aSortedPropsIds[ 1+GetPropertyOrderNr( nId ) ] = nId; + + if ( nId == BASEPROPERTY_FONTDESCRIPTOR ) + { + // single properties ... + for ( sal_uInt16 i = BASEPROPERTY_FONTDESCRIPTORPART_START; i <= BASEPROPERTY_FONTDESCRIPTORPART_END; i++ ) + aSortedPropsIds[ 1+GetPropertyOrderNr( i ) ] = i; + } + } + + sal_uInt32 nProps = aSortedPropsIds.size(); // could be more now + css::uno::Sequence< css::beans::Property> aProps( nProps ); + css::beans::Property* pProps = aProps.getArray(); + + sal_uInt32 n = 0; + for ( const auto& rPropIds : aSortedPropsIds ) + { + sal_uInt16 nId = rPropIds.second; + pProps[n].Name = GetPropertyName( nId ); + pProps[n].Handle = nId; + pProps[n].Type = *GetPropertyType( nId ); + pProps[n].Attributes = GetPropertyAttribs( nId ); + ++n; + } + + return aProps; +} + +css::beans::Property UnoPropertyArrayHelper::getPropertyByName(const OUString& rPropertyName) +{ + css::beans::Property aProp; + sal_uInt16 nId = GetPropertyId( rPropertyName ); + if ( ImplHasProperty( nId ) ) + { + aProp.Name = rPropertyName; + aProp.Handle = -1; + aProp.Type = *GetPropertyType( nId ); + aProp.Attributes = GetPropertyAttribs( nId ); + } + + return aProp; +} + +sal_Bool UnoPropertyArrayHelper::hasPropertyByName(const OUString& rPropertyName) +{ + return ImplHasProperty( GetPropertyId( rPropertyName ) ); +} + +sal_Int32 UnoPropertyArrayHelper::getHandleByName( const OUString & rPropertyName ) +{ + sal_Int32 nId = static_cast<sal_Int32>(GetPropertyId( rPropertyName )); + return nId ? nId : -1; +} + +sal_Int32 UnoPropertyArrayHelper::fillHandles( sal_Int32* pHandles, const css::uno::Sequence< OUString > & rPropNames ) +{ + const OUString* pNames = rPropNames.getConstArray(); + sal_Int32 nValues = rPropNames.getLength(); + sal_Int32 nValidHandles = 0; + + for ( sal_Int32 n = 0; n < nValues; n++ ) + { + sal_uInt16 nPropId = GetPropertyId( pNames[n] ); + if ( nPropId && ImplHasProperty( nPropId ) ) + { + pHandles[n] = nPropId; + nValidHandles++; + } + else + { + pHandles[n] = -1; + } + } + return nValidHandles; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/unowrapper.cxx b/toolkit/source/helper/unowrapper.cxx new file mode 100644 index 000000000..080847154 --- /dev/null +++ b/toolkit/source/helper/unowrapper.cxx @@ -0,0 +1,314 @@ +/* -*- 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 <toolkit/helper/vclunohelper.hxx> +#include <toolkit/awt/vclxwindow.hxx> +#include <toolkit/awt/vclxwindows.hxx> +#include <toolkit/awt/vclxmenu.hxx> +#include <awt/vclxcontainer.hxx> +#include <awt/vclxgraphics.hxx> +#include <awt/vclxtopwindow.hxx> +#include <awt/vclxwindows.hxx> + +#include <toolkit/dllapi.h> +#include <vcl/menu.hxx> + +#include <helper/unowrapper.hxx> + +using namespace ::com::sun::star; + +static rtl::Reference<VCLXWindow> CreateXWindow( vcl::Window const * pWindow ) +{ + switch ( pWindow->GetType() ) + { + case WindowType::IMAGEBUTTON: + case WindowType::SPINBUTTON: + case WindowType::MENUBUTTON: + case WindowType::MOREBUTTON: + case WindowType::PUSHBUTTON: + case WindowType::HELPBUTTON: + case WindowType::OKBUTTON: + case WindowType::CANCELBUTTON: return new VCLXButton; + case WindowType::CHECKBOX: return new VCLXCheckBox; + // #i95042# + // A Window of type <MetricBox> is inherited from type <ComboBox>. + // Thus, it does make more sense to return a <VCLXComboBox> instance + // instead of only a <VCLXWindow> instance, especially regarding its + // corresponding accessibility API. + case WindowType::METRICBOX: + case WindowType::COMBOBOX: return new VCLXComboBox; + case WindowType::FORMATTEDFIELD: return new SVTXNumericField; + case WindowType::SPINFIELD: + case WindowType::CURRENCYFIELD: return new VCLXNumericField; + case WindowType::DATEFIELD: return new VCLXDateField; + case WindowType::MULTILINEEDIT: + case WindowType::EDIT: return new VCLXEdit; + case WindowType::METRICFIELD: return new VCLXSpinField; + case WindowType::MESSBOX: + case WindowType::INFOBOX: + case WindowType::WARNINGBOX: + case WindowType::QUERYBOX: + case WindowType::ERRORBOX: return new VCLXMessageBox; + case WindowType::FIXEDIMAGE: return new VCLXImageControl; + case WindowType::FIXEDTEXT: return new VCLXFixedText; + case WindowType::MULTILISTBOX: + case WindowType::LISTBOX: return new VCLXListBox; + case WindowType::DIALOG: + case WindowType::TABDIALOG: + case WindowType::BUTTONDIALOG: + case WindowType::MODELESSDIALOG: return new VCLXDialog; + case WindowType::PATTERNFIELD: return new VCLXPatternField; + case WindowType::RADIOBUTTON: return new VCLXRadioButton; + case WindowType::SCROLLBAR: return new VCLXScrollBar; + case WindowType::TIMEFIELD: return new VCLXTimeField; + + case WindowType::WORKWINDOW: + case WindowType::DOCKINGWINDOW: + case WindowType::FLOATINGWINDOW: + case WindowType::HELPTEXTWINDOW: return new VCLXTopWindow; + + case WindowType::WINDOW: + case WindowType::TABPAGE: return new VCLXContainer; + + case WindowType::TOOLBOX: return new VCLXToolBox; + case WindowType::TABCONTROL: return new VCLXMultiPage; + + case WindowType::HEADERBAR: return new VCLXHeaderBar; + + // case WindowType::FIXEDLINE: + // case WindowType::FIXEDBITMAP: + // case WindowType::DATEBOX: + // case WindowType::GROUPBOX: + // case WindowType::LONGCURRENCYBOX: + // case WindowType::SPLITTER: + // case WindowType::STATUSBAR: + // case WindowType::TABCONTROL: + // case WindowType::NUMERICBOX: + // case WindowType::TRISTATEBOX: + // case WindowType::TIMEBOX: + // case WindowType::SPLITWINDOW: + // case WindowType::SCROLLBARBOX: + // case WindowType::PATTERNBOX: + // case WindowType::CURRENCYBOX: + default: return new VCLXWindow( true ); + } +} + + + + +extern "C" { + +TOOLKIT_DLLPUBLIC UnoWrapperBase* CreateUnoWrapper() +{ + return new UnoWrapper( nullptr ); +} + +} // extern "C" + + +UnoWrapper::UnoWrapper( const css::uno::Reference< css::awt::XToolkit>& rxToolkit ) +{ + mxToolkit = rxToolkit; +} + +void UnoWrapper::Destroy() +{ + delete this; +} + +UnoWrapper::~UnoWrapper() +{ +} + +css::uno::Reference< css::awt::XToolkit> UnoWrapper::GetVCLToolkit() +{ + if ( !mxToolkit.is() ) + mxToolkit = VCLUnoHelper::CreateToolkit(); + return mxToolkit; +} + +css::uno::Reference< css::awt::XWindowPeer> UnoWrapper::GetWindowInterface( vcl::Window* pWindow ) +{ + css::uno::Reference< css::awt::XWindowPeer> xPeer = pWindow->GetWindowPeer(); + if ( xPeer ) + return xPeer; + + rtl::Reference<VCLXWindow> xVCLXWindow = CreateXWindow( pWindow ); + xVCLXWindow->SetWindow( pWindow ); + pWindow->SetWindowPeer( xVCLXWindow, xVCLXWindow.get() ); + return xVCLXWindow; +} + +VclPtr<vcl::Window> UnoWrapper::GetWindow(const css::uno::Reference<css::awt::XWindow>& rWindow) +{ + return VCLUnoHelper::GetWindow(rWindow); +} + +void UnoWrapper::SetWindowInterface( vcl::Window* pWindow, const css::uno::Reference< css::awt::XWindowPeer> & xIFace ) +{ + VCLXWindow* pVCLXWindow = comphelper::getFromUnoTunnel<VCLXWindow>( xIFace ); + + assert( pVCLXWindow && "must be a VCLXWindow subclass" ); + if ( !pVCLXWindow ) + return; + + if (!pWindow) + { + // we are disconnecting a peer from a window + pVCLXWindow->SetWindow( nullptr ); + } + else + { + css::uno::Reference< css::awt::XWindowPeer> xPeer = pWindow->GetWindowPeer(); + if( xPeer.is() ) + { + bool bSameInstance( pVCLXWindow == dynamic_cast< VCLXWindow* >( xPeer.get() )); + SAL_WARN_IF( !bSameInstance, "toolkit.helper", "UnoWrapper::SetWindowInterface: there is already a WindowPeer/ComponentInterface for this VCL window" ); + if ( bSameInstance ) + return; + } + pVCLXWindow->SetWindow( pWindow ); + pWindow->SetWindowPeer( xIFace, pVCLXWindow ); + } +} + +css::uno::Reference<css::awt::XPopupMenu> UnoWrapper::CreateMenuInterface( PopupMenu* pPopupMenu ) +{ + return new VCLXPopupMenu(pPopupMenu); +} + +css::uno::Reference< css::awt::XGraphics> UnoWrapper::CreateGraphics( OutputDevice* pOutDev ) +{ + rtl::Reference<VCLXGraphics> pGrf = new VCLXGraphics; + pGrf->Init( pOutDev ); + return pGrf; +} + +void UnoWrapper::ReleaseAllGraphics( OutputDevice* pOutDev ) +{ + std::vector< VCLXGraphics* > *pLst = pOutDev->GetUnoGraphicsList(); + if ( pLst ) + { + for (VCLXGraphics* pGrf : *pLst) + { + pGrf->SetOutputDevice( nullptr ); + } + } + +} + +static bool lcl_ImplIsParent( vcl::Window const * pParentWindow, vcl::Window* pPossibleChild ) +{ + vcl::Window* pWindow = ( pPossibleChild != pParentWindow ) ? pPossibleChild : nullptr; + while ( pWindow && ( pWindow != pParentWindow ) ) + pWindow = pWindow->GetParent(); + + return pWindow != nullptr; +} + +void UnoWrapper::WindowDestroyed( vcl::Window* pWindow ) +{ + // their still might be some children created with css::loader::Java + // that would otherwise not be destroyed until the garbage collector cleans up + VclPtr< vcl::Window > pChild = pWindow->GetWindow( GetWindowType::FirstChild ); + while ( pChild ) + { + VclPtr< vcl::Window > pNextChild = pChild->GetWindow( GetWindowType::Next ); + + VclPtr< vcl::Window > pClient = pChild->GetWindow( GetWindowType::Client ); + if ( pClient && pClient->GetWindowPeer() ) + { + css::uno::Reference< css::lang::XComponent > xComp = pClient->GetComponentInterface( false ); + xComp->dispose(); + } + else + { + // We need it to dispose the child windows properly (even without window peer), + // otherwise the vcl::Window will be leaked. + pClient.disposeAndClear(); + } + + pChild = pNextChild; + } + + // find system windows... + VclPtr< vcl::Window > pOverlap = pWindow->GetWindow( GetWindowType::Overlap ); + if ( pOverlap ) + { + pOverlap = pOverlap->GetWindow( GetWindowType::FirstOverlap ); + while ( pOverlap ) + { + VclPtr< vcl::Window > pNextOverlap = pOverlap->GetWindow( GetWindowType::Next ); + VclPtr< vcl::Window > pClient = pOverlap->GetWindow( GetWindowType::Client ); + + if ( pClient && pClient->GetWindowPeer() && lcl_ImplIsParent( pWindow, pClient ) ) + { + css::uno::Reference< css::lang::XComponent > xComp = pClient->GetComponentInterface( false ); + xComp->dispose(); + } + + pOverlap = pNextOverlap; + } + } + + { + VclPtr< vcl::Window > pParent = pWindow->GetParent(); + if ( pParent && pParent->GetWindowPeer() ) + pParent->GetWindowPeer()->notifyWindowRemoved( *pWindow ); + } + + VCLXWindow* pWindowPeer = pWindow->GetWindowPeer(); + uno::Reference< lang::XComponent > xWindowPeerComp = pWindow->GetComponentInterface( false ); + OSL_ENSURE( ( pWindowPeer != nullptr ) == xWindowPeerComp.is(), + "UnoWrapper::WindowDestroyed: inconsistency in the window's peers!" ); + if ( pWindowPeer ) + { + pWindowPeer->SetWindow( nullptr ); + pWindow->SetWindowPeer( nullptr, nullptr ); + } + if ( xWindowPeerComp.is() ) + xWindowPeerComp->dispose(); + + // #102132# Iterate over frames after setting Window peer to NULL, + // because while destroying other frames, we get into the method again and try + // to destroy this window again... + // #i42462#/#116855# no, don't loop: Instead, just ensure that all our top-window-children + // are disposed, too (which should also be a valid fix for #102132#, but doesn't have the extreme + // performance penalties) + VclPtr< vcl::Window > pTopWindowChild = pWindow->GetWindow( GetWindowType::FirstTopWindowChild ); + while ( pTopWindowChild ) + { + OSL_ENSURE( pTopWindowChild->GetParent() == pWindow, + "UnoWrapper::WindowDestroyed: inconsistency in the SystemWindow relationship!" ); + + VclPtr< vcl::Window > pNextTopChild = pTopWindowChild->GetWindow( GetWindowType::NextTopWindowSibling ); + + pTopWindowChild.disposeAndClear(); + pTopWindowChild = pNextTopChild; + } +} + + +css::uno::Reference< css::accessibility::XAccessible > UnoWrapper::CreateAccessible( Menu* pMenu, bool bIsMenuBar ) +{ + return maAccessibleFactoryAccess.getFactory().createAccessible( pMenu, bIsMenuBar ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/helper/vclunohelper.cxx b/toolkit/source/helper/vclunohelper.cxx new file mode 100644 index 000000000..ec9d3ddf3 --- /dev/null +++ b/toolkit/source/helper/vclunohelper.cxx @@ -0,0 +1,608 @@ +/* -*- 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 <tools/stream.hxx> +#include <vcl/dibtools.hxx> +#include <vcl/event.hxx> +#include <vcl/graph.hxx> +#include <vcl/metric.hxx> +#include <vcl/ptrstyle.hxx> +#include <vcl/unohelp.hxx> +#include <vcl/window.hxx> +#include <com/sun/star/util/MeasureUnit.hpp> +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/awt/SimpleFontMetric.hpp> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/awt/XControlContainer.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/embed/EmbedMapUnits.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <toolkit/helper/vclunohelper.hxx> +#include <toolkit/helper/convert.hxx> +#include <awt/vclxbitmap.hxx> +#include <awt/vclxregion.hxx> +#include <toolkit/awt/vclxwindow.hxx> +#include <awt/vclxgraphics.hxx> +#include <toolkit/awt/vclxfont.hxx> +#include <controls/unocontrolcontainer.hxx> +#include <controls/unocontrolcontainermodel.hxx> +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/awt/Toolkit.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/awt/Point.hpp> + +using namespace ::com::sun::star; + + +uno::Reference< css::awt::XToolkit> VCLUnoHelper::CreateToolkit() +{ + uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + uno::Reference< awt::XToolkit> xToolkit( awt::Toolkit::create(xContext), uno::UNO_QUERY_THROW ); + return xToolkit; +} + +BitmapEx VCLUnoHelper::GetBitmap( const css::uno::Reference< css::awt::XBitmap>& rxBitmap ) +{ + BitmapEx aBmp; + + css::uno::Reference< css::graphic::XGraphic > xGraphic( rxBitmap, css::uno::UNO_QUERY ); + if( xGraphic.is() ) + { + Graphic aGraphic( xGraphic ); + aBmp = aGraphic.GetBitmapEx(); + } + else if ( rxBitmap.is() ) + { + VCLXBitmap* pVCLBitmap = comphelper::getFromUnoTunnel<VCLXBitmap>( rxBitmap ); + if ( pVCLBitmap ) + aBmp = pVCLBitmap->GetBitmap(); + else + { + Bitmap aDIB, aMask; + { + css::uno::Sequence<sal_Int8> aBytes = rxBitmap->getDIB(); + SvMemoryStream aMem( aBytes.getArray(), aBytes.getLength(), StreamMode::READ ); + ReadDIB(aDIB, aMem, true); + } + { + css::uno::Sequence<sal_Int8> aBytes = rxBitmap->getMaskDIB(); + SvMemoryStream aMem( aBytes.getArray(), aBytes.getLength(), StreamMode::READ ); + ReadDIB(aMask, aMem, true); + } + aBmp = BitmapEx( aDIB, aMask ); + } + } + return aBmp; +} + +css::uno::Reference< css::awt::XBitmap> VCLUnoHelper::CreateBitmap( const BitmapEx& rBitmap ) +{ + Graphic aGraphic( rBitmap ); + css::uno::Reference< css::awt::XBitmap> xBmp( aGraphic.GetXGraphic(), css::uno::UNO_QUERY ); + return xBmp; +} + +css::uno::Reference< css::awt::XBitmap> VCLUnoHelper::CreateVCLXBitmap( const BitmapEx& rBitmap ) +{ + return css::uno::Reference< css::awt::XBitmap >(new VCLXBitmap(rBitmap)); +} + +vcl::Window* VCLUnoHelper::GetWindow( const css::uno::Reference< css::awt::XWindow>& rxWindow ) +{ + VCLXWindow* pVCLXWindow = comphelper::getFromUnoTunnel<VCLXWindow>( rxWindow ); + return pVCLXWindow ? pVCLXWindow->GetWindow() : nullptr; +} + +vcl::Window* VCLUnoHelper::GetWindow( const css::uno::Reference< css::awt::XWindow2>& rxWindow ) +{ + VCLXWindow* pVCLXWindow = comphelper::getFromUnoTunnel<VCLXWindow>( rxWindow ); + return pVCLXWindow ? pVCLXWindow->GetWindow() : nullptr; +} + +vcl::Window* VCLUnoHelper::GetWindow( const css::uno::Reference< css::awt::XWindowPeer>& rxWindow ) +{ + VCLXWindow* pVCLXWindow = comphelper::getFromUnoTunnel<VCLXWindow>( rxWindow ); + return pVCLXWindow ? pVCLXWindow->GetWindow() : nullptr; +} + +vcl::Region VCLUnoHelper::GetRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion ) +{ + vcl::Region aRegion; + VCLXRegion* pVCLRegion = comphelper::getFromUnoTunnel<VCLXRegion>( rxRegion ); + if ( pVCLRegion ) + aRegion = pVCLRegion->GetRegion(); + else + { + const css::uno::Sequence< css::awt::Rectangle > aRects = rxRegion->getRectangles(); + for ( const auto& rRect : aRects ) + aRegion.Union( VCLRectangle( rRect ) ); + } + return aRegion; +} + +css::uno::Reference< css::awt::XWindow> VCLUnoHelper::GetInterface( vcl::Window* pWindow ) +{ + css::uno::Reference< css::awt::XWindow > xWin; + if ( pWindow ) + { + css::uno::Reference< css::awt::XWindowPeer> xPeer = pWindow->GetComponentInterface(); + xWin.set(xPeer, css::uno::UNO_QUERY); + } + return xWin; +} + +OutputDevice* VCLUnoHelper::GetOutputDevice( const css::uno::Reference< css::awt::XDevice>& rxDevice ) +{ + VclPtr<OutputDevice> pOutDev; + VCLXDevice* pDev = comphelper::getFromUnoTunnel<VCLXDevice>( rxDevice ); + if ( pDev ) + pOutDev = pDev->GetOutputDevice(); + return pOutDev; +} + +OutputDevice* VCLUnoHelper::GetOutputDevice( const css::uno::Reference< css::awt::XGraphics>& rxGraphics ) +{ + OutputDevice* pOutDev = nullptr; + VCLXGraphics* pGrf = comphelper::getFromUnoTunnel<VCLXGraphics>( rxGraphics ); + if ( pGrf ) + pOutDev = pGrf->GetOutputDevice(); + return pOutDev; +} + +tools::Polygon VCLUnoHelper::CreatePolygon( const css::uno::Sequence< sal_Int32 >& DataX, + const css::uno::Sequence< sal_Int32 >& DataY ) +{ + sal_Int32 nLen = DataX.getLength(); + const sal_Int32* pDataX = DataX.getConstArray(); + const sal_Int32* pDataY = DataY.getConstArray(); + tools::Polygon aPoly( static_cast<sal_uInt16>(nLen) ); + for ( sal_Int32 n = 0; n < nLen; n++ ) + { + Point aPnt; + aPnt.setX( pDataX[n] ); + aPnt.setY( pDataY[n] ); + aPoly[n] = aPnt; + } + return aPoly; +} + +css::uno::Reference< css::awt::XControlContainer> VCLUnoHelper::CreateControlContainer( vcl::Window* pWindow ) +{ + rtl::Reference<UnoControlContainer> pContainer = new UnoControlContainer( pWindow->GetComponentInterface() ); + + rtl::Reference<UnoControlModel> pContainerModel = new UnoControlContainerModel( ::comphelper::getProcessComponentContext() ); + pContainer->setModel( pContainerModel ); + + return pContainer; +} + +css::awt::FontDescriptor VCLUnoHelper::CreateFontDescriptor( const vcl::Font& rFont ) +{ + css::awt::FontDescriptor aFD; + aFD.Name = rFont.GetFamilyName(); + aFD.StyleName = rFont.GetStyleName(); + aFD.Height = static_cast<sal_Int16>(rFont.GetFontSize().Height()); + aFD.Width = static_cast<sal_Int16>(rFont.GetFontSize().Width()); + aFD.Family = sal::static_int_cast< sal_Int16 >(rFont.GetFamilyType()); + aFD.CharSet = rFont.GetCharSet(); + aFD.Pitch = sal::static_int_cast< sal_Int16 >(rFont.GetPitch()); + aFD.CharacterWidth = vcl::unohelper::ConvertFontWidth(rFont.GetWidthType()); + aFD.Weight = vcl::unohelper::ConvertFontWeight(rFont.GetWeight()); + aFD.Slant = vcl::unohelper::ConvertFontSlant(rFont.GetItalic()); + aFD.Underline = sal::static_int_cast< sal_Int16 >(rFont.GetUnderline()); + aFD.Strikeout = sal::static_int_cast< sal_Int16 >(rFont.GetStrikeout()); + aFD.Orientation = rFont.GetOrientation().get() / 10.0; + aFD.Kerning = rFont.IsKerning(); + aFD.WordLineMode = rFont.IsWordLineMode(); + aFD.Type = 0; // ??? => Only in Metric... + return aFD; +} + +vcl::Font VCLUnoHelper::CreateFont( const css::awt::FontDescriptor& rDescr, const vcl::Font& rInitFont ) +{ + vcl::Font aFont( rInitFont ); + if ( !rDescr.Name.isEmpty() ) + aFont.SetFamilyName( rDescr.Name ); + if ( !rDescr.StyleName.isEmpty() ) + aFont.SetStyleName( rDescr.StyleName ); + if ( rDescr.Height ) + aFont.SetFontSize( Size( rDescr.Width, rDescr.Height ) ); + if ( static_cast<FontFamily>(rDescr.Family) != FAMILY_DONTKNOW ) + aFont.SetFamily( static_cast<FontFamily>(rDescr.Family) ); + if ( static_cast<rtl_TextEncoding>(rDescr.CharSet) != RTL_TEXTENCODING_DONTKNOW ) + aFont.SetCharSet( static_cast<rtl_TextEncoding>(rDescr.CharSet) ); + if ( static_cast<FontPitch>(rDescr.Pitch) != PITCH_DONTKNOW ) + aFont.SetPitch( static_cast<FontPitch>(rDescr.Pitch) ); + if ( rDescr.CharacterWidth ) + aFont.SetWidthType(vcl::unohelper::ConvertFontWidth(rDescr.CharacterWidth)); + if ( rDescr.Weight ) + aFont.SetWeight(vcl::unohelper::ConvertFontWeight(rDescr.Weight)); + if ( rDescr.Slant != css::awt::FontSlant_DONTKNOW ) + aFont.SetItalic(vcl::unohelper::ConvertFontSlant(rDescr.Slant)); + if ( static_cast<FontLineStyle>(rDescr.Underline) != LINESTYLE_DONTKNOW ) + aFont.SetUnderline( static_cast<FontLineStyle>(rDescr.Underline) ); + if ( static_cast<FontStrikeout>(rDescr.Strikeout) != STRIKEOUT_DONTKNOW ) + aFont.SetStrikeout( static_cast<FontStrikeout>(rDescr.Strikeout) ); + + // Not DONTKNOW + aFont.SetOrientation( Degree10(static_cast<sal_Int16>(rDescr.Orientation * 10)) ); + aFont.SetKerning( static_cast<FontKerning>(rDescr.Kerning) ); + aFont.SetWordLineMode( rDescr.WordLineMode ); + + return aFont; +} + +vcl::Font VCLUnoHelper::CreateFont( const css::uno::Reference< css::awt::XFont >& rxFont ) +{ + vcl::Font aFont; + VCLXFont* pVCLXFont = comphelper::getFromUnoTunnel<VCLXFont>( rxFont ); + if ( pVCLXFont ) + aFont = pVCLXFont->GetFont(); + return aFont; +} + + +css::awt::SimpleFontMetric VCLUnoHelper::CreateFontMetric( const FontMetric& rFontMetric ) +{ + css::awt::SimpleFontMetric aFM; + aFM.Ascent = static_cast<sal_Int16>(rFontMetric.GetAscent()); + aFM.Descent = static_cast<sal_Int16>(rFontMetric.GetDescent()); + aFM.Leading = static_cast<sal_Int16>(rFontMetric.GetInternalLeading()); + aFM.Slant = static_cast<sal_Int16>(rFontMetric.GetSlant()); + aFM.FirstChar = 0x0020; + aFM.LastChar = 0xFFFD; + return aFM; +} + +bool VCLUnoHelper::IsZero(const css::awt::Rectangle& rRect) +{ + return ( !rRect.X && !rRect.Y && !rRect.Width && !rRect.Height ); +} + +MapUnit VCLUnoHelper::UnoEmbed2VCLMapUnit( sal_Int32 nUnoEmbedMapUnit ) +{ + switch( nUnoEmbedMapUnit ) + { + case css::embed::EmbedMapUnits::ONE_100TH_MM: + return MapUnit::Map100thMM; + case css::embed::EmbedMapUnits::ONE_10TH_MM: + return MapUnit::Map10thMM; + case css::embed::EmbedMapUnits::ONE_MM: + return MapUnit::MapMM; + case css::embed::EmbedMapUnits::ONE_CM: + return MapUnit::MapCM; + case css::embed::EmbedMapUnits::ONE_1000TH_INCH: + return MapUnit::Map1000thInch; + case css::embed::EmbedMapUnits::ONE_100TH_INCH: + return MapUnit::Map100thInch; + case css::embed::EmbedMapUnits::ONE_10TH_INCH: + return MapUnit::Map10thInch; + case css::embed::EmbedMapUnits::ONE_INCH: + return MapUnit::MapInch; + case css::embed::EmbedMapUnits::POINT: + return MapUnit::MapPoint; + case css::embed::EmbedMapUnits::TWIP: + return MapUnit::MapTwip; + case css::embed::EmbedMapUnits::PIXEL: + return MapUnit::MapPixel; + } + + OSL_FAIL( "Unexpected UNO map mode is provided!" ); + return MapUnit::LASTENUMDUMMY; +} + +sal_Int32 VCLUnoHelper::VCL2UnoEmbedMapUnit( MapUnit nVCLMapUnit ) +{ + switch( nVCLMapUnit ) + { + case MapUnit::Map100thMM: + return css::embed::EmbedMapUnits::ONE_100TH_MM; + case MapUnit::Map10thMM: + return css::embed::EmbedMapUnits::ONE_10TH_MM; + case MapUnit::MapMM: + return css::embed::EmbedMapUnits::ONE_MM; + case MapUnit::MapCM: + return css::embed::EmbedMapUnits::ONE_CM; + case MapUnit::Map1000thInch: + return css::embed::EmbedMapUnits::ONE_1000TH_INCH; + case MapUnit::Map100thInch: + return css::embed::EmbedMapUnits::ONE_100TH_INCH; + case MapUnit::Map10thInch: + return css::embed::EmbedMapUnits::ONE_10TH_INCH; + case MapUnit::MapInch: + return css::embed::EmbedMapUnits::ONE_INCH; + case MapUnit::MapPoint: + return css::embed::EmbedMapUnits::POINT; + case MapUnit::MapTwip: + return css::embed::EmbedMapUnits::TWIP; + case MapUnit::MapPixel: + return css::embed::EmbedMapUnits::PIXEL; + default: ; // avoid compiler warning + } + + OSL_FAIL( "Unexpected VCL map mode is provided!" ); + return -1; +} + +using namespace ::com::sun::star::util; + + +namespace +{ + enum UnitConversionDirection + { + FieldUnitToMeasurementUnit, + MeasurementUnitToFieldUnit + }; + + sal_Int16 convertMeasurementUnit( sal_Int16 _nUnit, UnitConversionDirection eDirection, sal_Int16& _rFieldToUNOValueFactor ) + { + static struct _unit_table + { + FieldUnit eFieldUnit; + sal_Int16 nMeasurementUnit; + sal_Int16 nFieldToMeasureFactor; + } const aUnits[] = { + { FieldUnit::NONE, -1 , -1}, + { FieldUnit::MM, MeasureUnit::MM, 1 }, // must precede MM_10TH + { FieldUnit::MM, MeasureUnit::MM_10TH, 10 }, + { FieldUnit::MM_100TH, MeasureUnit::MM_100TH, 1 }, + { FieldUnit::CM, MeasureUnit::CM, 1 }, + { FieldUnit::M, MeasureUnit::M, 1 }, + { FieldUnit::KM, MeasureUnit::KM, 1 }, + { FieldUnit::TWIP, MeasureUnit::TWIP, 1 }, + { FieldUnit::POINT, MeasureUnit::POINT, 1 }, + { FieldUnit::PICA, MeasureUnit::PICA, 1 }, + { FieldUnit::INCH, MeasureUnit::INCH, 1 }, // must precede INCH_*TH + { FieldUnit::INCH, MeasureUnit::INCH_10TH, 10 }, + { FieldUnit::INCH, MeasureUnit::INCH_100TH, 100 }, + { FieldUnit::INCH, MeasureUnit::INCH_1000TH, 1000 }, + { FieldUnit::FOOT, MeasureUnit::FOOT, 1 }, + { FieldUnit::MILE, MeasureUnit::MILE, 1 }, + }; + for (auto & aUnit : aUnits) + { + if ( eDirection == FieldUnitToMeasurementUnit ) + { + if ( ( aUnit.eFieldUnit == static_cast<FieldUnit>(_nUnit) ) && ( aUnit.nFieldToMeasureFactor == _rFieldToUNOValueFactor ) ) + return aUnit.nMeasurementUnit; + } + else + { + if ( aUnit.nMeasurementUnit == _nUnit ) + { + _rFieldToUNOValueFactor = aUnit.nFieldToMeasureFactor; + return static_cast<sal_Int16>(aUnit.eFieldUnit); + } + } + } + if ( eDirection == FieldUnitToMeasurementUnit ) + return -1; + + _rFieldToUNOValueFactor = 1; + return sal_Int16(FieldUnit::NONE); + } +} + +//= MeasurementUnitConversion + + +sal_Int16 VCLUnoHelper::ConvertToMeasurementUnit( FieldUnit _nFieldUnit, sal_Int16 _nUNOToFieldValueFactor ) +{ + return convertMeasurementUnit( static_cast<sal_Int16>(_nFieldUnit), FieldUnitToMeasurementUnit, _nUNOToFieldValueFactor ); +} + + +FieldUnit VCLUnoHelper::ConvertToFieldUnit( sal_Int16 _nMeasurementUnit, sal_Int16& _rFieldToUNOValueFactor ) +{ + return static_cast<FieldUnit>(convertMeasurementUnit( _nMeasurementUnit, MeasurementUnitToFieldUnit, _rFieldToUNOValueFactor )); +} + + +MapUnit /* MapModeUnit */ VCLUnoHelper::ConvertToMapModeUnit(sal_Int16 /* com.sun.star.util.MeasureUnit.* */ _nMeasureUnit) +{ + MapUnit eMode; + switch(_nMeasureUnit) + { + case css::util::MeasureUnit::MM_100TH: + eMode = MapUnit::Map100thMM; + break; + + case css::util::MeasureUnit::MM_10TH: + eMode = MapUnit::Map10thMM; + break; + + case css::util::MeasureUnit::MM: + eMode = MapUnit::MapMM; + break; + + case css::util::MeasureUnit::CM: + eMode = MapUnit::MapCM; + break; + + case css::util::MeasureUnit::INCH_1000TH: + eMode = MapUnit::Map1000thInch; + break; + + case css::util::MeasureUnit::INCH_100TH: + eMode = MapUnit::Map100thInch; + break; + + case css::util::MeasureUnit::INCH_10TH: + eMode = MapUnit::Map10thInch; + break; + + case css::util::MeasureUnit::INCH: + eMode = MapUnit::MapInch; + break; + + case css::util::MeasureUnit::POINT: + eMode = MapUnit::MapPoint; + break; + + case css::util::MeasureUnit::TWIP: + eMode = MapUnit::MapTwip; + break; + + case css::util::MeasureUnit::PIXEL: + eMode = MapUnit::MapPixel; + break; + + case css::util::MeasureUnit::APPFONT: + eMode = MapUnit::MapAppFont; + break; + + case css::util::MeasureUnit::SYSFONT: + eMode = MapUnit::MapSysFont; + break; + + default: + throw css::lang::IllegalArgumentException("Unsupported measure unit.", nullptr, 1 ); + } + return eMode; +} + +::Size VCLUnoHelper::ConvertToVCLSize(css::awt::Size const& _aSize) +{ + ::Size aVCLSize(_aSize.Width, _aSize.Height); + return aVCLSize; +} + +css::awt::Size VCLUnoHelper::ConvertToAWTSize(::Size /* VCLSize */ const& _aSize) +{ + css::awt::Size aAWTSize(_aSize.Width(), _aSize.Height()); + return aAWTSize; +} + + +::Point VCLUnoHelper::ConvertToVCLPoint(css::awt::Point const& _aPoint) +{ + ::Point aVCLPoint(_aPoint.X, _aPoint.Y); + return aVCLPoint; +} + +css::awt::Point VCLUnoHelper::ConvertToAWTPoint(::Point /* VCLPoint */ const& _aPoint) +{ + css::awt::Point aAWTPoint(_aPoint.X(), _aPoint.Y()); + return aAWTPoint; +} + +::tools::Rectangle VCLUnoHelper::ConvertToVCLRect( css::awt::Rectangle const & _rRect ) +{ + return ::tools::Rectangle( _rRect.X, _rRect.Y, _rRect.X + _rRect.Width - 1, _rRect.Y + _rRect.Height - 1 ); +} + +css::awt::Rectangle VCLUnoHelper::ConvertToAWTRect( ::tools::Rectangle const & _rRect ) +{ + return css::awt::Rectangle( _rRect.Left(), _rRect.Top(), _rRect.GetWidth(), _rRect.GetHeight() ); +} + +awt::MouseEvent VCLUnoHelper::createMouseEvent( const ::MouseEvent& _rVclEvent, const uno::Reference< uno::XInterface >& _rxContext ) +{ + awt::MouseEvent aMouseEvent; + aMouseEvent.Source = _rxContext; + + aMouseEvent.Modifiers = 0; + if ( _rVclEvent.IsShift() ) + aMouseEvent.Modifiers |= css::awt::KeyModifier::SHIFT; + if ( _rVclEvent.IsMod1() ) + aMouseEvent.Modifiers |= css::awt::KeyModifier::MOD1; + if ( _rVclEvent.IsMod2() ) + aMouseEvent.Modifiers |= css::awt::KeyModifier::MOD2; + + aMouseEvent.Buttons = 0; + if ( _rVclEvent.IsLeft() ) + aMouseEvent.Buttons |= css::awt::MouseButton::LEFT; + if ( _rVclEvent.IsRight() ) + aMouseEvent.Buttons |= css::awt::MouseButton::RIGHT; + if ( _rVclEvent.IsMiddle() ) + aMouseEvent.Buttons |= css::awt::MouseButton::MIDDLE; + + aMouseEvent.X = _rVclEvent.GetPosPixel().X(); + aMouseEvent.Y = _rVclEvent.GetPosPixel().Y(); + aMouseEvent.ClickCount = _rVclEvent.GetClicks(); + aMouseEvent.PopupTrigger = false; + + return aMouseEvent; +} + +::MouseEvent VCLUnoHelper::createVCLMouseEvent( const awt::MouseEvent& _rAwtEvent ) +{ + ::MouseEvent aMouseEvent( Point( _rAwtEvent.X, _rAwtEvent.Y ), _rAwtEvent.ClickCount, + ::MouseEventModifiers::NONE, _rAwtEvent.Buttons, _rAwtEvent.Modifiers ); + + return aMouseEvent; +} + +awt::KeyEvent VCLUnoHelper::createKeyEvent( const ::KeyEvent& _rVclEvent, const uno::Reference< uno::XInterface >& _rxContext ) +{ + awt::KeyEvent aKeyEvent; + aKeyEvent.Source = _rxContext; + + aKeyEvent.Modifiers = 0; + if ( _rVclEvent.GetKeyCode().IsShift() ) + aKeyEvent.Modifiers |= awt::KeyModifier::SHIFT; + if ( _rVclEvent.GetKeyCode().IsMod1() ) + aKeyEvent.Modifiers |= awt::KeyModifier::MOD1; + if ( _rVclEvent.GetKeyCode().IsMod2() ) + aKeyEvent.Modifiers |= awt::KeyModifier::MOD2; + if ( _rVclEvent.GetKeyCode().IsMod3() ) + aKeyEvent.Modifiers |= awt::KeyModifier::MOD3; + + aKeyEvent.KeyCode = _rVclEvent.GetKeyCode().GetCode(); + aKeyEvent.KeyChar = _rVclEvent.GetCharCode(); + aKeyEvent.KeyFunc = ::sal::static_int_cast< sal_Int16 >( _rVclEvent.GetKeyCode().GetFunction()); + + return aKeyEvent; +} + +::KeyEvent VCLUnoHelper::createVCLKeyEvent( const awt::KeyEvent& _rAwtEvent ) +{ + sal_Unicode nChar = _rAwtEvent.KeyChar; + vcl::KeyCode aKeyCode( _rAwtEvent.KeyCode, _rAwtEvent.Modifiers & awt::KeyModifier::SHIFT, + _rAwtEvent.Modifiers & awt::KeyModifier::MOD1, + _rAwtEvent.Modifiers & awt::KeyModifier::MOD2, + _rAwtEvent.Modifiers & awt::KeyModifier::MOD3 ); + + return ::KeyEvent (nChar, aKeyCode); + +} + +::PointerStyle VCLUnoHelper::getMousePointer(const css::uno::Reference<css::awt::XWindowPeer>& rWindowPeer) +{ + ::PointerStyle eType = ::PointerStyle::Arrow; // default ? + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(rWindowPeer); + if (pWindow) + eType = pWindow->GetPointer(); + return eType; +} + +void VCLUnoHelper::setMousePointer(const css::uno::Reference<css::awt::XWindowPeer>& rWindowPeer, ::PointerStyle ePointer) +{ + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(rWindowPeer); + if (!pWindow) + return; + pWindow->SetPointer(ePointer); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |