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 } 450 else 451 { 452 OSL_ASSERT("application name not recognized"); 453 continue; 454 } 455 } 456 else 457 { 458 // No conversion of the application name necessary. 459 aApplications.push_back(eApplication); 460 } 461 462 // Setup the actual context enum. 463 const EnumContext::Context eContext (EnumContext::GetContextEnum(sContextName)); 464 if (eContext == EnumContext::Context_Unknown) 465 { 466 OSL_ASSERT("context name not recognized"); 467 continue; 468 } 469 470 // Setup the flag that controls whether a deck/pane is 471 // initially visible/expanded. 472 bool bIsInitiallyVisible; 473 if (sInitialState.equalsAscii("visible")) 474 bIsInitiallyVisible = true; 475 else if (sInitialState.equalsAscii("hidden")) 476 bIsInitiallyVisible = false; 477 else 478 { 479 OSL_ASSERT("unrecognized state"); 480 continue; 481 } 482 483 // Add context descriptors. 484 for (::std::vector<EnumContext::Application>::const_iterator 485 iApplication(aApplications.begin()), 486 iEnd(aApplications.end()); 487 iApplication!=iEnd; 488 ++iApplication) 489 { 490 if (*iApplication != EnumContext::Application_None) 491 rContextList.AddContextDescription( 492 Context( 493 EnumContext::GetApplicationName(*iApplication), 494 EnumContext::GetContextName(eContext)), 495 bIsInitiallyVisible, 496 sMenuCommand); 497 } 498 } 499 } 500 501 502 503 504 void ResourceManager::ReadLegacyAddons (const Reference<frame::XFrame>& rxFrame) 505 { 506 // Get module name for given frame. 507 ::rtl::OUString sModuleName (GetModuleName(rxFrame)); 508 if (sModuleName.getLength() == 0) 509 return; 510 if (maProcessedApplications.find(sModuleName) != maProcessedApplications.end()) 511 { 512 // Addons for this application have already been read. 513 // There is nothing more to do. 514 return; 515 } 516 517 // Mark module as processed. Even when there is an error that 518 // prevents the configuration data from being read, this error 519 // will not be triggered a second time. 520 maProcessedApplications.insert(sModuleName); 521 522 // Get access to the configuration root node for the application. 523 ::utl::OConfigurationTreeRoot aLegacyRootNode (GetLegacyAddonRootNode(sModuleName)); 524 if ( ! aLegacyRootNode.isValid()) 525 return; 526 527 // Process child nodes. 528 ::std::vector<OUString> aMatchingNodeNames; 529 GetToolPanelNodeNames(aMatchingNodeNames, aLegacyRootNode); 530 const sal_Int32 nCount (aMatchingNodeNames.size()); 531 size_t nDeckWriteIndex (maDecks.size()); 532 size_t nPanelWriteIndex (maPanels.size()); 533 maDecks.resize(maDecks.size() + nCount); 534 maPanels.resize(maPanels.size() + nCount); 535 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex) 536 { 537 const OUString& rsNodeName (aMatchingNodeNames[nReadIndex]); 538 const ::utl::OConfigurationNode aChildNode (aLegacyRootNode.openNode(rsNodeName)); 539 if ( ! aChildNode.isValid()) 540 continue; 541 542 DeckDescriptor& rDeckDescriptor (maDecks[nDeckWriteIndex++]); 543 rDeckDescriptor.msTitle = ::comphelper::getString(aChildNode.getNodeValue("UIName")); 544 rDeckDescriptor.msId = rsNodeName; 545 rDeckDescriptor.msIconURL = ::comphelper::getString(aChildNode.getNodeValue("ImageURL")); 546 rDeckDescriptor.msHighContrastIconURL = rDeckDescriptor.msIconURL; 547 rDeckDescriptor.msHelpURL = ::comphelper::getString(aChildNode.getNodeValue("HelpURL")); 548 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle; 549 rDeckDescriptor.maContextList.AddContextDescription(Context(sModuleName, A2S("any")), true, OUString()); 550 rDeckDescriptor.mbIsEnabled = true; 551 552 PanelDescriptor& rPanelDescriptor (maPanels[nPanelWriteIndex++]); 553 rPanelDescriptor.msTitle = ::comphelper::getString(aChildNode.getNodeValue("UIName")); 554 rPanelDescriptor.mbIsTitleBarOptional = true; 555 rPanelDescriptor.msId = rsNodeName; 556 rPanelDescriptor.msDeckId = rsNodeName; 557 rPanelDescriptor.msHelpURL = ::comphelper::getString(aChildNode.getNodeValue("HelpURL")); 558 rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, A2S("any")), true, OUString()); 559 rPanelDescriptor.msImplementationURL = rsNodeName; 560 rPanelDescriptor.mbShowForReadOnlyDocuments = false; 561 } 562 563 // When there where invalid nodes then we have to adapt the size 564 // of the deck and panel vectors. 565 if (nDeckWriteIndex < maDecks.size()) 566 maDecks.resize(nDeckWriteIndex); 567 if (nPanelWriteIndex < maPanels.size()) 568 maPanels.resize(nPanelWriteIndex); 569 } 570 571 572 573 574 ::rtl::OUString ResourceManager::GetModuleName ( 575 const cssu::Reference<css::frame::XFrame>& rxFrame) 576 { 577 if ( ! rxFrame.is() || ! rxFrame->getController().is()) 578 return OUString(); 579 580 try 581 { 582 const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory()); 583 const Reference<frame::XModuleManager> xModuleManager ( 584 aContext.createComponent("com.sun.star.frame.ModuleManager"), 585 UNO_QUERY_THROW); 586 return xModuleManager->identify(rxFrame); 587 } 588 catch (const Exception&) 589 { 590 DBG_UNHANDLED_EXCEPTION(); 591 } 592 return OUString(); 593 } 594 595 596 597 598 ::utl::OConfigurationTreeRoot ResourceManager::GetLegacyAddonRootNode ( 599 const ::rtl::OUString& rsModuleName) const 600 { 601 try 602 { 603 const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory()); 604 const Reference<container::XNameAccess> xModuleAccess ( 605 aContext.createComponent("com.sun.star.frame.ModuleManager"), 606 UNO_QUERY_THROW); 607 const ::comphelper::NamedValueCollection aModuleProperties (xModuleAccess->getByName(rsModuleName)); 608 const ::rtl::OUString sWindowStateRef (aModuleProperties.getOrDefault( 609 "ooSetupFactoryWindowStateConfigRef", 610 ::rtl::OUString())); 611 612 ::rtl::OUStringBuffer aPathComposer; 613 aPathComposer.appendAscii("org.openoffice.Office.UI."); 614 aPathComposer.append(sWindowStateRef); 615 aPathComposer.appendAscii("/UIElements/States"); 616 617 return ::utl::OConfigurationTreeRoot(aContext, aPathComposer.makeStringAndClear(), false); 618 } 619 catch( const Exception& ) 620 { 621 DBG_UNHANDLED_EXCEPTION(); 622 } 623 624 return ::utl::OConfigurationTreeRoot(); 625 } 626 627 628 629 630 void ResourceManager::GetToolPanelNodeNames ( 631 ::std::vector<OUString>& rMatchingNames, 632 const ::utl::OConfigurationTreeRoot aRoot) const 633 { 634 Sequence<OUString> aChildNodeNames (aRoot.getNodeNames()); 635 const sal_Int32 nCount (aChildNodeNames.getLength()); 636 for (sal_Int32 nIndex(0); nIndex<nCount; ++nIndex) 637 { 638 if (aChildNodeNames[nIndex].matchAsciiL( 639 RTL_CONSTASCII_STRINGPARAM( "private:resource/toolpanel/"))) 640 rMatchingNames.push_back(aChildNodeNames[nIndex]); 641 } 642 } 643 644 645 646 647 bool ResourceManager::IsDeckEnabled ( 648 const OUString& rsDeckId, 649 const Context& rContext, 650 const Reference<frame::XFrame>& rxFrame) const 651 { 652 // Check if any panel that matches the current context can be 653 // displayed. 654 ResourceManager::PanelContextDescriptorContainer aPanelContextDescriptors; 655 ResourceManager::Instance().GetMatchingPanels( 656 aPanelContextDescriptors, 657 rContext, 658 rsDeckId, 659 rxFrame); 660 661 for (ResourceManager::PanelContextDescriptorContainer::const_iterator 662 iPanel(aPanelContextDescriptors.begin()), 663 iEnd(aPanelContextDescriptors.end()); 664 iPanel!=iEnd; 665 ++iPanel) 666 { 667 if (iPanel->mbShowForReadOnlyDocuments) 668 return true; 669 } 670 671 return false; 672 } 673 674 675 } } // end of namespace sfx2::sidebar 676