diff options
Diffstat (limited to 'sfx2/source/sidebar/ResourceManager.cxx')
-rw-r--r-- | sfx2/source/sidebar/ResourceManager.cxx | 806 |
1 files changed, 806 insertions, 0 deletions
diff --git a/sfx2/source/sidebar/ResourceManager.cxx b/sfx2/source/sidebar/ResourceManager.cxx new file mode 100644 index 0000000000..d4e5b97228 --- /dev/null +++ b/sfx2/source/sidebar/ResourceManager.cxx @@ -0,0 +1,806 @@ +/* -*- 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 <sidebar/DeckDescriptor.hxx> +#include <sidebar/PanelDescriptor.hxx> +#include <sfx2/sidebar/ResourceManager.hxx> +#include <sidebar/Tools.hxx> + +#include <officecfg/Office/Common.hxx> +#include <officecfg/Office/UI/Sidebar.hxx> +#include <unotools/confignode.hxx> +#include <comphelper/lok.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> + +#include <comphelper/diagnose_ex.hxx> +#include <sal/log.hxx> +#include <vcl/EnumContext.hxx> +#include <o3tl/string_view.hxx> + +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/ui/XSidebarPanel.hpp> +#include <com/sun/star/ui/XUpdateModel.hpp> + +#include <map> + +using namespace css; +using namespace css::uno; + +namespace sfx2::sidebar { + +namespace +{ + +OUString getString(utl::OConfigurationNode const & aNode, const char* pNodeName) +{ + return comphelper::getString(aNode.getNodeValue(pNodeName)); +} +sal_Int32 getInt32(utl::OConfigurationNode const & aNode, const char* pNodeName) +{ + return comphelper::getINT32(aNode.getNodeValue(pNodeName)); +} +bool getBool(utl::OConfigurationNode const & aNode, const char* pNodeName) +{ + return comphelper::getBOOL(aNode.getNodeValue(pNodeName)); +} + +css::uno::Sequence<OUString> BuildContextList (const ContextList& rContextList) +{ + const ::std::vector<ContextList::Entry>& entries = rContextList.GetEntries(); + + css::uno::Sequence<OUString> result(entries.size()); + auto resultRange = asNonConstRange(result); + tools::Long i = 0; + + for (auto const& entry : entries) + { + OUString appName = entry.maContext.msApplication; + OUString contextName = entry.maContext.msContext; + OUString menuCommand = entry.msMenuCommand; + + OUString visibility; + if (entry.mbIsInitiallyVisible) + visibility = "visible"; + else + visibility = "hidden"; + + OUString element = appName + ", " + contextName +", " + visibility; + + if (!menuCommand.isEmpty()) + element += ", "+menuCommand; + + resultRange[i] = element; + + ++i; + } + + return result; + +} + +} //end anonymous namespace + +ResourceManager::ResourceManager() +{ + ReadDeckList(); + ReadPanelList(); + ReadLastActive(); +} + +ResourceManager::~ResourceManager() +{ +} + +void ResourceManager::InitDeckContext(const Context& rContext) +{ + for (auto const& deck : maDecks) + { + const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext); + + bool bIsEnabled; + if (pMatchingEntry) + bIsEnabled = pMatchingEntry->mbIsInitiallyVisible; + else + bIsEnabled = false; + + deck->mbIsEnabled = bIsEnabled; + } +} + +std::shared_ptr<DeckDescriptor> ResourceManager::ImplGetDeckDescriptor(std::u16string_view rsDeckId) const +{ + for (auto const& deck : maDecks) + { + if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get()) + continue; + if (deck->msId == rsDeckId) + return deck; + } + return nullptr; +} + +std::shared_ptr<DeckDescriptor> ResourceManager::GetDeckDescriptor(std::u16string_view rsDeckId) const +{ + return ImplGetDeckDescriptor( rsDeckId ); +} + +std::shared_ptr<PanelDescriptor> ResourceManager::ImplGetPanelDescriptor(std::u16string_view rsPanelId) const +{ + for (auto const& panel : maPanels) + { + if (panel->msId == rsPanelId) + return panel; + } + return nullptr; +} + +std::shared_ptr<PanelDescriptor> ResourceManager::GetPanelDescriptor(std::u16string_view rsPanelId) const +{ + return ImplGetPanelDescriptor( rsPanelId ); +} + +const ResourceManager::DeckContextDescriptorContainer& ResourceManager::GetMatchingDecks ( + DeckContextDescriptorContainer& rDecks, + const Context& rContext, + const bool bIsDocumentReadOnly, + const Reference<frame::XController>& rxController) +{ + ReadLegacyAddons(rxController); + + std::multimap<sal_Int32,DeckContextDescriptor> aOrderedIds; + for (auto const& deck : maDecks) + { + if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get()) + continue; + + const DeckDescriptor& rDeckDescriptor (*deck); + if (rDeckDescriptor.maContextList.GetMatch(rContext) == nullptr) + continue; + + DeckContextDescriptor aDeckContextDescriptor; + aDeckContextDescriptor.msId = rDeckDescriptor.msId; + + aDeckContextDescriptor.mbIsEnabled = (! bIsDocumentReadOnly || IsDeckEnabled(rDeckDescriptor.msId, rContext, rxController) ) + && rDeckDescriptor.mbIsEnabled; + + + aOrderedIds.emplace(rDeckDescriptor.mnOrderIndex, aDeckContextDescriptor); + } + + for (auto const& orderId : aOrderedIds) + { + rDecks.push_back(orderId.second); + } + + return rDecks; +} + +const ResourceManager::PanelContextDescriptorContainer& ResourceManager::GetMatchingPanels ( + PanelContextDescriptorContainer& rPanelIds, + const Context& rContext, + std::u16string_view sDeckId, + const Reference<frame::XController>& rxController) +{ + ReadLegacyAddons(rxController); + + std::multimap<sal_Int32, PanelContextDescriptor> aOrderedIds; + for (auto const& panel : maPanels) + { + const PanelDescriptor& rPanelDescriptor (*panel); + if (rPanelDescriptor.mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get()) + continue; + if ( rPanelDescriptor.msDeckId != sDeckId ) + continue; + + const ContextList::Entry* pEntry = rPanelDescriptor.maContextList.GetMatch(rContext); + if (pEntry == nullptr) + continue; + + PanelContextDescriptor aPanelContextDescriptor; + aPanelContextDescriptor.msId = rPanelDescriptor.msId; + aPanelContextDescriptor.msMenuCommand = pEntry->msMenuCommand; + aPanelContextDescriptor.mbIsInitiallyVisible = pEntry->mbIsInitiallyVisible; + aPanelContextDescriptor.mbShowForReadOnlyDocuments = rPanelDescriptor.mbShowForReadOnlyDocuments; + aOrderedIds.emplace(rPanelDescriptor.mnOrderIndex, aPanelContextDescriptor); + } + + for (auto const& orderId : aOrderedIds) + { + rPanelIds.push_back(orderId.second); + } + + return rPanelIds; +} + +const OUString& ResourceManager::GetLastActiveDeck( const Context& rContext ) +{ + if( maLastActiveDecks.find( rContext.msApplication ) == maLastActiveDecks.end()) + return maLastActiveDecks["any"]; + else + return maLastActiveDecks[rContext.msApplication]; +} + +void ResourceManager::SetLastActiveDeck( const Context& rContext, const OUString &rsDeckId ) +{ + maLastActiveDecks[rContext.msApplication] = rsDeckId; +} + +void ResourceManager::ReadDeckList() +{ + const utl::OConfigurationTreeRoot aDeckRootNode( + comphelper::getProcessComponentContext(), + "org.openoffice.Office.UI.Sidebar/Content/DeckList", + false); + if (!aDeckRootNode.isValid()) + return; + + const Sequence<OUString> aDeckNodeNames (aDeckRootNode.getNodeNames()); + maDecks.clear(); + for (const OUString& aDeckName : aDeckNodeNames) + { + if (comphelper::LibreOfficeKit::isActive()) + { + // Hide these decks in LOK as they aren't fully functional. + if (aDeckName == "GalleryDeck" || aDeckName == "StyleListDeck") + continue; + } + + const utl::OConfigurationNode aDeckNode(aDeckRootNode.openNode(aDeckName)); + if (!aDeckNode.isValid()) + continue; + + maDecks.push_back(std::make_shared<DeckDescriptor>()); + DeckDescriptor& rDeckDescriptor (*maDecks.back()); + + rDeckDescriptor.msTitle = getString(aDeckNode, "Title"); + rDeckDescriptor.msId = getString(aDeckNode, "Id"); + rDeckDescriptor.msIconURL = getString(aDeckNode, "IconURL"); + rDeckDescriptor.msHighContrastIconURL = getString(aDeckNode, "HighContrastIconURL"); + rDeckDescriptor.msTitleBarIconURL = getString(aDeckNode, "TitleBarIconURL"); + rDeckDescriptor.msHighContrastTitleBarIconURL = getString(aDeckNode, "HighContrastTitleBarIconURL"); + rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle; + rDeckDescriptor.msHelpId = "SIDEBAR_" + rDeckDescriptor.msId.toAsciiUpperCase(); + rDeckDescriptor.mnOrderIndex = getInt32(aDeckNode, "OrderIndex"); + rDeckDescriptor.mbExperimental = getBool(aDeckNode, "IsExperimental"); + + rDeckDescriptor.msNodeName = aDeckName; + + ReadContextList( + aDeckNode, + rDeckDescriptor.maContextList, + OUString()); + + } +} + +void ResourceManager::SaveDecksSettings(const Context& rContext) +{ + for (auto const& deck : maDecks) + { + const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext); + if (pMatchingEntry) + { + std::shared_ptr<DeckDescriptor> xDeckDesc = GetDeckDescriptor(deck->msId); + if (xDeckDesc) + SaveDeckSettings(xDeckDesc.get()); + } + + } +} + +void ResourceManager::SaveDeckSettings(const DeckDescriptor* pDeckDesc) +{ + const utl::OConfigurationTreeRoot aDeckRootNode( + comphelper::getProcessComponentContext(), + "org.openoffice.Office.UI.Sidebar/Content/DeckList", + true); + if (!aDeckRootNode.isValid()) + return; + + // save deck settings + + ::uno::Sequence< OUString > sContextList = BuildContextList(pDeckDesc->maContextList); + + utl::OConfigurationNode aDeckNode (aDeckRootNode.openNode(pDeckDesc->msNodeName)); + + css::uno::Any aTitle(Any(pDeckDesc->msTitle)); + css::uno::Any aOrder(Any(pDeckDesc->mnOrderIndex)); + css::uno::Any aContextList(sContextList); + + bool bChanged = false; + if (aTitle != aDeckNode.getNodeValue("Title")) + { + aDeckNode.setNodeValue("Title", aTitle); + bChanged = true; + } + if (aOrder != aDeckNode.getNodeValue("OrderIndex")) + { + aDeckNode.setNodeValue("OrderIndex", aOrder); + bChanged = true; + } + if (aContextList != aDeckNode.getNodeValue("ContextList")) + { + aDeckNode.setNodeValue("ContextList", aContextList); + bChanged = true; + } + + if (bChanged) + aDeckRootNode.commit(); + + // save panel settings + + const utl::OConfigurationTreeRoot aPanelRootNode( + comphelper::getProcessComponentContext(), + "org.openoffice.Office.UI.Sidebar/Content/PanelList", + true); + + if (!aPanelRootNode.isValid()) + return; + + if (!pDeckDesc->mpDeck) // the deck has not been edited + return; + + SharedPanelContainer rPanels = pDeckDesc->mpDeck->GetPanels(); + + bChanged = false; + for (auto const& panel : rPanels) + { + OUString panelId = panel->GetId(); + std::shared_ptr<PanelDescriptor> xPanelDesc = GetPanelDescriptor(panelId); + + ::uno::Sequence< OUString > sPanelContextList = BuildContextList(xPanelDesc->maContextList); + + utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(xPanelDesc->msNodeName)); + + aTitle <<= xPanelDesc->msTitle; + aOrder <<= xPanelDesc->mnOrderIndex; + aContextList <<= sPanelContextList; + + if (aTitle != aPanelNode.getNodeValue("Title")) + { + aPanelNode.setNodeValue("Title", aTitle); + bChanged = true; + } + if (aOrder != aPanelNode.getNodeValue("OrderIndex")) + { + aPanelNode.setNodeValue("OrderIndex", aOrder); + bChanged = true; + } + if (aContextList != aPanelNode.getNodeValue("ContextList")) + { + aPanelNode.setNodeValue("ContextList", aContextList); + bChanged = true; + } + } + + if (bChanged) + aPanelRootNode.commit(); +} + +void ResourceManager::SaveLastActiveDeck(const Context& rContext, const OUString& rActiveDeck) +{ + maLastActiveDecks[rContext.msApplication] = rActiveDeck; + + std::set<OUString> aLastActiveDecks; + for ( auto const & rEntry : maLastActiveDecks ) + aLastActiveDecks.insert( rEntry.first + "," + rEntry.second); + + std::shared_ptr<comphelper::ConfigurationChanges> cfgWriter( comphelper::ConfigurationChanges::create() ); + + officecfg::Office::UI::Sidebar::Content::LastActiveDeck::set(comphelper::containerToSequence(aLastActiveDecks), cfgWriter); + cfgWriter->commit(); + +} + +void ResourceManager::ReadPanelList() +{ + const utl::OConfigurationTreeRoot aPanelRootNode( + comphelper::getProcessComponentContext(), + "org.openoffice.Office.UI.Sidebar/Content/PanelList", + false); + if (!aPanelRootNode.isValid()) + return; + + const Sequence<OUString> aPanelNodeNames (aPanelRootNode.getNodeNames()); + maPanels.clear(); + for (const auto& rPanelNodeName : aPanelNodeNames) + { + const utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(rPanelNodeName)); + if (!aPanelNode.isValid()) + continue; + + if (comphelper::LibreOfficeKit::isActive()) + { + // Hide these panels in LOK as they aren't fully functional. + OUString aPanelId = getString(aPanelNode, "Id"); + if (aPanelId == "PageStylesPanel" || aPanelId == "PageHeaderPanel" + || aPanelId == "PageFooterPanel") + continue; + } + + maPanels.push_back(std::make_shared<PanelDescriptor>()); + PanelDescriptor& rPanelDescriptor(*maPanels.back()); + + rPanelDescriptor.msTitle = getString(aPanelNode, "Title"); + rPanelDescriptor.mbIsTitleBarOptional = getBool(aPanelNode, "TitleBarIsOptional"); + rPanelDescriptor.msId = getString(aPanelNode, "Id"); + rPanelDescriptor.msDeckId = getString(aPanelNode, "DeckId"); + rPanelDescriptor.msTitleBarIconURL = getString(aPanelNode, "TitleBarIconURL"); + rPanelDescriptor.msHighContrastTitleBarIconURL = getString(aPanelNode, "HighContrastTitleBarIconURL"); + rPanelDescriptor.msImplementationURL = getString(aPanelNode, "ImplementationURL"); + rPanelDescriptor.mnOrderIndex = getInt32(aPanelNode, "OrderIndex"); + rPanelDescriptor.mbShowForReadOnlyDocuments = getBool(aPanelNode, "ShowForReadOnlyDocument"); + rPanelDescriptor.mbWantsCanvas = getBool(aPanelNode, "WantsCanvas"); + rPanelDescriptor.mbWantsAWT = getBool(aPanelNode, "WantsAWT"); + rPanelDescriptor.mbExperimental = getBool(aPanelNode, "IsExperimental"); + const OUString sDefaultMenuCommand(getString(aPanelNode, "DefaultMenuCommand")); + + rPanelDescriptor.msNodeName = rPanelNodeName; + + ReadContextList(aPanelNode, rPanelDescriptor.maContextList, sDefaultMenuCommand); + } +} + +void ResourceManager::ReadLastActive() +{ + const Sequence <OUString> aLastActive (officecfg::Office::UI::Sidebar::Content::LastActiveDeck::get()); + + for (const auto& rDeckInfo : aLastActive) + { + sal_Int32 nCharIdx = rDeckInfo.lastIndexOf(','); + if ( nCharIdx <= 0 || (nCharIdx == rDeckInfo.getLength() - 1) ) + { + SAL_WARN("sfx.sidebar", "Expecting 2 values separated by comma"); + continue; + } + + const OUString sApplicationName = rDeckInfo.copy( 0, nCharIdx ); + vcl::EnumContext::Application eApplication (vcl::EnumContext::GetApplicationEnum(sApplicationName)); + const OUString sLastUsed = rDeckInfo.copy( nCharIdx + 1 ); + + // guard against garbage in place of application + if (eApplication != vcl::EnumContext::Application::NONE) + maLastActiveDecks.insert( std::make_pair(sApplicationName, sLastUsed ) ); + } + + // Set up a default for Math - will do nothing if already set + maLastActiveDecks.emplace( + vcl::EnumContext::GetApplicationName(vcl::EnumContext::Application::Formula), + "ElementsDeck"); +} + +void ResourceManager::ReadContextList ( + const utl::OConfigurationNode& rParentNode, + ContextList& rContextList, + const OUString& rsDefaultMenuCommand) +{ + const Any aValue = rParentNode.getNodeValue("ContextList"); + Sequence<OUString> aValues; + if (!(aValue >>= aValues)) + return; + + for (const OUString& sValue : std::as_const(aValues)) + { + sal_Int32 nCharacterIndex (0); + const OUString sApplicationName (o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex))); + if (nCharacterIndex < 0) + { + if (sApplicationName.getLength() == 0) + { + // This is a valid case: in the XML file the separator + // was used as terminator. Using it in the last line + // creates an additional but empty entry. + break; + } + else + { + OSL_FAIL("expecting three or four values per ContextList entry, separated by comma"); + continue; + } + } + + const OUString sContextName(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex))); + if (nCharacterIndex < 0) + { + OSL_FAIL("expecting three or four values per ContextList entry, separated by comma"); + continue; + } + + const std::u16string_view sInitialState(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex))); + + // The fourth argument is optional. + const OUString sMenuCommandOverride( + nCharacterIndex < 0 + ? OUString() + : OUString(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex)))); + + const OUString sMenuCommand( + sMenuCommandOverride.getLength() > 0 + ? (sMenuCommandOverride == "none" + ? OUString() + : sMenuCommandOverride) + : rsDefaultMenuCommand); + + // Setup a list of application enums. Note that the + // application name may result in more than one value (eg + // DrawImpress will result in two enums, one for Draw and one + // for Impress). + std::vector<vcl::EnumContext::Application> aApplications; + vcl::EnumContext::Application eApplication (vcl::EnumContext::GetApplicationEnum(sApplicationName)); + + if (eApplication == vcl::EnumContext::Application::NONE + && sApplicationName != vcl::EnumContext::GetApplicationName(vcl::EnumContext::Application::NONE)) + { + // Handle some special names: abbreviations that make + // context descriptions more readable. + if (sApplicationName == "Writer") + aApplications.push_back(vcl::EnumContext::Application::Writer); + else if (sApplicationName == "Calc") + aApplications.push_back(vcl::EnumContext::Application::Calc); + else if (sApplicationName == "Draw") + aApplications.push_back(vcl::EnumContext::Application::Draw); + else if (sApplicationName == "Impress") + aApplications.push_back(vcl::EnumContext::Application::Impress); + else if (sApplicationName == "Chart") + aApplications.push_back(vcl::EnumContext::Application::Chart); + else if (sApplicationName == "Math") + aApplications.push_back(vcl::EnumContext::Application::Formula); + else if (sApplicationName == "DrawImpress") + { + // A special case among the special names: it is + // common to use the same context descriptions for + // both Draw and Impress. This special case helps to + // avoid duplication in the .xcu file. + aApplications.push_back(vcl::EnumContext::Application::Draw); + aApplications.push_back(vcl::EnumContext::Application::Impress); + } + else if (sApplicationName == "WriterVariants") + { + // Another special case for all Writer variants. + aApplications.push_back(vcl::EnumContext::Application::Writer); + aApplications.push_back(vcl::EnumContext::Application::WriterGlobal); + aApplications.push_back(vcl::EnumContext::Application::WriterWeb); + aApplications.push_back(vcl::EnumContext::Application::WriterXML); + aApplications.push_back(vcl::EnumContext::Application::WriterForm); + aApplications.push_back(vcl::EnumContext::Application::WriterReport); + } + else + { + SAL_WARN("sfx.sidebar", "application name " << sApplicationName << " not recognized"); + continue; + } + } + else + { + // No conversion of the application name necessary. + aApplications.push_back(eApplication); + } + + // Setup the actual context enum. + const vcl::EnumContext::Context eContext (vcl::EnumContext::GetContextEnum(sContextName)); + if (eContext == vcl::EnumContext::Context::Unknown) + { + SAL_WARN("sfx.sidebar", "context name " << sContextName << " not recognized"); + continue; + } + + // Setup the flag that controls whether a deck/pane is + // initially visible/expanded. + bool bIsInitiallyVisible; + if (sInitialState == u"visible") + bIsInitiallyVisible = true; + else if (sInitialState == u"hidden") + bIsInitiallyVisible = false; + else + { + OSL_FAIL("unrecognized state"); + continue; + } + + + // Add context descriptors. + for (auto const& application : aApplications) + { + if (application != vcl::EnumContext::Application::NONE) + { + rContextList.AddContextDescription( + Context( + vcl::EnumContext::GetApplicationName(application), + vcl::EnumContext::GetContextName(eContext)), + bIsInitiallyVisible, + sMenuCommand); + } + } + } +} + +void ResourceManager::ReadLegacyAddons (const Reference<frame::XController>& rxController) +{ + // Get module name for given frame. + OUString sModuleName (Tools::GetModuleName(rxController)); + if (sModuleName.getLength() == 0) + return; + if (maProcessedApplications.find(sModuleName) != maProcessedApplications.end()) + { + // Addons for this application have already been read. + // There is nothing more to do. + return; + } + + // Mark module as processed. Even when there is an error that + // prevents the configuration data from being read, this error + // will not be triggered a second time. + maProcessedApplications.insert(sModuleName); + + // Get access to the configuration root node for the application. + utl::OConfigurationTreeRoot aLegacyRootNode (GetLegacyAddonRootNode(sModuleName)); + if (!aLegacyRootNode.isValid()) + return; + + // Process child nodes. + std::vector<OUString> aMatchingNodeNames; + GetToolPanelNodeNames(aMatchingNodeNames, aLegacyRootNode); + const sal_Int32 nCount (aMatchingNodeNames.size()); + for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex) + { + const OUString& rsNodeName (aMatchingNodeNames[nReadIndex]); + const utl::OConfigurationNode aChildNode (aLegacyRootNode.openNode(rsNodeName)); + if (!aChildNode.isValid()) + continue; + + if ( rsNodeName == "private:resource/toolpanel/DrawingFramework/CustomAnimations" || + rsNodeName == "private:resource/toolpanel/DrawingFramework/Layouts" || + rsNodeName == "private:resource/toolpanel/DrawingFramework/MasterPages" || + rsNodeName == "private:resource/toolpanel/DrawingFramework/SlideTransitions" || + rsNodeName == "private:resource/toolpanel/DrawingFramework/TableDesign" ) + continue; + + maDecks.push_back(std::make_shared<DeckDescriptor>()); + DeckDescriptor& rDeckDescriptor(*maDecks.back()); + rDeckDescriptor.msTitle = getString(aChildNode, "UIName"); + rDeckDescriptor.msId = rsNodeName; + rDeckDescriptor.msIconURL = getString(aChildNode, "ImageURL"); + rDeckDescriptor.msHighContrastIconURL = rDeckDescriptor.msIconURL; + rDeckDescriptor.msTitleBarIconURL.clear(); + rDeckDescriptor.msHighContrastTitleBarIconURL.clear(); + rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle; + rDeckDescriptor.mbIsEnabled = true; + rDeckDescriptor.mnOrderIndex = 100000 + nReadIndex; + rDeckDescriptor.maContextList.AddContextDescription(Context(sModuleName, "any"), true, OUString()); + + maPanels.push_back(std::make_shared<PanelDescriptor>()); + PanelDescriptor& rPanelDescriptor(*maPanels.back()); + rPanelDescriptor.msTitle = getString(aChildNode, "UIName"); + rPanelDescriptor.mbIsTitleBarOptional = true; + rPanelDescriptor.msId = rsNodeName; + rPanelDescriptor.msDeckId = rsNodeName; + rPanelDescriptor.msTitleBarIconURL.clear(); + rPanelDescriptor.msHighContrastTitleBarIconURL.clear(); + rPanelDescriptor.msImplementationURL = rsNodeName; + rPanelDescriptor.mnOrderIndex = 100000 + nReadIndex; + rPanelDescriptor.mbShowForReadOnlyDocuments = false; + rPanelDescriptor.mbWantsCanvas = false; + rPanelDescriptor.mbWantsAWT = true; + rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, "any"), true, OUString()); + } +} + +void ResourceManager::StorePanelExpansionState ( + std::u16string_view rsPanelId, + const bool bExpansionState, + const Context& rContext) +{ + for (auto const& panel : maPanels) + { + if (panel->msId == rsPanelId) + { + ContextList::Entry* pEntry(panel->maContextList.GetMatch(rContext)); + if (pEntry != nullptr) + pEntry->mbIsInitiallyVisible = bExpansionState; + } + } +} + +utl::OConfigurationTreeRoot ResourceManager::GetLegacyAddonRootNode (const OUString& rsModuleName) +{ + try + { + const Reference<XComponentContext> xContext(comphelper::getProcessComponentContext()); + const Reference<frame::XModuleManager2> xModuleAccess = frame::ModuleManager::create(xContext); + const comphelper::NamedValueCollection aModuleProperties(xModuleAccess->getByName(rsModuleName)); + const OUString sWindowStateRef(aModuleProperties.getOrDefault( + "ooSetupFactoryWindowStateConfigRef", + OUString())); + + OUString aPathComposer = "org.openoffice.Office.UI." + sWindowStateRef + + "/UIElements/States"; + + return utl::OConfigurationTreeRoot(xContext, aPathComposer, false); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("sfx.sidebar"); + } + + return utl::OConfigurationTreeRoot(); +} + +void ResourceManager::GetToolPanelNodeNames ( + std::vector<OUString>& rMatchingNames, + const utl::OConfigurationTreeRoot& aRoot) +{ + const Sequence<OUString> aChildNodeNames (aRoot.getNodeNames()); + std::copy_if(aChildNodeNames.begin(), aChildNodeNames.end(), std::back_inserter(rMatchingNames), + [](const OUString& rChildNodeName) { return rChildNodeName.startsWith( "private:resource/toolpanel/" ); }); +} + +bool ResourceManager::IsDeckEnabled ( + std::u16string_view rsDeckId, + const Context& rContext, + const Reference<frame::XController>& rxController) +{ + + // Check if any panel that matches the current context can be + // displayed. + PanelContextDescriptorContainer aPanelContextDescriptors; + + GetMatchingPanels(aPanelContextDescriptors, rContext, rsDeckId, rxController); + + for (auto const& panelContextDescriptor : aPanelContextDescriptors) + { + if (panelContextDescriptor.mbShowForReadOnlyDocuments) + return true; + } + return false; +} + +void ResourceManager::UpdateModel(const css::uno::Reference<css::frame::XModel>& xModel) +{ + for (auto const& deck : maDecks) + { + if (!deck->mpDeck) + continue; + + const SharedPanelContainer& rContainer = deck->mpDeck->GetPanels(); + + for (auto const& elem : rContainer) + { + css::uno::Reference<css::ui::XUpdateModel> xPanel(elem->GetPanelComponent(), css::uno::UNO_QUERY); + if (xPanel.is()) // tdf#108814 interface is optional + { + xPanel->updateModel(xModel); + } + } + } +} + +void ResourceManager::disposeDecks() +{ + for (auto const& deck : maDecks) + { + deck->mpDeck.disposeAndClear(); + } +} + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |