1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
45 using namespace css::uno
;
47 namespace sfx2::sidebar
{
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());
72 for (auto const& entry
: entries
)
74 OUString appName
= entry
.maContext
.msApplication
;
75 OUString contextName
= entry
.maContext
.msContext
;
76 OUString menuCommand
= entry
.msMenuCommand
;
79 if (entry
.mbIsInitiallyVisible
)
80 visibility
= "visible";
82 visibility
= "hidden";
84 OUString element
= appName
+ ", " + contextName
+", " + visibility
;
86 if (!menuCommand
.isEmpty())
87 element
+= ", "+menuCommand
;
98 } //end anonymous namespace
100 ResourceManager::ResourceManager()
103 maProcessedApplications()
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
);
122 bIsEnabled
= pMatchingEntry
->mbIsInitiallyVisible
;
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())
136 if (deck
->msId
== rsDeckId
)
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
)
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())
176 const DeckDescriptor
& rDeckDescriptor (*deck
);
177 if (rDeckDescriptor
.maContextList
.GetMatch(rContext
) == nullptr)
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
);
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())
212 if ( rPanelDescriptor
.msDeckId
!= sDeckId
)
215 const ContextList::Entry
* pEntry
= rPanelDescriptor
.maContextList
.GetMatch(rContext
);
216 if (pEntry
== nullptr)
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
);
235 const OUString
& ResourceManager::GetLastActiveDeck( const Context
& rContext
)
237 if( maLastActiveDecks
.find( rContext
.msApplication
) == maLastActiveDecks
.end())
238 return maLastActiveDecks
["any"];
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",
254 if (!aDeckRootNode
.isValid())
257 const Sequence
<OUString
> aDeckNodeNames (aDeckRootNode
.getNodeNames());
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")
269 const utl::OConfigurationNode
aDeckNode(aDeckRootNode
.openNode(aDeckName
));
270 if (!aDeckNode
.isValid())
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
;
290 rDeckDescriptor
.maContextList
,
296 void ResourceManager::SaveDecksSettings(const Context
& rContext
)
298 for (auto const& deck
: maDecks
)
300 const ContextList::Entry
* pMatchingEntry
= deck
->maContextList
.GetMatch(rContext
);
303 std::shared_ptr
<DeckDescriptor
> xDeckDesc
= GetDeckDescriptor(deck
->msId
);
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",
317 if (!aDeckRootNode
.isValid())
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
);
336 if (aOrder
!= aDeckNode
.getNodeValue("OrderIndex"))
338 aDeckNode
.setNodeValue("OrderIndex", aOrder
);
341 if (aContextList
!= aDeckNode
.getNodeValue("ContextList"))
343 aDeckNode
.setNodeValue("ContextList", aContextList
);
348 aDeckRootNode
.commit();
350 // save panel settings
352 const utl::OConfigurationTreeRoot
aPanelRootNode(
353 comphelper::getProcessComponentContext(),
354 "org.openoffice.Office.UI.Sidebar/Content/PanelList",
357 if (!aPanelRootNode
.isValid())
360 if (!pDeckDesc
->mpDeck
) // the deck has not been edited
363 SharedPanelContainer rPanels
= pDeckDesc
->mpDeck
->GetPanels();
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
);
384 if (aOrder
!= aPanelNode
.getNodeValue("OrderIndex"))
386 aPanelNode
.setNodeValue("OrderIndex", aOrder
);
389 if (aContextList
!= aPanelNode
.getNodeValue("ContextList"))
391 aPanelNode
.setNodeValue("ContextList", aContextList
);
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
);
415 void ResourceManager::ReadPanelList()
417 const utl::OConfigurationTreeRoot
aPanelRootNode(
418 comphelper::getProcessComponentContext(),
419 "org.openoffice.Office.UI.Sidebar/Content/PanelList",
421 if (!aPanelRootNode
.isValid())
424 const Sequence
<OUString
> aPanelNodeNames (aPanelRootNode
.getNodeNames());
426 for (const auto& rPanelNodeName
: aPanelNodeNames
)
428 const utl::OConfigurationNode
aPanelNode (aPanelRootNode
.openNode(rPanelNodeName
));
429 if (!aPanelNode
.isValid())
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")
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");
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
))
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.
511 OSL_FAIL("expecting three or four values per ContextList entry, separated by comma");
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");
523 const OUString
sInitialState(sValue
.getToken(0, ',', nCharacterIndex
).trim());
525 // The fourth argument is optional.
526 const OUString
sMenuCommandOverride(
529 : sValue
.getToken(0, ',', nCharacterIndex
).trim());
531 const OUString
sMenuCommand(
532 sMenuCommandOverride
.getLength() > 0
533 ? (sMenuCommandOverride
== "none"
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
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
);
581 SAL_WARN("sfx.sidebar", "application name " << sApplicationName
<< " not recognized");
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");
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;
608 OSL_FAIL("unrecognized state");
613 // Add context descriptors.
614 for (auto const& application
: aApplications
)
616 if (application
!= vcl::EnumContext::Application::NONE
)
618 rContextList
.AddContextDescription(
620 vcl::EnumContext::GetApplicationName(application
),
621 vcl::EnumContext::GetContextName(eContext
)),
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)
635 if (maProcessedApplications
.find(sModuleName
) != maProcessedApplications
.end())
637 // Addons for this application have already been read.
638 // There is nothing more to do.
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())
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())
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" )
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",
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
756 PanelContextDescriptorContainer aPanelContextDescriptors
;
758 GetMatchingPanels(aPanelContextDescriptors
, rContext
, rsDeckId
, rxController
);
760 for (auto const& panelContextDescriptor
: aPanelContextDescriptors
)
762 if (panelContextDescriptor
.mbShowForReadOnlyDocuments
)
768 void ResourceManager::UpdateModel(const css::uno::Reference
<css::frame::XModel
>& xModel
)
770 for (auto const& deck
: maDecks
)
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: */