1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svtools/popupmenucontrollerbase.hxx>
22 #include <svx/SmartTagItem.hxx>
23 #include <toolkit/awt/vclxmenu.hxx>
24 #include <vcl/commandinfoprovider.hxx>
25 #include <vcl/menu.hxx>
27 const sal_uInt16 MN_ST_INSERT_START
= 500;
29 class SmartTagMenuController
: public svt::PopupMenuControllerBase
32 explicit SmartTagMenuController( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
35 virtual void SAL_CALL
statusChanged( const css::frame::FeatureStateEvent
& rEvent
) override
;
38 virtual OUString SAL_CALL
getImplementationName() override
;
39 virtual css::uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
43 DECL_LINK( MenuSelect
, Menu
*, bool );
46 css::uno::Reference
< css::smarttags::XSmartTagAction
> m_xAction
;
47 css::uno::Reference
< css::container::XStringKeyMap
> m_xSmartTagProperties
;
48 sal_uInt32
const m_nActionID
;
49 InvokeAction( css::uno::Reference
< css::smarttags::XSmartTagAction
> const & xAction
,
50 css::uno::Reference
< css::container::XStringKeyMap
> const & xSmartTagProperties
,
51 sal_uInt32 nActionID
) : m_xAction( xAction
), m_xSmartTagProperties( xSmartTagProperties
), m_nActionID( nActionID
) {}
53 std::vector
< InvokeAction
> m_aInvokeActions
;
54 std::unique_ptr
< const SvxSmartTagItem
> m_pSmartTagItem
;
57 SmartTagMenuController::SmartTagMenuController( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
)
58 : svt::PopupMenuControllerBase( rxContext
)
62 void SmartTagMenuController::statusChanged( const css::frame::FeatureStateEvent
& rEvent
)
64 resetPopupMenu( m_xPopupMenu
);
66 css::uno::Sequence
< css::beans::PropertyValue
> aProperties
;
67 if ( !rEvent
.IsEnabled
|| !( rEvent
.State
>>= aProperties
) )
70 css::uno::Sequence
< css::uno::Sequence
< css::uno::Reference
< css::smarttags::XSmartTagAction
> > > aActionComponents
;
71 css::uno::Sequence
< css::uno::Sequence
< sal_Int32
> > aActionIndices
;
72 css::uno::Sequence
< css::uno::Reference
< css::container::XStringKeyMap
> > aStringKeyMaps
;
73 css::uno::Reference
< css::text::XTextRange
> xTextRange
;
74 css::uno::Reference
< css::frame::XController
> xController
;
75 css::lang::Locale aLocale
;
76 OUString aApplicationName
;
79 for ( const auto& aProperty
: std::as_const(aProperties
) )
81 if ( aProperty
.Name
== "ActionComponents" )
82 aProperty
.Value
>>= aActionComponents
;
83 else if ( aProperty
.Name
== "ActionIndices" )
84 aProperty
.Value
>>= aActionIndices
;
85 else if ( aProperty
.Name
== "StringKeyMaps" )
86 aProperty
.Value
>>= aStringKeyMaps
;
87 else if ( aProperty
.Name
== "TextRange" )
88 aProperty
.Value
>>= xTextRange
;
89 else if ( aProperty
.Name
== "Controller" )
90 aProperty
.Value
>>= xController
;
91 else if ( aProperty
.Name
== "Locale" )
92 aProperty
.Value
>>= aLocale
;
93 else if ( aProperty
.Name
== "ApplicationName" )
94 aProperty
.Value
>>= aApplicationName
;
95 else if ( aProperty
.Name
== "RangeText" )
96 aProperty
.Value
>>= aRangeText
;
98 m_pSmartTagItem
.reset( new SvxSmartTagItem( 0, aActionComponents
, aActionIndices
, aStringKeyMaps
, xTextRange
, xController
, aLocale
, aApplicationName
, aRangeText
) );
102 void SmartTagMenuController::FillMenu()
104 if ( !m_pSmartTagItem
)
107 sal_uInt16 nMenuId
= 1;
108 sal_uInt16 nSubMenuId
= MN_ST_INSERT_START
;
110 VCLXMenu
* pAwtMenu
= comphelper::getUnoTunnelImplementation
<VCLXMenu
>( m_xPopupMenu
);
111 PopupMenu
* pVCLMenu
= static_cast< PopupMenu
* >( pAwtMenu
->GetMenu() );
113 const css::uno::Sequence
< css::uno::Sequence
< css::uno::Reference
< css::smarttags::XSmartTagAction
> > >& rActionComponentsSequence
= m_pSmartTagItem
->GetActionComponentsSequence();
114 const css::uno::Sequence
< css::uno::Sequence
< sal_Int32
> >& rActionIndicesSequence
= m_pSmartTagItem
->GetActionIndicesSequence();
115 const css::uno::Sequence
< css::uno::Reference
< css::container::XStringKeyMap
> >& rStringKeyMaps
= m_pSmartTagItem
->GetStringKeyMaps();
116 const css::lang::Locale
& rLocale
= m_pSmartTagItem
->GetLocale();
117 const OUString aApplicationName
= m_pSmartTagItem
->GetApplicationName();
118 const OUString aRangeText
= m_pSmartTagItem
->GetRangeText();
119 const css::uno::Reference
< css::text::XTextRange
>& xTextRange
= m_pSmartTagItem
->GetTextRange();
120 const css::uno::Reference
< css::frame::XController
>& xController
= m_pSmartTagItem
->GetController();
122 for ( sal_Int32 i
= 0; i
< rActionComponentsSequence
.getLength(); ++i
)
124 css::uno::Reference
< css::container::XStringKeyMap
> xSmartTagProperties
= rStringKeyMaps
[i
];
126 // Get all actions references associated with the current smart tag type
127 const css::uno::Sequence
< css::uno::Reference
< css::smarttags::XSmartTagAction
> >& rActionComponents
= rActionComponentsSequence
[i
];
128 const css::uno::Sequence
< sal_Int32
>& rActionIndices
= rActionIndicesSequence
[i
];
130 if ( !rActionComponents
.hasElements() || !rActionIndices
.hasElements() )
133 // Ask first entry for the smart tag type caption
134 css::uno::Reference
< css::smarttags::XSmartTagAction
> xFirstAction
= rActionComponents
[0];
136 if ( !xFirstAction
.is() )
139 const sal_Int32 nSmartTagIndex
= rActionIndices
[0];
140 const OUString aSmartTagType
= xFirstAction
->getSmartTagName( nSmartTagIndex
);
141 const OUString aSmartTagCaption
= xFirstAction
->getSmartTagCaption( nSmartTagIndex
, rLocale
);
143 // No sub-menus if there's only one smart tag type listed
144 PopupMenu
* pSubMenu
= pVCLMenu
;
145 if ( 1 < rActionComponentsSequence
.getLength() )
147 pVCLMenu
->InsertItem( nMenuId
, aSmartTagCaption
);
148 VclPtrInstance
<PopupMenu
> pMenu
;
150 pVCLMenu
->SetPopupMenu( nMenuId
++, pSubMenu
);
152 pSubMenu
->SetSelectHdl( LINK( this, SmartTagMenuController
, MenuSelect
) );
154 // Sub-menu starts with smart tag caption and separator
155 const OUString aSmartTagCaption2
= aSmartTagCaption
+ ": " + aRangeText
;
156 pSubMenu
->InsertItem( nMenuId
++, aSmartTagCaption2
, MenuItemBits::NOSELECT
);
157 pSubMenu
->InsertSeparator();
159 // Add subitem for every action reference for the current smart tag type
160 for ( const auto& xAction
: rActionComponents
)
162 for ( sal_Int32 j
= 0; j
< xAction
->getActionCount( aSmartTagType
, xController
, xSmartTagProperties
); ++j
)
164 const sal_uInt32 nActionID
= xAction
->getActionID( aSmartTagType
, j
, xController
);
165 OUString aActionCaption
= xAction
->getActionCaptionFromID( nActionID
,
174 pSubMenu
->InsertItem( nSubMenuId
++, aActionCaption
);
175 InvokeAction
aEntry( xAction
, xSmartTagProperties
, nActionID
);
176 m_aInvokeActions
.push_back( aEntry
);
181 if ( 0 < pVCLMenu
->GetItemCount() )
183 const OUString aCommand
= ".uno:AutoCorrectDlg?OpenSmartTag:bool=true";
184 pVCLMenu
->InsertSeparator();
185 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(aCommand
, m_aModuleName
);
186 pVCLMenu
->InsertItem( nMenuId
, vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties
) );
187 pVCLMenu
->SetItemCommand( nMenuId
, aCommand
);
191 IMPL_LINK( SmartTagMenuController
, MenuSelect
, Menu
*, pMenu
, bool )
193 if ( !m_pSmartTagItem
)
196 sal_uInt16 nMyId
= pMenu
->GetCurItemId();
197 if ( nMyId
< MN_ST_INSERT_START
)
200 nMyId
-= MN_ST_INSERT_START
;
202 // Compute SmartTag lib index and action index
203 css::uno::Reference
< css::smarttags::XSmartTagAction
> xSmartTagAction
= m_aInvokeActions
[nMyId
].m_xAction
;
206 if ( xSmartTagAction
.is() )
208 xSmartTagAction
->invokeAction( m_aInvokeActions
[nMyId
].m_nActionID
,
209 m_pSmartTagItem
->GetApplicationName(),
210 m_pSmartTagItem
->GetController(),
211 m_pSmartTagItem
->GetTextRange(),
212 m_aInvokeActions
[nMyId
].m_xSmartTagProperties
,
213 m_pSmartTagItem
->GetRangeText(),
215 m_pSmartTagItem
->GetLocale() );
220 OUString
SmartTagMenuController::getImplementationName()
222 return "com.sun.star.comp.svx.SmartTagMenuController";
225 css::uno::Sequence
< OUString
> SmartTagMenuController::getSupportedServiceNames()
227 return { "com.sun.star.frame.PopupMenuController" };
230 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
231 com_sun_star_comp_svx_SmartTagMenuController_get_implementation(
232 css::uno::XComponentContext
* xContext
,
233 css::uno::Sequence
< css::uno::Any
> const & )
235 return cppu::acquire( new SmartTagMenuController( xContext
) );
238 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */