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 .
20 #include <vcl/commandinfoprovider.hxx>
21 #include <vcl/keycod.hxx>
22 #include <vcl/mnemonic.hxx>
23 #include <comphelper/string.hxx>
24 #include <comphelper/sequence.hxx>
25 #include <comphelper/processfactory.hxx>
26 #include <cppuhelper/weakref.hxx>
28 #include <com/sun/star/frame/XFrame.hpp>
29 #include <com/sun/star/frame/ModuleManager.hpp>
30 #include <com/sun/star/frame/theUICommandDescription.hpp>
31 #include <com/sun/star/ui/GlobalAcceleratorConfiguration.hpp>
32 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
33 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
34 #include <com/sun/star/ui/ImageType.hpp>
35 #include <com/sun/star/ui/XImageManager.hpp>
36 #include <com/sun/star/awt/KeyModifier.hpp>
39 using namespace css::uno
;
41 namespace vcl
{ namespace CommandInfoProvider
{
43 static Reference
<container::XNameAccess
> GetCommandDescription()
45 static WeakReference
<container::XNameAccess
> xWeakRef
;
46 css::uno::Reference
<container::XNameAccess
> xRef(xWeakRef
);
50 xRef
= frame::theUICommandDescription::get(comphelper::getProcessComponentContext());
57 static Reference
<ui::XModuleUIConfigurationManagerSupplier
> GetModuleConfigurationSupplier()
59 static WeakReference
<ui::XModuleUIConfigurationManagerSupplier
> xWeakRef
;
60 css::uno::Reference
<ui::XModuleUIConfigurationManagerSupplier
> xRef(xWeakRef
);
64 xRef
= ui::theModuleUIConfigurationManagerSupplier::get(comphelper::getProcessComponentContext());
71 static Reference
<ui::XAcceleratorConfiguration
> GetGlobalAcceleratorConfiguration()
73 static WeakReference
<ui::XAcceleratorConfiguration
> xWeakRef
;
74 css::uno::Reference
<ui::XAcceleratorConfiguration
> xRef(xWeakRef
);
78 xRef
= ui::GlobalAcceleratorConfiguration::create(comphelper::getProcessComponentContext());
85 static Reference
<ui::XAcceleratorConfiguration
> GetDocumentAcceleratorConfiguration(const Reference
<frame::XFrame
>& rxFrame
)
87 Reference
<frame::XController
> xController
= rxFrame
->getController();
90 Reference
<ui::XUIConfigurationManagerSupplier
> xSupplier(xController
->getModel(), UNO_QUERY
);
93 Reference
<ui::XUIConfigurationManager
> xConfigurationManager(
94 xSupplier
->getUIConfigurationManager());
95 if (xConfigurationManager
.is())
97 return xConfigurationManager
->getShortCutManager();
104 static Reference
<ui::XAcceleratorConfiguration
> GetModuleAcceleratorConfiguration(const Reference
<frame::XFrame
>& rxFrame
)
106 css::uno::Reference
<css::ui::XAcceleratorConfiguration
> curModuleAcceleratorConfiguration
;
109 Reference
<ui::XModuleUIConfigurationManagerSupplier
> xSupplier(GetModuleConfigurationSupplier());
110 Reference
<ui::XUIConfigurationManager
> xManager (
111 xSupplier
->getUIConfigurationManager(GetModuleIdentifier(rxFrame
)));
114 curModuleAcceleratorConfiguration
= xManager
->getShortCutManager();
120 return curModuleAcceleratorConfiguration
;
123 static vcl::KeyCode
AWTKey2VCLKey(const awt::KeyEvent
& aAWTKey
)
125 bool bShift
= ((aAWTKey
.Modifiers
& awt::KeyModifier::SHIFT
) == awt::KeyModifier::SHIFT
);
126 bool bMod1
= ((aAWTKey
.Modifiers
& awt::KeyModifier::MOD1
) == awt::KeyModifier::MOD1
);
127 bool bMod2
= ((aAWTKey
.Modifiers
& awt::KeyModifier::MOD2
) == awt::KeyModifier::MOD2
);
128 bool bMod3
= ((aAWTKey
.Modifiers
& awt::KeyModifier::MOD3
) == awt::KeyModifier::MOD3
);
129 sal_uInt16 nKey
= static_cast<sal_uInt16
>(aAWTKey
.KeyCode
);
131 return vcl::KeyCode(nKey
, bShift
, bMod1
, bMod2
, bMod3
);
134 static OUString
RetrieveShortcutsFromConfiguration(
135 const Reference
<ui::XAcceleratorConfiguration
>& rxConfiguration
,
136 const OUString
& rsCommandName
)
138 if (rxConfiguration
.is())
142 Sequence
<OUString
> aCommands
{ rsCommandName
};
144 Sequence
<Any
> aKeyCodes (rxConfiguration
->getPreferredKeyEventsForCommandList(aCommands
));
145 if (aCommands
.getLength() == 1)
147 awt::KeyEvent aKeyEvent
;
148 if (aKeyCodes
[0] >>= aKeyEvent
)
150 return AWTKey2VCLKey(aKeyEvent
).GetName();
154 catch (css::lang::IllegalArgumentException
&)
161 static bool ResourceHasKey(const OUString
& rsResourceName
, const OUString
& rsCommandName
, const OUString
& rsModuleName
)
163 Sequence
< OUString
> aSequence
;
166 if (!rsModuleName
.isEmpty())
168 Reference
<container::XNameAccess
> xNameAccess(GetCommandDescription());
169 Reference
<container::XNameAccess
> xUICommandLabels
;
170 if (xNameAccess
->getByName(rsModuleName
) >>= xUICommandLabels
)
172 xUICommandLabels
->getByName(rsResourceName
) >>= aSequence
;
173 if (comphelper::findValue(aSequence
, rsCommandName
) != -1)
184 Sequence
<beans::PropertyValue
> GetCommandProperties(const OUString
& rsCommandName
, const OUString
& rsModuleName
)
186 Sequence
<beans::PropertyValue
> aProperties
;
190 if (!rsModuleName
.isEmpty())
192 Reference
<container::XNameAccess
> xNameAccess(GetCommandDescription());
193 Reference
<container::XNameAccess
> xUICommandLabels
;
194 if ((xNameAccess
->getByName(rsModuleName
) >>= xUICommandLabels
) && xUICommandLabels
->hasByName(rsCommandName
))
195 xUICommandLabels
->getByName(rsCommandName
) >>= aProperties
;
205 static OUString
GetCommandProperty(const OUString
& rsProperty
, const Sequence
<beans::PropertyValue
> &rProperties
)
207 auto pProp
= std::find_if(rProperties
.begin(), rProperties
.end(),
208 [&rsProperty
](const beans::PropertyValue
& rProp
) { return rProp
.Name
== rsProperty
; });
209 if (pProp
!= rProperties
.end())
212 pProp
->Value
>>= sLabel
;
218 OUString
GetLabelForCommand(const css::uno::Sequence
<css::beans::PropertyValue
>& rProperties
)
220 return GetCommandProperty("Name", rProperties
);
223 OUString
GetMenuLabelForCommand(const css::uno::Sequence
<css::beans::PropertyValue
>& rProperties
)
225 // Here we want to use "Label", not "Name". "Name" is a stripped-down version of "Label" without accelerators
226 // and ellipsis. In the menu, we want to have those accelerators and ellipsis.
227 return GetCommandProperty("Label", rProperties
);
230 OUString
GetPopupLabelForCommand(const css::uno::Sequence
<css::beans::PropertyValue
>& rProperties
)
232 OUString
sPopupLabel(GetCommandProperty("PopupLabel", rProperties
));
233 if (!sPopupLabel
.isEmpty())
235 return GetCommandProperty("Label", rProperties
);
238 OUString
GetTooltipForCommand(
239 const OUString
& rsCommandName
,
240 const css::uno::Sequence
<css::beans::PropertyValue
>& rProperties
,
241 const Reference
<frame::XFrame
>& rxFrame
)
243 OUString
sLabel(GetCommandProperty("TooltipLabel", rProperties
));
244 if (sLabel
.isEmpty()) {
245 sLabel
= GetPopupLabelForCommand(rProperties
);
246 // Remove '...' at the end and mnemonics (we don't want those in tooltips)
247 sLabel
= comphelper::string::stripEnd(sLabel
, '.');
248 sLabel
= MnemonicGenerator::EraseAllMnemonicChars(sLabel
);
251 // Command can be just an alias to another command,
252 // so need to get the shortcut of the "real" command.
253 const OUString
sRealCommand(GetRealCommandForCommand(rProperties
));
254 const OUString
sShortCut(GetCommandShortcut(!sRealCommand
.isEmpty() ? sRealCommand
: rsCommandName
, rxFrame
));
255 if (!sShortCut
.isEmpty())
256 return sLabel
+ " (" + sShortCut
+ ")";
260 OUString
GetCommandShortcut (const OUString
& rsCommandName
,
261 const Reference
<frame::XFrame
>& rxFrame
)
266 sShortcut
= RetrieveShortcutsFromConfiguration(GetDocumentAcceleratorConfiguration(rxFrame
), rsCommandName
);
267 if (sShortcut
.getLength() > 0)
270 sShortcut
= RetrieveShortcutsFromConfiguration(GetModuleAcceleratorConfiguration(rxFrame
), rsCommandName
);
271 if (sShortcut
.getLength() > 0)
274 sShortcut
= RetrieveShortcutsFromConfiguration(GetGlobalAcceleratorConfiguration(), rsCommandName
);
275 if (sShortcut
.getLength() > 0)
281 OUString
GetRealCommandForCommand(const css::uno::Sequence
<css::beans::PropertyValue
>& rProperties
)
283 return GetCommandProperty("TargetURL", rProperties
);
286 Reference
<graphic::XGraphic
> GetXGraphicForCommand(const OUString
& rsCommandName
,
287 const Reference
<frame::XFrame
>& rxFrame
,
288 vcl::ImageType eImageType
)
290 if (rsCommandName
.isEmpty())
293 sal_Int16
nImageType(ui::ImageType::COLOR_NORMAL
| ui::ImageType::SIZE_DEFAULT
);
295 if (eImageType
== vcl::ImageType::Size26
)
296 nImageType
|= ui::ImageType::SIZE_LARGE
;
297 else if (eImageType
== vcl::ImageType::Size32
)
298 nImageType
|= ui::ImageType::SIZE_32
;
302 Reference
<frame::XController
> xController(rxFrame
->getController(), UNO_SET_THROW
);
303 Reference
<ui::XUIConfigurationManagerSupplier
> xSupplier(xController
->getModel(), UNO_QUERY
);
306 Reference
<ui::XUIConfigurationManager
> xDocUICfgMgr(xSupplier
->getUIConfigurationManager());
307 Reference
<ui::XImageManager
> xDocImgMgr(xDocUICfgMgr
->getImageManager(), UNO_QUERY
);
309 Sequence
< Reference
<graphic::XGraphic
> > aGraphicSeq
;
310 Sequence
<OUString
> aImageCmdSeq
{ rsCommandName
};
312 aGraphicSeq
= xDocImgMgr
->getImages( nImageType
, aImageCmdSeq
);
313 Reference
<graphic::XGraphic
> xGraphic
= aGraphicSeq
[0];
323 Reference
<ui::XModuleUIConfigurationManagerSupplier
> xModuleCfgMgrSupplier(GetModuleConfigurationSupplier());
324 Reference
<ui::XUIConfigurationManager
> xUICfgMgr(xModuleCfgMgrSupplier
->getUIConfigurationManager(GetModuleIdentifier(rxFrame
)));
326 Sequence
< Reference
<graphic::XGraphic
> > aGraphicSeq
;
327 Reference
<ui::XImageManager
> xModuleImageManager(xUICfgMgr
->getImageManager(), UNO_QUERY
);
329 Sequence
<OUString
> aImageCmdSeq
{ rsCommandName
};
331 aGraphicSeq
= xModuleImageManager
->getImages(nImageType
, aImageCmdSeq
);
333 Reference
<graphic::XGraphic
> xGraphic(aGraphicSeq
[0]);
344 Image
GetImageForCommand(const OUString
& rsCommandName
,
345 const Reference
<frame::XFrame
>& rxFrame
,
346 vcl::ImageType eImageType
)
348 return Image(GetXGraphicForCommand(rsCommandName
, rxFrame
, eImageType
));
351 sal_Int32
GetPropertiesForCommand (
352 const OUString
& rsCommandName
,
353 const OUString
& rsModuleName
)
355 sal_Int32 nValue
= 0;
356 const Sequence
<beans::PropertyValue
> aProperties (GetCommandProperties(rsCommandName
, rsModuleName
));
358 auto pProp
= std::find_if(aProperties
.begin(), aProperties
.end(),
359 [](const beans::PropertyValue
& rProp
) { return rProp
.Name
== "Properties"; });
360 if (pProp
!= aProperties
.end())
361 pProp
->Value
>>= nValue
;
366 bool IsRotated(const OUString
& rsCommandName
, const OUString
& rsModuleName
)
368 return ResourceHasKey("private:resource/image/commandrotateimagelist", rsCommandName
, rsModuleName
);
371 bool IsMirrored(const OUString
& rsCommandName
, const OUString
& rsModuleName
)
373 return ResourceHasKey("private:resource/image/commandmirrorimagelist", rsCommandName
, rsModuleName
);
376 bool IsExperimental(const OUString
& rsCommandName
, const OUString
& rModuleName
)
378 Sequence
<beans::PropertyValue
> aProperties
;
381 if( rModuleName
.getLength() > 0)
383 Reference
<container::XNameAccess
> xNameAccess(GetCommandDescription());
384 Reference
<container::XNameAccess
> xUICommandLabels
;
385 if (xNameAccess
->getByName( rModuleName
) >>= xUICommandLabels
)
386 xUICommandLabels
->getByName(rsCommandName
) >>= aProperties
;
388 auto pProp
= std::find_if(aProperties
.begin(), aProperties
.end(),
389 [](const beans::PropertyValue
& rProp
) { return rProp
.Name
== "IsExperimental"; });
390 if (pProp
!= aProperties
.end())
393 return (pProp
->Value
>>= bValue
) && bValue
;
403 OUString
GetModuleIdentifier(const Reference
<frame::XFrame
>& rxFrame
)
405 static WeakReference
<frame::XModuleManager2
> xWeakRef
;
406 css::uno::Reference
<frame::XModuleManager2
> xRef(xWeakRef
);
410 xRef
= frame::ModuleManager::create(comphelper::getProcessComponentContext());
416 return xRef
->identify(rxFrame
);
418 catch (const Exception
&)
426 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */