LibreOffice Module vcl (master)  1
commandinfoprovider.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
21 #include <vcl/keycod.hxx>
22 #include <vcl/mnemonic.hxx>
23 #include <comphelper/string.hxx>
24 #include <comphelper/sequence.hxx>
26 #include <cppuhelper/weakref.hxx>
27 
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>
37 
38 using namespace css;
39 using namespace css::uno;
40 
42 
44 {
45  static WeakReference<container::XNameAccess> xWeakRef;
46  css::uno::Reference<container::XNameAccess> xRef(xWeakRef);
47 
48  if (!xRef.is())
49  {
50  xRef = frame::theUICommandDescription::get(comphelper::getProcessComponentContext());
51  xWeakRef = xRef;
52  }
53 
54  return xRef;
55 }
56 
57 static Reference<ui::XModuleUIConfigurationManagerSupplier> GetModuleConfigurationSupplier()
58 {
59  static WeakReference<ui::XModuleUIConfigurationManagerSupplier> xWeakRef;
60  css::uno::Reference<ui::XModuleUIConfigurationManagerSupplier> xRef(xWeakRef);
61 
62  if (!xRef.is())
63  {
64  xRef = ui::theModuleUIConfigurationManagerSupplier::get(comphelper::getProcessComponentContext());
65  xWeakRef = xRef;
66  }
67 
68  return xRef;
69 }
70 
71 static Reference<ui::XAcceleratorConfiguration> GetGlobalAcceleratorConfiguration()
72 {
73  static WeakReference<ui::XAcceleratorConfiguration> xWeakRef;
74  css::uno::Reference<ui::XAcceleratorConfiguration> xRef(xWeakRef);
75 
76  if (!xRef.is())
77  {
78  xRef = ui::GlobalAcceleratorConfiguration::create(comphelper::getProcessComponentContext());
79  xWeakRef = xRef;
80  }
81 
82  return xRef;
83 }
84 
85 static Reference<ui::XAcceleratorConfiguration> GetDocumentAcceleratorConfiguration(const Reference<frame::XFrame>& rxFrame)
86 {
87  Reference<frame::XController> xController = rxFrame->getController();
88  if (xController.is())
89  {
90  Reference<ui::XUIConfigurationManagerSupplier> xSupplier(xController->getModel(), UNO_QUERY);
91  if (xSupplier.is())
92  {
93  Reference<ui::XUIConfigurationManager> xConfigurationManager(
94  xSupplier->getUIConfigurationManager());
95  if (xConfigurationManager.is())
96  {
97  return xConfigurationManager->getShortCutManager();
98  }
99  }
100  }
101  return nullptr;
102 }
103 
104 static Reference<ui::XAcceleratorConfiguration> GetModuleAcceleratorConfiguration(const Reference<frame::XFrame>& rxFrame)
105 {
106  css::uno::Reference<css::ui::XAcceleratorConfiguration> curModuleAcceleratorConfiguration;
107  try
108  {
109  Reference<ui::XModuleUIConfigurationManagerSupplier> xSupplier(GetModuleConfigurationSupplier());
110  Reference<ui::XUIConfigurationManager> xManager (
111  xSupplier->getUIConfigurationManager(GetModuleIdentifier(rxFrame)));
112  if (xManager.is())
113  {
114  curModuleAcceleratorConfiguration = xManager->getShortCutManager();
115  }
116  }
117  catch (Exception&)
118  {
119  }
120  return curModuleAcceleratorConfiguration;
121 }
122 
123 static vcl::KeyCode AWTKey2VCLKey(const awt::KeyEvent& aAWTKey)
124 {
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);
130 
131  return vcl::KeyCode(nKey, bShift, bMod1, bMod2, bMod3);
132 }
133 
135  const Reference<ui::XAcceleratorConfiguration>& rxConfiguration,
136  const OUString& rsCommandName)
137 {
138  if (rxConfiguration.is())
139  {
140  try
141  {
142  Sequence<OUString> aCommands { rsCommandName };
143 
144  Sequence<Any> aKeyCodes (rxConfiguration->getPreferredKeyEventsForCommandList(aCommands));
145  if (aCommands.getLength() == 1)
146  {
147  awt::KeyEvent aKeyEvent;
148  if (aKeyCodes[0] >>= aKeyEvent)
149  {
150  return AWTKey2VCLKey(aKeyEvent).GetName();
151  }
152  }
153  }
154  catch (css::lang::IllegalArgumentException&)
155  {
156  }
157  }
158  return OUString();
159 }
160 
162  const Reference<ui::XAcceleratorConfiguration>& rxConfiguration,
163  const OUString& rsCommandName)
164 {
165  if (rxConfiguration.is())
166  {
167  try
168  {
169  Sequence<OUString> aCommands { rsCommandName };
170 
171  Sequence<Any> aKeyCodes (rxConfiguration->getPreferredKeyEventsForCommandList(aCommands));
172  if (aCommands.getLength() == 1)
173  {
174  awt::KeyEvent aKeyEvent;
175  if (aKeyCodes[0] >>= aKeyEvent)
176  {
177  return AWTKey2VCLKey(aKeyEvent);
178  }
179  }
180  }
181  catch (css::lang::IllegalArgumentException&)
182  {
183  }
184  }
185  return vcl::KeyCode();
186 }
187 
188 static bool ResourceHasKey(const OUString& rsResourceName, const OUString& rsCommandName, const OUString& rsModuleName)
189 {
190  Sequence< OUString > aSequence;
191  try
192  {
193  if (!rsModuleName.isEmpty())
194  {
196  Reference<container::XNameAccess> xUICommandLabels;
197  if (xNameAccess->getByName(rsModuleName) >>= xUICommandLabels)
198  {
199  xUICommandLabels->getByName(rsResourceName) >>= aSequence;
200  if (comphelper::findValue(aSequence, rsCommandName) != -1)
201  return true;
202  }
203  }
204  }
205  catch (Exception&)
206  {
207  }
208  return false;
209 }
210 
211 Sequence<beans::PropertyValue> GetCommandProperties(const OUString& rsCommandName, const OUString& rsModuleName)
212 {
214 
215  try
216  {
217  if (!rsModuleName.isEmpty())
218  {
220  Reference<container::XNameAccess> xUICommandLabels;
221  if ((xNameAccess->getByName(rsModuleName) >>= xUICommandLabels) && xUICommandLabels->hasByName(rsCommandName))
222  xUICommandLabels->getByName(rsCommandName) >>= aProperties;
223  }
224  }
225  catch (Exception&)
226  {
227  }
228 
229  return aProperties;
230 }
231 
232 static OUString GetCommandProperty(const OUString& rsProperty, const Sequence<beans::PropertyValue> &rProperties)
233 {
234  auto pProp = std::find_if(rProperties.begin(), rProperties.end(),
235  [&rsProperty](const beans::PropertyValue& rProp) { return rProp.Name == rsProperty; });
236  if (pProp != rProperties.end())
237  {
238  OUString sLabel;
239  pProp->Value >>= sLabel;
240  return sLabel;
241  }
242  return OUString();
243 }
244 
245 OUString GetLabelForCommand(const css::uno::Sequence<css::beans::PropertyValue>& rProperties)
246 {
247  return GetCommandProperty("Name", rProperties);
248 }
249 
250 OUString GetMenuLabelForCommand(const css::uno::Sequence<css::beans::PropertyValue>& rProperties)
251 {
252  // Here we want to use "Label", not "Name". "Name" is a stripped-down version of "Label" without accelerators
253  // and ellipsis. In the menu, we want to have those accelerators and ellipsis.
254  return GetCommandProperty("Label", rProperties);
255 }
256 
257 OUString GetPopupLabelForCommand(const css::uno::Sequence<css::beans::PropertyValue>& rProperties)
258 {
259  OUString sPopupLabel(GetCommandProperty("PopupLabel", rProperties));
260  if (!sPopupLabel.isEmpty())
261  return sPopupLabel;
262  return GetCommandProperty("Label", rProperties);
263 }
264 
265 OUString GetTooltipLabelForCommand(const css::uno::Sequence<css::beans::PropertyValue>& rProperties)
266 {
267  OUString sLabel(GetCommandProperty("TooltipLabel", rProperties));
268  if (!sLabel.isEmpty())
269  return sLabel;
270  return GetCommandProperty("Label", rProperties);
271 }
272 
274  const OUString& rsCommandName,
275  const css::uno::Sequence<css::beans::PropertyValue>& rProperties,
276  const Reference<frame::XFrame>& rxFrame)
277 {
278  OUString sLabel(GetCommandProperty("TooltipLabel", rProperties));
279  if (sLabel.isEmpty()) {
280  sLabel = GetPopupLabelForCommand(rProperties);
281  // Remove '...' at the end and mnemonics (we don't want those in tooltips)
282  sLabel = comphelper::string::stripEnd(sLabel, '.');
284  }
285 
286  // Command can be just an alias to another command,
287  // so need to get the shortcut of the "real" command.
288  const OUString sRealCommand(GetRealCommandForCommand(rProperties));
289  const OUString sShortCut(GetCommandShortcut(!sRealCommand.isEmpty() ? sRealCommand : rsCommandName, rxFrame));
290  if (!sShortCut.isEmpty())
291  return sLabel + " (" + sShortCut + ")";
292  return sLabel;
293 }
294 
295 OUString GetCommandShortcut (const OUString& rsCommandName,
296  const Reference<frame::XFrame>& rxFrame)
297 {
298 
299  OUString sShortcut;
300 
301  sShortcut = RetrieveShortcutsFromConfiguration(GetDocumentAcceleratorConfiguration(rxFrame), rsCommandName);
302  if (sShortcut.getLength() > 0)
303  return sShortcut;
304 
305  sShortcut = RetrieveShortcutsFromConfiguration(GetModuleAcceleratorConfiguration(rxFrame), rsCommandName);
306  if (sShortcut.getLength() > 0)
307  return sShortcut;
308 
310  if (sShortcut.getLength() > 0)
311  return sShortcut;
312 
313  return OUString();
314 }
315 
316 vcl::KeyCode GetCommandKeyCodeShortcut (const OUString& rsCommandName, const Reference<frame::XFrame>& rxFrame)
317 {
318  vcl::KeyCode aKeyCodeShortcut;
319 
320  aKeyCodeShortcut = RetrieveKeyCodeShortcutsFromConfiguration(GetDocumentAcceleratorConfiguration(rxFrame), rsCommandName);
321  if (aKeyCodeShortcut.GetCode())
322  return aKeyCodeShortcut;
323 
324  aKeyCodeShortcut = RetrieveKeyCodeShortcutsFromConfiguration(GetModuleAcceleratorConfiguration(rxFrame), rsCommandName);
325  if (aKeyCodeShortcut.GetCode())
326  return aKeyCodeShortcut;
327 
329  if (aKeyCodeShortcut.GetCode())
330  return aKeyCodeShortcut;
331 
332  return vcl::KeyCode();
333 }
334 
335 OUString GetRealCommandForCommand(const css::uno::Sequence<css::beans::PropertyValue>& rProperties)
336 {
337  return GetCommandProperty("TargetURL", rProperties);
338 }
339 
340 Reference<graphic::XGraphic> GetXGraphicForCommand(const OUString& rsCommandName,
341  const Reference<frame::XFrame>& rxFrame,
342  vcl::ImageType eImageType)
343 {
344  if (rsCommandName.isEmpty())
345  return nullptr;
346 
347  sal_Int16 nImageType(ui::ImageType::COLOR_NORMAL | ui::ImageType::SIZE_DEFAULT);
348 
349  if (eImageType == vcl::ImageType::Size26)
350  nImageType |= ui::ImageType::SIZE_LARGE;
351  else if (eImageType == vcl::ImageType::Size32)
352  nImageType |= ui::ImageType::SIZE_32;
353 
354  try
355  {
356  Reference<frame::XController> xController(rxFrame->getController(), UNO_SET_THROW);
357  Reference<ui::XUIConfigurationManagerSupplier> xSupplier(xController->getModel(), UNO_QUERY);
358  if (xSupplier.is())
359  {
360  Reference<ui::XUIConfigurationManager> xDocUICfgMgr(xSupplier->getUIConfigurationManager());
361  Reference<ui::XImageManager> xDocImgMgr(xDocUICfgMgr->getImageManager(), UNO_QUERY);
362 
363  Sequence< Reference<graphic::XGraphic> > aGraphicSeq;
364  Sequence<OUString> aImageCmdSeq { rsCommandName };
365 
366  aGraphicSeq = xDocImgMgr->getImages( nImageType, aImageCmdSeq );
367  Reference<graphic::XGraphic> xGraphic = aGraphicSeq[0];
368  if (xGraphic.is())
369  return xGraphic;
370  }
371  }
372  catch (Exception&)
373  {
374  }
375 
376  try {
377  Reference<ui::XModuleUIConfigurationManagerSupplier> xModuleCfgMgrSupplier(GetModuleConfigurationSupplier());
378  Reference<ui::XUIConfigurationManager> xUICfgMgr(xModuleCfgMgrSupplier->getUIConfigurationManager(GetModuleIdentifier(rxFrame)));
379 
380  Sequence< Reference<graphic::XGraphic> > aGraphicSeq;
381  Reference<ui::XImageManager> xModuleImageManager(xUICfgMgr->getImageManager(), UNO_QUERY);
382 
383  Sequence<OUString> aImageCmdSeq { rsCommandName };
384 
385  aGraphicSeq = xModuleImageManager->getImages(nImageType, aImageCmdSeq);
386 
387  Reference<graphic::XGraphic> xGraphic(aGraphicSeq[0]);
388 
389  return xGraphic;
390  }
391  catch (Exception&)
392  {
393  }
394 
395  return nullptr;
396 }
397 
398 Image GetImageForCommand(const OUString& rsCommandName,
399  const Reference<frame::XFrame>& rxFrame,
400  vcl::ImageType eImageType)
401 {
402  return Image(GetXGraphicForCommand(rsCommandName, rxFrame, eImageType));
403 }
404 
406  const OUString& rsCommandName,
407  const OUString& rsModuleName)
408 {
409  sal_Int32 nValue = 0;
410  const Sequence<beans::PropertyValue> aProperties (GetCommandProperties(rsCommandName, rsModuleName));
411 
412  auto pProp = std::find_if(aProperties.begin(), aProperties.end(),
413  [](const beans::PropertyValue& rProp) { return rProp.Name == "Properties"; });
414  if (pProp != aProperties.end())
415  pProp->Value >>= nValue;
416 
417  return nValue;
418 }
419 
420 bool IsRotated(const OUString& rsCommandName, const OUString& rsModuleName)
421 {
422  return ResourceHasKey("private:resource/image/commandrotateimagelist", rsCommandName, rsModuleName);
423 }
424 
425 bool IsMirrored(const OUString& rsCommandName, const OUString& rsModuleName)
426 {
427  return ResourceHasKey("private:resource/image/commandmirrorimagelist", rsCommandName, rsModuleName);
428 }
429 
430 bool IsExperimental(const OUString& rsCommandName, const OUString& rModuleName)
431 {
433  try
434  {
435  if( rModuleName.getLength() > 0)
436  {
438  Reference<container::XNameAccess> xUICommandLabels;
439  if (xNameAccess->getByName( rModuleName ) >>= xUICommandLabels )
440  xUICommandLabels->getByName(rsCommandName) >>= aProperties;
441 
442  auto pProp = std::find_if(aProperties.begin(), aProperties.end(),
443  [](const beans::PropertyValue& rProp) { return rProp.Name == "IsExperimental"; });
444  if (pProp != aProperties.end())
445  {
446  bool bValue;
447  return (pProp->Value >>= bValue) && bValue;
448  }
449  }
450  }
451  catch (Exception&)
452  {
453  }
454  return false;
455 }
456 
457 OUString GetModuleIdentifier(const Reference<frame::XFrame>& rxFrame)
458 {
459  static WeakReference<frame::XModuleManager2> xWeakRef;
460  css::uno::Reference<frame::XModuleManager2> xRef(xWeakRef);
461 
462  if (!xRef.is())
463  {
464  xRef = frame::ModuleManager::create(comphelper::getProcessComponentContext());
465  xWeakRef = xRef;
466  }
467 
468  try
469  {
470  return xRef->identify(rxFrame);
471  }
472  catch (const Exception&)
473  {}
474 
475  return OUString();
476 }
477 
478 }
479 
480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OString stripEnd(const OString &rIn, char c)
static Reference< ui::XModuleUIConfigurationManagerSupplier > GetModuleConfigurationSupplier()
OUString GetTooltipLabelForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
static Reference< ui::XAcceleratorConfiguration > GetGlobalAcceleratorConfiguration()
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
static vcl::KeyCode AWTKey2VCLKey(const awt::KeyEvent &aAWTKey)
OUString GetLabelForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
Return a label for the given command.
OUString GetMenuLabelForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
sal_uInt16 GetCode() const
Definition: keycod.hxx:53
vcl::KeyCode GetCommandKeyCodeShortcut(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame)
static Reference< container::XNameAccess > GetCommandDescription()
bool IsMirrored(const long nPageLeftMargin, const long nPageRightMargin, const long nPageTopMargin, const long nPageBottomMargin, bool bMirrored)
OUString GetRealCommandForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
Reference< XController > xController
PropertiesInfo aProperties
bool IsExperimental(const OUString &rsCommandName, const OUString &rModuleName)
Returns whether the command is experimental.
static bool ResourceHasKey(const OUString &rsResourceName, const OUString &rsCommandName, const OUString &rsModuleName)
static OUString RetrieveShortcutsFromConfiguration(const Reference< ui::XAcceleratorConfiguration > &rxConfiguration, const OUString &rsCommandName)
OUString GetPopupLabelForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
Image GetImageForCommand(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame, vcl::ImageType eImageType)
OUString GetModuleIdentifier(const Reference< frame::XFrame > &rxFrame)
ImageType
Definition: vclenum.hxx:329
Reference< graphic::XGraphic > GetXGraphicForCommand(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame, vcl::ImageType eImageType)
static Reference< ui::XAcceleratorConfiguration > GetModuleAcceleratorConfiguration(const Reference< frame::XFrame > &rxFrame)
static vcl::KeyCode RetrieveKeyCodeShortcutsFromConfiguration(const Reference< ui::XAcceleratorConfiguration > &rxConfiguration, const OUString &rsCommandName)
OUString GetName(vcl::Window *pWindow=nullptr) const
Definition: keycod.cxx:78
static OUString GetCommandProperty(const OUString &rsProperty, const Sequence< beans::PropertyValue > &rProperties)
Sequence< beans::PropertyValue > GetCommandProperties(const OUString &rsCommandName, const OUString &rsModuleName)
Return a label for the given command.
sal_Int32 GetPropertiesForCommand(const OUString &rsCommandName, const OUString &rsModuleName)
Definition: image.hxx:40
Reference< XComponentContext > getProcessComponentContext()
OUString GetCommandShortcut(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame)
static OUString EraseAllMnemonicChars(const OUString &rStr)
Definition: mnemonic.cxx:307
bool IsRotated(const OUString &rsCommandName, const OUString &rsModuleName)
OUString GetTooltipForCommand(const OUString &rsCommandName, const css::uno::Sequence< css::beans::PropertyValue > &rProperties, const Reference< frame::XFrame > &rxFrame)
Reference< XGraphic > xGraphic
sal_Int16 nValue
static Reference< ui::XAcceleratorConfiguration > GetDocumentAcceleratorConfiguration(const Reference< frame::XFrame > &rxFrame)