bump product version to 4.1.6.2
[LibreOffice.git] / sfx2 / source / sidebar / ResourceManager.cxx
blobdc09419b9beb5e73c03f23dc78646278a5503f08
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include "ResourceManager.hxx"
20 #include "sfx2/sidebar/Tools.hxx"
22 #include <unotools/confignode.hxx>
23 #include <comphelper/componentcontext.hxx>
24 #include <comphelper/processfactory.hxx>
25 #include <comphelper/namedvaluecollection.hxx>
26 #include <comphelper/types.hxx>
27 #include <comphelper/stlunosequence.hxx>
29 #include <rtl/ustrbuf.hxx>
30 #include <tools/diagnose_ex.h>
32 #include <com/sun/star/frame/XModuleManager.hpp>
34 #include <map>
36 using ::rtl::OUString;
37 using namespace css;
38 using namespace cssu;
40 namespace sfx2 { namespace sidebar {
42 class ResourceManager::Deleter
44 public:
45 void operator() (ResourceManager* pObject)
47 delete pObject;
51 ResourceManager& ResourceManager::Instance (void)
53 static ResourceManager maInstance;
54 return maInstance;
60 ResourceManager::ResourceManager (void)
61 : maDecks(),
62 maPanels(),
63 maProcessedApplications()
65 ReadDeckList();
66 ReadPanelList();
72 ResourceManager::~ResourceManager (void)
74 maPanels.clear();
75 maDecks.clear();
81 const DeckDescriptor* ResourceManager::GetDeckDescriptor (
82 const ::rtl::OUString& rsDeckId) const
84 for (DeckContainer::const_iterator
85 iDeck(maDecks.begin()),
86 iEnd(maDecks.end());
87 iDeck!=iEnd;
88 ++iDeck)
90 if (iDeck->msId.equals(rsDeckId))
91 return &*iDeck;
93 return NULL;
99 const PanelDescriptor* ResourceManager::GetPanelDescriptor (
100 const ::rtl::OUString& rsPanelId) const
102 for (PanelContainer::const_iterator
103 iPanel(maPanels.begin()),
104 iEnd(maPanels.end());
105 iPanel!=iEnd;
106 ++iPanel)
108 if (iPanel->msId.equals(rsPanelId))
109 return &*iPanel;
111 return NULL;
117 void ResourceManager::SetIsDeckEnabled (
118 const ::rtl::OUString& rsDeckId,
119 const bool bIsEnabled)
121 for (DeckContainer::iterator
122 iDeck(maDecks.begin()),
123 iEnd(maDecks.end());
124 iDeck!=iEnd;
125 ++iDeck)
127 if (iDeck->msId.equals(rsDeckId))
129 iDeck->mbIsEnabled = bIsEnabled;
130 return;
138 const ResourceManager::DeckContextDescriptorContainer& ResourceManager::GetMatchingDecks (
139 DeckContextDescriptorContainer& rDecks,
140 const Context& rContext,
141 const bool bIsDocumentReadOnly,
142 const Reference<frame::XFrame>& rxFrame)
144 ReadLegacyAddons(rxFrame);
146 ::std::multimap<sal_Int32,DeckContextDescriptor> aOrderedIds;
147 for (DeckContainer::const_iterator
148 iDeck(maDecks.begin()),
149 iEnd (maDecks.end());
150 iDeck!=iEnd;
151 ++iDeck)
153 const DeckDescriptor& rDeckDescriptor (*iDeck);
154 if (rDeckDescriptor.maContextList.GetMatch(rContext) == NULL)
155 continue;
156 DeckContextDescriptor aDeckContextDescriptor;
157 aDeckContextDescriptor.msId = rDeckDescriptor.msId;
158 aDeckContextDescriptor.mbIsEnabled =
159 ! bIsDocumentReadOnly
160 || IsDeckEnabled(rDeckDescriptor.msId, rContext, rxFrame);
161 aOrderedIds.insert(::std::multimap<sal_Int32,DeckContextDescriptor>::value_type(
162 rDeckDescriptor.mnOrderIndex,
163 aDeckContextDescriptor));
166 for (::std::multimap<sal_Int32,DeckContextDescriptor>::const_iterator
167 iId(aOrderedIds.begin()),
168 iEnd(aOrderedIds.end());
169 iId!=iEnd;
170 ++iId)
172 rDecks.push_back(iId->second);
175 return rDecks;
181 const ResourceManager::PanelContextDescriptorContainer& ResourceManager::GetMatchingPanels (
182 PanelContextDescriptorContainer& rPanelIds,
183 const Context& rContext,
184 const ::rtl::OUString& rsDeckId,
185 const Reference<frame::XFrame>& rxFrame)
187 ReadLegacyAddons(rxFrame);
189 ::std::multimap<sal_Int32,PanelContextDescriptor> aOrderedIds;
190 for (PanelContainer::const_iterator
191 iPanel(maPanels.begin()),
192 iEnd(maPanels.end());
193 iPanel!=iEnd;
194 ++iPanel)
196 const PanelDescriptor& rPanelDescriptor (*iPanel);
197 if ( ! rPanelDescriptor.msDeckId.equals(rsDeckId))
198 continue;
200 const ContextList::Entry* pEntry = rPanelDescriptor.maContextList.GetMatch(rContext);
201 if (pEntry == NULL)
202 continue;
204 PanelContextDescriptor aPanelContextDescriptor;
205 aPanelContextDescriptor.msId = rPanelDescriptor.msId;
206 aPanelContextDescriptor.msMenuCommand = pEntry->msMenuCommand;
207 aPanelContextDescriptor.mbIsInitiallyVisible = pEntry->mbIsInitiallyVisible;
208 aPanelContextDescriptor.mbShowForReadOnlyDocuments = rPanelDescriptor.mbShowForReadOnlyDocuments;
209 aOrderedIds.insert(::std::multimap<sal_Int32,PanelContextDescriptor>::value_type(
210 rPanelDescriptor.mnOrderIndex,
211 aPanelContextDescriptor));
214 for (::std::multimap<sal_Int32,PanelContextDescriptor>::const_iterator
215 iId(aOrderedIds.begin()),
216 iEnd(aOrderedIds.end());
217 iId!=iEnd;
218 ++iId)
220 rPanelIds.push_back(iId->second);
223 return rPanelIds;
229 void ResourceManager::ReadDeckList (void)
231 const ::utl::OConfigurationTreeRoot aDeckRootNode (
232 ::comphelper::getProcessComponentContext(),
233 A2S("org.openoffice.Office.UI.Sidebar/Content/DeckList"),
234 false);
235 if ( ! aDeckRootNode.isValid() )
236 return;
238 const Sequence<OUString> aDeckNodeNames (aDeckRootNode.getNodeNames());
239 const sal_Int32 nCount (aDeckNodeNames.getLength());
240 maDecks.resize(nCount);
241 sal_Int32 nWriteIndex(0);
242 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex)
244 const ::utl::OConfigurationNode aDeckNode (aDeckRootNode.openNode(aDeckNodeNames[nReadIndex]));
245 if ( ! aDeckNode.isValid())
246 continue;
248 DeckDescriptor& rDeckDescriptor (maDecks[nWriteIndex++]);
250 rDeckDescriptor.msTitle = ::comphelper::getString(
251 aDeckNode.getNodeValue("Title"));
252 rDeckDescriptor.msId = ::comphelper::getString(
253 aDeckNode.getNodeValue("Id"));
254 rDeckDescriptor.msIconURL = ::comphelper::getString(
255 aDeckNode.getNodeValue("IconURL"));
256 rDeckDescriptor.msHighContrastIconURL = ::comphelper::getString(
257 aDeckNode.getNodeValue("HighContrastIconURL"));
258 rDeckDescriptor.msTitleBarIconURL = ::comphelper::getString(
259 aDeckNode.getNodeValue("TitleBarIconURL"));
260 rDeckDescriptor.msHighContrastTitleBarIconURL = ::comphelper::getString(
261 aDeckNode.getNodeValue("HighContrastTitleBarIconURL"));
262 rDeckDescriptor.msHelpURL = ::comphelper::getString(
263 aDeckNode.getNodeValue("HelpURL"));
264 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
265 rDeckDescriptor.mbIsEnabled = true;
266 rDeckDescriptor.mnOrderIndex = ::comphelper::getINT32(
267 aDeckNode.getNodeValue("OrderIndex"));
269 ReadContextList(
270 aDeckNode,
271 rDeckDescriptor.maContextList,
272 OUString());
275 // When there where invalid nodes then we have to adapt the size
276 // of the deck vector.
277 if (nWriteIndex<nCount)
278 maDecks.resize(nWriteIndex);
284 void ResourceManager::ReadPanelList (void)
286 const ::utl::OConfigurationTreeRoot aPanelRootNode (
287 ::comphelper::getProcessComponentContext(),
288 A2S("org.openoffice.Office.UI.Sidebar/Content/PanelList"),
289 false);
290 if ( ! aPanelRootNode.isValid() )
291 return;
293 const Sequence<OUString> aPanelNodeNames (aPanelRootNode.getNodeNames());
294 const sal_Int32 nCount (aPanelNodeNames.getLength());
295 maPanels.resize(nCount);
296 sal_Int32 nWriteIndex (0);
297 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex)
299 const ::utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(aPanelNodeNames[nReadIndex]));
300 if ( ! aPanelNode.isValid())
301 continue;
303 PanelDescriptor& rPanelDescriptor (maPanels[nWriteIndex++]);
305 rPanelDescriptor.msTitle = ::comphelper::getString(
306 aPanelNode.getNodeValue("Title"));
307 rPanelDescriptor.mbIsTitleBarOptional = ::comphelper::getBOOL(
308 aPanelNode.getNodeValue("TitleBarIsOptional"));
309 rPanelDescriptor.msId = ::comphelper::getString(
310 aPanelNode.getNodeValue("Id"));
311 rPanelDescriptor.msDeckId = ::comphelper::getString(
312 aPanelNode.getNodeValue("DeckId"));
313 rPanelDescriptor.msTitleBarIconURL = ::comphelper::getString(
314 aPanelNode.getNodeValue("TitleBarIconURL"));
315 rPanelDescriptor.msHighContrastTitleBarIconURL = ::comphelper::getString(
316 aPanelNode.getNodeValue("HighContrastTitleBarIconURL"));
317 rPanelDescriptor.msHelpURL = ::comphelper::getString(
318 aPanelNode.getNodeValue("HelpURL"));
319 rPanelDescriptor.msImplementationURL = ::comphelper::getString(
320 aPanelNode.getNodeValue("ImplementationURL"));
321 rPanelDescriptor.mnOrderIndex = ::comphelper::getINT32(
322 aPanelNode.getNodeValue("OrderIndex"));
323 rPanelDescriptor.mbShowForReadOnlyDocuments = ::comphelper::getBOOL(
324 aPanelNode.getNodeValue("ShowForReadOnlyDocument"));
325 rPanelDescriptor.mbWantsCanvas = ::comphelper::getBOOL(
326 aPanelNode.getNodeValue("WantsCanvas"));
327 const OUString sDefaultMenuCommand (::comphelper::getString(
328 aPanelNode.getNodeValue("DefaultMenuCommand")));
330 ReadContextList(
331 aPanelNode,
332 rPanelDescriptor.maContextList,
333 sDefaultMenuCommand);
336 // When there where invalid nodes then we have to adapt the size
337 // of the deck vector.
338 if (nWriteIndex<nCount)
339 maPanels.resize(nWriteIndex);
345 void ResourceManager::ReadContextList (
346 const ::utl::OConfigurationNode& rParentNode,
347 ContextList& rContextList,
348 const OUString& rsDefaultMenuCommand) const
350 const Any aValue = rParentNode.getNodeValue("ContextList");
351 Sequence<OUString> aValues;
352 sal_Int32 nCount;
353 if (aValue >>= aValues)
354 nCount = aValues.getLength();
355 else
356 nCount = 0;
358 for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
360 const OUString sValue (aValues[nIndex]);
361 sal_Int32 nCharacterIndex (0);
362 const OUString sApplicationName (sValue.getToken(0, ',', nCharacterIndex).trim());
363 if (nCharacterIndex < 0)
365 if (sApplicationName.getLength() == 0)
367 // This is a valid case: in the XML file the separator
368 // was used as terminator. Using it in the last line
369 // creates an additional but empty entry.
370 break;
372 else
374 OSL_ASSERT("expecting three or four values per ContextList entry, separated by comma");
375 continue;
379 const OUString sContextName (sValue.getToken(0, ',', nCharacterIndex).trim());
380 if (nCharacterIndex < 0)
382 OSL_ASSERT("expecting three or four values per ContextList entry, separated by comma");
383 continue;
386 const OUString sInitialState (sValue.getToken(0, ',', nCharacterIndex).trim());
388 // The fourth argument is optional.
389 const OUString sMenuCommandOverride (
390 nCharacterIndex<0
391 ? OUString()
392 : sValue.getToken(0, ',', nCharacterIndex).trim());
393 const OUString sMenuCommand (
394 sMenuCommandOverride.getLength()>0
395 ? (sMenuCommandOverride.equalsAscii("none")
396 ? OUString()
397 : sMenuCommandOverride)
398 : rsDefaultMenuCommand);
400 // Setup a list of application enums. Note that the
401 // application name may result in more than one value (eg
402 // DrawImpress will result in two enums, one for Draw and one
403 // for Impress).
404 ::std::vector<EnumContext::Application> aApplications;
405 EnumContext::Application eApplication (EnumContext::GetApplicationEnum(sApplicationName));
406 if (eApplication == EnumContext::Application_None
407 && !sApplicationName.equals(EnumContext::GetApplicationName(EnumContext::Application_None)))
409 // Handle some special names: abbreviations that make
410 // context descriptions more readable.
411 if (sApplicationName.equalsAscii("Writer"))
412 aApplications.push_back(EnumContext::Application_Writer);
413 else if (sApplicationName.equalsAscii("Calc"))
414 aApplications.push_back(EnumContext::Application_Calc);
415 else if (sApplicationName.equalsAscii("Draw"))
416 aApplications.push_back(EnumContext::Application_Draw);
417 else if (sApplicationName.equalsAscii("Impress"))
418 aApplications.push_back(EnumContext::Application_Impress);
419 else if (sApplicationName.equalsAscii("DrawImpress"))
421 // A special case among the special names: it is
422 // common to use the same context descriptions for
423 // both Draw and Impress. This special case helps to
424 // avoid duplication in the .xcu file.
425 aApplications.push_back(EnumContext::Application_Draw);
426 aApplications.push_back(EnumContext::Application_Impress);
428 else if (sApplicationName.equalsAscii("WriterVariants"))
430 // Another special case for all Writer variants.
431 aApplications.push_back(EnumContext::Application_Writer);
432 aApplications.push_back(EnumContext::Application_WriterGlobal);
433 aApplications.push_back(EnumContext::Application_WriterWeb);
434 aApplications.push_back(EnumContext::Application_WriterXML);
435 aApplications.push_back(EnumContext::Application_WriterForm);
436 aApplications.push_back(EnumContext::Application_WriterReport);
438 else
440 OSL_ASSERT("application name not recognized");
441 continue;
444 else
446 // No conversion of the application name necessary.
447 aApplications.push_back(eApplication);
450 // Setup the actual context enum.
451 const EnumContext::Context eContext (EnumContext::GetContextEnum(sContextName));
452 if (eContext == EnumContext::Context_Unknown)
454 OSL_ASSERT("context name not recognized");
455 continue;
458 // Setup the flag that controls whether a deck/pane is
459 // initially visible/expanded.
460 bool bIsInitiallyVisible;
461 if (sInitialState.equalsAscii("visible"))
462 bIsInitiallyVisible = true;
463 else if (sInitialState.equalsAscii("hidden"))
464 bIsInitiallyVisible = false;
465 else
467 OSL_ASSERT("unrecognized state");
468 continue;
471 // Add context descriptors.
472 for (::std::vector<EnumContext::Application>::const_iterator
473 iApplication(aApplications.begin()),
474 iEnd(aApplications.end());
475 iApplication!=iEnd;
476 ++iApplication)
478 if (*iApplication != EnumContext::Application_None)
479 rContextList.AddContextDescription(
480 Context(
481 EnumContext::GetApplicationName(*iApplication),
482 EnumContext::GetContextName(eContext)),
483 bIsInitiallyVisible,
484 sMenuCommand);
492 void ResourceManager::ReadLegacyAddons (const Reference<frame::XFrame>& rxFrame)
494 // Get module name for given frame.
495 ::rtl::OUString sModuleName (Tools::GetModuleName(rxFrame));
496 if (sModuleName.getLength() == 0)
497 return;
498 if (maProcessedApplications.find(sModuleName) != maProcessedApplications.end())
500 // Addons for this application have already been read.
501 // There is nothing more to do.
502 return;
505 // Mark module as processed. Even when there is an error that
506 // prevents the configuration data from being read, this error
507 // will not be triggered a second time.
508 maProcessedApplications.insert(sModuleName);
510 // Get access to the configuration root node for the application.
511 ::utl::OConfigurationTreeRoot aLegacyRootNode (GetLegacyAddonRootNode(sModuleName));
512 if ( ! aLegacyRootNode.isValid())
513 return;
515 // Process child nodes.
516 ::std::vector<OUString> aMatchingNodeNames;
517 GetToolPanelNodeNames(aMatchingNodeNames, aLegacyRootNode);
518 const sal_Int32 nCount (aMatchingNodeNames.size());
519 size_t nDeckWriteIndex (maDecks.size());
520 size_t nPanelWriteIndex (maPanels.size());
521 maDecks.resize(maDecks.size() + nCount);
522 maPanels.resize(maPanels.size() + nCount);
523 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex)
525 const OUString& rsNodeName (aMatchingNodeNames[nReadIndex]);
526 const ::utl::OConfigurationNode aChildNode (aLegacyRootNode.openNode(rsNodeName));
527 if ( ! aChildNode.isValid())
528 continue;
530 if ( rsNodeName == "private:resource/toolpanel/DrawingFramework/CustomAnimations" ||
531 rsNodeName == "private:resource/toolpanel/DrawingFramework/Layouts" ||
532 rsNodeName == "private:resource/toolpanel/DrawingFramework/MasterPages" ||
533 rsNodeName == "private:resource/toolpanel/DrawingFramework/SlideTransitions" ||
534 rsNodeName == "private:resource/toolpanel/DrawingFramework/TableDesign" )
535 continue;
537 DeckDescriptor& rDeckDescriptor (maDecks[nDeckWriteIndex++]);
538 rDeckDescriptor.msTitle = ::comphelper::getString(aChildNode.getNodeValue("UIName"));
539 rDeckDescriptor.msId = rsNodeName;
540 rDeckDescriptor.msIconURL = ::comphelper::getString(aChildNode.getNodeValue("ImageURL"));
541 rDeckDescriptor.msHighContrastIconURL = rDeckDescriptor.msIconURL;
542 rDeckDescriptor.msTitleBarIconURL = OUString();
543 rDeckDescriptor.msHighContrastTitleBarIconURL = OUString();
544 rDeckDescriptor.msHelpURL = ::comphelper::getString(aChildNode.getNodeValue("HelpURL"));
545 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
546 rDeckDescriptor.mbIsEnabled = true;
547 rDeckDescriptor.mnOrderIndex = 100000 + nReadIndex;
548 rDeckDescriptor.maContextList.AddContextDescription(Context(sModuleName, A2S("any")), true, OUString());
550 PanelDescriptor& rPanelDescriptor (maPanels[nPanelWriteIndex++]);
551 rPanelDescriptor.msTitle = ::comphelper::getString(aChildNode.getNodeValue("UIName"));
552 rPanelDescriptor.mbIsTitleBarOptional = true;
553 rPanelDescriptor.msId = rsNodeName;
554 rPanelDescriptor.msDeckId = rsNodeName;
555 rPanelDescriptor.msTitleBarIconURL = OUString();
556 rPanelDescriptor.msHighContrastTitleBarIconURL = OUString();
557 rPanelDescriptor.msHelpURL = ::comphelper::getString(aChildNode.getNodeValue("HelpURL"));
558 rPanelDescriptor.msImplementationURL = rsNodeName;
559 rPanelDescriptor.mnOrderIndex = 100000 + nReadIndex;
560 rPanelDescriptor.mbShowForReadOnlyDocuments = false;
561 rPanelDescriptor.mbWantsCanvas = false;
562 rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, A2S("any")), true, OUString());
565 // When there where invalid nodes then we have to adapt the size
566 // of the deck and panel vectors.
567 if (nDeckWriteIndex < maDecks.size())
568 maDecks.resize(nDeckWriteIndex);
569 if (nPanelWriteIndex < maPanels.size())
570 maPanels.resize(nPanelWriteIndex);
576 void ResourceManager::StorePanelExpansionState (
577 const ::rtl::OUString& rsPanelId,
578 const bool bExpansionState,
579 const Context& rContext)
581 for (PanelContainer::iterator
582 iPanel(maPanels.begin()),
583 iEnd(maPanels.end());
584 iPanel!=iEnd;
585 ++iPanel)
587 if (iPanel->msId.equals(rsPanelId))
589 ContextList::Entry* pEntry (
590 iPanel->maContextList.GetMatch (rContext));
591 if (pEntry != NULL)
592 pEntry->mbIsInitiallyVisible = bExpansionState;
600 ::utl::OConfigurationTreeRoot ResourceManager::GetLegacyAddonRootNode (
601 const ::rtl::OUString& rsModuleName) const
605 const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory());
606 const Reference<container::XNameAccess> xModuleAccess (
607 aContext.createComponent("com.sun.star.frame.ModuleManager"),
608 UNO_QUERY_THROW);
609 const ::comphelper::NamedValueCollection aModuleProperties (xModuleAccess->getByName(rsModuleName));
610 const ::rtl::OUString sWindowStateRef (aModuleProperties.getOrDefault(
611 "ooSetupFactoryWindowStateConfigRef",
612 ::rtl::OUString()));
614 ::rtl::OUStringBuffer aPathComposer;
615 aPathComposer.appendAscii("org.openoffice.Office.UI.");
616 aPathComposer.append(sWindowStateRef);
617 aPathComposer.appendAscii("/UIElements/States");
619 return ::utl::OConfigurationTreeRoot(::comphelper::getProcessComponentContext(),
620 aPathComposer.makeStringAndClear(), false);
622 catch( const Exception& )
624 DBG_UNHANDLED_EXCEPTION();
627 return ::utl::OConfigurationTreeRoot();
633 void ResourceManager::GetToolPanelNodeNames (
634 ::std::vector<OUString>& rMatchingNames,
635 const ::utl::OConfigurationTreeRoot aRoot) const
637 Sequence<OUString> aChildNodeNames (aRoot.getNodeNames());
638 const sal_Int32 nCount (aChildNodeNames.getLength());
639 for (sal_Int32 nIndex(0); nIndex<nCount; ++nIndex)
641 if (aChildNodeNames[nIndex].matchAsciiL(
642 RTL_CONSTASCII_STRINGPARAM( "private:resource/toolpanel/")))
643 rMatchingNames.push_back(aChildNodeNames[nIndex]);
650 bool ResourceManager::IsDeckEnabled (
651 const OUString& rsDeckId,
652 const Context& rContext,
653 const Reference<frame::XFrame>& rxFrame) const
655 // Check if any panel that matches the current context can be
656 // displayed.
657 ResourceManager::PanelContextDescriptorContainer aPanelContextDescriptors;
658 ResourceManager::Instance().GetMatchingPanels(
659 aPanelContextDescriptors,
660 rContext,
661 rsDeckId,
662 rxFrame);
664 for (ResourceManager::PanelContextDescriptorContainer::const_iterator
665 iPanel(aPanelContextDescriptors.begin()),
666 iEnd(aPanelContextDescriptors.end());
667 iPanel!=iEnd;
668 ++iPanel)
670 if (iPanel->mbShowForReadOnlyDocuments)
671 return true;
674 return false;
678 } } // end of namespace sfx2::sidebar