bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / helper / commandinfoprovider.cxx
blob234a73eb29496fd22114d9ecd8d78a12ff554f35
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
38 using namespace css;
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);
48 if (!xRef.is())
50 xRef = frame::theUICommandDescription::get(comphelper::getProcessComponentContext());
51 xWeakRef = xRef;
54 return xRef;
57 static Reference<ui::XModuleUIConfigurationManagerSupplier> GetModuleConfigurationSupplier()
59 static WeakReference<ui::XModuleUIConfigurationManagerSupplier> xWeakRef;
60 css::uno::Reference<ui::XModuleUIConfigurationManagerSupplier> xRef(xWeakRef);
62 if (!xRef.is())
64 xRef = ui::theModuleUIConfigurationManagerSupplier::get(comphelper::getProcessComponentContext());
65 xWeakRef = xRef;
68 return xRef;
71 static Reference<ui::XAcceleratorConfiguration> GetGlobalAcceleratorConfiguration()
73 static WeakReference<ui::XAcceleratorConfiguration> xWeakRef;
74 css::uno::Reference<ui::XAcceleratorConfiguration> xRef(xWeakRef);
76 if (!xRef.is())
78 xRef = ui::GlobalAcceleratorConfiguration::create(comphelper::getProcessComponentContext());
79 xWeakRef = xRef;
82 return xRef;
85 static Reference<ui::XAcceleratorConfiguration> GetDocumentAcceleratorConfiguration(const Reference<frame::XFrame>& rxFrame)
87 Reference<frame::XController> xController = rxFrame->getController();
88 if (xController.is())
90 Reference<ui::XUIConfigurationManagerSupplier> xSupplier(xController->getModel(), UNO_QUERY);
91 if (xSupplier.is())
93 Reference<ui::XUIConfigurationManager> xConfigurationManager(
94 xSupplier->getUIConfigurationManager());
95 if (xConfigurationManager.is())
97 return xConfigurationManager->getShortCutManager();
101 return nullptr;
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)));
112 if (xManager.is())
114 curModuleAcceleratorConfiguration = xManager->getShortCutManager();
117 catch (Exception&)
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&)
158 return OUString();
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)
174 return true;
178 catch (Exception&)
181 return false;
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;
198 catch (Exception&)
202 return 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())
211 OUString sLabel;
212 pProp->Value >>= sLabel;
213 return sLabel;
215 return OUString();
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())
234 return sPopupLabel;
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 + ")";
257 return sLabel;
260 OUString GetCommandShortcut (const OUString& rsCommandName,
261 const Reference<frame::XFrame>& rxFrame)
264 OUString sShortcut;
266 sShortcut = RetrieveShortcutsFromConfiguration(GetDocumentAcceleratorConfiguration(rxFrame), rsCommandName);
267 if (sShortcut.getLength() > 0)
268 return sShortcut;
270 sShortcut = RetrieveShortcutsFromConfiguration(GetModuleAcceleratorConfiguration(rxFrame), rsCommandName);
271 if (sShortcut.getLength() > 0)
272 return sShortcut;
274 sShortcut = RetrieveShortcutsFromConfiguration(GetGlobalAcceleratorConfiguration(), rsCommandName);
275 if (sShortcut.getLength() > 0)
276 return sShortcut;
278 return OUString();
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())
291 return nullptr;
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);
304 if (xSupplier.is())
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];
314 if (xGraphic.is())
315 return xGraphic;
318 catch (Exception&)
322 try {
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]);
335 return xGraphic;
337 catch (Exception&)
341 return nullptr;
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;
363 return 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())
392 bool bValue;
393 return (pProp->Value >>= bValue) && bValue;
397 catch (Exception&)
400 return false;
403 OUString GetModuleIdentifier(const Reference<frame::XFrame>& rxFrame)
405 static WeakReference<frame::XModuleManager2> xWeakRef;
406 css::uno::Reference<frame::XModuleManager2> xRef(xWeakRef);
408 if (!xRef.is())
410 xRef = frame::ModuleManager::create(comphelper::getProcessComponentContext());
411 xWeakRef = xRef;
416 return xRef->identify(rxFrame);
418 catch (const Exception&)
421 return OUString();
426 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */