diff options
Diffstat (limited to 'svx')
-rw-r--r-- | svx/Library_svx.mk | 1 | ||||
-rw-r--r-- | svx/source/items/SmartTagItem.cxx | 16 | ||||
-rw-r--r-- | svx/source/mnuctrls/smarttagmenu.cxx | 246 | ||||
-rw-r--r-- | svx/util/svx.component | 4 |
4 files changed, 264 insertions, 3 deletions
diff --git a/svx/Library_svx.mk b/svx/Library_svx.mk index c30276e2b7ad..90cfe49ca532 100644 --- a/svx/Library_svx.mk +++ b/svx/Library_svx.mk @@ -167,6 +167,7 @@ $(eval $(call gb_Library_add_exception_objects,svx,\ svx/source/mnuctrls/fntctl \ svx/source/mnuctrls/fntszctl \ svx/source/mnuctrls/SmartTagCtl \ + svx/source/mnuctrls/smarttagmenu \ svx/source/sidebar/ContextChangeEventMultiplexer \ svx/source/sidebar/EmptyPanel \ svx/source/sidebar/nbdtmg \ diff --git a/svx/source/items/SmartTagItem.cxx b/svx/source/items/SmartTagItem.cxx index 565174ef6e1c..cb9e351755b4 100644 --- a/svx/source/items/SmartTagItem.cxx +++ b/svx/source/items/SmartTagItem.cxx @@ -17,7 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ - +#include <comphelper/propertysequence.hxx> #include <svx/SmartTagItem.hxx> #include <com/sun/star/container/XStringKeyMap.hpp> @@ -53,9 +53,19 @@ SvxSmartTagItem::SvxSmartTagItem( const sal_uInt16 nId, -bool SvxSmartTagItem::QueryValue( uno::Any& /* rVal */, sal_uInt8 /* nMemberId */ ) const +bool SvxSmartTagItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const { - return false; + rVal <<= comphelper::InitPropertySequence( { + { "ActionComponents", css::uno::makeAny( maActionComponentsSequence ) }, + { "ActionIndices", css::uno::makeAny( maActionIndicesSequence ) }, + { "StringKeyMaps", css::uno::makeAny( maStringKeyMaps ) }, + { "TextRange", css::uno::makeAny( mxRange ) }, + { "Controller", css::uno::makeAny( mxController ) }, + { "Locale", css::uno::makeAny( maLocale ) }, + { "ApplicationName", css::uno::makeAny( maApplicationName ) }, + { "RangeText", css::uno::makeAny( maRangeText ) }, + } ); + return true; } bool SvxSmartTagItem::PutValue( const uno::Any& /*rVal*/, sal_uInt8 /* nMemberId */) diff --git a/svx/source/mnuctrls/smarttagmenu.cxx b/svx/source/mnuctrls/smarttagmenu.cxx new file mode 100644 index 000000000000..16b0f02756fb --- /dev/null +++ b/svx/source/mnuctrls/smarttagmenu.cxx @@ -0,0 +1,246 @@ +/* -*- 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 <svtools/popupmenucontrollerbase.hxx> +#include <svx/SmartTagItem.hxx> +#include <vcl/commandinfoprovider.hxx> +#include <vcl/menu.hxx> + +const sal_uInt16 MN_ST_INSERT_START = 500; + +class SmartTagMenuController : public svt::PopupMenuControllerBase +{ +public: + explicit SmartTagMenuController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + virtual ~SmartTagMenuController(); + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) throw ( css::uno::RuntimeException, std::exception ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw ( css::uno::RuntimeException, std::exception ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw ( css::uno::RuntimeException, std::exception ) override; + +private: + void FillMenu(); + DECL_LINK_TYPED( MenuSelect, Menu*, bool ); + 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( xAction ), m_xSmartTagProperties( xSmartTagProperties ), m_nActionID( nActionID ) {} + }; + std::vector< InvokeAction > m_aInvokeActions; + std::vector< std::unique_ptr< PopupMenu > > m_aSubMenus; + std::unique_ptr< const SvxSmartTagItem > m_pSmartTagItem; +}; + +SmartTagMenuController::SmartTagMenuController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ) + : svt::PopupMenuControllerBase( rxContext ) +{ +} + +SmartTagMenuController::~SmartTagMenuController() +{ +} + +void SmartTagMenuController::statusChanged( const css::frame::FeatureStateEvent& rEvent ) + throw ( css::uno::RuntimeException, std::exception ) +{ + resetPopupMenu( m_xPopupMenu ); + m_aSubMenus.clear(); + + css::uno::Sequence< css::beans::PropertyValue > aProperties; + if ( rEvent.IsEnabled && ( rEvent.State >>= aProperties ) ) + { + 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 : 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( 0, aActionComponents, aActionIndices, aStringKeyMaps, xTextRange, xController, aLocale, aApplicationName, aRangeText ) ); + FillMenu(); + } +} + +void SmartTagMenuController::FillMenu() +{ + if ( !m_pSmartTagItem ) + return; + + sal_uInt16 nMenuId = 1; + sal_uInt16 nSubMenuId = MN_ST_INSERT_START; + + VCLXMenu* pAwtMenu = VCLXMenu::GetImplementation( m_xPopupMenu ); + PopupMenu* pVCLMenu = static_cast< PopupMenu* >( pAwtMenu->GetMenu() ); + + 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 ( 0 == rActionComponents.getLength() || 0 == rActionIndices.getLength() ) + 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 + PopupMenu* pSubMenu = pVCLMenu; + if ( 1 < rActionComponentsSequence.getLength() ) + { + pVCLMenu->InsertItem( nMenuId, aSmartTagCaption ); + pSubMenu = new PopupMenu; + m_aSubMenus.push_back( std::unique_ptr< PopupMenu >( pSubMenu ) ); + pVCLMenu->SetPopupMenu( nMenuId++, pSubMenu ); + } + pSubMenu->SetSelectHdl( LINK( this, SmartTagMenuController, MenuSelect ) ); + + // Sub-menu starts with smart tag caption and separator + const OUString aSmartTagCaption2 = aSmartTagCaption + ": " + aRangeText; + pSubMenu->InsertItem( nMenuId++, aSmartTagCaption2, MenuItemBits::NOSELECT ); + pSubMenu->InsertSeparator(); + + // 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 ); + + pSubMenu->InsertItem( nSubMenuId++, aActionCaption ); + InvokeAction aEntry( xAction, xSmartTagProperties, nActionID ); + m_aInvokeActions.push_back( aEntry ); + } + } + } + + if ( 0 < pVCLMenu->GetItemCount() ) + { + const OUString aCommand = ".uno:AutoCorrectDlg?OpenSmartTag:bool=true"; + pVCLMenu->InsertSeparator(); + pVCLMenu->InsertItem( nMenuId, vcl::CommandInfoProvider::Instance().GetPopupLabelForCommand( aCommand, m_xFrame ) ); + pVCLMenu->SetItemCommand( nMenuId, aCommand ); + } +} + +IMPL_LINK_TYPED( SmartTagMenuController, MenuSelect, Menu*, pMenu, bool ) +{ + if ( !m_pSmartTagItem ) + return false; + + sal_uInt16 nMyId = pMenu->GetCurItemId(); + 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; + + // Execute action + if ( xSmartTagAction.is() ) + { + 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 false; +} + +OUString SmartTagMenuController::getImplementationName() + throw ( css::uno::RuntimeException, std::exception ) +{ + return OUString( "com.sun.star.comp.svx.SmartTagMenuController" ); +} + +css::uno::Sequence< OUString > SmartTagMenuController::getSupportedServiceNames() + throw ( css::uno::RuntimeException, std::exception ) +{ + css::uno::Sequence< OUString > aRet { "com.sun.star.frame.PopupMenuController" }; + return aRet; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL +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: */ diff --git a/svx/util/svx.component b/svx/util/svx.component index 0cff72e9b423..3f0e38e1eba3 100644 --- a/svx/util/svx.component +++ b/svx/util/svx.component @@ -88,4 +88,8 @@ constructor="com_sun_star_comp_svx_NumberingToolBoxControl_get_implementation"> <service name="com.sun.star.frame.ToolbarController"/> </implementation> + <implementation name="com.sun.star.comp.svx.SmartTagMenuController" + constructor="com_sun_star_comp_svx_SmartTagMenuController_get_implementation"> + <service name="com.sun.star.frame.PopupMenuController"/> + </implementation> </component> |