/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace css; using namespace css::uno; namespace vcl::CommandInfoProvider { static Reference GetCommandDescription() { static WeakReference xWeakRef; css::uno::Reference xRef(xWeakRef); if (!xRef.is()) { xRef = frame::theUICommandDescription::get(comphelper::getProcessComponentContext()); xWeakRef = xRef; } return xRef; } static Reference GetModuleConfigurationSupplier() { static WeakReference xWeakRef; css::uno::Reference xRef(xWeakRef); if (!xRef.is()) { xRef = ui::theModuleUIConfigurationManagerSupplier::get(comphelper::getProcessComponentContext()); xWeakRef = xRef; } return xRef; } static Reference GetGlobalAcceleratorConfiguration() { static WeakReference xWeakRef; css::uno::Reference xRef(xWeakRef); if (!xRef.is()) { xRef = ui::GlobalAcceleratorConfiguration::create(comphelper::getProcessComponentContext()); xWeakRef = xRef; } return xRef; } static Reference GetDocumentAcceleratorConfiguration(const Reference& rxFrame) { Reference xController = rxFrame->getController(); if (xController.is()) { Reference xSupplier(xController->getModel(), UNO_QUERY); if (xSupplier.is()) { Reference xConfigurationManager( xSupplier->getUIConfigurationManager()); if (xConfigurationManager.is()) { return xConfigurationManager->getShortCutManager(); } } } return nullptr; } static Reference GetModuleAcceleratorConfiguration(const Reference& rxFrame) { css::uno::Reference curModuleAcceleratorConfiguration; try { Reference xSupplier(GetModuleConfigurationSupplier()); Reference xManager ( xSupplier->getUIConfigurationManager(GetModuleIdentifier(rxFrame))); if (xManager.is()) { curModuleAcceleratorConfiguration = xManager->getShortCutManager(); } } catch (Exception&) { } return curModuleAcceleratorConfiguration; } static vcl::KeyCode AWTKey2VCLKey(const awt::KeyEvent& aAWTKey) { bool bShift = ((aAWTKey.Modifiers & awt::KeyModifier::SHIFT) == awt::KeyModifier::SHIFT ); bool bMod1 = ((aAWTKey.Modifiers & awt::KeyModifier::MOD1 ) == awt::KeyModifier::MOD1 ); bool bMod2 = ((aAWTKey.Modifiers & awt::KeyModifier::MOD2 ) == awt::KeyModifier::MOD2 ); bool bMod3 = ((aAWTKey.Modifiers & awt::KeyModifier::MOD3 ) == awt::KeyModifier::MOD3 ); sal_uInt16 nKey = static_cast(aAWTKey.KeyCode); return vcl::KeyCode(nKey, bShift, bMod1, bMod2, bMod3); } static OUString RetrieveShortcutsFromConfiguration( const Reference& rxConfiguration, const OUString& rsCommandName) { if (rxConfiguration.is()) { try { Sequence aCommands { rsCommandName }; Sequence aKeyCodes (rxConfiguration->getPreferredKeyEventsForCommandList(aCommands)); if (aCommands.getLength() == 1) { awt::KeyEvent aKeyEvent; if (aKeyCodes[0] >>= aKeyEvent) { return AWTKey2VCLKey(aKeyEvent).GetName(); } } } catch (css::lang::IllegalArgumentException&) { } } return OUString(); } static vcl::KeyCode RetrieveKeyCodeShortcutsFromConfiguration( const Reference& rxConfiguration, const OUString& rsCommandName) { if (rxConfiguration.is()) { try { Sequence aCommands { rsCommandName }; Sequence aKeyCodes (rxConfiguration->getPreferredKeyEventsForCommandList(aCommands)); if (aCommands.getLength() == 1) { awt::KeyEvent aKeyEvent; if (aKeyCodes[0] >>= aKeyEvent) { return AWTKey2VCLKey(aKeyEvent); } } } catch (css::lang::IllegalArgumentException&) { } } return vcl::KeyCode(); } static bool ResourceHasKey(const OUString& rsResourceName, const OUString& rsCommandName, const OUString& rsModuleName) { Sequence< OUString > aSequence; try { if (!rsModuleName.isEmpty()) { Reference xNameAccess(GetCommandDescription()); Reference xUICommandLabels; if (xNameAccess->getByName(rsModuleName) >>= xUICommandLabels) { xUICommandLabels->getByName(rsResourceName) >>= aSequence; if (comphelper::findValue(aSequence, rsCommandName) != -1) return true; } } } catch (Exception&) { } return false; } Sequence GetCommandProperties(const OUString& rsCommandName, const OUString& rsModuleName) { Sequence aProperties; try { if (!rsModuleName.isEmpty()) { Reference xNameAccess(GetCommandDescription()); Reference xUICommandLabels; if ((xNameAccess->getByName(rsModuleName) >>= xUICommandLabels) && xUICommandLabels->hasByName(rsCommandName)) xUICommandLabels->getByName(rsCommandName) >>= aProperties; } } catch (Exception&) { } return aProperties; } static OUString GetCommandProperty(const OUString& rsProperty, const Sequence &rProperties) { auto pProp = std::find_if(rProperties.begin(), rProperties.end(), [&rsProperty](const beans::PropertyValue& rProp) { return rProp.Name == rsProperty; }); if (pProp != rProperties.end()) { OUString sLabel; pProp->Value >>= sLabel; return sLabel; } return OUString(); } OUString GetLabelForCommand(const css::uno::Sequence& rProperties) { return GetCommandProperty(u"Name"_ustr, rProperties); } OUString GetMenuLabelForCommand(const css::uno::Sequence& rProperties) { // Here we want to use "Label", not "Name". "Name" is a stripped-down version of "Label" without accelerators // and ellipsis. In the menu, we want to have those accelerators and ellipsis. return GetCommandProperty(u"Label"_ustr, rProperties); } OUString GetPopupLabelForCommand(const css::uno::Sequence& rProperties) { OUString sPopupLabel(GetCommandProperty(u"PopupLabel"_ustr, rProperties)); if (!sPopupLabel.isEmpty()) return sPopupLabel; return GetCommandProperty(u"Label"_ustr, rProperties); } OUString GetTooltipLabelForCommand(const css::uno::Sequence& rProperties) { OUString sLabel(GetCommandProperty(u"TooltipLabel"_ustr, rProperties)); if (!sLabel.isEmpty()) return sLabel; return GetCommandProperty(u"Label"_ustr, rProperties); } OUString GetTooltipForCommand( const OUString& rsCommandName, const css::uno::Sequence& rProperties, const Reference& rxFrame) { OUString sLabel(GetCommandProperty(u"TooltipLabel"_ustr, rProperties)); if (sLabel.isEmpty()) { sLabel = GetPopupLabelForCommand(rProperties); // Remove '...' at the end and mnemonics (we don't want those in tooltips) sLabel = comphelper::string::stripEnd(sLabel, '.'); sLabel = MnemonicGenerator::EraseAllMnemonicChars(sLabel); } // Command can be just an alias to another command, // so need to get the shortcut of the "real" command. const OUString sRealCommand(GetRealCommandForCommand(rProperties)); const OUString sShortCut(GetCommandShortcut(!sRealCommand.isEmpty() ? sRealCommand : rsCommandName, rxFrame)); if (!sShortCut.isEmpty()) return sLabel + " (" + sShortCut + ")"; return sLabel; } OUString GetCommandShortcut (const OUString& rsCommandName, const Reference& rxFrame) { OUString sShortcut; sShortcut = RetrieveShortcutsFromConfiguration(GetDocumentAcceleratorConfiguration(rxFrame), rsCommandName); if (sShortcut.getLength() > 0) return sShortcut; sShortcut = RetrieveShortcutsFromConfiguration(GetModuleAcceleratorConfiguration(rxFrame), rsCommandName); if (sShortcut.getLength() > 0) return sShortcut; sShortcut = RetrieveShortcutsFromConfiguration(GetGlobalAcceleratorConfiguration(), rsCommandName); if (sShortcut.getLength() > 0) return sShortcut; return OUString(); } vcl::KeyCode GetCommandKeyCodeShortcut (const OUString& rsCommandName, const Reference& rxFrame) { vcl::KeyCode aKeyCodeShortcut; aKeyCodeShortcut = RetrieveKeyCodeShortcutsFromConfiguration(GetDocumentAcceleratorConfiguration(rxFrame), rsCommandName); if (aKeyCodeShortcut.GetCode()) return aKeyCodeShortcut; aKeyCodeShortcut = RetrieveKeyCodeShortcutsFromConfiguration(GetModuleAcceleratorConfiguration(rxFrame), rsCommandName); if (aKeyCodeShortcut.GetCode()) return aKeyCodeShortcut; aKeyCodeShortcut = RetrieveKeyCodeShortcutsFromConfiguration(GetGlobalAcceleratorConfiguration(), rsCommandName); if (aKeyCodeShortcut.GetCode()) return aKeyCodeShortcut; return vcl::KeyCode(); } OUString GetRealCommandForCommand(const css::uno::Sequence& rProperties) { return GetCommandProperty(u"TargetURL"_ustr, rProperties); } Reference GetXGraphicForCommand(const OUString& rsCommandName, const Reference& rxFrame, vcl::ImageType eImageType) { if (rsCommandName.isEmpty()) return nullptr; sal_Int16 nImageType(ui::ImageType::COLOR_NORMAL | ui::ImageType::SIZE_DEFAULT); if (eImageType == vcl::ImageType::Size26) nImageType |= ui::ImageType::SIZE_LARGE; else if (eImageType == vcl::ImageType::Size32) nImageType |= ui::ImageType::SIZE_32; try { Reference xController(rxFrame->getController(), UNO_SET_THROW); Reference xSupplier(xController->getModel(), UNO_QUERY); if (xSupplier.is()) { Reference xDocUICfgMgr(xSupplier->getUIConfigurationManager()); Reference xDocImgMgr(xDocUICfgMgr->getImageManager(), UNO_QUERY); Sequence aImageCmdSeq { rsCommandName }; Sequence> aGraphicSeq = xDocImgMgr->getImages(nImageType, aImageCmdSeq); Reference xGraphic = aGraphicSeq[0]; if (xGraphic.is()) return xGraphic; } } catch (Exception&) { } try { Reference xModuleCfgMgrSupplier(GetModuleConfigurationSupplier()); Reference xUICfgMgr(xModuleCfgMgrSupplier->getUIConfigurationManager(GetModuleIdentifier(rxFrame))); Reference xModuleImageManager(xUICfgMgr->getImageManager(), UNO_QUERY); Sequence aImageCmdSeq { rsCommandName }; Sequence> aGraphicSeq = xModuleImageManager->getImages(nImageType, aImageCmdSeq); Reference xGraphic(aGraphicSeq[0]); return xGraphic; } catch (Exception&) { } return nullptr; } Image GetImageForCommand(const OUString& rsCommandName, const Reference& rxFrame, vcl::ImageType eImageType) { return Image(GetXGraphicForCommand(rsCommandName, rxFrame, eImageType)); } sal_Int32 GetPropertiesForCommand ( const OUString& rsCommandName, const OUString& rsModuleName) { sal_Int32 nValue = 0; const Sequence aProperties (GetCommandProperties(rsCommandName, rsModuleName)); auto pProp = std::find_if(aProperties.begin(), aProperties.end(), [](const beans::PropertyValue& rProp) { return rProp.Name == "Properties"; }); if (pProp != aProperties.end()) pProp->Value >>= nValue; return nValue; } bool IsRotated(const OUString& rsCommandName, const OUString& rsModuleName) { return ResourceHasKey(u"private:resource/image/commandrotateimagelist"_ustr, rsCommandName, rsModuleName); } bool IsMirrored(const OUString& rsCommandName, const OUString& rsModuleName) { return ResourceHasKey(u"private:resource/image/commandmirrorimagelist"_ustr, rsCommandName, rsModuleName); } bool IsExperimental(const OUString& rsCommandName, const OUString& rModuleName) { Sequence aProperties; try { if( rModuleName.getLength() > 0) { Reference xNameAccess(GetCommandDescription()); Reference xUICommandLabels; if (xNameAccess->getByName( rModuleName ) >>= xUICommandLabels ) xUICommandLabels->getByName(rsCommandName) >>= aProperties; auto pProp = std::find_if(std::cbegin(aProperties), std::cend(aProperties), [](const beans::PropertyValue& rProp) { return rProp.Name == "IsExperimental"; }); if (pProp != std::cend(aProperties)) { bool bValue; return (pProp->Value >>= bValue) && bValue; } } } catch (Exception&) { } return false; } OUString GetModuleIdentifier(const Reference& rxFrame) { static WeakReference xWeakRef; css::uno::Reference xRef(xWeakRef); if (!xRef.is()) { xRef = frame::ModuleManager::create(comphelper::getProcessComponentContext()); xWeakRef = xRef; } try { return xRef->identify(rxFrame); } catch (const Exception&) {} return OUString(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */