LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / sidebar / ResourceManager.cxx
blob4c9ea97a03098da495df2571e58de864464ea84e
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 auto resultRange = asNonConstRange(result);
71 tools::Long i = 0;
73 for (auto const& entry : entries)
75 OUString appName = entry.maContext.msApplication;
76 OUString contextName = entry.maContext.msContext;
77 OUString menuCommand = entry.msMenuCommand;
79 OUString visibility;
80 if (entry.mbIsInitiallyVisible)
81 visibility = "visible";
82 else
83 visibility = "hidden";
85 OUString element = appName + ", " + contextName +", " + visibility;
87 if (!menuCommand.isEmpty())
88 element += ", "+menuCommand;
90 resultRange[i] = element;
92 ++i;
95 return result;
99 } //end anonymous namespace
101 ResourceManager::ResourceManager()
103 ReadDeckList();
104 ReadPanelList();
105 ReadLastActive();
108 ResourceManager::~ResourceManager()
112 void ResourceManager::InitDeckContext(const Context& rContext)
114 for (auto const& deck : maDecks)
116 const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext);
118 bool bIsEnabled;
119 if (pMatchingEntry)
120 bIsEnabled = pMatchingEntry->mbIsInitiallyVisible;
121 else
122 bIsEnabled = false;
124 deck->mbIsEnabled = bIsEnabled;
128 std::shared_ptr<DeckDescriptor> ResourceManager::ImplGetDeckDescriptor(std::u16string_view rsDeckId) const
130 for (auto const& deck : maDecks)
132 if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
133 continue;
134 if (deck->msId == rsDeckId)
135 return deck;
137 return nullptr;
140 std::shared_ptr<DeckDescriptor> ResourceManager::GetDeckDescriptor(std::u16string_view rsDeckId) const
142 return ImplGetDeckDescriptor( rsDeckId );
145 std::shared_ptr<PanelDescriptor> ResourceManager::ImplGetPanelDescriptor(std::u16string_view rsPanelId) const
147 for (auto const& panel : maPanels)
149 if (panel->msId == rsPanelId)
150 return panel;
152 return nullptr;
155 std::shared_ptr<PanelDescriptor> ResourceManager::GetPanelDescriptor(std::u16string_view rsPanelId) const
157 return ImplGetPanelDescriptor( rsPanelId );
160 const ResourceManager::DeckContextDescriptorContainer& ResourceManager::GetMatchingDecks (
161 DeckContextDescriptorContainer& rDecks,
162 const Context& rContext,
163 const bool bIsDocumentReadOnly,
164 const Reference<frame::XController>& rxController)
166 ReadLegacyAddons(rxController);
168 std::multimap<sal_Int32,DeckContextDescriptor> aOrderedIds;
169 for (auto const& deck : maDecks)
171 if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
172 continue;
174 const DeckDescriptor& rDeckDescriptor (*deck);
175 if (rDeckDescriptor.maContextList.GetMatch(rContext) == nullptr)
176 continue;
178 DeckContextDescriptor aDeckContextDescriptor;
179 aDeckContextDescriptor.msId = rDeckDescriptor.msId;
181 aDeckContextDescriptor.mbIsEnabled = (! bIsDocumentReadOnly || IsDeckEnabled(rDeckDescriptor.msId, rContext, rxController) )
182 && rDeckDescriptor.mbIsEnabled;
185 aOrderedIds.emplace(rDeckDescriptor.mnOrderIndex, aDeckContextDescriptor);
188 for (auto const& orderId : aOrderedIds)
190 rDecks.push_back(orderId.second);
193 return rDecks;
196 const ResourceManager::PanelContextDescriptorContainer& ResourceManager::GetMatchingPanels (
197 PanelContextDescriptorContainer& rPanelIds,
198 const Context& rContext,
199 std::u16string_view sDeckId,
200 const Reference<frame::XController>& rxController)
202 ReadLegacyAddons(rxController);
204 std::multimap<sal_Int32, PanelContextDescriptor> aOrderedIds;
205 for (auto const& panel : maPanels)
207 const PanelDescriptor& rPanelDescriptor (*panel);
208 if (rPanelDescriptor.mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
209 continue;
210 if ( rPanelDescriptor.msDeckId != sDeckId )
211 continue;
213 const ContextList::Entry* pEntry = rPanelDescriptor.maContextList.GetMatch(rContext);
214 if (pEntry == nullptr)
215 continue;
217 PanelContextDescriptor aPanelContextDescriptor;
218 aPanelContextDescriptor.msId = rPanelDescriptor.msId;
219 aPanelContextDescriptor.msMenuCommand = pEntry->msMenuCommand;
220 aPanelContextDescriptor.mbIsInitiallyVisible = pEntry->mbIsInitiallyVisible;
221 aPanelContextDescriptor.mbShowForReadOnlyDocuments = rPanelDescriptor.mbShowForReadOnlyDocuments;
222 aOrderedIds.emplace(rPanelDescriptor.mnOrderIndex, aPanelContextDescriptor);
225 for (auto const& orderId : aOrderedIds)
227 rPanelIds.push_back(orderId.second);
230 return rPanelIds;
233 const OUString& ResourceManager::GetLastActiveDeck( const Context& rContext )
235 if( maLastActiveDecks.find( rContext.msApplication ) == maLastActiveDecks.end())
236 return maLastActiveDecks["any"];
237 else
238 return maLastActiveDecks[rContext.msApplication];
241 void ResourceManager::SetLastActiveDeck( const Context& rContext, const OUString &rsDeckId )
243 maLastActiveDecks[rContext.msApplication] = rsDeckId;
246 void ResourceManager::ReadDeckList()
248 const utl::OConfigurationTreeRoot aDeckRootNode(
249 comphelper::getProcessComponentContext(),
250 "org.openoffice.Office.UI.Sidebar/Content/DeckList",
251 false);
252 if (!aDeckRootNode.isValid())
253 return;
255 const Sequence<OUString> aDeckNodeNames (aDeckRootNode.getNodeNames());
256 maDecks.clear();
257 for (const OUString& aDeckName : aDeckNodeNames)
259 if (comphelper::LibreOfficeKit::isActive())
261 // Hide these decks in LOK as they aren't fully functional.
262 if (aDeckName == "GalleryDeck" || aDeckName == "NavigatorDeck"
263 || aDeckName == "StyleListDeck")
264 continue;
267 const utl::OConfigurationNode aDeckNode(aDeckRootNode.openNode(aDeckName));
268 if (!aDeckNode.isValid())
269 continue;
271 maDecks.push_back(std::make_shared<DeckDescriptor>());
272 DeckDescriptor& rDeckDescriptor (*maDecks.back());
274 rDeckDescriptor.msTitle = getString(aDeckNode, "Title");
275 rDeckDescriptor.msId = getString(aDeckNode, "Id");
276 rDeckDescriptor.msIconURL = getString(aDeckNode, "IconURL");
277 rDeckDescriptor.msHighContrastIconURL = getString(aDeckNode, "HighContrastIconURL");
278 rDeckDescriptor.msTitleBarIconURL = getString(aDeckNode, "TitleBarIconURL");
279 rDeckDescriptor.msHighContrastTitleBarIconURL = getString(aDeckNode, "HighContrastTitleBarIconURL");
280 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
281 rDeckDescriptor.mnOrderIndex = getInt32(aDeckNode, "OrderIndex");
282 rDeckDescriptor.mbExperimental = getBool(aDeckNode, "IsExperimental");
284 rDeckDescriptor.msNodeName = aDeckName;
286 ReadContextList(
287 aDeckNode,
288 rDeckDescriptor.maContextList,
289 OUString());
294 void ResourceManager::SaveDecksSettings(const Context& rContext)
296 for (auto const& deck : maDecks)
298 const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext);
299 if (pMatchingEntry)
301 std::shared_ptr<DeckDescriptor> xDeckDesc = GetDeckDescriptor(deck->msId);
302 if (xDeckDesc)
303 SaveDeckSettings(xDeckDesc.get());
309 void ResourceManager::SaveDeckSettings(const DeckDescriptor* pDeckDesc)
311 const utl::OConfigurationTreeRoot aDeckRootNode(
312 comphelper::getProcessComponentContext(),
313 "org.openoffice.Office.UI.Sidebar/Content/DeckList",
314 true);
315 if (!aDeckRootNode.isValid())
316 return;
318 // save deck settings
320 ::uno::Sequence< OUString > sContextList = BuildContextList(pDeckDesc->maContextList);
322 utl::OConfigurationNode aDeckNode (aDeckRootNode.openNode(pDeckDesc->msNodeName));
324 css::uno::Any aTitle(makeAny(pDeckDesc->msTitle));
325 css::uno::Any aOrder(makeAny(pDeckDesc->mnOrderIndex));
326 css::uno::Any aContextList(makeAny(sContextList));
328 bool bChanged = false;
329 if (aTitle != aDeckNode.getNodeValue("Title"))
331 aDeckNode.setNodeValue("Title", aTitle);
332 bChanged = true;
334 if (aOrder != aDeckNode.getNodeValue("OrderIndex"))
336 aDeckNode.setNodeValue("OrderIndex", aOrder);
337 bChanged = true;
339 if (aContextList != aDeckNode.getNodeValue("ContextList"))
341 aDeckNode.setNodeValue("ContextList", aContextList);
342 bChanged = true;
345 if (bChanged)
346 aDeckRootNode.commit();
348 // save panel settings
350 const utl::OConfigurationTreeRoot aPanelRootNode(
351 comphelper::getProcessComponentContext(),
352 "org.openoffice.Office.UI.Sidebar/Content/PanelList",
353 true);
355 if (!aPanelRootNode.isValid())
356 return;
358 if (!pDeckDesc->mpDeck) // the deck has not been edited
359 return;
361 SharedPanelContainer rPanels = pDeckDesc->mpDeck->GetPanels();
363 bChanged = false;
364 for (auto const& panel : rPanels)
366 OUString panelId = panel->GetId();
367 std::shared_ptr<PanelDescriptor> xPanelDesc = GetPanelDescriptor(panelId);
369 ::uno::Sequence< OUString > sPanelContextList = BuildContextList(xPanelDesc->maContextList);
371 utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(xPanelDesc->msNodeName));
373 aTitle <<= xPanelDesc->msTitle;
374 aOrder <<= xPanelDesc->mnOrderIndex;
375 aContextList <<= sPanelContextList;
377 if (aTitle != aPanelNode.getNodeValue("Title"))
379 aPanelNode.setNodeValue("Title", aTitle);
380 bChanged = true;
382 if (aOrder != aPanelNode.getNodeValue("OrderIndex"))
384 aPanelNode.setNodeValue("OrderIndex", aOrder);
385 bChanged = true;
387 if (aContextList != aPanelNode.getNodeValue("ContextList"))
389 aPanelNode.setNodeValue("ContextList", aContextList);
390 bChanged = true;
394 if (bChanged)
395 aPanelRootNode.commit();
398 void ResourceManager::SaveLastActiveDeck(const Context& rContext, const OUString& rActiveDeck)
400 maLastActiveDecks[rContext.msApplication] = rActiveDeck;
402 std::set<OUString> aLastActiveDecks;
403 for ( auto const & rEntry : maLastActiveDecks )
404 aLastActiveDecks.insert( rEntry.first + "," + rEntry.second);
406 std::shared_ptr<comphelper::ConfigurationChanges> cfgWriter( comphelper::ConfigurationChanges::create() );
408 officecfg::Office::UI::Sidebar::Content::LastActiveDeck::set(comphelper::containerToSequence(aLastActiveDecks), cfgWriter);
409 cfgWriter->commit();
413 void ResourceManager::ReadPanelList()
415 const utl::OConfigurationTreeRoot aPanelRootNode(
416 comphelper::getProcessComponentContext(),
417 "org.openoffice.Office.UI.Sidebar/Content/PanelList",
418 false);
419 if (!aPanelRootNode.isValid())
420 return;
422 const Sequence<OUString> aPanelNodeNames (aPanelRootNode.getNodeNames());
423 maPanels.clear();
424 for (const auto& rPanelNodeName : aPanelNodeNames)
426 const utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(rPanelNodeName));
427 if (!aPanelNode.isValid())
428 continue;
430 if (comphelper::LibreOfficeKit::isActive())
432 // Hide these panels in LOK as they aren't fully functional.
433 OUString aPanelId = getString(aPanelNode, "Id");
434 if (aPanelId == "PageStylesPanel" || aPanelId == "PageHeaderPanel"
435 || aPanelId == "PageFooterPanel")
436 continue;
439 maPanels.push_back(std::make_shared<PanelDescriptor>());
440 PanelDescriptor& rPanelDescriptor(*maPanels.back());
442 rPanelDescriptor.msTitle = getString(aPanelNode, "Title");
443 rPanelDescriptor.mbIsTitleBarOptional = getBool(aPanelNode, "TitleBarIsOptional");
444 rPanelDescriptor.msId = getString(aPanelNode, "Id");
445 rPanelDescriptor.msDeckId = getString(aPanelNode, "DeckId");
446 rPanelDescriptor.msTitleBarIconURL = getString(aPanelNode, "TitleBarIconURL");
447 rPanelDescriptor.msHighContrastTitleBarIconURL = getString(aPanelNode, "HighContrastTitleBarIconURL");
448 rPanelDescriptor.msImplementationURL = getString(aPanelNode, "ImplementationURL");
449 rPanelDescriptor.mnOrderIndex = getInt32(aPanelNode, "OrderIndex");
450 rPanelDescriptor.mbShowForReadOnlyDocuments = getBool(aPanelNode, "ShowForReadOnlyDocument");
451 rPanelDescriptor.mbWantsCanvas = getBool(aPanelNode, "WantsCanvas");
452 rPanelDescriptor.mbWantsAWT = getBool(aPanelNode, "WantsAWT");
453 rPanelDescriptor.mbExperimental = getBool(aPanelNode, "IsExperimental");
454 const OUString sDefaultMenuCommand(getString(aPanelNode, "DefaultMenuCommand"));
456 rPanelDescriptor.msNodeName = rPanelNodeName;
458 ReadContextList(aPanelNode, rPanelDescriptor.maContextList, sDefaultMenuCommand);
462 void ResourceManager::ReadLastActive()
464 const Sequence <OUString> aLastActive (officecfg::Office::UI::Sidebar::Content::LastActiveDeck::get());
466 for (const auto& rDeckInfo : aLastActive)
468 sal_Int32 nCharIdx = rDeckInfo.lastIndexOf(',');
469 if ( nCharIdx <= 0 || (nCharIdx == rDeckInfo.getLength() - 1) )
471 SAL_WARN("sfx.sidebar", "Expecting 2 values separated by comma");
472 continue;
475 const OUString sApplicationName = rDeckInfo.copy( 0, nCharIdx );
476 vcl::EnumContext::Application eApplication (vcl::EnumContext::GetApplicationEnum(sApplicationName));
477 const OUString sLastUsed = rDeckInfo.copy( nCharIdx + 1 );
479 // guard against garbage in place of application
480 if (eApplication != vcl::EnumContext::Application::NONE)
481 maLastActiveDecks.insert( std::make_pair(sApplicationName, sLastUsed ) );
484 // Set up a default for Math - will do nothing if already set
485 maLastActiveDecks.emplace(
486 vcl::EnumContext::GetApplicationName(vcl::EnumContext::Application::Formula),
487 "ElementsDeck");
490 void ResourceManager::ReadContextList (
491 const utl::OConfigurationNode& rParentNode,
492 ContextList& rContextList,
493 const OUString& rsDefaultMenuCommand)
495 const Any aValue = rParentNode.getNodeValue("ContextList");
496 Sequence<OUString> aValues;
497 if (!(aValue >>= aValues))
498 return;
500 for (const OUString& sValue : std::as_const(aValues))
502 sal_Int32 nCharacterIndex (0);
503 const OUString sApplicationName (sValue.getToken(0, ',', nCharacterIndex).trim());
504 if (nCharacterIndex < 0)
506 if (sApplicationName.getLength() == 0)
508 // This is a valid case: in the XML file the separator
509 // was used as terminator. Using it in the last line
510 // creates an additional but empty entry.
511 break;
513 else
515 OSL_FAIL("expecting three or four values per ContextList entry, separated by comma");
516 continue;
520 const OUString sContextName(sValue.getToken(0, ',', nCharacterIndex).trim());
521 if (nCharacterIndex < 0)
523 OSL_FAIL("expecting three or four values per ContextList entry, separated by comma");
524 continue;
527 const OUString sInitialState(sValue.getToken(0, ',', nCharacterIndex).trim());
529 // The fourth argument is optional.
530 const OUString sMenuCommandOverride(
531 nCharacterIndex < 0
532 ? OUString()
533 : sValue.getToken(0, ',', nCharacterIndex).trim());
535 const OUString sMenuCommand(
536 sMenuCommandOverride.getLength() > 0
537 ? (sMenuCommandOverride == "none"
538 ? OUString()
539 : sMenuCommandOverride)
540 : rsDefaultMenuCommand);
542 // Setup a list of application enums. Note that the
543 // application name may result in more than one value (eg
544 // DrawImpress will result in two enums, one for Draw and one
545 // for Impress).
546 std::vector<vcl::EnumContext::Application> aApplications;
547 vcl::EnumContext::Application eApplication (vcl::EnumContext::GetApplicationEnum(sApplicationName));
549 if (eApplication == vcl::EnumContext::Application::NONE
550 && sApplicationName != vcl::EnumContext::GetApplicationName(vcl::EnumContext::Application::NONE))
552 // Handle some special names: abbreviations that make
553 // context descriptions more readable.
554 if (sApplicationName == "Writer")
555 aApplications.push_back(vcl::EnumContext::Application::Writer);
556 else if (sApplicationName == "Calc")
557 aApplications.push_back(vcl::EnumContext::Application::Calc);
558 else if (sApplicationName == "Draw")
559 aApplications.push_back(vcl::EnumContext::Application::Draw);
560 else if (sApplicationName == "Impress")
561 aApplications.push_back(vcl::EnumContext::Application::Impress);
562 else if (sApplicationName == "Chart")
563 aApplications.push_back(vcl::EnumContext::Application::Chart);
564 else if (sApplicationName == "Math")
565 aApplications.push_back(vcl::EnumContext::Application::Formula);
566 else if (sApplicationName == "DrawImpress")
568 // A special case among the special names: it is
569 // common to use the same context descriptions for
570 // both Draw and Impress. This special case helps to
571 // avoid duplication in the .xcu file.
572 aApplications.push_back(vcl::EnumContext::Application::Draw);
573 aApplications.push_back(vcl::EnumContext::Application::Impress);
575 else if (sApplicationName == "WriterVariants")
577 // Another special case for all Writer variants.
578 aApplications.push_back(vcl::EnumContext::Application::Writer);
579 aApplications.push_back(vcl::EnumContext::Application::WriterGlobal);
580 aApplications.push_back(vcl::EnumContext::Application::WriterWeb);
581 aApplications.push_back(vcl::EnumContext::Application::WriterXML);
582 aApplications.push_back(vcl::EnumContext::Application::WriterForm);
583 aApplications.push_back(vcl::EnumContext::Application::WriterReport);
585 else
587 SAL_WARN("sfx.sidebar", "application name " << sApplicationName << " not recognized");
588 continue;
591 else
593 // No conversion of the application name necessary.
594 aApplications.push_back(eApplication);
597 // Setup the actual context enum.
598 const vcl::EnumContext::Context eContext (vcl::EnumContext::GetContextEnum(sContextName));
599 if (eContext == vcl::EnumContext::Context::Unknown)
601 SAL_WARN("sfx.sidebar", "context name " << sContextName << " not recognized");
602 continue;
605 // Setup the flag that controls whether a deck/pane is
606 // initially visible/expanded.
607 bool bIsInitiallyVisible;
608 if (sInitialState == "visible")
609 bIsInitiallyVisible = true;
610 else if (sInitialState == "hidden")
611 bIsInitiallyVisible = false;
612 else
614 OSL_FAIL("unrecognized state");
615 continue;
619 // Add context descriptors.
620 for (auto const& application : aApplications)
622 if (application != vcl::EnumContext::Application::NONE)
624 rContextList.AddContextDescription(
625 Context(
626 vcl::EnumContext::GetApplicationName(application),
627 vcl::EnumContext::GetContextName(eContext)),
628 bIsInitiallyVisible,
629 sMenuCommand);
635 void ResourceManager::ReadLegacyAddons (const Reference<frame::XController>& rxController)
637 // Get module name for given frame.
638 OUString sModuleName (Tools::GetModuleName(rxController));
639 if (sModuleName.getLength() == 0)
640 return;
641 if (maProcessedApplications.find(sModuleName) != maProcessedApplications.end())
643 // Addons for this application have already been read.
644 // There is nothing more to do.
645 return;
648 // Mark module as processed. Even when there is an error that
649 // prevents the configuration data from being read, this error
650 // will not be triggered a second time.
651 maProcessedApplications.insert(sModuleName);
653 // Get access to the configuration root node for the application.
654 utl::OConfigurationTreeRoot aLegacyRootNode (GetLegacyAddonRootNode(sModuleName));
655 if (!aLegacyRootNode.isValid())
656 return;
658 // Process child nodes.
659 std::vector<OUString> aMatchingNodeNames;
660 GetToolPanelNodeNames(aMatchingNodeNames, aLegacyRootNode);
661 const sal_Int32 nCount (aMatchingNodeNames.size());
662 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex)
664 const OUString& rsNodeName (aMatchingNodeNames[nReadIndex]);
665 const utl::OConfigurationNode aChildNode (aLegacyRootNode.openNode(rsNodeName));
666 if (!aChildNode.isValid())
667 continue;
669 if ( rsNodeName == "private:resource/toolpanel/DrawingFramework/CustomAnimations" ||
670 rsNodeName == "private:resource/toolpanel/DrawingFramework/Layouts" ||
671 rsNodeName == "private:resource/toolpanel/DrawingFramework/MasterPages" ||
672 rsNodeName == "private:resource/toolpanel/DrawingFramework/SlideTransitions" ||
673 rsNodeName == "private:resource/toolpanel/DrawingFramework/TableDesign" )
674 continue;
676 maDecks.push_back(std::make_shared<DeckDescriptor>());
677 DeckDescriptor& rDeckDescriptor(*maDecks.back());
678 rDeckDescriptor.msTitle = getString(aChildNode, "UIName");
679 rDeckDescriptor.msId = rsNodeName;
680 rDeckDescriptor.msIconURL = getString(aChildNode, "ImageURL");
681 rDeckDescriptor.msHighContrastIconURL = rDeckDescriptor.msIconURL;
682 rDeckDescriptor.msTitleBarIconURL.clear();
683 rDeckDescriptor.msHighContrastTitleBarIconURL.clear();
684 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
685 rDeckDescriptor.mbIsEnabled = true;
686 rDeckDescriptor.mnOrderIndex = 100000 + nReadIndex;
687 rDeckDescriptor.maContextList.AddContextDescription(Context(sModuleName, "any"), true, OUString());
689 maPanels.push_back(std::make_shared<PanelDescriptor>());
690 PanelDescriptor& rPanelDescriptor(*maPanels.back());
691 rPanelDescriptor.msTitle = getString(aChildNode, "UIName");
692 rPanelDescriptor.mbIsTitleBarOptional = true;
693 rPanelDescriptor.msId = rsNodeName;
694 rPanelDescriptor.msDeckId = rsNodeName;
695 rPanelDescriptor.msTitleBarIconURL.clear();
696 rPanelDescriptor.msHighContrastTitleBarIconURL.clear();
697 rPanelDescriptor.msImplementationURL = rsNodeName;
698 rPanelDescriptor.mnOrderIndex = 100000 + nReadIndex;
699 rPanelDescriptor.mbShowForReadOnlyDocuments = false;
700 rPanelDescriptor.mbWantsCanvas = false;
701 rPanelDescriptor.mbWantsAWT = true;
702 fprintf(stderr, "THIS PLACE\n");
703 rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, "any"), true, OUString());
707 void ResourceManager::StorePanelExpansionState (
708 std::u16string_view rsPanelId,
709 const bool bExpansionState,
710 const Context& rContext)
712 for (auto const& panel : maPanels)
714 if (panel->msId == rsPanelId)
716 ContextList::Entry* pEntry(panel->maContextList.GetMatch(rContext));
717 if (pEntry != nullptr)
718 pEntry->mbIsInitiallyVisible = bExpansionState;
723 utl::OConfigurationTreeRoot ResourceManager::GetLegacyAddonRootNode (const OUString& rsModuleName)
727 const Reference<XComponentContext> xContext(comphelper::getProcessComponentContext());
728 const Reference<frame::XModuleManager2> xModuleAccess = frame::ModuleManager::create(xContext);
729 const comphelper::NamedValueCollection aModuleProperties(xModuleAccess->getByName(rsModuleName));
730 const OUString sWindowStateRef(aModuleProperties.getOrDefault(
731 "ooSetupFactoryWindowStateConfigRef",
732 OUString()));
734 OUString aPathComposer = "org.openoffice.Office.UI." + sWindowStateRef +
735 "/UIElements/States";
737 return utl::OConfigurationTreeRoot(xContext, aPathComposer, false);
739 catch (const Exception&)
741 DBG_UNHANDLED_EXCEPTION("sfx.sidebar");
744 return utl::OConfigurationTreeRoot();
747 void ResourceManager::GetToolPanelNodeNames (
748 std::vector<OUString>& rMatchingNames,
749 const utl::OConfigurationTreeRoot& aRoot)
751 const Sequence<OUString> aChildNodeNames (aRoot.getNodeNames());
752 std::copy_if(aChildNodeNames.begin(), aChildNodeNames.end(), std::back_inserter(rMatchingNames),
753 [](const OUString& rChildNodeName) { return rChildNodeName.startsWith( "private:resource/toolpanel/" ); });
756 bool ResourceManager::IsDeckEnabled (
757 std::u16string_view rsDeckId,
758 const Context& rContext,
759 const Reference<frame::XController>& rxController)
762 // Check if any panel that matches the current context can be
763 // displayed.
764 PanelContextDescriptorContainer aPanelContextDescriptors;
766 GetMatchingPanels(aPanelContextDescriptors, rContext, rsDeckId, rxController);
768 for (auto const& panelContextDescriptor : aPanelContextDescriptors)
770 if (panelContextDescriptor.mbShowForReadOnlyDocuments)
771 return true;
773 return false;
776 void ResourceManager::UpdateModel(const css::uno::Reference<css::frame::XModel>& xModel)
778 for (auto const& deck : maDecks)
780 if (!deck->mpDeck)
781 continue;
783 const SharedPanelContainer& rContainer = deck->mpDeck->GetPanels();
785 for (auto const& elem : rContainer)
787 css::uno::Reference<css::ui::XUpdateModel> xPanel(elem->GetPanelComponent(), css::uno::UNO_QUERY);
788 if (xPanel.is()) // tdf#108814 interface is optional
790 xPanel->updateModel(xModel);
796 void ResourceManager::disposeDecks()
798 for (auto const& deck : maDecks)
800 deck->mpDeck.disposeAndClear();
804 } // end of namespace sfx2::sidebar
806 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */