Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / sidebar / ResourceManager.cxx
bloba1ff9752e1e0a99d4a7b2c7dcb1406f669264d0c
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 <sidebar/DeckDescriptor.hxx>
21 #include <sidebar/PanelDescriptor.hxx>
22 #include <sfx2/sidebar/ResourceManager.hxx>
23 #include <sidebar/Tools.hxx>
25 #include <officecfg/Office/Common.hxx>
26 #include <officecfg/Office/UI/Sidebar.hxx>
27 #include <unotools/confignode.hxx>
28 #include <comphelper/lok.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/namedvaluecollection.hxx>
31 #include <comphelper/sequence.hxx>
32 #include <comphelper/types.hxx>
34 #include <tools/diagnose_ex.h>
35 #include <sal/log.hxx>
36 #include <vcl/EnumContext.hxx>
38 #include <com/sun/star/frame/ModuleManager.hpp>
39 #include <com/sun/star/ui/XSidebarPanel.hpp>
40 #include <com/sun/star/ui/XUpdateModel.hpp>
42 #include <map>
44 using namespace css;
45 using namespace css::uno;
47 namespace sfx2::sidebar {
49 namespace
52 OUString getString(utl::OConfigurationNode const & aNode, const char* pNodeName)
54 return comphelper::getString(aNode.getNodeValue(pNodeName));
56 sal_Int32 getInt32(utl::OConfigurationNode const & aNode, const char* pNodeName)
58 return comphelper::getINT32(aNode.getNodeValue(pNodeName));
60 bool getBool(utl::OConfigurationNode const & aNode, const char* pNodeName)
62 return comphelper::getBOOL(aNode.getNodeValue(pNodeName));
65 css::uno::Sequence<OUString> BuildContextList (const ContextList& rContextList)
67 const ::std::vector<ContextList::Entry>& entries = rContextList.GetEntries();
69 css::uno::Sequence<OUString> result(entries.size());
70 tools::Long i = 0;
72 for (auto const& entry : entries)
74 OUString appName = entry.maContext.msApplication;
75 OUString contextName = entry.maContext.msContext;
76 OUString menuCommand = entry.msMenuCommand;
78 OUString visibility;
79 if (entry.mbIsInitiallyVisible)
80 visibility = "visible";
81 else
82 visibility = "hidden";
84 OUString element = appName + ", " + contextName +", " + visibility;
86 if (!menuCommand.isEmpty())
87 element += ", "+menuCommand;
89 result[i] = element;
91 ++i;
94 return result;
98 } //end anonymous namespace
100 ResourceManager::ResourceManager()
101 : maDecks(),
102 maPanels(),
103 maProcessedApplications()
105 ReadDeckList();
106 ReadPanelList();
107 ReadLastActive();
110 ResourceManager::~ResourceManager()
114 void ResourceManager::InitDeckContext(const Context& rContext)
116 for (auto const& deck : maDecks)
118 const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext);
120 bool bIsEnabled;
121 if (pMatchingEntry)
122 bIsEnabled = pMatchingEntry->mbIsInitiallyVisible;
123 else
124 bIsEnabled = false;
126 deck->mbIsEnabled = bIsEnabled;
130 std::shared_ptr<DeckDescriptor> ResourceManager::ImplGetDeckDescriptor(const OUString& rsDeckId) const
132 for (auto const& deck : maDecks)
134 if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
135 continue;
136 if (deck->msId == rsDeckId)
137 return deck;
139 return nullptr;
142 std::shared_ptr<DeckDescriptor> ResourceManager::GetDeckDescriptor(const OUString& rsDeckId) const
144 return ImplGetDeckDescriptor( rsDeckId );
147 std::shared_ptr<PanelDescriptor> ResourceManager::ImplGetPanelDescriptor(const OUString& rsPanelId) const
149 for (auto const& panel : maPanels)
151 if (panel->msId == rsPanelId)
152 return panel;
154 return nullptr;
157 std::shared_ptr<PanelDescriptor> ResourceManager::GetPanelDescriptor(const OUString& rsPanelId) const
159 return ImplGetPanelDescriptor( rsPanelId );
162 const ResourceManager::DeckContextDescriptorContainer& ResourceManager::GetMatchingDecks (
163 DeckContextDescriptorContainer& rDecks,
164 const Context& rContext,
165 const bool bIsDocumentReadOnly,
166 const Reference<frame::XController>& rxController)
168 ReadLegacyAddons(rxController);
170 std::multimap<sal_Int32,DeckContextDescriptor> aOrderedIds;
171 for (auto const& deck : maDecks)
173 if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
174 continue;
176 const DeckDescriptor& rDeckDescriptor (*deck);
177 if (rDeckDescriptor.maContextList.GetMatch(rContext) == nullptr)
178 continue;
180 DeckContextDescriptor aDeckContextDescriptor;
181 aDeckContextDescriptor.msId = rDeckDescriptor.msId;
183 aDeckContextDescriptor.mbIsEnabled = (! bIsDocumentReadOnly || IsDeckEnabled(rDeckDescriptor.msId, rContext, rxController) )
184 && rDeckDescriptor.mbIsEnabled;
187 aOrderedIds.emplace(rDeckDescriptor.mnOrderIndex, aDeckContextDescriptor);
190 for (auto const& orderId : aOrderedIds)
192 rDecks.push_back(orderId.second);
195 return rDecks;
198 const ResourceManager::PanelContextDescriptorContainer& ResourceManager::GetMatchingPanels (
199 PanelContextDescriptorContainer& rPanelIds,
200 const Context& rContext,
201 const OUString& sDeckId,
202 const Reference<frame::XController>& rxController)
204 ReadLegacyAddons(rxController);
206 std::multimap<sal_Int32, PanelContextDescriptor> aOrderedIds;
207 for (auto const& panel : maPanels)
209 const PanelDescriptor& rPanelDescriptor (*panel);
210 if (rPanelDescriptor.mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
211 continue;
212 if ( rPanelDescriptor.msDeckId != sDeckId )
213 continue;
215 const ContextList::Entry* pEntry = rPanelDescriptor.maContextList.GetMatch(rContext);
216 if (pEntry == nullptr)
217 continue;
219 PanelContextDescriptor aPanelContextDescriptor;
220 aPanelContextDescriptor.msId = rPanelDescriptor.msId;
221 aPanelContextDescriptor.msMenuCommand = pEntry->msMenuCommand;
222 aPanelContextDescriptor.mbIsInitiallyVisible = pEntry->mbIsInitiallyVisible;
223 aPanelContextDescriptor.mbShowForReadOnlyDocuments = rPanelDescriptor.mbShowForReadOnlyDocuments;
224 aOrderedIds.emplace(rPanelDescriptor.mnOrderIndex, aPanelContextDescriptor);
227 for (auto const& orderId : aOrderedIds)
229 rPanelIds.push_back(orderId.second);
232 return rPanelIds;
235 const OUString& ResourceManager::GetLastActiveDeck( const Context& rContext )
237 if( maLastActiveDecks.find( rContext.msApplication ) == maLastActiveDecks.end())
238 return maLastActiveDecks["any"];
239 else
240 return maLastActiveDecks[rContext.msApplication];
243 void ResourceManager::SetLastActiveDeck( const Context& rContext, const OUString &rsDeckId )
245 maLastActiveDecks[rContext.msApplication] = rsDeckId;
248 void ResourceManager::ReadDeckList()
250 const utl::OConfigurationTreeRoot aDeckRootNode(
251 comphelper::getProcessComponentContext(),
252 "org.openoffice.Office.UI.Sidebar/Content/DeckList",
253 false);
254 if (!aDeckRootNode.isValid())
255 return;
257 const Sequence<OUString> aDeckNodeNames (aDeckRootNode.getNodeNames());
258 maDecks.clear();
259 for (const OUString& aDeckName : aDeckNodeNames)
261 if (comphelper::LibreOfficeKit::isActive())
263 // Hide these decks in LOK as they aren't fully functional.
264 if (aDeckName == "GalleryDeck" || aDeckName == "NavigatorDeck"
265 || aDeckName == "StyleListDeck")
266 continue;
269 const utl::OConfigurationNode aDeckNode(aDeckRootNode.openNode(aDeckName));
270 if (!aDeckNode.isValid())
271 continue;
273 maDecks.push_back(std::make_shared<DeckDescriptor>());
274 DeckDescriptor& rDeckDescriptor (*maDecks.back());
276 rDeckDescriptor.msTitle = getString(aDeckNode, "Title");
277 rDeckDescriptor.msId = getString(aDeckNode, "Id");
278 rDeckDescriptor.msIconURL = getString(aDeckNode, "IconURL");
279 rDeckDescriptor.msHighContrastIconURL = getString(aDeckNode, "HighContrastIconURL");
280 rDeckDescriptor.msTitleBarIconURL = getString(aDeckNode, "TitleBarIconURL");
281 rDeckDescriptor.msHighContrastTitleBarIconURL = getString(aDeckNode, "HighContrastTitleBarIconURL");
282 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
283 rDeckDescriptor.mnOrderIndex = getInt32(aDeckNode, "OrderIndex");
284 rDeckDescriptor.mbExperimental = getBool(aDeckNode, "IsExperimental");
286 rDeckDescriptor.msNodeName = aDeckName;
288 ReadContextList(
289 aDeckNode,
290 rDeckDescriptor.maContextList,
291 OUString());
296 void ResourceManager::SaveDecksSettings(const Context& rContext)
298 for (auto const& deck : maDecks)
300 const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext);
301 if (pMatchingEntry)
303 std::shared_ptr<DeckDescriptor> xDeckDesc = GetDeckDescriptor(deck->msId);
304 if (xDeckDesc)
305 SaveDeckSettings(xDeckDesc.get());
311 void ResourceManager::SaveDeckSettings(const DeckDescriptor* pDeckDesc)
313 const utl::OConfigurationTreeRoot aDeckRootNode(
314 comphelper::getProcessComponentContext(),
315 "org.openoffice.Office.UI.Sidebar/Content/DeckList",
316 true);
317 if (!aDeckRootNode.isValid())
318 return;
320 // save deck settings
322 ::uno::Sequence< OUString > sContextList = BuildContextList(pDeckDesc->maContextList);
324 utl::OConfigurationNode aDeckNode (aDeckRootNode.openNode(pDeckDesc->msNodeName));
326 css::uno::Any aTitle(makeAny(pDeckDesc->msTitle));
327 css::uno::Any aOrder(makeAny(pDeckDesc->mnOrderIndex));
328 css::uno::Any aContextList(makeAny(sContextList));
330 bool bChanged = false;
331 if (aTitle != aDeckNode.getNodeValue("Title"))
333 aDeckNode.setNodeValue("Title", aTitle);
334 bChanged = true;
336 if (aOrder != aDeckNode.getNodeValue("OrderIndex"))
338 aDeckNode.setNodeValue("OrderIndex", aOrder);
339 bChanged = true;
341 if (aContextList != aDeckNode.getNodeValue("ContextList"))
343 aDeckNode.setNodeValue("ContextList", aContextList);
344 bChanged = true;
347 if (bChanged)
348 aDeckRootNode.commit();
350 // save panel settings
352 const utl::OConfigurationTreeRoot aPanelRootNode(
353 comphelper::getProcessComponentContext(),
354 "org.openoffice.Office.UI.Sidebar/Content/PanelList",
355 true);
357 if (!aPanelRootNode.isValid())
358 return;
360 if (!pDeckDesc->mpDeck) // the deck has not been edited
361 return;
363 SharedPanelContainer rPanels = pDeckDesc->mpDeck->GetPanels();
365 bChanged = false;
366 for (auto const& panel : rPanels)
368 OUString panelId = panel->GetId();
369 std::shared_ptr<PanelDescriptor> xPanelDesc = GetPanelDescriptor(panelId);
371 ::uno::Sequence< OUString > sPanelContextList = BuildContextList(xPanelDesc->maContextList);
373 utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(xPanelDesc->msNodeName));
375 aTitle <<= xPanelDesc->msTitle;
376 aOrder <<= xPanelDesc->mnOrderIndex;
377 aContextList <<= sPanelContextList;
379 if (aTitle != aPanelNode.getNodeValue("Title"))
381 aPanelNode.setNodeValue("Title", aTitle);
382 bChanged = true;
384 if (aOrder != aPanelNode.getNodeValue("OrderIndex"))
386 aPanelNode.setNodeValue("OrderIndex", aOrder);
387 bChanged = true;
389 if (aContextList != aPanelNode.getNodeValue("ContextList"))
391 aPanelNode.setNodeValue("ContextList", aContextList);
392 bChanged = true;
396 if (bChanged)
397 aPanelRootNode.commit();
400 void ResourceManager::SaveLastActiveDeck(const Context& rContext, const OUString& rActiveDeck)
402 maLastActiveDecks[rContext.msApplication] = rActiveDeck;
404 std::set<OUString> aLastActiveDecks;
405 for ( auto const & rEntry : maLastActiveDecks )
406 aLastActiveDecks.insert( rEntry.first + "," + rEntry.second);
408 std::shared_ptr<comphelper::ConfigurationChanges> cfgWriter( comphelper::ConfigurationChanges::create() );
410 officecfg::Office::UI::Sidebar::Content::LastActiveDeck::set(comphelper::containerToSequence(aLastActiveDecks), cfgWriter);
411 cfgWriter->commit();
415 void ResourceManager::ReadPanelList()
417 const utl::OConfigurationTreeRoot aPanelRootNode(
418 comphelper::getProcessComponentContext(),
419 "org.openoffice.Office.UI.Sidebar/Content/PanelList",
420 false);
421 if (!aPanelRootNode.isValid())
422 return;
424 const Sequence<OUString> aPanelNodeNames (aPanelRootNode.getNodeNames());
425 maPanels.clear();
426 for (const auto& rPanelNodeName : aPanelNodeNames)
428 const utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(rPanelNodeName));
429 if (!aPanelNode.isValid())
430 continue;
432 if (comphelper::LibreOfficeKit::isActive())
434 // Hide these panels in LOK as they aren't fully functional.
435 OUString aPanelId = getString(aPanelNode, "Id");
436 if (aPanelId == "PageStylesPanel" || aPanelId == "PageHeaderPanel"
437 || aPanelId == "PageFooterPanel")
438 continue;
441 maPanels.push_back(std::make_shared<PanelDescriptor>());
442 PanelDescriptor& rPanelDescriptor(*maPanels.back());
444 rPanelDescriptor.msTitle = getString(aPanelNode, "Title");
445 rPanelDescriptor.mbIsTitleBarOptional = getBool(aPanelNode, "TitleBarIsOptional");
446 rPanelDescriptor.msId = getString(aPanelNode, "Id");
447 rPanelDescriptor.msDeckId = getString(aPanelNode, "DeckId");
448 rPanelDescriptor.msTitleBarIconURL = getString(aPanelNode, "TitleBarIconURL");
449 rPanelDescriptor.msHighContrastTitleBarIconURL = getString(aPanelNode, "HighContrastTitleBarIconURL");
450 rPanelDescriptor.msImplementationURL = getString(aPanelNode, "ImplementationURL");
451 rPanelDescriptor.mnOrderIndex = getInt32(aPanelNode, "OrderIndex");
452 rPanelDescriptor.mbShowForReadOnlyDocuments = getBool(aPanelNode, "ShowForReadOnlyDocument");
453 rPanelDescriptor.mbWantsCanvas = getBool(aPanelNode, "WantsCanvas");
454 rPanelDescriptor.mbExperimental = getBool(aPanelNode, "IsExperimental");
455 const OUString sDefaultMenuCommand(getString(aPanelNode, "DefaultMenuCommand"));
457 rPanelDescriptor.msNodeName = rPanelNodeName;
459 ReadContextList(aPanelNode, rPanelDescriptor.maContextList, sDefaultMenuCommand);
463 void ResourceManager::ReadLastActive()
465 const Sequence <OUString> aLastActive (officecfg::Office::UI::Sidebar::Content::LastActiveDeck::get());
467 for (const auto& rDeckInfo : aLastActive)
469 sal_Int32 nCharIdx = rDeckInfo.lastIndexOf(',');
470 if ( nCharIdx <= 0 || (nCharIdx == rDeckInfo.getLength() - 1) )
472 SAL_WARN("sfx.sidebar", "Expecting 2 values separated by comma");
473 continue;
476 const OUString sApplicationName = rDeckInfo.copy( 0, nCharIdx );
477 vcl::EnumContext::Application eApplication (vcl::EnumContext::GetApplicationEnum(sApplicationName));
478 const OUString sLastUsed = rDeckInfo.copy( nCharIdx + 1 );
480 // guard against garbage in place of application
481 if (eApplication != vcl::EnumContext::Application::NONE)
482 maLastActiveDecks.insert( std::make_pair(sApplicationName, sLastUsed ) );
486 void ResourceManager::ReadContextList (
487 const utl::OConfigurationNode& rParentNode,
488 ContextList& rContextList,
489 const OUString& rsDefaultMenuCommand)
491 const Any aValue = rParentNode.getNodeValue("ContextList");
492 Sequence<OUString> aValues;
493 if (!(aValue >>= aValues))
494 return;
496 for (const OUString& sValue : std::as_const(aValues))
498 sal_Int32 nCharacterIndex (0);
499 const OUString sApplicationName (sValue.getToken(0, ',', nCharacterIndex).trim());
500 if (nCharacterIndex < 0)
502 if (sApplicationName.getLength() == 0)
504 // This is a valid case: in the XML file the separator
505 // was used as terminator. Using it in the last line
506 // creates an additional but empty entry.
507 break;
509 else
511 OSL_FAIL("expecting three or four values per ContextList entry, separated by comma");
512 continue;
516 const OUString sContextName(sValue.getToken(0, ',', nCharacterIndex).trim());
517 if (nCharacterIndex < 0)
519 OSL_FAIL("expecting three or four values per ContextList entry, separated by comma");
520 continue;
523 const OUString sInitialState(sValue.getToken(0, ',', nCharacterIndex).trim());
525 // The fourth argument is optional.
526 const OUString sMenuCommandOverride(
527 nCharacterIndex < 0
528 ? OUString()
529 : sValue.getToken(0, ',', nCharacterIndex).trim());
531 const OUString sMenuCommand(
532 sMenuCommandOverride.getLength() > 0
533 ? (sMenuCommandOverride == "none"
534 ? OUString()
535 : sMenuCommandOverride)
536 : rsDefaultMenuCommand);
538 // Setup a list of application enums. Note that the
539 // application name may result in more than one value (eg
540 // DrawImpress will result in two enums, one for Draw and one
541 // for Impress).
542 std::vector<vcl::EnumContext::Application> aApplications;
543 vcl::EnumContext::Application eApplication (vcl::EnumContext::GetApplicationEnum(sApplicationName));
545 if (eApplication == vcl::EnumContext::Application::NONE
546 && sApplicationName != vcl::EnumContext::GetApplicationName(vcl::EnumContext::Application::NONE))
548 // Handle some special names: abbreviations that make
549 // context descriptions more readable.
550 if (sApplicationName == "Writer")
551 aApplications.push_back(vcl::EnumContext::Application::Writer);
552 else if (sApplicationName == "Calc")
553 aApplications.push_back(vcl::EnumContext::Application::Calc);
554 else if (sApplicationName == "Draw")
555 aApplications.push_back(vcl::EnumContext::Application::Draw);
556 else if (sApplicationName == "Impress")
557 aApplications.push_back(vcl::EnumContext::Application::Impress);
558 else if (sApplicationName == "Chart")
559 aApplications.push_back(vcl::EnumContext::Application::Chart);
560 else if (sApplicationName == "DrawImpress")
562 // A special case among the special names: it is
563 // common to use the same context descriptions for
564 // both Draw and Impress. This special case helps to
565 // avoid duplication in the .xcu file.
566 aApplications.push_back(vcl::EnumContext::Application::Draw);
567 aApplications.push_back(vcl::EnumContext::Application::Impress);
569 else if (sApplicationName == "WriterVariants")
571 // Another special case for all Writer variants.
572 aApplications.push_back(vcl::EnumContext::Application::Writer);
573 aApplications.push_back(vcl::EnumContext::Application::WriterGlobal);
574 aApplications.push_back(vcl::EnumContext::Application::WriterWeb);
575 aApplications.push_back(vcl::EnumContext::Application::WriterXML);
576 aApplications.push_back(vcl::EnumContext::Application::WriterForm);
577 aApplications.push_back(vcl::EnumContext::Application::WriterReport);
579 else
581 SAL_WARN("sfx.sidebar", "application name " << sApplicationName << " not recognized");
582 continue;
585 else
587 // No conversion of the application name necessary.
588 aApplications.push_back(eApplication);
591 // Setup the actual context enum.
592 const vcl::EnumContext::Context eContext (vcl::EnumContext::GetContextEnum(sContextName));
593 if (eContext == vcl::EnumContext::Context::Unknown)
595 SAL_WARN("sfx.sidebar", "context name " << sContextName << " not recognized");
596 continue;
599 // Setup the flag that controls whether a deck/pane is
600 // initially visible/expanded.
601 bool bIsInitiallyVisible;
602 if (sInitialState == "visible")
603 bIsInitiallyVisible = true;
604 else if (sInitialState == "hidden")
605 bIsInitiallyVisible = false;
606 else
608 OSL_FAIL("unrecognized state");
609 continue;
613 // Add context descriptors.
614 for (auto const& application : aApplications)
616 if (application != vcl::EnumContext::Application::NONE)
618 rContextList.AddContextDescription(
619 Context(
620 vcl::EnumContext::GetApplicationName(application),
621 vcl::EnumContext::GetContextName(eContext)),
622 bIsInitiallyVisible,
623 sMenuCommand);
629 void ResourceManager::ReadLegacyAddons (const Reference<frame::XController>& rxController)
631 // Get module name for given frame.
632 OUString sModuleName (Tools::GetModuleName(rxController));
633 if (sModuleName.getLength() == 0)
634 return;
635 if (maProcessedApplications.find(sModuleName) != maProcessedApplications.end())
637 // Addons for this application have already been read.
638 // There is nothing more to do.
639 return;
642 // Mark module as processed. Even when there is an error that
643 // prevents the configuration data from being read, this error
644 // will not be triggered a second time.
645 maProcessedApplications.insert(sModuleName);
647 // Get access to the configuration root node for the application.
648 utl::OConfigurationTreeRoot aLegacyRootNode (GetLegacyAddonRootNode(sModuleName));
649 if (!aLegacyRootNode.isValid())
650 return;
652 // Process child nodes.
653 std::vector<OUString> aMatchingNodeNames;
654 GetToolPanelNodeNames(aMatchingNodeNames, aLegacyRootNode);
655 const sal_Int32 nCount (aMatchingNodeNames.size());
656 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex)
658 const OUString& rsNodeName (aMatchingNodeNames[nReadIndex]);
659 const utl::OConfigurationNode aChildNode (aLegacyRootNode.openNode(rsNodeName));
660 if (!aChildNode.isValid())
661 continue;
663 if ( rsNodeName == "private:resource/toolpanel/DrawingFramework/CustomAnimations" ||
664 rsNodeName == "private:resource/toolpanel/DrawingFramework/Layouts" ||
665 rsNodeName == "private:resource/toolpanel/DrawingFramework/MasterPages" ||
666 rsNodeName == "private:resource/toolpanel/DrawingFramework/SlideTransitions" ||
667 rsNodeName == "private:resource/toolpanel/DrawingFramework/TableDesign" )
668 continue;
670 maDecks.push_back(std::make_shared<DeckDescriptor>());
671 DeckDescriptor& rDeckDescriptor(*maDecks.back());
672 rDeckDescriptor.msTitle = getString(aChildNode, "UIName");
673 rDeckDescriptor.msId = rsNodeName;
674 rDeckDescriptor.msIconURL = getString(aChildNode, "ImageURL");
675 rDeckDescriptor.msHighContrastIconURL = rDeckDescriptor.msIconURL;
676 rDeckDescriptor.msTitleBarIconURL.clear();
677 rDeckDescriptor.msHighContrastTitleBarIconURL.clear();
678 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
679 rDeckDescriptor.mbIsEnabled = true;
680 rDeckDescriptor.mnOrderIndex = 100000 + nReadIndex;
681 rDeckDescriptor.maContextList.AddContextDescription(Context(sModuleName, "any"), true, OUString());
683 maPanels.push_back(std::make_shared<PanelDescriptor>());
684 PanelDescriptor& rPanelDescriptor(*maPanels.back());
685 rPanelDescriptor.msTitle = getString(aChildNode, "UIName");
686 rPanelDescriptor.mbIsTitleBarOptional = true;
687 rPanelDescriptor.msId = rsNodeName;
688 rPanelDescriptor.msDeckId = rsNodeName;
689 rPanelDescriptor.msTitleBarIconURL.clear();
690 rPanelDescriptor.msHighContrastTitleBarIconURL.clear();
691 rPanelDescriptor.msImplementationURL = rsNodeName;
692 rPanelDescriptor.mnOrderIndex = 100000 + nReadIndex;
693 rPanelDescriptor.mbShowForReadOnlyDocuments = false;
694 rPanelDescriptor.mbWantsCanvas = false;
695 rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, "any"), true, OUString());
699 void ResourceManager::StorePanelExpansionState (
700 const OUString& rsPanelId,
701 const bool bExpansionState,
702 const Context& rContext)
704 for (auto const& panel : maPanels)
706 if (panel->msId == rsPanelId)
708 ContextList::Entry* pEntry(panel->maContextList.GetMatch(rContext));
709 if (pEntry != nullptr)
710 pEntry->mbIsInitiallyVisible = bExpansionState;
715 utl::OConfigurationTreeRoot ResourceManager::GetLegacyAddonRootNode (const OUString& rsModuleName)
719 const Reference<XComponentContext> xContext(comphelper::getProcessComponentContext());
720 const Reference<frame::XModuleManager2> xModuleAccess = frame::ModuleManager::create(xContext);
721 const comphelper::NamedValueCollection aModuleProperties(xModuleAccess->getByName(rsModuleName));
722 const OUString sWindowStateRef(aModuleProperties.getOrDefault(
723 "ooSetupFactoryWindowStateConfigRef",
724 OUString()));
726 OUString aPathComposer = "org.openoffice.Office.UI." + sWindowStateRef +
727 "/UIElements/States";
729 return utl::OConfigurationTreeRoot(xContext, aPathComposer, false);
731 catch (const Exception&)
733 DBG_UNHANDLED_EXCEPTION("sfx.sidebar");
736 return utl::OConfigurationTreeRoot();
739 void ResourceManager::GetToolPanelNodeNames (
740 std::vector<OUString>& rMatchingNames,
741 const utl::OConfigurationTreeRoot& aRoot)
743 Sequence<OUString> aChildNodeNames (aRoot.getNodeNames());
744 std::copy_if(aChildNodeNames.begin(), aChildNodeNames.end(), std::back_inserter(rMatchingNames),
745 [](const OUString& rChildNodeName) { return rChildNodeName.startsWith( "private:resource/toolpanel/" ); });
748 bool ResourceManager::IsDeckEnabled (
749 const OUString& rsDeckId,
750 const Context& rContext,
751 const Reference<frame::XController>& rxController)
754 // Check if any panel that matches the current context can be
755 // displayed.
756 PanelContextDescriptorContainer aPanelContextDescriptors;
758 GetMatchingPanels(aPanelContextDescriptors, rContext, rsDeckId, rxController);
760 for (auto const& panelContextDescriptor : aPanelContextDescriptors)
762 if (panelContextDescriptor.mbShowForReadOnlyDocuments)
763 return true;
765 return false;
768 void ResourceManager::UpdateModel(const css::uno::Reference<css::frame::XModel>& xModel)
770 for (auto const& deck : maDecks)
772 if (!deck->mpDeck)
773 continue;
775 const SharedPanelContainer& rContainer = deck->mpDeck->GetPanels();
777 for (auto const& elem : rContainer)
779 css::uno::Reference<css::ui::XUpdateModel> xPanel(elem->GetPanelComponent(), css::uno::UNO_QUERY);
780 if (xPanel.is()) // tdf#108814 interface is optional
782 xPanel->updateModel(xModel);
788 void ResourceManager::disposeDecks()
790 for (auto const& deck : maDecks)
792 deck->mpDeck.disposeAndClear();
796 } // end of namespace sfx2::sidebar
798 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */