diff options
Diffstat (limited to '')
-rw-r--r-- | svx/source/mnuctrls/clipboardctl.cxx | 119 | ||||
-rw-r--r-- | svx/source/mnuctrls/smarttagmenu.cxx | 249 |
2 files changed, 368 insertions, 0 deletions
diff --git a/svx/source/mnuctrls/clipboardctl.cxx b/svx/source/mnuctrls/clipboardctl.cxx new file mode 100644 index 0000000000..0659d195de --- /dev/null +++ b/svx/source/mnuctrls/clipboardctl.cxx @@ -0,0 +1,119 @@ +/* -*- 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 <sal/config.h> + +#include <comphelper/propertyvalue.hxx> +#include <sfx2/tbxctrl.hxx> +#include <svl/intitem.hxx> +#include <svl/voiditem.hxx> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/weldutils.hxx> +#include <svx/clipboardctl.hxx> +#include <svx/clipfmtitem.hxx> + +#include <svtools/insdlg.hxx> +#include <svx/svxids.hrc> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + + +SFX_IMPL_TOOLBOX_CONTROL( SvxClipBoardControl, SfxVoidItem /*SfxUInt16Item*/ ); + + +SvxClipBoardControl::SvxClipBoardControl( + sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx ) : + + SfxToolBoxControl( nSlotId, nId, rTbx ), + bDisabled( false ) +{ + addStatusListener( ".uno:ClipboardFormatItems"); + ToolBox& rBox = GetToolBox(); + rBox.SetItemBits( nId, ToolBoxItemBits::DROPDOWN | rBox.GetItemBits( nId ) ); + rBox.Invalidate(); +} + +SvxClipBoardControl::~SvxClipBoardControl() +{ +} + +void SvxClipBoardControl::CreatePopupWindow() +{ + if ( pClipboardFmtItem ) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "svx/ui/clipboardmenu.ui")); + std::unique_ptr<weld::Menu> xPopup(xBuilder->weld_menu("menu")); + + sal_uInt16 nCount = pClipboardFmtItem->Count(); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + SotClipboardFormatId nFmtID = pClipboardFmtItem->GetClipbrdFormatId( i ); + OUString aFmtStr( pClipboardFmtItem->GetClipbrdFormatName( i ) ); + if (aFmtStr.isEmpty()) + aFmtStr = SvPasteObjectHelper::GetSotFormatUIName( nFmtID ); + xPopup->append(OUString::number(static_cast<sal_uInt32>(nFmtID)), aFmtStr); + } + + ToolBox& rBox = GetToolBox(); + ToolBoxItemId nId = GetId(); + rBox.SetItemDown( nId, true ); + + ::tools::Rectangle aRect(rBox.GetItemRect(nId)); + weld::Window* pParent = weld::GetPopupParent(rBox, aRect); + OUString sResult = xPopup->popup_at_rect(pParent, aRect); + + rBox.SetItemDown( nId, false ); + + SfxUInt32Item aItem(SID_CLIPBOARD_FORMAT_ITEMS, sResult.toUInt32()); + + Any a; + aItem.QueryValue( a ); + Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue("SelectedFormat", a) }; + Dispatch( ".uno:ClipboardFormatItems", + aArgs ); + } + + GetToolBox().EndSelection(); +} + +void SvxClipBoardControl::StateChangedAtToolBoxControl( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) +{ + if ( SID_CLIPBOARD_FORMAT_ITEMS == nSID ) + { + pClipboardFmtItem.reset(); + if ( eState >= SfxItemState::DEFAULT ) + { + pClipboardFmtItem.reset( static_cast<SvxClipboardFormatItem*>(pState->Clone()) ); + GetToolBox().SetItemBits( GetId(), GetToolBox().GetItemBits( GetId() ) | ToolBoxItemBits::DROPDOWN ); + } + else if ( !bDisabled ) + GetToolBox().SetItemBits( GetId(), GetToolBox().GetItemBits( GetId() ) & ~ToolBoxItemBits::DROPDOWN ); + GetToolBox().Invalidate( GetToolBox().GetItemRect( GetId() ) ); + } + else + { + // enable the item as a whole + bDisabled = (GetItemState(pState) == SfxItemState::DISABLED); + GetToolBox().EnableItem( GetId(), (GetItemState(pState) != SfxItemState::DISABLED) ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/mnuctrls/smarttagmenu.cxx b/svx/source/mnuctrls/smarttagmenu.cxx new file mode 100644 index 0000000000..f914be7d34 --- /dev/null +++ b/svx/source/mnuctrls/smarttagmenu.cxx @@ -0,0 +1,249 @@ +/* -*- 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 <svtools/popupmenucontrollerbase.hxx> +#include <svx/SmartTagItem.hxx> +#include <toolkit/awt/vclxmenu.hxx> +#include <utility> +#include <vcl/commandinfoprovider.hxx> + +const sal_uInt16 MN_ST_INSERT_START = 500; + +namespace { + +class SmartTagMenuController : public svt::PopupMenuControllerBase +{ +public: + explicit SmartTagMenuController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; + + // XMenuListener + virtual void SAL_CALL itemSelected( const css::awt::MenuEvent& rEvent ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + +private: + void FillMenu(); + bool MenuSelect(sal_uInt16 nMyId); + struct InvokeAction + { + css::uno::Reference< css::smarttags::XSmartTagAction > m_xAction; + css::uno::Reference< css::container::XStringKeyMap > m_xSmartTagProperties; + sal_uInt32 m_nActionID; + InvokeAction( css::uno::Reference< css::smarttags::XSmartTagAction > xAction, + css::uno::Reference< css::container::XStringKeyMap > xSmartTagProperties, + sal_uInt32 nActionID ) : m_xAction(std::move( xAction )), m_xSmartTagProperties(std::move( xSmartTagProperties )), m_nActionID( nActionID ) {} + }; + std::vector< InvokeAction > m_aInvokeActions; + std::unique_ptr< const SvxSmartTagItem > m_pSmartTagItem; +}; + +} + +SmartTagMenuController::SmartTagMenuController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ) + : svt::PopupMenuControllerBase( rxContext ) +{ +} + +void SmartTagMenuController::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + resetPopupMenu( m_xPopupMenu ); + + css::uno::Sequence< css::beans::PropertyValue > aProperties; + if ( !rEvent.IsEnabled || !( rEvent.State >>= aProperties ) ) + return; + + css::uno::Sequence< css::uno::Sequence< css::uno::Reference< css::smarttags::XSmartTagAction > > > aActionComponents; + css::uno::Sequence< css::uno::Sequence< sal_Int32 > > aActionIndices; + css::uno::Sequence< css::uno::Reference< css::container::XStringKeyMap > > aStringKeyMaps; + css::uno::Reference< css::text::XTextRange > xTextRange; + css::uno::Reference< css::frame::XController > xController; + css::lang::Locale aLocale; + OUString aApplicationName; + OUString aRangeText; + + for ( const auto& aProperty : std::as_const(aProperties) ) + { + if ( aProperty.Name == "ActionComponents" ) + aProperty.Value >>= aActionComponents; + else if ( aProperty.Name == "ActionIndices" ) + aProperty.Value >>= aActionIndices; + else if ( aProperty.Name == "StringKeyMaps" ) + aProperty.Value >>= aStringKeyMaps; + else if ( aProperty.Name == "TextRange" ) + aProperty.Value >>= xTextRange; + else if ( aProperty.Name == "Controller" ) + aProperty.Value >>= xController; + else if ( aProperty.Name == "Locale" ) + aProperty.Value >>= aLocale; + else if ( aProperty.Name == "ApplicationName" ) + aProperty.Value >>= aApplicationName; + else if ( aProperty.Name == "RangeText" ) + aProperty.Value >>= aRangeText; + } + m_pSmartTagItem.reset( new SvxSmartTagItem( TypedWhichId<SvxSmartTagItem>(0), aActionComponents, aActionIndices, aStringKeyMaps, xTextRange, xController, std::move(aLocale), aApplicationName, aRangeText ) ); + FillMenu(); +} + +void SmartTagMenuController::FillMenu() +{ + if ( !m_pSmartTagItem ) + return; + + sal_uInt16 nMenuId = 1; + sal_uInt16 nSubMenuId = MN_ST_INSERT_START; + + const css::uno::Sequence< css::uno::Sequence< css::uno::Reference< css::smarttags::XSmartTagAction > > >& rActionComponentsSequence = m_pSmartTagItem->GetActionComponentsSequence(); + const css::uno::Sequence< css::uno::Sequence< sal_Int32 > >& rActionIndicesSequence = m_pSmartTagItem->GetActionIndicesSequence(); + const css::uno::Sequence< css::uno::Reference< css::container::XStringKeyMap > >& rStringKeyMaps = m_pSmartTagItem->GetStringKeyMaps(); + const css::lang::Locale& rLocale = m_pSmartTagItem->GetLocale(); + const OUString aApplicationName = m_pSmartTagItem->GetApplicationName(); + const OUString aRangeText = m_pSmartTagItem->GetRangeText(); + const css::uno::Reference< css::text::XTextRange >& xTextRange = m_pSmartTagItem->GetTextRange(); + const css::uno::Reference< css::frame::XController >& xController = m_pSmartTagItem->GetController(); + + for ( sal_Int32 i = 0; i < rActionComponentsSequence.getLength(); ++i ) + { + css::uno::Reference< css::container::XStringKeyMap > xSmartTagProperties = rStringKeyMaps[i]; + + // Get all actions references associated with the current smart tag type + const css::uno::Sequence< css::uno::Reference< css::smarttags::XSmartTagAction > >& rActionComponents = rActionComponentsSequence[i]; + const css::uno::Sequence< sal_Int32 >& rActionIndices = rActionIndicesSequence[i]; + + if ( !rActionComponents.hasElements() || !rActionIndices.hasElements() ) + continue; + + // Ask first entry for the smart tag type caption + css::uno::Reference< css::smarttags::XSmartTagAction > xFirstAction = rActionComponents[0]; + + if ( !xFirstAction.is() ) + continue; + + const sal_Int32 nSmartTagIndex = rActionIndices[0]; + const OUString aSmartTagType = xFirstAction->getSmartTagName( nSmartTagIndex ); + const OUString aSmartTagCaption = xFirstAction->getSmartTagCaption( nSmartTagIndex, rLocale ); + + // No sub-menus if there's only one smart tag type listed + css::uno::Reference<css::awt::XPopupMenu> xSubMenu = m_xPopupMenu; + if ( 1 < rActionComponentsSequence.getLength() ) + { + m_xPopupMenu->insertItem(nMenuId, aSmartTagCaption, 0, -1); + xSubMenu.set(new VCLXPopupMenu); + m_xPopupMenu->setPopupMenu(nMenuId++, xSubMenu); + } + + // Sub-menu starts with smart tag caption and separator + const OUString aSmartTagCaption2 = aSmartTagCaption + ": " + aRangeText; + xSubMenu->insertItem(nMenuId++, aSmartTagCaption2, static_cast<sal_Int16>(MenuItemBits::NOSELECT), -1); + xSubMenu->insertSeparator(-1); + + // Add subitem for every action reference for the current smart tag type + for ( const auto& xAction : rActionComponents ) + { + for ( sal_Int32 j = 0; j < xAction->getActionCount( aSmartTagType, xController, xSmartTagProperties ); ++j ) + { + const sal_uInt32 nActionID = xAction->getActionID( aSmartTagType, j, xController ); + OUString aActionCaption = xAction->getActionCaptionFromID( nActionID, + aApplicationName, + rLocale, + xSmartTagProperties, + aRangeText, + OUString(), + xController, + xTextRange ); + + xSubMenu->insertItem(nSubMenuId++, aActionCaption, 0, -1); + InvokeAction aEntry( xAction, xSmartTagProperties, nActionID ); + m_aInvokeActions.push_back( aEntry ); + } + } + } + + sal_Int16 nItemCount = m_xPopupMenu->getItemCount(); + if (nItemCount > 0) + { + static constexpr OUString aCommand = u".uno:AutoCorrectDlg?OpenSmartTag:bool=true"_ustr; + m_xPopupMenu->insertSeparator(nItemCount++); + auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(aCommand, m_aModuleName); + m_xPopupMenu->insertItem(nMenuId, vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties), + 0, nItemCount); + m_xPopupMenu->setCommand(nMenuId, aCommand); + } +} + +void SmartTagMenuController::itemSelected(const css::awt::MenuEvent& rEvent) +{ + if (MenuSelect(rEvent.MenuId)) + return; + svt::PopupMenuControllerBase::itemSelected(rEvent); +} + +bool SmartTagMenuController::MenuSelect(sal_uInt16 nMyId) +{ + if ( !m_pSmartTagItem ) + return false; + + if ( nMyId < MN_ST_INSERT_START ) + return false; + + nMyId -= MN_ST_INSERT_START; + + // Compute SmartTag lib index and action index + css::uno::Reference< css::smarttags::XSmartTagAction > xSmartTagAction = m_aInvokeActions[nMyId].m_xAction; + + if (!xSmartTagAction.is()) + return false; + + // Execute action + xSmartTagAction->invokeAction( m_aInvokeActions[nMyId].m_nActionID, + m_pSmartTagItem->GetApplicationName(), + m_pSmartTagItem->GetController(), + m_pSmartTagItem->GetTextRange(), + m_aInvokeActions[nMyId].m_xSmartTagProperties, + m_pSmartTagItem->GetRangeText(), + OUString(), + m_pSmartTagItem->GetLocale() ); + + return true; +} + +OUString SmartTagMenuController::getImplementationName() +{ + return "com.sun.star.comp.svx.SmartTagMenuController"; +} + +css::uno::Sequence< OUString > SmartTagMenuController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.PopupMenuController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_SmartTagMenuController_get_implementation( + css::uno::XComponentContext* xContext, + css::uno::Sequence< css::uno::Any > const & ) +{ + return cppu::acquire( new SmartTagMenuController( xContext ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |