/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/** Inner implementation class of the MasterPageContainer.
*/ class MasterPageContainer::Implementation
: public SdGlobalResource, public MasterPageContainerFiller::ContainerAdapter, public MasterPageContainerQueue::ContainerAdapter
{ public: mutable ::osl::Mutex maMutex;
/** Called by the MasterPageContainerFiller to notify that all master pages from template documents have been added.
*/ virtualvoid FillingDone() override;
std::unique_ptr<MasterPageContainerQueue> mpRequestQueue;
css::uno::Reference<css::frame::XModel> mxModel;
SdDrawDocument* mpDocument;
PreviewRenderer maPreviewRenderer; /** Remember whether the first page object has already been used to determine the correct size ratio.
*/ bool mbFirstPageObjectSeen;
// The widths for the previews contain two pixels for the border that is // painted around the preview. staticconstint SMALL_PREVIEW_WIDTH = 72 + 2; staticconstint LARGE_PREVIEW_WIDTH = 2*72 + 2;
/** This substitution of page preview shows "Preparing preview" and is shown as long as the actual previews are not being present.
*/
Image maLargePreviewBeingCreated;
Image maSmallPreviewBeingCreated;
/** This substitution of page preview is shown when a preview can not be created and thus is not available.
*/
Image maLargePreviewNotAvailable;
Image maSmallPreviewNotAvailable;
// We have to remember the tasks for initialization and filling in case // a MasterPageContainer object is destroyed before these tasks have // been completed.
std::weak_ptr<sd::tools::TimerBasedTaskExecution> mpFillerTask;
SdPage* pPageObject = nullptr;
SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor)
{
pPageObject = pDescriptor->mpMasterPage; if (pPageObject == nullptr)
{ // The page object is not (yet) present. Call // UpdateDescriptor() to trigger the PageObjectProvider() to // provide it. if (bLoad)
mpImpl->GetModel(); if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true))
pPageObject = pDescriptor->mpMasterPage;
}
} return pPageObject;
}
MasterPageContainer::Implementation::~Implementation()
{ // When the initializer or filler tasks are still running then we have // to stop them now in order to prevent them from calling us back.
tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask);
// Get page object and preview when that is inexpensive.
UpdateDescriptor(rpDescriptor,false,false, false);
// Look up the new MasterPageDescriptor and either insert it or update // an already existing one.
MasterPageContainerType::iterator aEntry (
::std::find_if (
maContainer.begin(),
maContainer.end(),
MasterPageDescriptor::AllComparator(rpDescriptor))); if (aEntry == maContainer.end())
{ // Insert a new MasterPageDescriptor. bool bIgnore(rpDescriptor->mpPageObjectProvider == nullptr
&& rpDescriptor->msURL.isEmpty());
// Templates are precious, i.e. we lock them so that they will // not be destroyed when (temporarily) no one references them. // They will only be deleted when the container is destroyed. switch (rpDescriptor->meOrigin)
{ caseTEMPLATE: caseDEFAULT:
++rpDescriptor->mnUseCount; break;
FireContainerChange(MasterPageContainerChangeEvent::EventType::CHILD_ADDED,aResult);
}
} else
{ // Update an existing MasterPageDescriptor.
aResult = (*aEntry)->maToken;
std::unique_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes(
(*aEntry)->Update(*rpDescriptor)); if (pEventTypes != nullptr && !pEventTypes->empty())
{ // One or more aspects of the descriptor have changed. Send // appropriate events to the listeners.
UpdateDescriptor(*aEntry,false,false, true);
// When the preview is missing but inexpensively creatable then do that // now. if (pDescriptor)
{ if (ePreviewState == PS_CREATABLE) if (UpdateDescriptor(pDescriptor, false,false, true)) if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
ePreviewState = PS_AVAILABLE;
switch (ePreviewState)
{ case PS_AVAILABLE:
aPreview = pDescriptor->GetPreview(ePreviewSize); break;
case PS_PREPARING: case PS_CREATABLE:
aPreview = GetPreviewSubstitution(
STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
ePreviewSize); break;
SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); if (pDescriptor)
{ if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
eState = PS_AVAILABLE; elseif (pDescriptor->mpPreviewProvider != nullptr)
{ // The preview does not exist but can be created. When that is // not expensive then do it at once. if (mpRequestQueue->HasRequest(aToken))
eState = PS_PREPARING; else
eState = PS_CREATABLE;
} else
eState = PS_NOT_AVAILABLE;
}
if ( ! mxModel.is())
{ // Create a new model.
mxModel.set(
::comphelper::getProcessServiceFactory()->createInstance(
u"com.sun.star.presentation.PresentationDocument"_ustr),
uno::UNO_QUERY);
// Initialize the model.
uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY); if (xLoadable.is())
xLoadable->initNew();
// Use its tunnel to get a pointer to its core implementation.
uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY); if (auto pSdXImpressDocument = comphelper::getFromUnoTunnel<SdXImpressDocument>(xUnoTunnel))
{
mpDocument = pSdXImpressDocument->GetDoc();
}
// Create a default page.
uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY); if (xSlideSupplier.is())
{
uno::Reference<drawing::XDrawPages> xSlides =
xSlideSupplier->getDrawPages(); if (xSlides.is())
{
uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(0));
uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY); if (xProperties.is())
xProperties->setPropertyValue(
u"Layout"_ustr,
Any(sal_Int16(AUTOLAYOUT_TITLE)));
}
}
} return mxModel;
}
void MasterPageContainer::Implementation::CleanContainer()
{ // Remove the empty elements at the end of the container. The empty // elements in the middle can not be removed because that would // invalidate the references still held by others. int nIndex (maContainer.size()-1); while (nIndex>=0 && !maContainer[nIndex])
--nIndex;
maContainer.resize(++nIndex);
}
// We have to create the page object when the preview provider needs it // and the caller needs the preview.
bForcePageObject |= (bForcePreview
&& rpDescriptor->mpPreviewProvider->NeedsPageObject()
&& rpDescriptor->mpMasterPage==nullptr);
// Define a cost threshold so that an update or page object or preview // that is at least this cost are made at once. Updates with higher cost // are scheduled for later.
sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0);
// Update the page object (which may be used for the preview update). if (bForcePageObject)
GetDocument(); int nPageObjectModified (rpDescriptor->UpdatePageObject(
(bForcePageObject ? -1 : nCostThreshold),
mpDocument)); if (nPageObjectModified == 1 && bSendEvents)
FireContainerChange(
MasterPageContainerChangeEvent::EventType::DATA_CHANGED,
rpDescriptor->maToken); if (nPageObjectModified == -1 && bSendEvents)
FireContainerChange(
MasterPageContainerChangeEvent::EventType::CHILD_REMOVED,
rpDescriptor->maToken); if (nPageObjectModified && ! mbFirstPageObjectSeen)
UpdatePreviewSizePixel();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.