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