LibreOffice Module sfx2 (master) 1
ResourceManager.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
23#include <sidebar/Tools.hxx>
24
25#include <officecfg/Office/Common.hxx>
26#include <officecfg/Office/UI/Sidebar.hxx>
28#include <comphelper/lok.hxx>
32#include <comphelper/types.hxx>
33
35#include <sal/log.hxx>
36#include <vcl/EnumContext.hxx>
37#include <o3tl/string_view.hxx>
38
39#include <com/sun/star/frame/ModuleManager.hpp>
40#include <com/sun/star/ui/XSidebarPanel.hpp>
41#include <com/sun/star/ui/XUpdateModel.hpp>
42
43#include <map>
44
45using namespace css;
46using namespace css::uno;
47
48namespace sfx2::sidebar {
49
50namespace
51{
52
53OUString getString(utl::OConfigurationNode const & aNode, const char* pNodeName)
54{
55 return comphelper::getString(aNode.getNodeValue(pNodeName));
56}
57sal_Int32 getInt32(utl::OConfigurationNode const & aNode, const char* pNodeName)
58{
59 return comphelper::getINT32(aNode.getNodeValue(pNodeName));
60}
61bool getBool(utl::OConfigurationNode const & aNode, const char* pNodeName)
62{
63 return comphelper::getBOOL(aNode.getNodeValue(pNodeName));
64}
65
66css::uno::Sequence<OUString> BuildContextList (const ContextList& rContextList)
67{
68 const ::std::vector<ContextList::Entry>& entries = rContextList.GetEntries();
69
70 css::uno::Sequence<OUString> result(entries.size());
71 auto resultRange = asNonConstRange(result);
72 tools::Long i = 0;
73
74 for (auto const& entry : entries)
75 {
76 OUString appName = entry.maContext.msApplication;
77 OUString contextName = entry.maContext.msContext;
78 OUString menuCommand = entry.msMenuCommand;
79
80 OUString visibility;
81 if (entry.mbIsInitiallyVisible)
82 visibility = "visible";
83 else
84 visibility = "hidden";
85
86 OUString element = appName + ", " + contextName +", " + visibility;
87
88 if (!menuCommand.isEmpty())
89 element += ", "+menuCommand;
90
91 resultRange[i] = element;
92
93 ++i;
94 }
95
96 return result;
97
98}
99
100} //end anonymous namespace
101
103{
104 ReadDeckList();
107}
108
110{
111}
112
114{
115 for (auto const& deck : maDecks)
116 {
117 const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext);
118
119 bool bIsEnabled;
120 if (pMatchingEntry)
121 bIsEnabled = pMatchingEntry->mbIsInitiallyVisible;
122 else
123 bIsEnabled = false;
124
125 deck->mbIsEnabled = bIsEnabled;
126 }
127}
128
129std::shared_ptr<DeckDescriptor> ResourceManager::ImplGetDeckDescriptor(std::u16string_view rsDeckId) const
130{
131 for (auto const& deck : maDecks)
132 {
133 if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
134 continue;
135 if (deck->msId == rsDeckId)
136 return deck;
137 }
138 return nullptr;
139}
140
141std::shared_ptr<DeckDescriptor> ResourceManager::GetDeckDescriptor(std::u16string_view rsDeckId) const
142{
143 return ImplGetDeckDescriptor( rsDeckId );
144}
145
146std::shared_ptr<PanelDescriptor> ResourceManager::ImplGetPanelDescriptor(std::u16string_view rsPanelId) const
147{
148 for (auto const& panel : maPanels)
149 {
150 if (panel->msId == rsPanelId)
151 return panel;
152 }
153 return nullptr;
154}
155
156std::shared_ptr<PanelDescriptor> ResourceManager::GetPanelDescriptor(std::u16string_view rsPanelId) const
157{
158 return ImplGetPanelDescriptor( rsPanelId );
159}
160
163 const Context& rContext,
164 const bool bIsDocumentReadOnly,
165 const Reference<frame::XController>& rxController)
166{
167 ReadLegacyAddons(rxController);
168
169 std::multimap<sal_Int32,DeckContextDescriptor> aOrderedIds;
170 for (auto const& deck : maDecks)
171 {
172 if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
173 continue;
174
175 const DeckDescriptor& rDeckDescriptor (*deck);
176 if (rDeckDescriptor.maContextList.GetMatch(rContext) == nullptr)
177 continue;
178
179 DeckContextDescriptor aDeckContextDescriptor;
180 aDeckContextDescriptor.msId = rDeckDescriptor.msId;
181
182 aDeckContextDescriptor.mbIsEnabled = (! bIsDocumentReadOnly || IsDeckEnabled(rDeckDescriptor.msId, rContext, rxController) )
183 && rDeckDescriptor.mbIsEnabled;
184
185
186 aOrderedIds.emplace(rDeckDescriptor.mnOrderIndex, aDeckContextDescriptor);
187 }
188
189 for (auto const& orderId : aOrderedIds)
190 {
191 rDecks.push_back(orderId.second);
192 }
193
194 return rDecks;
195}
196
199 const Context& rContext,
200 std::u16string_view sDeckId,
201 const Reference<frame::XController>& rxController)
202{
203 ReadLegacyAddons(rxController);
204
205 std::multimap<sal_Int32, PanelContextDescriptor> aOrderedIds;
206 for (auto const& panel : maPanels)
207 {
208 const PanelDescriptor& rPanelDescriptor (*panel);
209 if (rPanelDescriptor.mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
210 continue;
211 if ( rPanelDescriptor.msDeckId != sDeckId )
212 continue;
213
214 const ContextList::Entry* pEntry = rPanelDescriptor.maContextList.GetMatch(rContext);
215 if (pEntry == nullptr)
216 continue;
217
218 PanelContextDescriptor aPanelContextDescriptor;
219 aPanelContextDescriptor.msId = rPanelDescriptor.msId;
220 aPanelContextDescriptor.msMenuCommand = pEntry->msMenuCommand;
221 aPanelContextDescriptor.mbIsInitiallyVisible = pEntry->mbIsInitiallyVisible;
222 aPanelContextDescriptor.mbShowForReadOnlyDocuments = rPanelDescriptor.mbShowForReadOnlyDocuments;
223 aOrderedIds.emplace(rPanelDescriptor.mnOrderIndex, aPanelContextDescriptor);
224 }
225
226 for (auto const& orderId : aOrderedIds)
227 {
228 rPanelIds.push_back(orderId.second);
229 }
230
231 return rPanelIds;
232}
233
234const OUString& ResourceManager::GetLastActiveDeck( const Context& rContext )
235{
236 if( maLastActiveDecks.find( rContext.msApplication ) == maLastActiveDecks.end())
237 return maLastActiveDecks["any"];
238 else
239 return maLastActiveDecks[rContext.msApplication];
240}
241
242void ResourceManager::SetLastActiveDeck( const Context& rContext, const OUString &rsDeckId )
243{
244 maLastActiveDecks[rContext.msApplication] = rsDeckId;
245}
246
248{
249 const utl::OConfigurationTreeRoot aDeckRootNode(
251 "org.openoffice.Office.UI.Sidebar/Content/DeckList",
252 false);
253 if (!aDeckRootNode.isValid())
254 return;
255
256 const Sequence<OUString> aDeckNodeNames (aDeckRootNode.getNodeNames());
257 maDecks.clear();
258 for (const OUString& aDeckName : aDeckNodeNames)
259 {
261 {
262 // Hide these decks in LOK as they aren't fully functional.
263 if (aDeckName == "GalleryDeck" || aDeckName == "StyleListDeck")
264 continue;
265 }
266
267 const utl::OConfigurationNode aDeckNode(aDeckRootNode.openNode(aDeckName));
268 if (!aDeckNode.isValid())
269 continue;
270
271 maDecks.push_back(std::make_shared<DeckDescriptor>());
272 DeckDescriptor& rDeckDescriptor (*maDecks.back());
273
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");
283
284 rDeckDescriptor.msNodeName = aDeckName;
285
287 aDeckNode,
288 rDeckDescriptor.maContextList,
289 OUString());
290
291 }
292}
293
295{
296 for (auto const& deck : maDecks)
297 {
298 const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext);
299 if (pMatchingEntry)
300 {
301 std::shared_ptr<DeckDescriptor> xDeckDesc = GetDeckDescriptor(deck->msId);
302 if (xDeckDesc)
303 SaveDeckSettings(xDeckDesc.get());
304 }
305
306 }
307}
308
310{
311 const utl::OConfigurationTreeRoot aDeckRootNode(
313 "org.openoffice.Office.UI.Sidebar/Content/DeckList",
314 true);
315 if (!aDeckRootNode.isValid())
316 return;
317
318 // save deck settings
319
320 ::uno::Sequence< OUString > sContextList = BuildContextList(pDeckDesc->maContextList);
321
322 utl::OConfigurationNode aDeckNode (aDeckRootNode.openNode(pDeckDesc->msNodeName));
323
324 css::uno::Any aTitle(Any(pDeckDesc->msTitle));
325 css::uno::Any aOrder(Any(pDeckDesc->mnOrderIndex));
326 css::uno::Any aContextList(sContextList);
327
328 bool bChanged = false;
329 if (aTitle != aDeckNode.getNodeValue("Title"))
330 {
331 aDeckNode.setNodeValue("Title", aTitle);
332 bChanged = true;
333 }
334 if (aOrder != aDeckNode.getNodeValue("OrderIndex"))
335 {
336 aDeckNode.setNodeValue("OrderIndex", aOrder);
337 bChanged = true;
338 }
339 if (aContextList != aDeckNode.getNodeValue("ContextList"))
340 {
341 aDeckNode.setNodeValue("ContextList", aContextList);
342 bChanged = true;
343 }
344
345 if (bChanged)
346 aDeckRootNode.commit();
347
348 // save panel settings
349
350 const utl::OConfigurationTreeRoot aPanelRootNode(
352 "org.openoffice.Office.UI.Sidebar/Content/PanelList",
353 true);
354
355 if (!aPanelRootNode.isValid())
356 return;
357
358 if (!pDeckDesc->mpDeck) // the deck has not been edited
359 return;
360
361 SharedPanelContainer rPanels = pDeckDesc->mpDeck->GetPanels();
362
363 bChanged = false;
364 for (auto const& panel : rPanels)
365 {
366 OUString panelId = panel->GetId();
367 std::shared_ptr<PanelDescriptor> xPanelDesc = GetPanelDescriptor(panelId);
368
369 ::uno::Sequence< OUString > sPanelContextList = BuildContextList(xPanelDesc->maContextList);
370
371 utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(xPanelDesc->msNodeName));
372
373 aTitle <<= xPanelDesc->msTitle;
374 aOrder <<= xPanelDesc->mnOrderIndex;
375 aContextList <<= sPanelContextList;
376
377 if (aTitle != aPanelNode.getNodeValue("Title"))
378 {
379 aPanelNode.setNodeValue("Title", aTitle);
380 bChanged = true;
381 }
382 if (aOrder != aPanelNode.getNodeValue("OrderIndex"))
383 {
384 aPanelNode.setNodeValue("OrderIndex", aOrder);
385 bChanged = true;
386 }
387 if (aContextList != aPanelNode.getNodeValue("ContextList"))
388 {
389 aPanelNode.setNodeValue("ContextList", aContextList);
390 bChanged = true;
391 }
392 }
393
394 if (bChanged)
395 aPanelRootNode.commit();
396}
397
398void ResourceManager::SaveLastActiveDeck(const Context& rContext, const OUString& rActiveDeck)
399{
400 maLastActiveDecks[rContext.msApplication] = rActiveDeck;
401
402 std::set<OUString> aLastActiveDecks;
403 for ( auto const & rEntry : maLastActiveDecks )
404 aLastActiveDecks.insert( rEntry.first + "," + rEntry.second);
405
406 std::shared_ptr<comphelper::ConfigurationChanges> cfgWriter( comphelper::ConfigurationChanges::create() );
407
408 officecfg::Office::UI::Sidebar::Content::LastActiveDeck::set(comphelper::containerToSequence(aLastActiveDecks), cfgWriter);
409 cfgWriter->commit();
410
411}
412
414{
415 const utl::OConfigurationTreeRoot aPanelRootNode(
417 "org.openoffice.Office.UI.Sidebar/Content/PanelList",
418 false);
419 if (!aPanelRootNode.isValid())
420 return;
421
422 const Sequence<OUString> aPanelNodeNames (aPanelRootNode.getNodeNames());
423 maPanels.clear();
424 for (const auto& rPanelNodeName : aPanelNodeNames)
425 {
426 const utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(rPanelNodeName));
427 if (!aPanelNode.isValid())
428 continue;
429
431 {
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;
437 }
438
439 maPanels.push_back(std::make_shared<PanelDescriptor>());
440 PanelDescriptor& rPanelDescriptor(*maPanels.back());
441
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"));
455
456 rPanelDescriptor.msNodeName = rPanelNodeName;
457
458 ReadContextList(aPanelNode, rPanelDescriptor.maContextList, sDefaultMenuCommand);
459 }
460}
461
463{
464 const Sequence <OUString> aLastActive (officecfg::Office::UI::Sidebar::Content::LastActiveDeck::get());
465
466 for (const auto& rDeckInfo : aLastActive)
467 {
468 sal_Int32 nCharIdx = rDeckInfo.lastIndexOf(',');
469 if ( nCharIdx <= 0 || (nCharIdx == rDeckInfo.getLength() - 1) )
470 {
471 SAL_WARN("sfx.sidebar", "Expecting 2 values separated by comma");
472 continue;
473 }
474
475 const OUString sApplicationName = rDeckInfo.copy( 0, nCharIdx );
477 const OUString sLastUsed = rDeckInfo.copy( nCharIdx + 1 );
478
479 // guard against garbage in place of application
480 if (eApplication != vcl::EnumContext::Application::NONE)
481 maLastActiveDecks.insert( std::make_pair(sApplicationName, sLastUsed ) );
482 }
483
484 // Set up a default for Math - will do nothing if already set
485 maLastActiveDecks.emplace(
487 "ElementsDeck");
488}
489
491 const utl::OConfigurationNode& rParentNode,
492 ContextList& rContextList,
493 const OUString& rsDefaultMenuCommand)
494{
495 const Any aValue = rParentNode.getNodeValue("ContextList");
496 Sequence<OUString> aValues;
497 if (!(aValue >>= aValues))
498 return;
499
500 for (const OUString& sValue : std::as_const(aValues))
501 {
502 sal_Int32 nCharacterIndex (0);
503 const OUString sApplicationName (o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex)));
504 if (nCharacterIndex < 0)
505 {
506 if (sApplicationName.getLength() == 0)
507 {
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;
512 }
513 else
514 {
515 OSL_FAIL("expecting three or four values per ContextList entry, separated by comma");
516 continue;
517 }
518 }
519
520 const OUString sContextName(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex)));
521 if (nCharacterIndex < 0)
522 {
523 OSL_FAIL("expecting three or four values per ContextList entry, separated by comma");
524 continue;
525 }
526
527 const std::u16string_view sInitialState(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex)));
528
529 // The fourth argument is optional.
530 const OUString sMenuCommandOverride(
531 nCharacterIndex < 0
532 ? OUString()
533 : OUString(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex))));
534
535 const OUString sMenuCommand(
536 sMenuCommandOverride.getLength() > 0
537 ? (sMenuCommandOverride == "none"
538 ? OUString()
539 : sMenuCommandOverride)
540 : rsDefaultMenuCommand);
541
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;
548
549 if (eApplication == vcl::EnumContext::Application::NONE
551 {
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")
567 {
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);
574 }
575 else if (sApplicationName == "WriterVariants")
576 {
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);
584 }
585 else
586 {
587 SAL_WARN("sfx.sidebar", "application name " << sApplicationName << " not recognized");
588 continue;
589 }
590 }
591 else
592 {
593 // No conversion of the application name necessary.
594 aApplications.push_back(eApplication);
595 }
596
597 // Setup the actual context enum.
598 const vcl::EnumContext::Context eContext (vcl::EnumContext::GetContextEnum(sContextName));
600 {
601 SAL_WARN("sfx.sidebar", "context name " << sContextName << " not recognized");
602 continue;
603 }
604
605 // Setup the flag that controls whether a deck/pane is
606 // initially visible/expanded.
607 bool bIsInitiallyVisible;
608 if (sInitialState == u"visible")
609 bIsInitiallyVisible = true;
610 else if (sInitialState == u"hidden")
611 bIsInitiallyVisible = false;
612 else
613 {
614 OSL_FAIL("unrecognized state");
615 continue;
616 }
617
618
619 // Add context descriptors.
620 for (auto const& application : aApplications)
621 {
622 if (application != vcl::EnumContext::Application::NONE)
623 {
624 rContextList.AddContextDescription(
625 Context(
628 bIsInitiallyVisible,
629 sMenuCommand);
630 }
631 }
632 }
633}
634
635void ResourceManager::ReadLegacyAddons (const Reference<frame::XController>& rxController)
636{
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())
642 {
643 // Addons for this application have already been read.
644 // There is nothing more to do.
645 return;
646 }
647
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);
652
653 // Get access to the configuration root node for the application.
654 utl::OConfigurationTreeRoot aLegacyRootNode (GetLegacyAddonRootNode(sModuleName));
655 if (!aLegacyRootNode.isValid())
656 return;
657
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)
663 {
664 const OUString& rsNodeName (aMatchingNodeNames[nReadIndex]);
665 const utl::OConfigurationNode aChildNode (aLegacyRootNode.openNode(rsNodeName));
666 if (!aChildNode.isValid())
667 continue;
668
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;
675
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());
688
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 rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, "any"), true, OUString());
703 }
704}
705
707 std::u16string_view rsPanelId,
708 const bool bExpansionState,
709 const Context& rContext)
710{
711 for (auto const& panel : maPanels)
712 {
713 if (panel->msId == rsPanelId)
714 {
715 ContextList::Entry* pEntry(panel->maContextList.GetMatch(rContext));
716 if (pEntry != nullptr)
717 pEntry->mbIsInitiallyVisible = bExpansionState;
718 }
719 }
720}
721
723{
724 try
725 {
726 const Reference<XComponentContext> xContext(comphelper::getProcessComponentContext());
727 const Reference<frame::XModuleManager2> xModuleAccess = frame::ModuleManager::create(xContext);
728 const comphelper::NamedValueCollection aModuleProperties(xModuleAccess->getByName(rsModuleName));
729 const OUString sWindowStateRef(aModuleProperties.getOrDefault(
730 "ooSetupFactoryWindowStateConfigRef",
731 OUString()));
732
733 OUString aPathComposer = "org.openoffice.Office.UI." + sWindowStateRef +
734 "/UIElements/States";
735
736 return utl::OConfigurationTreeRoot(xContext, aPathComposer, false);
737 }
738 catch (const Exception&)
739 {
740 DBG_UNHANDLED_EXCEPTION("sfx.sidebar");
741 }
742
744}
745
747 std::vector<OUString>& rMatchingNames,
748 const utl::OConfigurationTreeRoot& aRoot)
749{
750 const Sequence<OUString> aChildNodeNames (aRoot.getNodeNames());
751 std::copy_if(aChildNodeNames.begin(), aChildNodeNames.end(), std::back_inserter(rMatchingNames),
752 [](const OUString& rChildNodeName) { return rChildNodeName.startsWith( "private:resource/toolpanel/" ); });
753}
754
756 std::u16string_view rsDeckId,
757 const Context& rContext,
758 const Reference<frame::XController>& rxController)
759{
760
761 // Check if any panel that matches the current context can be
762 // displayed.
763 PanelContextDescriptorContainer aPanelContextDescriptors;
764
765 GetMatchingPanels(aPanelContextDescriptors, rContext, rsDeckId, rxController);
766
767 for (auto const& panelContextDescriptor : aPanelContextDescriptors)
768 {
769 if (panelContextDescriptor.mbShowForReadOnlyDocuments)
770 return true;
771 }
772 return false;
773}
774
775void ResourceManager::UpdateModel(const css::uno::Reference<css::frame::XModel>& xModel)
776{
777 for (auto const& deck : maDecks)
778 {
779 if (!deck->mpDeck)
780 continue;
781
782 const SharedPanelContainer& rContainer = deck->mpDeck->GetPanels();
783
784 for (auto const& elem : rContainer)
785 {
786 css::uno::Reference<css::ui::XUpdateModel> xPanel(elem->GetPanelComponent(), css::uno::UNO_QUERY);
787 if (xPanel.is()) // tdf#108814 interface is optional
788 {
789 xPanel->updateModel(xModel);
790 }
791 }
792 }
793}
794
796{
797 for (auto const& deck : maDecks)
798 {
799 deck->mpDeck.disposeAndClear();
800 }
801}
802
803} // end of namespace sfx2::sidebar
804
805/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static std::shared_ptr< ConfigurationChanges > create()
VALUE_TYPE getOrDefault(const OUString &_rValueName, const VALUE_TYPE &_rDefault) const
Per context data for deck and panel descriptors.
Definition: ContextList.hxx:31
void AddContextDescription(const Context &rContext, const bool bIsInitiallyVisible, const OUString &rsMenuCommand)
Definition: ContextList.cxx:70
const Entry * GetMatch(const Context &rContext) const
Return <TRUE> when the given context matches any of the stored contexts.
Definition: ContextList.cxx:28
OUString msApplication
Definition: Context.hxx:30
static utl::OConfigurationTreeRoot GetLegacyAddonRootNode(const OUString &rsModuleName)
void SaveDeckSettings(const DeckDescriptor *pDeckDesc)
std::map< OUString, OUString > maLastActiveDecks
void InitDeckContext(const Context &rContex)
static void ReadContextList(const utl::OConfigurationNode &rNode, ContextList &rContextList, const OUString &rsDefaultMenuCommand)
std::vector< PanelContextDescriptor > PanelContextDescriptorContainer
void UpdateModel(const css::uno::Reference< css::frame::XModel > &xModel)
const OUString & GetLastActiveDeck(const Context &rContext)
void StorePanelExpansionState(std::u16string_view rsPanelId, const bool bExpansionState, const Context &rContext)
Remember the expansions state per panel and context.
static void GetToolPanelNodeNames(std::vector< OUString > &rMatchingNames, const utl::OConfigurationTreeRoot &aRoot)
std::shared_ptr< DeckDescriptor > ImplGetDeckDescriptor(std::u16string_view rsDeckId) const
void ReadLegacyAddons(const css::uno::Reference< css::frame::XController > &rxController)
std::shared_ptr< PanelDescriptor > ImplGetPanelDescriptor(std::u16string_view rsPanelId) const
std::set< OUString > maProcessedApplications
const PanelContextDescriptorContainer & GetMatchingPanels(PanelContextDescriptorContainer &rPanelDescriptors, const Context &rContext, std::u16string_view rsDeckId, const css::uno::Reference< css::frame::XController > &rxController)
std::shared_ptr< DeckDescriptor > GetDeckDescriptor(std::u16string_view rsDeckId) const
void SetLastActiveDeck(const Context &rContext, const OUString &rsDeckId)
std::vector< DeckContextDescriptor > DeckContextDescriptorContainer
void SaveDecksSettings(const Context &rContext)
void SaveLastActiveDeck(const Context &rContext, const OUString &rActiveDeck)
std::shared_ptr< PanelDescriptor > GetPanelDescriptor(std::u16string_view rsPanelId) const
const DeckContextDescriptorContainer & GetMatchingDecks(DeckContextDescriptorContainer &rDeckDescriptors, const Context &rContext, const bool bIsDocumentReadOnly, const css::uno::Reference< css::frame::XController > &rxController)
bool IsDeckEnabled(std::u16string_view rsDeckId, const Context &rContext, const css::uno::Reference< css::frame::XController > &rxController)
static OUString GetModuleName(const css::uno::Reference< css::frame::XController > &rxFrame)
Definition: Tools.cxx:92
css::uno::Sequence< OUString > getNodeNames() const noexcept
css::uno::Any getNodeValue(const OUString &_rPath) const noexcept
bool setNodeValue(const OUString &_rPath, const css::uno::Any &_rValue) const noexcept
OConfigurationNode openNode(const OUString &_rPath) const noexcept
bool commit() const noexcept
static Application GetApplicationEnum(const OUString &rsApplicationName)
static const OUString & GetApplicationName(const Application eApplication)
static const OUString & GetContextName(const Context eContext)
static Context GetContextEnum(const OUString &rsContextName)
int nCount
#define DBG_UNHANDLED_EXCEPTION(...)
float u
#define SAL_WARN(area, stream)
@ Exception
bool getBOOL(const Any &_rAny)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
sal_Int32 getINT32(const Any &_rAny)
Reference< XComponentContext > getProcessComponentContext()
OUString getString(const Any &_rAny)
int i
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
std::vector< std::shared_ptr< Panel > > SharedPanelContainer
Definition: Panel.hxx:118
long Long
Reference< XModel > xModel
bool bIsEnabled
Any result