1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 #include "precompiled_sfx2.hxx" 23 24 #include "ResourceManager.hxx" 25 #include "Tools.hxx" 26 27 #include <unotools/confignode.hxx> 28 #include <comphelper/componentcontext.hxx> 29 #include <comphelper/processfactory.hxx> 30 #include <comphelper/namedvaluecollection.hxx> 31 #include <comphelper/types.hxx> 32 #include <comphelper/stlunosequence.hxx> 33 34 #include <rtl/ustrbuf.hxx> 35 #include <tools/diagnose_ex.h> 36 37 #include <com/sun/star/frame/XModuleManager.hpp> 38 39 #include <map> 40 41 42 43 using ::rtl::OUString; 44 using namespace css; 45 using namespace cssu; 46 47 namespace sfx2 { namespace sidebar { 48 49 #define gsPrivateResourceToolpanelPrefix "private:resource/toolpanel/" 50 51 52 53 class ResourceManager::Deleter 54 { 55 public: 56 void operator() (ResourceManager* pObject) 57 { 58 delete pObject; 59 } 60 }; 61 62 63 ResourceManager& ResourceManager::Instance (void) 64 { 65 static ResourceManager maInstance; 66 return maInstance; 67 } 68 69 70 71 72 ResourceManager::ResourceManager (void) 73 : maDecks(), 74 maPanels(), 75 maProcessedApplications() 76 { 77 ReadDeckList(); 78 ReadPanelList(); 79 } 80 81 82 83 84 ResourceManager::~ResourceManager (void) 85 { 86 maPanels.clear(); 87 maDecks.clear(); 88 } 89 90 91 92 93 const DeckDescriptor* ResourceManager::GetDeckDescriptor ( 94 const ::rtl::OUString& rsDeckId) const 95 { 96 for (DeckContainer::const_iterator 97 iDeck(maDecks.begin()), 98 iEnd(maDecks.end()); 99 iDeck!=iEnd; 100 ++iDeck) 101 { 102 if (iDeck->msId.equals(rsDeckId)) 103 return &*iDeck; 104 } 105 return NULL; 106 } 107 108 109 110 111 const PanelDescriptor* ResourceManager::GetPanelDescriptor ( 112 const ::rtl::OUString& rsPanelId) const 113 { 114 for (PanelContainer::const_iterator 115 iPanel(maPanels.begin()), 116 iEnd(maPanels.end()); 117 iPanel!=iEnd; 118 ++iPanel) 119 { 120 if (iPanel->msId.equals(rsPanelId)) 121 return &*iPanel; 122 } 123 return NULL; 124 } 125 126 127 128 129 void ResourceManager::SetIsDeckEnabled ( 130 const ::rtl::OUString& rsDeckId, 131 const bool bIsEnabled) 132 { 133 for (DeckContainer::iterator 134 iDeck(maDecks.begin()), 135 iEnd(maDecks.end()); 136 iDeck!=iEnd; 137 ++iDeck) 138 { 139 if (iDeck->msId.equals(rsDeckId)) 140 { 141 iDeck->mbIsEnabled = bIsEnabled; 142 return; 143 } 144 } 145 } 146 147 148 149 150 const ResourceManager::DeckContextDescriptorContainer& ResourceManager::GetMatchingDecks ( 151 DeckContextDescriptorContainer& rDecks, 152 const Context& rContext, 153 const bool bIsDocumentReadOnly, 154 const Reference<frame::XFrame>& rxFrame) 155 { 156 ReadLegacyAddons(rxFrame); 157 158 ::std::multimap<sal_Int32,DeckContextDescriptor> aOrderedIds; 159 for (DeckContainer::const_iterator 160 iDeck(maDecks.begin()), 161 iEnd (maDecks.end()); 162 iDeck!=iEnd; 163 ++iDeck) 164 { 165 const DeckDescriptor& rDeckDescriptor (*iDeck); 166 if (rDeckDescriptor.maContextList.GetMatch(rContext) == NULL) 167 continue; 168 DeckContextDescriptor aDeckContextDescriptor; 169 aDeckContextDescriptor.msId = rDeckDescriptor.msId; 170 aDeckContextDescriptor.mbIsEnabled = 171 ! bIsDocumentReadOnly 172 || IsDeckEnabled(rDeckDescriptor.msId, rContext, rxFrame); 173 aOrderedIds.insert(::std::multimap<sal_Int32,DeckContextDescriptor>::value_type( 174 rDeckDescriptor.mnOrderIndex, 175 aDeckContextDescriptor)); 176 } 177 178 for (::std::multimap<sal_Int32,DeckContextDescriptor>::const_iterator 179 iId(aOrderedIds.begin()), 180 iEnd(aOrderedIds.end()); 181 iId!=iEnd; 182 ++iId) 183 { 184 rDecks.push_back(iId->second); 185 } 186 187 return rDecks; 188 } 189 190 191 192 193 const ResourceManager::PanelContextDescriptorContainer& ResourceManager::GetMatchingPanels ( 194 PanelContextDescriptorContainer& rPanelIds, 195 const Context& rContext, 196 const ::rtl::OUString& rsDeckId, 197 const Reference<frame::XFrame>& rxFrame) 198 { 199 ReadLegacyAddons(rxFrame); 200 201 ::std::multimap<sal_Int32,PanelContextDescriptor> aOrderedIds; 202 for (PanelContainer::const_iterator 203 iPanel(maPanels.begin()), 204 iEnd(maPanels.end()); 205 iPanel!=iEnd; 206 ++iPanel) 207 { 208 const PanelDescriptor& rPanelDescriptor (*iPanel); 209 if ( ! rPanelDescriptor.msDeckId.equals(rsDeckId)) 210 continue; 211 212 const ContextList::Entry* pEntry = rPanelDescriptor.maContextList.GetMatch(rContext); 213 if (pEntry == NULL) 214 continue; 215 216 PanelContextDescriptor aPanelContextDescriptor; 217 aPanelContextDescriptor.msId = rPanelDescriptor.msId; 218 aPanelContextDescriptor.msMenuCommand = pEntry->msMenuCommand; 219 aPanelContextDescriptor.mbIsInitiallyVisible = pEntry->mbIsInitiallyVisible; 220 aPanelContextDescriptor.mbShowForReadOnlyDocuments = rPanelDescriptor.mbShowForReadOnlyDocuments; 221 aOrderedIds.insert(::std::multimap<sal_Int32,PanelContextDescriptor>::value_type( 222 rPanelDescriptor.mnOrderIndex, 223 aPanelContextDescriptor)); 224 } 225 226 for (::std::multimap<sal_Int32,PanelContextDescriptor>::const_iterator 227 iId(aOrderedIds.begin()), 228 iEnd(aOrderedIds.end()); 229 iId!=iEnd; 230 ++iId) 231 { 232 rPanelIds.push_back(iId->second); 233 } 234 235 return rPanelIds; 236 } 237 238 239 240 241 void ResourceManager::ReadDeckList (void) 242 { 243 const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory()); 244 const ::utl::OConfigurationTreeRoot aDeckRootNode ( 245 aContext, 246 A2S("org.openoffice.Office.UI.Sidebar/Content/DeckList"), 247 false); 248 if ( ! aDeckRootNode.isValid() ) 249 return; 250 251 const Sequence<OUString> aDeckNodeNames (aDeckRootNode.getNodeNames()); 252 const sal_Int32 nCount (aDeckNodeNames.getLength()); 253 maDecks.resize(nCount); 254 sal_Int32 nWriteIndex(0); 255 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex) 256 { 257 const ::utl::OConfigurationNode aDeckNode (aDeckRootNode.openNode(aDeckNodeNames[nReadIndex])); 258 if ( ! aDeckNode.isValid()) 259 continue; 260 261 DeckDescriptor& rDeckDescriptor (maDecks[nWriteIndex++]); 262 263 rDeckDescriptor.msTitle = ::comphelper::getString( 264 aDeckNode.getNodeValue("Title")); 265 rDeckDescriptor.msId = ::comphelper::getString( 266 aDeckNode.getNodeValue("Id")); 267 rDeckDescriptor.msIconURL = ::comphelper::getString( 268 aDeckNode.getNodeValue("IconURL")); 269 rDeckDescriptor.msHighContrastIconURL = ::comphelper::getString( 270 aDeckNode.getNodeValue("HighContrastIconURL")); 271 rDeckDescriptor.msTitleBarIconURL = ::comphelper::getString( 272 aDeckNode.getNodeValue("TitleBarIconURL")); 273 rDeckDescriptor.msHighContrastTitleBarIconURL = ::comphelper::getString( 274 aDeckNode.getNodeValue("HighContrastTitleBarIconURL")); 275 rDeckDescriptor.msHelpURL = ::comphelper::getString( 276 aDeckNode.getNodeValue("HelpURL")); 277 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle; 278 rDeckDescriptor.mbIsEnabled = true; 279 rDeckDescriptor.mnOrderIndex = ::comphelper::getINT32( 280 aDeckNode.getNodeValue("OrderIndex")); 281 282 ReadContextList( 283 aDeckNode, 284 rDeckDescriptor.maContextList, 285 OUString()); 286 } 287 288 // When there where invalid nodes then we have to adapt the size 289 // of the deck vector. 290 if (nWriteIndex<nCount) 291 maDecks.resize(nWriteIndex); 292 } 293 294 295 296 297 void ResourceManager::ReadPanelList (void) 298 { 299 const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory()); 300 const ::utl::OConfigurationTreeRoot aPanelRootNode ( 301 aContext, 302 A2S("org.openoffice.Office.UI.Sidebar/Content/PanelList"), 303 false); 304 if ( ! aPanelRootNode.isValid() ) 305 return; 306 307 const Sequence<OUString> aPanelNodeNames (aPanelRootNode.getNodeNames()); 308 const sal_Int32 nCount (aPanelNodeNames.getLength()); 309 maPanels.resize(nCount); 310 sal_Int32 nWriteIndex (0); 311 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex) 312 { 313 const ::utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(aPanelNodeNames[nReadIndex])); 314 if ( ! aPanelNode.isValid()) 315 continue; 316 317 PanelDescriptor& rPanelDescriptor (maPanels[nWriteIndex++]); 318 319 rPanelDescriptor.msTitle = ::comphelper::getString( 320 aPanelNode.getNodeValue("Title")); 321 rPanelDescriptor.mbIsTitleBarOptional = ::comphelper::getBOOL( 322 aPanelNode.getNodeValue("TitleBarIsOptional")); 323 rPanelDescriptor.msId = ::comphelper::getString( 324 aPanelNode.getNodeValue("Id")); 325 rPanelDescriptor.msDeckId = ::comphelper::getString( 326 aPanelNode.getNodeValue("DeckId")); 327 rPanelDescriptor.msTitleBarIconURL = ::comphelper::getString( 328 aPanelNode.getNodeValue("TitleBarIconURL")); 329 rPanelDescriptor.msHighContrastTitleBarIconURL = ::comphelper::getString( 330 aPanelNode.getNodeValue("HighContrastTitleBarIconURL")); 331 rPanelDescriptor.msHelpURL = ::comphelper::getString( 332 aPanelNode.getNodeValue("HelpURL")); 333 rPanelDescriptor.msImplementationURL = ::comphelper::getString( 334 aPanelNode.getNodeValue("ImplementationURL")); 335 rPanelDescriptor.mnOrderIndex = ::comphelper::getINT32( 336 aPanelNode.getNodeValue("OrderIndex")); 337 rPanelDescriptor.mbShowForReadOnlyDocuments = ::comphelper::getBOOL( 338 aPanelNode.getNodeValue("ShowForReadOnlyDocument")); 339 rPanelDescriptor.mbWantsCanvas = ::comphelper::getBOOL( 340 aPanelNode.getNodeValue("WantsCanvas")); 341 const OUString sDefaultMenuCommand (::comphelper::getString( 342 aPanelNode.getNodeValue("DefaultMenuCommand"))); 343 344 ReadContextList( 345 aPanelNode, 346 rPanelDescriptor.maContextList, 347 sDefaultMenuCommand); 348 } 349 350 // When there where invalid nodes then we have to adapt the size 351 // of the deck vector. 352 if (nWriteIndex<nCount) 353 maPanels.resize(nWriteIndex); 354 } 355 356 357 358 359 void ResourceManager::ReadContextList ( 360 const ::utl::OConfigurationNode& rParentNode, 361 ContextList& rContextList, 362 const OUString& rsDefaultMenuCommand) const 363 { 364 const Any aValue = rParentNode.getNodeValue("ContextList"); 365 Sequence<OUString> aValues; 366 sal_Int32 nCount; 367 if (aValue >>= aValues) 368 nCount = aValues.getLength(); 369 else 370 nCount = 0; 371 372 for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex) 373 { 374 const OUString sValue (aValues[nIndex]); 375 sal_Int32 nCharacterIndex (0); 376 const OUString sApplicationName (sValue.getToken(0, ',', nCharacterIndex).trim()); 377 if (nCharacterIndex < 0) 378 { 379 if (sApplicationName.getLength() == 0) 380 { 381 // This is a valid case: in the XML file the separator 382 // was used as terminator. Using it in the last line 383 // creates an additional but empty entry. 384 break; 385 } 386 else 387 { 388 OSL_ASSERT("expecting three or four values per ContextList entry, separated by comma"); 389 continue; 390 } 391 } 392 393 const OUString sContextName (sValue.getToken(0, ',', nCharacterIndex).trim()); 394 if (nCharacterIndex < 0) 395 { 396 OSL_ASSERT("expecting three or four values per ContextList entry, separated by comma"); 397 continue; 398 } 399 400 const OUString sInitialState (sValue.getToken(0, ',', nCharacterIndex).trim()); 401 402 // The fourth argument is optional. 403 const OUString sMenuCommandOverride ( 404 nCharacterIndex<0 405 ? OUString() 406 : sValue.getToken(0, ',', nCharacterIndex).trim()); 407 const OUString sMenuCommand ( 408 sMenuCommandOverride.getLength()>0 409 ? (sMenuCommandOverride.equalsAscii("none") 410 ? OUString() 411 : sMenuCommandOverride) 412 : rsDefaultMenuCommand); 413 414 // Setup a list of application enums. Note that the 415 // application name may result in more than one value (eg 416 // DrawImpress will result in two enums, one for Draw and one 417 // for Impress). 418 ::std::vector<EnumContext::Application> aApplications; 419 EnumContext::Application eApplication (EnumContext::GetApplicationEnum(sApplicationName)); 420 if (eApplication == EnumContext::Application_None 421 && !sApplicationName.equals(EnumContext::GetApplicationName(EnumContext::Application_None))) 422 { 423 // Handle some special names: abbreviations that make 424 // context descriptions more readable. 425 if (sApplicationName.equalsAscii("Writer")) 426 aApplications.push_back(EnumContext::Application_Writer); 427 else if (sApplicationName.equalsAscii("Calc")) 428 aApplications.push_back(EnumContext::Application_Calc); 429 else if (sApplicationName.equalsAscii("Draw")) 430 aApplications.push_back(EnumContext::Application_Draw); 431 else if (sApplicationName.equalsAscii("Impress")) 432 aApplications.push_back(EnumContext::Application_Impress); 433 else if (sApplicationName.equalsAscii("DrawImpress")) 434 { 435 // A special case among the special names: it is 436 // common to use the same context descriptions for 437 // both Draw and Impress. This special case helps to 438 // avoid duplication in the .xcu file. 439 aApplications.push_back(EnumContext::Application_Draw); 440 aApplications.push_back(EnumContext::Application_Impress); 441 } 442 else if (sApplicationName.equalsAscii("WriterVariants")) 443 { 444 // Another special case for all Writer variants. 445 aApplications.push_back(EnumContext::Application_Writer); 446 aApplications.push_back(EnumContext::Application_WriterGlobal); 447 aApplications.push_back(EnumContext::Application_WriterWeb); 448 aApplications.push_back(EnumContext::Application_WriterXML); 449 aApplications.push_back(EnumContext::Application_WriterForm); 450 } 451 else 452 { 453 OSL_ASSERT("application name not recognized"); 454 continue; 455 } 456 } 457 else 458 { 459 // No conversion of the application name necessary. 460 aApplications.push_back(eApplication); 461 } 462 463 // Setup the actual context enum. 464 const EnumContext::Context eContext (EnumContext::GetContextEnum(sContextName)); 465 if (eContext == EnumContext::Context_Unknown) 466 { 467 OSL_ASSERT("context name not recognized"); 468 continue; 469 } 470 471 // Setup the flag that controls whether a deck/pane is 472 // initially visible/expanded. 473 bool bIsInitiallyVisible; 474 if (sInitialState.equalsAscii("visible")) 475 bIsInitiallyVisible = true; 476 else if (sInitialState.equalsAscii("hidden")) 477 bIsInitiallyVisible = false; 478 else 479 { 480 OSL_ASSERT("unrecognized state"); 481 continue; 482 } 483 484 // Add context descriptors. 485 for (::std::vector<EnumContext::Application>::const_iterator 486 iApplication(aApplications.begin()), 487 iEnd(aApplications.end()); 488 iApplication!=iEnd; 489 ++iApplication) 490 { 491 if (*iApplication != EnumContext::Application_None) 492 rContextList.AddContextDescription( 493 Context( 494 EnumContext::GetApplicationName(*iApplication), 495 EnumContext::GetContextName(eContext)), 496 bIsInitiallyVisible, 497 sMenuCommand); 498 } 499 } 500 } 501 502 503 504 505 void ResourceManager::ReadLegacyAddons (const Reference<frame::XFrame>& rxFrame) 506 { 507 // Get module name for given frame. 508 ::rtl::OUString sModuleName (GetModuleName(rxFrame)); 509 if (sModuleName.getLength() == 0) 510 return; 511 if (maProcessedApplications.find(sModuleName) != maProcessedApplications.end()) 512 { 513 // Addons for this application have already been read. 514 // There is nothing more to do. 515 return; 516 } 517 518 // Mark module as processed. Even when there is an error that 519 // prevents the configuration data from being read, this error 520 // will not be triggered a second time. 521 maProcessedApplications.insert(sModuleName); 522 523 // Get access to the configuration root node for the application. 524 ::utl::OConfigurationTreeRoot aLegacyRootNode (GetLegacyAddonRootNode(sModuleName)); 525 if ( ! aLegacyRootNode.isValid()) 526 return; 527 528 // Process child nodes. 529 ::std::vector<OUString> aMatchingNodeNames; 530 GetToolPanelNodeNames(aMatchingNodeNames, aLegacyRootNode); 531 const sal_Int32 nCount (aMatchingNodeNames.size()); 532 size_t nDeckWriteIndex (maDecks.size()); 533 size_t nPanelWriteIndex (maPanels.size()); 534 maDecks.resize(maDecks.size() + nCount); 535 maPanels.resize(maPanels.size() + nCount); 536 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex) 537 { 538 const OUString& rsNodeName (aMatchingNodeNames[nReadIndex]); 539 const ::utl::OConfigurationNode aChildNode (aLegacyRootNode.openNode(rsNodeName)); 540 if ( ! aChildNode.isValid()) 541 continue; 542 543 DeckDescriptor& rDeckDescriptor (maDecks[nDeckWriteIndex++]); 544 rDeckDescriptor.msTitle = ::comphelper::getString(aChildNode.getNodeValue("UIName")); 545 rDeckDescriptor.msId = rsNodeName; 546 rDeckDescriptor.msIconURL = ::comphelper::getString(aChildNode.getNodeValue("ImageURL")); 547 rDeckDescriptor.msHighContrastIconURL = rDeckDescriptor.msIconURL; 548 rDeckDescriptor.msHelpURL = ::comphelper::getString(aChildNode.getNodeValue("HelpURL")); 549 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle; 550 rDeckDescriptor.maContextList.AddContextDescription(Context(sModuleName, A2S("any")), true, OUString()); 551 rDeckDescriptor.mbIsEnabled = true; 552 553 PanelDescriptor& rPanelDescriptor (maPanels[nPanelWriteIndex++]); 554 rPanelDescriptor.msTitle = ::comphelper::getString(aChildNode.getNodeValue("UIName")); 555 rPanelDescriptor.mbIsTitleBarOptional = true; 556 rPanelDescriptor.msId = rsNodeName; 557 rPanelDescriptor.msDeckId = rsNodeName; 558 rPanelDescriptor.msHelpURL = ::comphelper::getString(aChildNode.getNodeValue("HelpURL")); 559 rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, A2S("any")), true, OUString()); 560 rPanelDescriptor.msImplementationURL = rsNodeName; 561 rPanelDescriptor.mbShowForReadOnlyDocuments = false; 562 } 563 564 // When there where invalid nodes then we have to adapt the size 565 // of the deck and panel vectors. 566 if (nDeckWriteIndex < maDecks.size()) 567 maDecks.resize(nDeckWriteIndex); 568 if (nPanelWriteIndex < maPanels.size()) 569 maPanels.resize(nPanelWriteIndex); 570 } 571 572 573 574 575 ::rtl::OUString ResourceManager::GetModuleName ( 576 const cssu::Reference<css::frame::XFrame>& rxFrame) 577 { 578 if ( ! rxFrame.is() || ! rxFrame->getController().is()) 579 return OUString(); 580 581 try 582 { 583 const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory()); 584 const Reference<frame::XModuleManager> xModuleManager ( 585 aContext.createComponent("com.sun.star.frame.ModuleManager"), 586 UNO_QUERY_THROW); 587 return xModuleManager->identify(rxFrame); 588 } 589 catch (const Exception&) 590 { 591 DBG_UNHANDLED_EXCEPTION(); 592 } 593 return OUString(); 594 } 595 596 597 598 599 ::utl::OConfigurationTreeRoot ResourceManager::GetLegacyAddonRootNode ( 600 const ::rtl::OUString& rsModuleName) const 601 { 602 try 603 { 604 const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory()); 605 const Reference<container::XNameAccess> xModuleAccess ( 606 aContext.createComponent("com.sun.star.frame.ModuleManager"), 607 UNO_QUERY_THROW); 608 const ::comphelper::NamedValueCollection aModuleProperties (xModuleAccess->getByName(rsModuleName)); 609 const ::rtl::OUString sWindowStateRef (aModuleProperties.getOrDefault( 610 "ooSetupFactoryWindowStateConfigRef", 611 ::rtl::OUString())); 612 613 ::rtl::OUStringBuffer aPathComposer; 614 aPathComposer.appendAscii("org.openoffice.Office.UI."); 615 aPathComposer.append(sWindowStateRef); 616 aPathComposer.appendAscii("/UIElements/States"); 617 618 return ::utl::OConfigurationTreeRoot(aContext, aPathComposer.makeStringAndClear(), false); 619 } 620 catch( const Exception& ) 621 { 622 DBG_UNHANDLED_EXCEPTION(); 623 } 624 625 return ::utl::OConfigurationTreeRoot(); 626 } 627 628 629 630 631 void ResourceManager::GetToolPanelNodeNames ( 632 ::std::vector<OUString>& rMatchingNames, 633 const ::utl::OConfigurationTreeRoot aRoot) const 634 { 635 Sequence<OUString> aChildNodeNames (aRoot.getNodeNames()); 636 const sal_Int32 nCount (aChildNodeNames.getLength()); 637 for (sal_Int32 nIndex(0); nIndex<nCount; ++nIndex) 638 { 639 if (aChildNodeNames[nIndex].matchAsciiL( 640 RTL_CONSTASCII_STRINGPARAM( "private:resource/toolpanel/"))) 641 rMatchingNames.push_back(aChildNodeNames[nIndex]); 642 } 643 } 644 645 646 647 648 bool ResourceManager::IsDeckEnabled ( 649 const OUString& rsDeckId, 650 const Context& rContext, 651 const Reference<frame::XFrame>& rxFrame) const 652 { 653 // Check if any panel that matches the current context can be 654 // displayed. 655 ResourceManager::PanelContextDescriptorContainer aPanelContextDescriptors; 656 ResourceManager::Instance().GetMatchingPanels( 657 aPanelContextDescriptors, 658 rContext, 659 rsDeckId, 660 rxFrame); 661 662 for (ResourceManager::PanelContextDescriptorContainer::const_iterator 663 iPanel(aPanelContextDescriptors.begin()), 664 iEnd(aPanelContextDescriptors.end()); 665 iPanel!=iEnd; 666 ++iPanel) 667 { 668 if (iPanel->mbShowForReadOnlyDocuments) 669 return true; 670 } 671 672 return false; 673 } 674 675 676 } } // end of namespace sfx2::sidebar 677