build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / helper / commandinfoprovider.cxx
blobe48367cc0b1ec567db277acebca09e616e75da38
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/mnemonic.hxx>
22 #include <comphelper/string.hxx>
23 #include <comphelper/processfactory.hxx>
24 #include <cppuhelper/compbase.hxx>
25 #include <cppuhelper/basemutex.hxx>
27 #include <com/sun/star/frame/ModuleManager.hpp>
28 #include <com/sun/star/frame/theUICommandDescription.hpp>
29 #include <com/sun/star/ui/GlobalAcceleratorConfiguration.hpp>
30 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
31 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
32 #include <com/sun/star/ui/ImageType.hpp>
33 #include <com/sun/star/ui/XImageManager.hpp>
34 #include <com/sun/star/awt/KeyModifier.hpp>
36 #include "svdata.hxx"
38 using namespace css;
39 using namespace css::uno;
42 namespace
44 typedef ::cppu::WeakComponentImplHelper <
45 css::frame::XFrameActionListener
46 > FrameListenerInterfaceBase;
47 class FrameListener
48 : public ::cppu::BaseMutex,
49 public FrameListenerInterfaceBase
51 public:
52 FrameListener (vcl::CommandInfoProvider& rInfoProvider, const Reference<frame::XFrame>& rxFrame)
53 : FrameListenerInterfaceBase(m_aMutex),
54 mrInfoProvider(rInfoProvider),
55 mxFrame(rxFrame)
57 if (mxFrame.is())
58 mxFrame->addFrameActionListener(this);
61 virtual void SAL_CALL frameAction(const css::frame::FrameActionEvent& aEvent)
62 throw (css::uno::RuntimeException, std::exception) override
64 // The same frame can be reused for a different component, e.g.
65 // starting component from the start center, so need to re-init the cached data.
66 if (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING)
67 mrInfoProvider.SetFrame(nullptr);
69 virtual void SAL_CALL disposing() override
71 if (mxFrame.is())
72 mxFrame->removeFrameActionListener(this);
74 virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
75 throw (RuntimeException, std::exception) override
77 (void)rEvent;
78 mrInfoProvider.SetFrame(nullptr);
79 mxFrame = nullptr;
82 private:
83 vcl::CommandInfoProvider& mrInfoProvider;
84 Reference<frame::XFrame> mxFrame;
88 namespace vcl {
90 CommandInfoProvider& CommandInfoProvider::Instance()
92 static CommandInfoProvider aProvider;
93 return aProvider;
96 CommandInfoProvider::CommandInfoProvider()
97 : mxContext(comphelper::getProcessComponentContext()),
98 mxCachedDataFrame(),
99 mxCachedDocumentAcceleratorConfiguration(),
100 mxCachedModuleAcceleratorConfiguration(),
101 mxCachedGlobalAcceleratorConfiguration(),
102 msCachedModuleIdentifier(),
103 mxFrameListener()
105 ImplGetSVData()->mpCommandInfoProvider = this;
108 void CommandInfoProvider::dispose()
110 if (mxFrameListener.is())
112 mxFrameListener->dispose();
113 mxFrameListener.clear();
115 mxCachedGlobalAcceleratorConfiguration.clear();
116 mxCachedModuleAcceleratorConfiguration.clear();
117 mxCachedDocumentAcceleratorConfiguration.clear();
118 mxCachedDataFrame.clear();
119 mxContext.clear();
122 CommandInfoProvider::~CommandInfoProvider()
124 dispose();
127 OUString CommandInfoProvider::GetLabelForCommand (
128 const OUString& rsCommandName,
129 const Reference<frame::XFrame>& rxFrame)
131 SetFrame(rxFrame);
133 return GetCommandProperty("Name", rsCommandName);
136 OUString CommandInfoProvider::GetMenuLabelForCommand (
137 const OUString& rsCommandName,
138 const Reference<frame::XFrame>& rxFrame)
140 SetFrame(rxFrame);
142 // Here we want to use "Label", not "Name". "Name" is a stripped-down version of "Label" without accelerators
143 // and ellipsis. In the menu, we want to have those accelerators and ellipsis.
144 return GetCommandProperty("Label", rsCommandName);
147 OUString CommandInfoProvider::GetPopupLabelForCommand (
148 const OUString& rsCommandName,
149 const css::uno::Reference<css::frame::XFrame>& rxFrame)
151 SetFrame(rxFrame);
153 OUString sPopupLabel(GetCommandProperty("PopupLabel", rsCommandName));
154 if (!sPopupLabel.isEmpty())
155 return sPopupLabel;
156 return GetCommandProperty("Label", rsCommandName);
159 OUString CommandInfoProvider::GetTooltipForCommand (
160 const OUString& rsCommandName,
161 const Reference<frame::XFrame>& rxFrame)
163 SetFrame(rxFrame);
165 OUString sLabel (GetCommandProperty("TooltipLabel", rsCommandName));
166 if (sLabel.isEmpty()) {
167 sLabel = GetPopupLabelForCommand(rsCommandName, rxFrame);
168 // Remove '...' at the end and mnemonics (we don't want those in tooltips)
169 sLabel = comphelper::string::stripEnd(sLabel, '.');
170 sLabel = MnemonicGenerator::EraseAllMnemonicChars(sLabel);
173 // Command can be just an alias to another command,
174 // so need to get the shortcut of the "real" command.
175 const OUString sRealCommand(GetRealCommandForCommand(rsCommandName, rxFrame));
176 const OUString sShortCut(GetCommandShortcut(!sRealCommand.isEmpty() ? sRealCommand : rsCommandName, rxFrame));
177 if (!sShortCut.isEmpty())
178 return sLabel + " (" + sShortCut + ")";
179 return sLabel;
182 OUString CommandInfoProvider::GetCommandShortcut (const OUString& rsCommandName,
183 const Reference<frame::XFrame>& rxFrame)
185 SetFrame(rxFrame);
187 OUString sShortcut;
189 sShortcut = RetrieveShortcutsFromConfiguration(GetDocumentAcceleratorConfiguration(), rsCommandName);
190 if (sShortcut.getLength() > 0)
191 return sShortcut;
193 sShortcut = RetrieveShortcutsFromConfiguration(GetModuleAcceleratorConfiguration(), rsCommandName);
194 if (sShortcut.getLength() > 0)
195 return sShortcut;
197 sShortcut = RetrieveShortcutsFromConfiguration(GetGlobalAcceleratorConfiguration(), rsCommandName);
198 if (sShortcut.getLength() > 0)
199 return sShortcut;
201 return OUString();
204 OUString CommandInfoProvider::GetRealCommandForCommand(const OUString& rCommandName,
205 const css::uno::Reference<frame::XFrame>& rxFrame)
207 SetFrame(rxFrame);
209 return GetCommandProperty("TargetURL", rCommandName);
212 Image CommandInfoProvider::GetImageForCommand(const OUString& rsCommandName,
213 const Reference<frame::XFrame>& rxFrame,
214 vcl::ImageType eImageType)
216 SetFrame(rxFrame);
218 if (rsCommandName.isEmpty())
219 return Image();
221 sal_Int16 nImageType(ui::ImageType::COLOR_NORMAL | ui::ImageType::SIZE_DEFAULT);
223 if (eImageType == vcl::ImageType::Size26)
224 nImageType |= ui::ImageType::SIZE_LARGE;
225 else if (eImageType == vcl::ImageType::Size32)
226 nImageType |= ui::ImageType::SIZE_32;
230 Reference<frame::XController> xController(rxFrame->getController());
231 Reference<frame::XModel> xModel(xController->getModel());
233 Reference<ui::XUIConfigurationManagerSupplier> xSupplier(xModel, UNO_QUERY);
234 if (xSupplier.is())
236 Reference<ui::XUIConfigurationManager> xDocUICfgMgr(xSupplier->getUIConfigurationManager(), UNO_QUERY);
237 Reference<ui::XImageManager> xDocImgMgr(xDocUICfgMgr->getImageManager(), UNO_QUERY);
239 Sequence< Reference<graphic::XGraphic> > aGraphicSeq;
240 Sequence<OUString> aImageCmdSeq { rsCommandName };
242 aGraphicSeq = xDocImgMgr->getImages( nImageType, aImageCmdSeq );
243 Reference<graphic::XGraphic> xGraphic = aGraphicSeq[0];
244 Image aImage(xGraphic);
246 if (!!aImage)
247 return aImage;
250 catch (Exception&)
254 try {
255 Reference<ui::XModuleUIConfigurationManagerSupplier> xModuleCfgMgrSupplier(ui::theModuleUIConfigurationManagerSupplier::get(mxContext));
256 Reference<ui::XUIConfigurationManager> xUICfgMgr(xModuleCfgMgrSupplier->getUIConfigurationManager(GetModuleIdentifier()));
258 Sequence< Reference<graphic::XGraphic> > aGraphicSeq;
259 Reference<ui::XImageManager> xModuleImageManager(xUICfgMgr->getImageManager(), UNO_QUERY);
261 Sequence<OUString> aImageCmdSeq { rsCommandName };
263 aGraphicSeq = xModuleImageManager->getImages(nImageType, aImageCmdSeq);
265 Reference<graphic::XGraphic> xGraphic(aGraphicSeq[0]);
267 return Image(xGraphic);
269 catch (Exception&)
273 return Image();
276 sal_Int32 CommandInfoProvider::GetPropertiesForCommand (
277 const OUString& rsCommandName,
278 const Reference<frame::XFrame>& rxFrame)
280 SetFrame(rxFrame);
282 sal_Int32 nValue = 0;
283 const Sequence<beans::PropertyValue> aProperties (GetCommandProperties(rsCommandName));
284 for (sal_Int32 nIndex=0; nIndex<aProperties.getLength(); ++nIndex)
286 if (aProperties[nIndex].Name == "Properties")
288 aProperties[nIndex].Value >>= nValue;
289 break;
292 return nValue;
295 bool CommandInfoProvider::IsRotated(const OUString& rsCommandName)
297 return ResourceHasKey("private:resource/image/commandrotateimagelist", rsCommandName);
300 bool CommandInfoProvider::IsMirrored(const OUString& rsCommandName)
302 return ResourceHasKey("private:resource/image/commandmirrorimagelist", rsCommandName);
305 bool CommandInfoProvider::IsExperimental(const OUString& rsCommandName,
306 const OUString& rModuleName)
308 Sequence<beans::PropertyValue> aProperties;
311 if( rModuleName.getLength() > 0)
313 Reference<container::XNameAccess> xNameAccess = frame::theUICommandDescription::get(mxContext);
314 Reference<container::XNameAccess> xUICommandLabels;
315 if (xNameAccess->getByName( rModuleName ) >>= xUICommandLabels )
316 xUICommandLabels->getByName(rsCommandName) >>= aProperties;
318 for (sal_Int32 nIndex=0; nIndex<aProperties.getLength(); ++nIndex)
320 if (aProperties[nIndex].Name == "IsExperimental")
322 bool bValue;
323 return (aProperties[nIndex].Value >>= bValue) && bValue;
328 catch (Exception&)
331 return false;
334 void CommandInfoProvider::SetFrame (const Reference<frame::XFrame>& rxFrame)
336 if (rxFrame != mxCachedDataFrame)
338 // Detach from the old frame.
339 if (mxFrameListener.is())
341 mxFrameListener->dispose();
342 mxFrameListener = nullptr;
345 // Release objects that are tied to the old frame.
346 mxCachedDocumentAcceleratorConfiguration = nullptr;
347 mxCachedModuleAcceleratorConfiguration = nullptr;
348 msCachedModuleIdentifier.clear();
349 mxCachedDataFrame = rxFrame;
351 // Connect to the new frame.
352 if (rxFrame.is())
353 mxFrameListener = new FrameListener(*this, rxFrame);
357 Reference<ui::XAcceleratorConfiguration> const & CommandInfoProvider::GetDocumentAcceleratorConfiguration()
359 if ( ! mxCachedDocumentAcceleratorConfiguration.is())
361 // Get the accelerator configuration for the document.
362 if (mxCachedDataFrame.is())
364 Reference<frame::XController> xController = mxCachedDataFrame->getController();
365 if (xController.is())
367 Reference<frame::XModel> xModel (xController->getModel());
368 if (xModel.is())
370 Reference<ui::XUIConfigurationManagerSupplier> xSupplier (xModel, UNO_QUERY);
371 if (xSupplier.is())
373 Reference<ui::XUIConfigurationManager> xConfigurationManager(
374 xSupplier->getUIConfigurationManager(),
375 UNO_QUERY);
376 if (xConfigurationManager.is())
378 mxCachedDocumentAcceleratorConfiguration = xConfigurationManager->getShortCutManager();
385 return mxCachedDocumentAcceleratorConfiguration;
388 Reference<ui::XAcceleratorConfiguration> const & CommandInfoProvider::GetModuleAcceleratorConfiguration()
390 if ( ! mxCachedModuleAcceleratorConfiguration.is())
394 Reference<ui::XModuleUIConfigurationManagerSupplier> xSupplier = ui::theModuleUIConfigurationManagerSupplier::get(mxContext);
395 Reference<ui::XUIConfigurationManager> xManager (
396 xSupplier->getUIConfigurationManager(GetModuleIdentifier()));
397 if (xManager.is())
399 mxCachedModuleAcceleratorConfiguration = xManager->getShortCutManager();
402 catch (Exception&)
406 return mxCachedModuleAcceleratorConfiguration;
409 Reference<ui::XAcceleratorConfiguration> const & CommandInfoProvider::GetGlobalAcceleratorConfiguration()
411 // Get the global accelerator configuration.
412 if ( ! mxCachedGlobalAcceleratorConfiguration.is())
414 mxCachedGlobalAcceleratorConfiguration = ui::GlobalAcceleratorConfiguration::create(mxContext);
417 return mxCachedGlobalAcceleratorConfiguration;
420 OUString const & CommandInfoProvider::GetModuleIdentifier()
422 if (msCachedModuleIdentifier.getLength() == 0)
424 Reference<frame::XModuleManager2> xModuleManager = frame::ModuleManager::create(mxContext);
425 msCachedModuleIdentifier = xModuleManager->identify(mxCachedDataFrame);
427 return msCachedModuleIdentifier;
430 OUString CommandInfoProvider::RetrieveShortcutsFromConfiguration(
431 const Reference<ui::XAcceleratorConfiguration>& rxConfiguration,
432 const OUString& rsCommandName)
434 if (rxConfiguration.is())
438 Sequence<OUString> aCommands { rsCommandName };
440 Sequence<Any> aKeyCodes (rxConfiguration->getPreferredKeyEventsForCommandList(aCommands));
441 if (aCommands.getLength() == 1)
443 awt::KeyEvent aKeyEvent;
444 if (aKeyCodes[0] >>= aKeyEvent)
446 return AWTKey2VCLKey(aKeyEvent).GetName();
450 catch (css::lang::IllegalArgumentException&)
454 return OUString();
457 bool CommandInfoProvider::ResourceHasKey(const OUString& rsResourceName, const OUString& rsCommandName)
459 Sequence< OUString > aSequence;
462 const OUString sModuleIdentifier (GetModuleIdentifier());
463 if (!sModuleIdentifier.isEmpty())
465 Reference<container::XNameAccess> xNameAccess = frame::theUICommandDescription::get(mxContext);
466 Reference<container::XNameAccess> xUICommandLabels;
467 if (xNameAccess->getByName(sModuleIdentifier) >>= xUICommandLabels) {
468 xUICommandLabels->getByName(rsResourceName) >>= aSequence;
469 for ( sal_Int32 i = 0; i < aSequence.getLength(); i++ )
471 if (aSequence[i] == rsCommandName)
472 return true;
477 catch (Exception&)
480 return false;
483 Sequence<beans::PropertyValue> CommandInfoProvider::GetCommandProperties(const OUString& rsCommandName)
485 Sequence<beans::PropertyValue> aProperties;
489 const OUString sModuleIdentifier (GetModuleIdentifier());
490 if (sModuleIdentifier.getLength() > 0)
492 Reference<container::XNameAccess> xNameAccess = frame::theUICommandDescription::get(mxContext);
493 Reference<container::XNameAccess> xUICommandLabels;
494 if (xNameAccess->getByName(sModuleIdentifier) >>= xUICommandLabels)
495 xUICommandLabels->getByName(rsCommandName) >>= aProperties;
498 catch (Exception&)
502 return aProperties;
505 OUString CommandInfoProvider::GetCommandProperty(const OUString& rsProperty, const OUString& rsCommandName)
507 const Sequence<beans::PropertyValue> aProperties (GetCommandProperties(rsCommandName));
508 for (sal_Int32 nIndex=0; nIndex<aProperties.getLength(); ++nIndex)
510 if (aProperties[nIndex].Name == rsProperty)
512 OUString sLabel;
513 aProperties[nIndex].Value >>= sLabel;
514 return sLabel;
517 return OUString();
520 OUString CommandInfoProvider::GetCommandPropertyFromModule( const OUString& rCommandName, const OUString& rModuleName )
522 OUString sLabel;
523 if ( rCommandName.isEmpty() )
524 return sLabel;
526 Sequence<beans::PropertyValue> aProperties;
529 if( rModuleName.getLength() > 0)
531 Reference<container::XNameAccess> xNameAccess = frame::theUICommandDescription::get(mxContext);
532 Reference<container::XNameAccess> xUICommandLabels;
533 if (xNameAccess->getByName( rModuleName ) >>= xUICommandLabels )
534 xUICommandLabels->getByName(rCommandName) >>= aProperties;
536 for (sal_Int32 nIndex=0; nIndex<aProperties.getLength(); ++nIndex)
538 if(aProperties[nIndex].Name == "Label")
540 aProperties[nIndex].Value >>= sLabel;
541 return sLabel;
546 catch (Exception&)
549 return OUString();
552 vcl::KeyCode CommandInfoProvider::AWTKey2VCLKey(const awt::KeyEvent& aAWTKey)
554 bool bShift = ((aAWTKey.Modifiers & awt::KeyModifier::SHIFT) == awt::KeyModifier::SHIFT );
555 bool bMod1 = ((aAWTKey.Modifiers & awt::KeyModifier::MOD1 ) == awt::KeyModifier::MOD1 );
556 bool bMod2 = ((aAWTKey.Modifiers & awt::KeyModifier::MOD2 ) == awt::KeyModifier::MOD2 );
557 bool bMod3 = ((aAWTKey.Modifiers & awt::KeyModifier::MOD3 ) == awt::KeyModifier::MOD3 );
558 sal_uInt16 nKey = (sal_uInt16)aAWTKey.KeyCode;
560 return vcl::KeyCode(nKey, bShift, bMod1, bMod2, bMod3);
564 } // end of namespace vcl
566 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */