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_sd.hxx" 23 24 #include "MasterPageContainer.hxx" 25 26 #include "MasterPageDescriptor.hxx" 27 #include "MasterPageContainerFiller.hxx" 28 #include "MasterPageContainerQueue.hxx" 29 #include "TemplateScanner.hxx" 30 #include "tools/AsynchronousTask.hxx" 31 #include "strings.hrc" 32 #include <algorithm> 33 #include <list> 34 #include <set> 35 36 #include "unomodel.hxx" 37 #include <com/sun/star/frame/XComponentLoader.hpp> 38 #include <com/sun/star/io/XStream.hpp> 39 #include <com/sun/star/io/XInputStream.hpp> 40 #include <com/sun/star/lang/XSingleServiceFactory.hpp> 41 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 42 #include <com/sun/star/uno/Reference.hxx> 43 #include <com/sun/star/uno/Any.hxx> 44 #include <com/sun/star/uno/Sequence.hxx> 45 #include <com/sun/star/util/XCloseable.hpp> 46 #include <comphelper/processfactory.hxx> 47 #include <tools/urlobj.hxx> 48 #include <sfx2/app.hxx> 49 #include <svx/svdpage.hxx> 50 #include "DrawDocShell.hxx" 51 #include "drawdoc.hxx" 52 #include "sdpage.hxx" 53 #include <svl/itemset.hxx> 54 #include <svl/eitem.hxx> 55 #include "sdresid.hxx" 56 #include "tools/TimerBasedTaskExecution.hxx" 57 #include "pres.hxx" 58 #include <osl/mutex.hxx> 59 #include <boost/weak_ptr.hpp> 60 61 using namespace ::com::sun::star; 62 using namespace ::com::sun::star::uno; 63 64 namespace { 65 66 typedef ::std::vector<sd::sidebar::SharedMasterPageDescriptor> MasterPageContainerType; 67 68 } // end of anonymous namespace 69 70 71 namespace sd { namespace sidebar { 72 73 74 /** Inner implementation class of the MasterPageContainer. 75 */ 76 class MasterPageContainer::Implementation 77 : public SdGlobalResource, 78 public MasterPageContainerFiller::ContainerAdapter, 79 public MasterPageContainerQueue::ContainerAdapter 80 { 81 public: 82 mutable ::osl::Mutex maMutex; 83 84 static ::boost::weak_ptr<Implementation> mpInstance; 85 MasterPageContainerType maContainer; 86 87 static ::boost::shared_ptr<Implementation> Instance (void); 88 89 void LateInit (void); 90 void AddChangeListener (const Link& rLink); 91 void RemoveChangeListener (const Link& rLink); 92 void UpdatePreviewSizePixel (void); 93 Size GetPreviewSizePixel (PreviewSize eSize) const; 94 95 bool HasToken (Token aToken) const; 96 const SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken) const; 97 SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken); 98 virtual Token PutMasterPage (const SharedMasterPageDescriptor& rDescriptor); 99 void InvalidatePreview (Token aToken); 100 Image GetPreviewForToken ( 101 Token aToken, 102 PreviewSize ePreviewSize); 103 PreviewState GetPreviewState (Token aToken) const; 104 bool RequestPreview (Token aToken); 105 106 Reference<frame::XModel> GetModel (void); 107 SdDrawDocument* GetDocument (void); 108 109 void FireContainerChange ( 110 MasterPageContainerChangeEvent::EventType eType, 111 Token aToken, 112 bool bNotifyAsynchronously = false); 113 114 virtual bool UpdateDescriptor ( 115 const SharedMasterPageDescriptor& rpDescriptor, 116 bool bForcePageObject, 117 bool bForcePreview, 118 bool bSendEvents); 119 120 void ReleaseDescriptor (Token aToken); 121 122 /** Called by the MasterPageContainerFiller to notify that all master 123 pages from template documents have been added. 124 */ 125 virtual void FillingDone (void); 126 127 private: 128 Implementation (void); 129 virtual ~Implementation (void); 130 131 class Deleter { public: 132 void operator() (Implementation* pObject) { delete pObject; } 133 }; 134 friend class Deleter; 135 136 enum InitializationState { NOT_INITIALIZED, INITIALIZING, INITIALIZED } meInitializationState; 137 138 ::boost::scoped_ptr<MasterPageContainerQueue> mpRequestQueue; 139 ::com::sun::star::uno::Reference<com::sun::star::frame::XModel> mxModel; 140 SdDrawDocument* mpDocument; 141 PreviewRenderer maPreviewRenderer; 142 /** Remember whether the first page object has already been used to 143 determine the correct size ratio. 144 */ 145 bool mbFirstPageObjectSeen; 146 147 // The widths for the previews contain two pixels for the border that is 148 // painted arround the preview. 149 static const int SMALL_PREVIEW_WIDTH = 72 + 2; 150 static const int LARGE_PREVIEW_WIDTH = 2*72 + 2; 151 152 /** This substition of page preview shows "Preparing preview" and is 153 shown as long as the actual previews are not being present. 154 */ 155 Image maLargePreviewBeingCreated; 156 Image maSmallPreviewBeingCreated; 157 158 /** This substition of page preview is shown when a preview can not be 159 created and thus is not available. 160 */ 161 Image maLargePreviewNotAvailable; 162 Image maSmallPreviewNotAvailable; 163 164 ::std::vector<Link> maChangeListeners; 165 166 // We have to remember the tasks for initialization and filling in case 167 // a MasterPageContainer object is destroyed before these tasks have 168 // been completed. 169 ::boost::weak_ptr<sd::tools::TimerBasedTaskExecution> mpFillerTask; 170 171 Size maSmallPreviewSizePixel; 172 Size maLargePreviewSizePixel; 173 bool mbPageRatioKnown; 174 175 bool mbContainerCleaningPending; 176 177 typedef ::std::pair<MasterPageContainerChangeEvent::EventType,Token> EventData; 178 DECL_LINK(AsynchronousNotifyCallback, EventData*); 179 ::sd::DrawDocShell* LoadDocument ( 180 const String& sFileName, 181 SfxObjectShellLock& rxDocumentShell); 182 183 Image GetPreviewSubstitution (sal_uInt16 nId, PreviewSize ePreviewSize); 184 185 void CleanContainer (void); 186 }; 187 188 189 190 191 //===== MasterPageContainer =================================================== 192 193 ::boost::weak_ptr<MasterPageContainer::Implementation> 194 MasterPageContainer::Implementation::mpInstance; 195 static const MasterPageContainer::Token NIL_TOKEN (-1); 196 197 198 199 200 ::boost::shared_ptr<MasterPageContainer::Implementation> 201 MasterPageContainer::Implementation::Instance (void) 202 { 203 ::boost::shared_ptr<MasterPageContainer::Implementation> pInstance; 204 205 if (Implementation::mpInstance.expired()) 206 { 207 ::osl::GetGlobalMutex aMutexFunctor; 208 ::osl::MutexGuard aGuard (aMutexFunctor()); 209 if (Implementation::mpInstance.expired()) 210 { 211 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 212 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>( 213 new MasterPageContainer::Implementation(), 214 MasterPageContainer::Implementation::Deleter()); 215 SdGlobalResourceContainer::Instance().AddResource(pInstance); 216 Implementation::mpInstance = pInstance; 217 } 218 else 219 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>( 220 Implementation::mpInstance); 221 } 222 else 223 { 224 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 225 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>( 226 Implementation::mpInstance); 227 } 228 229 DBG_ASSERT (pInstance.get()!=NULL, 230 "MasterPageContainer::Implementation::Instance(): instance is NULL"); 231 return pInstance; 232 } 233 234 235 236 237 MasterPageContainer::MasterPageContainer (void) 238 : mpImpl(Implementation::Instance()), 239 mePreviewSize(SMALL) 240 { 241 mpImpl->LateInit(); 242 } 243 244 245 246 247 MasterPageContainer::~MasterPageContainer (void) 248 { 249 } 250 251 252 253 254 void MasterPageContainer::AddChangeListener (const Link& rLink) 255 { 256 mpImpl->AddChangeListener(rLink); 257 } 258 259 260 261 262 void MasterPageContainer::RemoveChangeListener (const Link& rLink) 263 { 264 mpImpl->RemoveChangeListener(rLink); 265 } 266 267 268 269 270 void MasterPageContainer::SetPreviewSize (PreviewSize eSize) 271 { 272 mePreviewSize = eSize; 273 mpImpl->FireContainerChange( 274 MasterPageContainerChangeEvent::SIZE_CHANGED, 275 NIL_TOKEN); 276 } 277 278 279 280 281 MasterPageContainer::PreviewSize MasterPageContainer::GetPreviewSize (void) const 282 { 283 return mePreviewSize; 284 } 285 286 287 288 289 Size MasterPageContainer::GetPreviewSizePixel (void) const 290 { 291 return mpImpl->GetPreviewSizePixel(mePreviewSize); 292 } 293 294 295 296 297 MasterPageContainer::Token MasterPageContainer::PutMasterPage ( 298 const SharedMasterPageDescriptor& rDescriptor) 299 { 300 return mpImpl->PutMasterPage(rDescriptor); 301 } 302 303 304 305 306 void MasterPageContainer::AcquireToken (Token aToken) 307 { 308 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); 309 if (pDescriptor.get() != NULL) 310 { 311 ++pDescriptor->mnUseCount; 312 } 313 } 314 315 316 317 318 void MasterPageContainer::ReleaseToken (Token aToken) 319 { 320 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); 321 if (pDescriptor.get() != NULL) 322 { 323 OSL_ASSERT(pDescriptor->mnUseCount>0); 324 --pDescriptor->mnUseCount; 325 if (pDescriptor->mnUseCount <= 0) 326 { 327 switch (pDescriptor->meOrigin) 328 { 329 case DEFAULT: 330 case TEMPLATE: 331 default: 332 break; 333 334 case MASTERPAGE: 335 mpImpl->ReleaseDescriptor(aToken); 336 break; 337 } 338 } 339 } 340 } 341 342 343 344 345 int MasterPageContainer::GetTokenCount (void) const 346 { 347 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 348 349 return mpImpl->maContainer.size(); 350 } 351 352 353 354 355 bool MasterPageContainer::HasToken (Token aToken) const 356 { 357 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 358 359 return mpImpl->HasToken(aToken); 360 } 361 362 363 364 365 MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex) 366 { 367 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 368 369 Token aResult (NIL_TOKEN); 370 if (HasToken(nIndex)) 371 aResult = mpImpl->maContainer[nIndex]->maToken; 372 return aResult; 373 } 374 375 376 377 378 MasterPageContainer::Token MasterPageContainer::GetTokenForURL ( 379 const String& sURL) 380 { 381 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 382 383 Token aResult (NIL_TOKEN); 384 if (sURL.Len() > 0) 385 { 386 MasterPageContainerType::iterator iEntry ( 387 ::std::find_if ( 388 mpImpl->maContainer.begin(), 389 mpImpl->maContainer.end(), 390 MasterPageDescriptor::URLComparator(sURL))); 391 if (iEntry != mpImpl->maContainer.end()) 392 aResult = (*iEntry)->maToken; 393 } 394 return aResult; 395 } 396 397 398 399 400 MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const String& sStyleName) 401 { 402 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 403 404 Token aResult (NIL_TOKEN); 405 if (sStyleName.Len() > 0) 406 { 407 MasterPageContainerType::iterator iEntry ( 408 ::std::find_if ( 409 mpImpl->maContainer.begin(), 410 mpImpl->maContainer.end(), 411 MasterPageDescriptor::StyleNameComparator(sStyleName))); 412 if (iEntry != mpImpl->maContainer.end()) 413 aResult = (*iEntry)->maToken; 414 } 415 return aResult; 416 } 417 418 419 420 421 MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject ( 422 const SdPage* pPage) 423 { 424 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 425 426 Token aResult (NIL_TOKEN); 427 if (pPage != NULL) 428 { 429 MasterPageContainerType::iterator iEntry ( 430 ::std::find_if ( 431 mpImpl->maContainer.begin(), 432 mpImpl->maContainer.end(), 433 MasterPageDescriptor::PageObjectComparator(pPage))); 434 if (iEntry != mpImpl->maContainer.end()) 435 aResult = (*iEntry)->maToken; 436 } 437 return aResult; 438 } 439 440 441 442 443 String MasterPageContainer::GetURLForToken ( 444 MasterPageContainer::Token aToken) 445 { 446 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 447 448 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); 449 if (pDescriptor.get() != NULL) 450 return pDescriptor->msURL; 451 else 452 return String(); 453 } 454 455 456 457 458 String MasterPageContainer::GetPageNameForToken ( 459 MasterPageContainer::Token aToken) 460 { 461 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 462 463 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); 464 if (pDescriptor.get() != NULL) 465 return pDescriptor->msPageName; 466 else 467 return String(); 468 } 469 470 471 472 473 String MasterPageContainer::GetStyleNameForToken ( 474 MasterPageContainer::Token aToken) 475 { 476 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 477 478 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); 479 if (pDescriptor.get() != NULL) 480 return pDescriptor->msStyleName; 481 else 482 return String(); 483 } 484 485 486 487 488 SdPage* MasterPageContainer::GetPageObjectForToken ( 489 MasterPageContainer::Token aToken, 490 bool bLoad) 491 { 492 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 493 494 SdPage* pPageObject = NULL; 495 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); 496 if (pDescriptor.get() != NULL) 497 { 498 pPageObject = pDescriptor->mpMasterPage; 499 if (pPageObject == NULL) 500 { 501 // The page object is not (yet) present. Call 502 // UpdateDescriptor() to trigger the PageObjectProvider() to 503 // provide it. 504 if (bLoad) 505 mpImpl->GetModel(); 506 if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true)) 507 pPageObject = pDescriptor->mpMasterPage; 508 } 509 } 510 return pPageObject; 511 } 512 513 514 515 516 MasterPageContainer::Origin MasterPageContainer::GetOriginForToken (Token aToken) 517 { 518 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 519 520 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); 521 if (pDescriptor.get() != NULL) 522 return pDescriptor->meOrigin; 523 else 524 return UNKNOWN; 525 } 526 527 528 529 530 sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken) 531 { 532 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 533 534 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); 535 if (pDescriptor.get() != NULL) 536 return pDescriptor->mnTemplateIndex; 537 else 538 return -1; 539 } 540 541 542 543 544 SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken ( 545 MasterPageContainer::Token aToken) 546 { 547 const ::osl::MutexGuard aGuard (mpImpl->maMutex); 548 549 return mpImpl->GetDescriptor(aToken); 550 } 551 552 553 554 void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken) 555 { 556 mpImpl->InvalidatePreview(aToken); 557 } 558 559 560 561 562 Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken) 563 { 564 return mpImpl->GetPreviewForToken(aToken,mePreviewSize); 565 } 566 567 568 569 570 MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken) 571 { 572 return mpImpl->GetPreviewState(aToken); 573 } 574 575 576 577 578 bool MasterPageContainer::RequestPreview (Token aToken) 579 { 580 return mpImpl->RequestPreview(aToken); 581 } 582 583 584 585 586 //==== Implementation ================================================ 587 588 MasterPageContainer::Implementation::Implementation (void) 589 : maMutex(), 590 maContainer(), 591 meInitializationState(NOT_INITIALIZED), 592 mpRequestQueue(NULL), 593 mxModel(NULL), 594 mpDocument(NULL), 595 maPreviewRenderer(), 596 mbFirstPageObjectSeen(false), 597 maLargePreviewBeingCreated(), 598 maSmallPreviewBeingCreated(), 599 maLargePreviewNotAvailable(), 600 maSmallPreviewNotAvailable(), 601 maChangeListeners(), 602 maSmallPreviewSizePixel(), 603 maLargePreviewSizePixel(), 604 mbPageRatioKnown(false), 605 mbContainerCleaningPending(true) 606 607 { 608 UpdatePreviewSizePixel(); 609 } 610 611 612 613 614 MasterPageContainer::Implementation::~Implementation (void) 615 { 616 // When the initializer or filler tasks are still running then we have 617 // to stop them now in order to prevent them from calling us back. 618 tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask); 619 620 mpRequestQueue.reset(); 621 622 uno::Reference<util::XCloseable> xCloseable (mxModel, uno::UNO_QUERY); 623 if (xCloseable.is()) 624 { 625 try 626 { 627 xCloseable->close(true); 628 } 629 catch (::com::sun::star::util::CloseVetoException aException) 630 { 631 } 632 } 633 mxModel = NULL; 634 } 635 636 637 638 639 void MasterPageContainer::Implementation::LateInit (void) 640 { 641 const ::osl::MutexGuard aGuard (maMutex); 642 643 if (meInitializationState == NOT_INITIALIZED) 644 { 645 meInitializationState = INITIALIZING; 646 647 OSL_ASSERT(Instance().get()==this); 648 mpRequestQueue.reset(MasterPageContainerQueue::Create( 649 ::boost::shared_ptr<MasterPageContainerQueue::ContainerAdapter>(Instance()))); 650 651 mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create( 652 ::boost::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)), 653 5, 654 50); 655 656 meInitializationState = INITIALIZED; 657 } 658 } 659 660 661 662 663 void MasterPageContainer::Implementation::AddChangeListener (const Link& rLink) 664 { 665 const ::osl::MutexGuard aGuard (maMutex); 666 667 ::std::vector<Link>::iterator iListener ( 668 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink)); 669 if (iListener == maChangeListeners.end()) 670 maChangeListeners.push_back(rLink); 671 672 } 673 674 675 676 677 void MasterPageContainer::Implementation::RemoveChangeListener (const Link& rLink) 678 { 679 const ::osl::MutexGuard aGuard (maMutex); 680 681 ::std::vector<Link>::iterator iListener ( 682 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink)); 683 if (iListener != maChangeListeners.end()) 684 maChangeListeners.erase(iListener); 685 } 686 687 688 689 690 void MasterPageContainer::Implementation::UpdatePreviewSizePixel (void) 691 { 692 const ::osl::MutexGuard aGuard (maMutex); 693 694 // The default aspect ratio is 4:3 695 int nWidth (4); 696 int nHeight (3); 697 698 // Search for the first entry with an existing master page. 699 MasterPageContainerType::const_iterator iDescriptor; 700 MasterPageContainerType::const_iterator iContainerEnd(maContainer.end()); 701 for (iDescriptor=maContainer.begin(); iDescriptor!=iContainerEnd; ++iDescriptor) 702 if (*iDescriptor!=NULL && (*iDescriptor)->mpMasterPage != NULL) 703 { 704 Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize()); 705 nWidth = aPageSize.Width(); 706 nHeight = aPageSize.Height(); 707 mbFirstPageObjectSeen = true; 708 break; 709 } 710 711 maSmallPreviewSizePixel.Width() = SMALL_PREVIEW_WIDTH; 712 maLargePreviewSizePixel.Width() = LARGE_PREVIEW_WIDTH; 713 714 int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2); 715 int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2); 716 717 if (nNewSmallHeight!=maSmallPreviewSizePixel.Height() 718 || nNewLargeHeight!=maLargePreviewSizePixel.Height()) 719 { 720 maSmallPreviewSizePixel.Height() = nNewSmallHeight; 721 maLargePreviewSizePixel.Height() = nNewLargeHeight; 722 FireContainerChange( 723 MasterPageContainerChangeEvent::SIZE_CHANGED, 724 NIL_TOKEN); 725 } 726 } 727 728 729 730 731 Size MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const 732 { 733 if (eSize == SMALL) 734 return maSmallPreviewSizePixel; 735 else 736 return maLargePreviewSizePixel; 737 } 738 739 740 741 742 IMPL_LINK(MasterPageContainer::Implementation,AsynchronousNotifyCallback, EventData*, pData) 743 { 744 const ::osl::MutexGuard aGuard (maMutex); 745 746 if (pData != NULL) 747 { 748 FireContainerChange(pData->first, pData->second, false); 749 delete pData; 750 } 751 752 return 0; 753 } 754 755 756 757 758 MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage ( 759 const SharedMasterPageDescriptor& rpDescriptor) 760 { 761 const ::osl::MutexGuard aGuard (maMutex); 762 763 Token aResult (NIL_TOKEN); 764 765 // Get page object and preview when that is inexpensive. 766 UpdateDescriptor(rpDescriptor,false,false, false); 767 768 // Look up the new MasterPageDescriptor and either insert it or update 769 // an already existing one. 770 MasterPageContainerType::iterator aEntry ( 771 ::std::find_if ( 772 maContainer.begin(), 773 maContainer.end(), 774 MasterPageDescriptor::AllComparator(rpDescriptor))); 775 if (aEntry == maContainer.end()) 776 { 777 // Insert a new MasterPageDescriptor. 778 bool bIgnore (rpDescriptor->mpPageObjectProvider.get()==NULL 779 && rpDescriptor->msURL.getLength()==0); 780 781 if ( ! bIgnore) 782 { 783 if (mbContainerCleaningPending) 784 CleanContainer(); 785 786 aResult = maContainer.size(); 787 rpDescriptor->SetToken(aResult); 788 789 // Templates are precious, i.e. we lock them so that they will 790 // not be destroyed when (temporarily) no one references them. 791 // They will only be deleted when the container is destroyed. 792 switch (rpDescriptor->meOrigin) 793 { 794 case TEMPLATE: 795 case DEFAULT: 796 ++rpDescriptor->mnUseCount; 797 break; 798 799 default: 800 break; 801 } 802 803 maContainer.push_back(rpDescriptor); 804 aEntry = maContainer.end()-1; 805 806 FireContainerChange(MasterPageContainerChangeEvent::CHILD_ADDED,aResult); 807 } 808 } 809 else 810 { 811 // Update an existing MasterPageDescriptor. 812 aResult = (*aEntry)->maToken; 813 ::std::auto_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes( 814 (*aEntry)->Update(*rpDescriptor)); 815 if (pEventTypes.get()!=NULL && pEventTypes->size()>0) 816 { 817 // One or more aspects of the descriptor have changed. Send 818 // appropriate events to the listeners. 819 UpdateDescriptor(*aEntry,false,false, true); 820 821 std::vector<MasterPageContainerChangeEvent::EventType>::const_iterator iEventType; 822 for (iEventType=pEventTypes->begin(); iEventType!=pEventTypes->end(); ++iEventType) 823 { 824 FireContainerChange( 825 *iEventType, 826 (*aEntry)->maToken, 827 false); 828 } 829 } 830 } 831 832 return aResult; 833 } 834 835 836 837 838 bool MasterPageContainer::Implementation::HasToken (Token aToken) const 839 { 840 return aToken>=0 841 && (unsigned)aToken<maContainer.size() 842 && maContainer[aToken].get()!=NULL; 843 } 844 845 846 847 848 const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor ( 849 Token aToken) const 850 { 851 if (aToken>=0 && (unsigned)aToken<maContainer.size()) 852 return maContainer[aToken]; 853 else 854 return SharedMasterPageDescriptor(); 855 } 856 857 858 859 860 SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken) 861 { 862 if (aToken>=0 && (unsigned)aToken<maContainer.size()) 863 return maContainer[aToken]; 864 else 865 return SharedMasterPageDescriptor(); 866 } 867 868 869 870 871 void MasterPageContainer::Implementation::InvalidatePreview (Token aToken) 872 { 873 const ::osl::MutexGuard aGuard (maMutex); 874 875 SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken)); 876 if (pDescriptor.get() != NULL) 877 { 878 pDescriptor->maSmallPreview = Image(); 879 pDescriptor->maLargePreview = Image(); 880 RequestPreview(aToken); 881 } 882 } 883 884 885 886 887 Image MasterPageContainer::Implementation::GetPreviewForToken ( 888 MasterPageContainer::Token aToken, 889 PreviewSize ePreviewSize) 890 { 891 const ::osl::MutexGuard aGuard (maMutex); 892 893 Image aPreview; 894 PreviewState ePreviewState (GetPreviewState(aToken)); 895 896 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); 897 898 // When the preview is missing but inexpensively creatable then do that 899 // now. 900 if (pDescriptor.get()!=NULL) 901 { 902 if (ePreviewState == PS_CREATABLE) 903 if (UpdateDescriptor(pDescriptor, false,false, true)) 904 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0) 905 ePreviewState = PS_AVAILABLE; 906 907 switch (ePreviewState) 908 { 909 case PS_AVAILABLE: 910 aPreview = pDescriptor->GetPreview(ePreviewSize); 911 break; 912 913 case PS_PREPARING: 914 aPreview = GetPreviewSubstitution( 915 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION, 916 ePreviewSize); 917 break; 918 919 case PS_CREATABLE: 920 aPreview = GetPreviewSubstitution( 921 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION, 922 ePreviewSize); 923 break; 924 925 case PS_NOT_AVAILABLE: 926 aPreview = GetPreviewSubstitution( 927 STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION, 928 ePreviewSize); 929 if (ePreviewSize == SMALL) 930 pDescriptor->maSmallPreview = aPreview; 931 else 932 pDescriptor->maLargePreview = aPreview; 933 break; 934 } 935 } 936 937 return aPreview; 938 } 939 940 941 942 943 MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState ( 944 Token aToken) const 945 { 946 const ::osl::MutexGuard aGuard (maMutex); 947 948 PreviewState eState (PS_NOT_AVAILABLE); 949 950 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); 951 if (pDescriptor.get() != NULL) 952 { 953 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0) 954 eState = PS_AVAILABLE; 955 else if (pDescriptor->mpPreviewProvider.get() != NULL) 956 { 957 // The preview does not exist but can be created. When that is 958 // not expensive then do it at once. 959 if (mpRequestQueue->HasRequest(aToken)) 960 eState = PS_PREPARING; 961 else 962 eState = PS_CREATABLE; 963 } 964 else 965 eState = PS_NOT_AVAILABLE; 966 } 967 968 return eState; 969 } 970 971 972 973 974 bool MasterPageContainer::Implementation::RequestPreview (Token aToken) 975 { 976 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); 977 if (pDescriptor.get() != NULL) 978 return mpRequestQueue->RequestPreview(pDescriptor); 979 else 980 return false; 981 } 982 983 984 985 986 Reference<frame::XModel> MasterPageContainer::Implementation::GetModel (void) 987 { 988 const ::osl::MutexGuard aGuard (maMutex); 989 990 if ( ! mxModel.is()) 991 { 992 // Get the desktop a s service factory. 993 ::rtl::OUString sDesktopServiceName ( 994 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")); 995 uno::Reference<frame::XComponentLoader> xDesktop ( 996 ::comphelper::getProcessServiceFactory()->createInstance( 997 sDesktopServiceName), 998 uno::UNO_QUERY); 999 1000 // Create a new model. 1001 ::rtl::OUString sModelServiceName ( 1002 RTL_CONSTASCII_USTRINGPARAM( 1003 "com.sun.star.presentation.PresentationDocument")); 1004 mxModel = uno::Reference<frame::XModel>( 1005 ::comphelper::getProcessServiceFactory()->createInstance( 1006 sModelServiceName), 1007 uno::UNO_QUERY); 1008 1009 // Initialize the model. 1010 uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY); 1011 if (xLoadable.is()) 1012 xLoadable->initNew(); 1013 1014 // Use its tunnel to get a pointer to its core implementation. 1015 uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY); 1016 if (xUnoTunnel.is()) 1017 { 1018 mpDocument = reinterpret_cast<SdXImpressDocument*>( 1019 xUnoTunnel->getSomething( 1020 SdXImpressDocument::getUnoTunnelId()))->GetDoc(); 1021 } 1022 1023 // Create a default page. 1024 uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY); 1025 if (xSlideSupplier.is()) 1026 { 1027 uno::Reference<drawing::XDrawPages> xSlides ( 1028 xSlideSupplier->getDrawPages(), uno::UNO_QUERY); 1029 if (xSlides.is()) 1030 { 1031 sal_Int32 nIndex (0); 1032 uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(nIndex)); 1033 uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY); 1034 if (xProperties.is()) 1035 xProperties->setPropertyValue( 1036 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Layout")), 1037 makeAny((sal_Int16)AUTOLAYOUT_TITLE)); 1038 } 1039 } 1040 } 1041 return mxModel; 1042 } 1043 1044 1045 1046 1047 SdDrawDocument* MasterPageContainer::Implementation::GetDocument (void) 1048 { 1049 GetModel(); 1050 return mpDocument; 1051 } 1052 1053 1054 1055 1056 Image MasterPageContainer::Implementation::GetPreviewSubstitution ( 1057 sal_uInt16 nId, 1058 PreviewSize ePreviewSize) 1059 { 1060 const ::osl::MutexGuard aGuard (maMutex); 1061 1062 Image aPreview; 1063 1064 switch (nId) 1065 { 1066 case STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION: 1067 { 1068 Image& rPreview (ePreviewSize==SMALL 1069 ? maSmallPreviewBeingCreated 1070 : maLargePreviewBeingCreated); 1071 if (rPreview.GetSizePixel().Width() == 0) 1072 { 1073 rPreview = maPreviewRenderer.RenderSubstitution( 1074 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel, 1075 SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION)); 1076 } 1077 aPreview = rPreview; 1078 } 1079 break; 1080 1081 case STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION: 1082 { 1083 Image& rPreview (ePreviewSize==SMALL 1084 ? maSmallPreviewNotAvailable 1085 : maLargePreviewNotAvailable); 1086 if (rPreview.GetSizePixel().Width() == 0) 1087 { 1088 rPreview = maPreviewRenderer.RenderSubstitution( 1089 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel, 1090 SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION)); 1091 } 1092 aPreview = rPreview; 1093 } 1094 break; 1095 } 1096 1097 return aPreview; 1098 } 1099 1100 1101 1102 1103 void MasterPageContainer::Implementation::CleanContainer (void) 1104 { 1105 // Remove the empty elements at the end of the container. The empty 1106 // elements in the middle can not be removed because that would 1107 // invalidate the references still held by others. 1108 int nIndex (maContainer.size()-1); 1109 while (nIndex>=0 && maContainer[nIndex].get()==NULL) 1110 --nIndex; 1111 maContainer.resize(++nIndex); 1112 } 1113 1114 1115 1116 1117 void MasterPageContainer::Implementation::FireContainerChange ( 1118 MasterPageContainerChangeEvent::EventType eType, 1119 Token aToken, 1120 bool bNotifyAsynchronously) 1121 { 1122 if (bNotifyAsynchronously) 1123 { 1124 Application::PostUserEvent( 1125 LINK(this,Implementation,AsynchronousNotifyCallback), 1126 new EventData(eType,aToken)); 1127 } 1128 else 1129 { 1130 ::std::vector<Link> aCopy(maChangeListeners.begin(),maChangeListeners.end()); 1131 ::std::vector<Link>::iterator iListener; 1132 MasterPageContainerChangeEvent aEvent; 1133 aEvent.meEventType = eType; 1134 aEvent.maChildToken = aToken; 1135 for (iListener=aCopy.begin(); iListener!=aCopy.end(); ++iListener) 1136 iListener->Call(&aEvent); 1137 } 1138 } 1139 1140 1141 1142 1143 bool MasterPageContainer::Implementation::UpdateDescriptor ( 1144 const SharedMasterPageDescriptor& rpDescriptor, 1145 bool bForcePageObject, 1146 bool bForcePreview, 1147 bool bSendEvents) 1148 { 1149 const ::osl::MutexGuard aGuard (maMutex); 1150 1151 // We have to create the page object when the preview provider needs it 1152 // and the caller needs the preview. 1153 bForcePageObject |= (bForcePreview 1154 && rpDescriptor->mpPreviewProvider->NeedsPageObject() 1155 && rpDescriptor->mpMasterPage==NULL); 1156 1157 // Define a cost threshold so that an update or page object or preview 1158 // that is at least this cost are made at once. Updates with higher cost 1159 // are scheduled for later. 1160 sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0); 1161 1162 // Update the page object (which may be used for the preview update). 1163 if (bForcePageObject) 1164 GetDocument(); 1165 bool bPageObjectModified (rpDescriptor->UpdatePageObject( 1166 (bForcePageObject ? -1 : nCostThreshold), 1167 mpDocument)); 1168 if (bPageObjectModified && bSendEvents) 1169 FireContainerChange( 1170 MasterPageContainerChangeEvent::DATA_CHANGED, 1171 rpDescriptor->maToken); 1172 if (bPageObjectModified && ! mbFirstPageObjectSeen) 1173 UpdatePreviewSizePixel(); 1174 1175 // Update the preview. 1176 bool bPreviewModified (rpDescriptor->UpdatePreview( 1177 (bForcePreview ? -1 : nCostThreshold), 1178 maSmallPreviewSizePixel, 1179 maLargePreviewSizePixel, 1180 maPreviewRenderer)); 1181 1182 if (bPreviewModified && bSendEvents) 1183 FireContainerChange( 1184 MasterPageContainerChangeEvent::PREVIEW_CHANGED, 1185 rpDescriptor->maToken); 1186 1187 return bPageObjectModified || bPreviewModified; 1188 } 1189 1190 1191 1192 1193 void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken) 1194 { 1195 if (aToken>=0 && (unsigned)aToken<maContainer.size()) 1196 { 1197 maContainer[aToken].reset(); 1198 mbContainerCleaningPending = true; 1199 } 1200 } 1201 1202 1203 1204 1205 void MasterPageContainer::Implementation::FillingDone (void) 1206 { 1207 mpRequestQueue->ProcessAllRequests(); 1208 } 1209 1210 1211 1212 } } // end of namespace sd::sidebar 1213