You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by af...@apache.org on 2013/02/19 10:09:05 UTC

svn commit: r1447641 [5/9] - in /openoffice/branches/sidebar/main: default_images/sfx2/res/symphony/ framework/inc/services/ framework/source/services/ offapi/com/sun/star/ui/ officecfg/registry/data/org/openoffice/Office/ officecfg/registry/data/org/o...

Added: openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainer.cxx
URL: http://svn.apache.org/viewvc/openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainer.cxx?rev=1447641&view=auto
==============================================================================
--- openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainer.cxx (added)
+++ openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainer.cxx Tue Feb 19 09:09:02 2013
@@ -0,0 +1,1212 @@
+/**************************************************************
+ * 
+ * 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
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "MasterPageContainer.hxx"
+
+#include "MasterPageDescriptor.hxx"
+#include "MasterPageContainerFiller.hxx"
+#include "MasterPageContainerQueue.hxx"
+#include "TemplateScanner.hxx"
+#include "tools/AsynchronousTask.hxx"
+#include "strings.hrc"
+#include <algorithm>
+#include <list>
+#include <set>
+
+#include "unomodel.hxx"
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <comphelper/processfactory.hxx>
+#include <tools/urlobj.hxx>
+#include <sfx2/app.hxx>
+#include <svx/svdpage.hxx>
+#include "DrawDocShell.hxx"
+#include "drawdoc.hxx"
+#include "sdpage.hxx"
+#include <svl/itemset.hxx>
+#include <svl/eitem.hxx>
+#include "sdresid.hxx"
+#include "tools/TimerBasedTaskExecution.hxx"
+#include "pres.hxx"
+#include <osl/mutex.hxx>
+#include <boost/weak_ptr.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace {
+
+typedef ::std::vector<sd::sidebar::SharedMasterPageDescriptor> MasterPageContainerType;
+
+} // end of anonymous namespace
+
+
+namespace sd { namespace sidebar {
+
+
+/** Inner implementation class of the MasterPageContainer.
+*/
+class MasterPageContainer::Implementation
+    : public SdGlobalResource,
+      public MasterPageContainerFiller::ContainerAdapter,
+      public MasterPageContainerQueue::ContainerAdapter
+{
+public:
+    mutable ::osl::Mutex maMutex;
+
+    static ::boost::weak_ptr<Implementation> mpInstance;
+    MasterPageContainerType maContainer;
+
+    static ::boost::shared_ptr<Implementation> Instance (void);
+
+    void LateInit (void);
+    void AddChangeListener (const Link& rLink);
+    void RemoveChangeListener (const Link& rLink);
+    void UpdatePreviewSizePixel (void);
+    Size GetPreviewSizePixel (PreviewSize eSize) const;
+
+    bool HasToken (Token aToken) const;
+    const SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken) const;
+    SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken);
+    virtual Token PutMasterPage (const SharedMasterPageDescriptor& rDescriptor);
+    void InvalidatePreview (Token aToken);
+    Image GetPreviewForToken (
+        Token aToken,
+        PreviewSize ePreviewSize);
+    PreviewState GetPreviewState (Token aToken) const;
+    bool RequestPreview (Token aToken);
+
+    Reference<frame::XModel> GetModel (void);
+    SdDrawDocument* GetDocument (void);
+
+    void FireContainerChange (
+        MasterPageContainerChangeEvent::EventType eType,
+        Token aToken,
+        bool bNotifyAsynchronously = false);
+
+    virtual bool UpdateDescriptor (
+        const SharedMasterPageDescriptor& rpDescriptor,
+        bool bForcePageObject,
+        bool bForcePreview,
+        bool bSendEvents);
+
+    void ReleaseDescriptor (Token aToken);
+
+    /** Called by the MasterPageContainerFiller to notify that all master
+        pages from template documents have been added.
+    */
+    virtual void FillingDone (void);
+
+private:
+    Implementation (void);
+    virtual ~Implementation (void);
+
+    class Deleter { public:
+        void operator() (Implementation* pObject) { delete pObject; }
+    };
+    friend class Deleter;
+
+    enum InitializationState { NOT_INITIALIZED, INITIALIZING, INITIALIZED } meInitializationState;
+
+    ::boost::scoped_ptr<MasterPageContainerQueue> mpRequestQueue;
+    ::com::sun::star::uno::Reference<com::sun::star::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 arround the preview.
+    static const int SMALL_PREVIEW_WIDTH = 72 + 2;
+    static const int LARGE_PREVIEW_WIDTH = 2*72 + 2;
+
+    /** This substition of page preview shows "Preparing preview" and is
+        shown as long as the actual previews are not being present.
+    */
+    Image maLargePreviewBeingCreated;
+    Image maSmallPreviewBeingCreated;
+
+    /** This substition of page preview is shown when a preview can not be
+        created and thus is not available.
+    */
+    Image maLargePreviewNotAvailable;
+    Image maSmallPreviewNotAvailable;
+
+    ::std::vector<Link> maChangeListeners;
+
+    // We have to remember the tasks for initialization and filling in case
+    // a MasterPageContainer object is destroyed before these tasks have
+    // been completed.
+    ::boost::weak_ptr<sd::tools::TimerBasedTaskExecution> mpFillerTask;
+
+    Size maSmallPreviewSizePixel;
+    Size maLargePreviewSizePixel;
+    bool mbPageRatioKnown;
+
+    bool mbContainerCleaningPending;
+
+    typedef ::std::pair<MasterPageContainerChangeEvent::EventType,Token> EventData;
+    DECL_LINK(AsynchronousNotifyCallback, EventData*);
+    ::sd::DrawDocShell* LoadDocument (
+        const String& sFileName,
+        SfxObjectShellLock& rxDocumentShell);
+
+    Image GetPreviewSubstitution (sal_uInt16 nId, PreviewSize ePreviewSize);
+
+    void CleanContainer (void);
+};
+
+
+
+
+//===== MasterPageContainer ===================================================
+
+::boost::weak_ptr<MasterPageContainer::Implementation>
+    MasterPageContainer::Implementation::mpInstance;
+static const MasterPageContainer::Token NIL_TOKEN (-1);
+
+
+
+
+::boost::shared_ptr<MasterPageContainer::Implementation>
+    MasterPageContainer::Implementation::Instance (void)
+{
+    ::boost::shared_ptr<MasterPageContainer::Implementation> pInstance;
+    
+    if (Implementation::mpInstance.expired())
+    {
+        ::osl::GetGlobalMutex aMutexFunctor;
+        ::osl::MutexGuard aGuard (aMutexFunctor());
+        if (Implementation::mpInstance.expired())
+        {
+            OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+            pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
+                new MasterPageContainer::Implementation(),
+                MasterPageContainer::Implementation::Deleter());
+            SdGlobalResourceContainer::Instance().AddResource(pInstance);
+            Implementation::mpInstance = pInstance;
+        }
+        else
+            pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
+                Implementation::mpInstance);
+    }
+    else
+    {
+        OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+        pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
+            Implementation::mpInstance);
+    }
+
+    DBG_ASSERT (pInstance.get()!=NULL,
+        "MasterPageContainer::Implementation::Instance(): instance is NULL");
+    return pInstance;
+}
+
+
+
+
+MasterPageContainer::MasterPageContainer (void)
+    : mpImpl(Implementation::Instance()),
+      mePreviewSize(SMALL)
+{
+    mpImpl->LateInit();
+}
+
+
+
+
+MasterPageContainer::~MasterPageContainer (void)
+{
+}
+
+
+
+
+void MasterPageContainer::AddChangeListener (const Link& rLink)
+{
+    mpImpl->AddChangeListener(rLink);
+}
+
+
+
+
+void MasterPageContainer::RemoveChangeListener (const Link& rLink)
+{
+    mpImpl->RemoveChangeListener(rLink);
+}
+
+
+
+
+void MasterPageContainer::SetPreviewSize (PreviewSize eSize)
+{
+    mePreviewSize = eSize;
+    mpImpl->FireContainerChange(
+        MasterPageContainerChangeEvent::SIZE_CHANGED,
+        NIL_TOKEN);
+}
+
+
+
+
+MasterPageContainer::PreviewSize MasterPageContainer::GetPreviewSize (void) const
+{
+    return mePreviewSize;
+}
+
+
+
+
+Size MasterPageContainer::GetPreviewSizePixel (void) const
+{
+    return mpImpl->GetPreviewSizePixel(mePreviewSize);
+}
+
+
+
+
+MasterPageContainer::Token MasterPageContainer::PutMasterPage (
+    const SharedMasterPageDescriptor& rDescriptor)
+{
+    return mpImpl->PutMasterPage(rDescriptor);
+}
+
+
+
+
+void MasterPageContainer::AcquireToken (Token aToken)
+{
+    SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+    {
+        ++pDescriptor->mnUseCount;
+    }
+}
+
+
+
+
+void MasterPageContainer::ReleaseToken (Token aToken)
+{
+    SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+    {
+        OSL_ASSERT(pDescriptor->mnUseCount>0);
+        --pDescriptor->mnUseCount;
+        if (pDescriptor->mnUseCount <= 0)
+        {
+            switch (pDescriptor->meOrigin)
+            {
+                case DEFAULT:
+                case TEMPLATE:
+                default:
+                    break;
+
+                case MASTERPAGE:
+                    mpImpl->ReleaseDescriptor(aToken);
+                    break;
+            }
+        }
+    }
+}
+
+
+
+
+int MasterPageContainer::GetTokenCount (void) const
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    return mpImpl->maContainer.size();
+}
+
+
+
+
+bool MasterPageContainer::HasToken (Token aToken) const
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    return mpImpl->HasToken(aToken);
+}
+
+
+
+
+MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    Token aResult (NIL_TOKEN);
+    if (HasToken(nIndex))
+        aResult = mpImpl->maContainer[nIndex]->maToken;
+    return aResult;
+}
+
+
+
+
+MasterPageContainer::Token MasterPageContainer::GetTokenForURL (
+    const String& sURL)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    Token aResult (NIL_TOKEN);
+    if (sURL.Len() > 0)
+    {
+        MasterPageContainerType::iterator iEntry (
+            ::std::find_if (
+                mpImpl->maContainer.begin(),
+                mpImpl->maContainer.end(),
+                MasterPageDescriptor::URLComparator(sURL)));
+        if (iEntry != mpImpl->maContainer.end())
+            aResult = (*iEntry)->maToken;
+    }
+    return aResult;
+}
+
+
+
+
+MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const String& sStyleName)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    Token aResult (NIL_TOKEN);
+    if (sStyleName.Len() > 0)
+    {
+        MasterPageContainerType::iterator iEntry (
+            ::std::find_if (
+                mpImpl->maContainer.begin(),
+                mpImpl->maContainer.end(),
+                MasterPageDescriptor::StyleNameComparator(sStyleName)));
+        if (iEntry != mpImpl->maContainer.end())
+            aResult = (*iEntry)->maToken;
+    }
+    return aResult;
+}
+
+
+
+
+MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject (
+    const SdPage* pPage)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    Token aResult (NIL_TOKEN);
+    if (pPage != NULL)
+    {
+        MasterPageContainerType::iterator iEntry (
+            ::std::find_if (
+                mpImpl->maContainer.begin(),
+                mpImpl->maContainer.end(),
+                MasterPageDescriptor::PageObjectComparator(pPage)));
+        if (iEntry != mpImpl->maContainer.end())
+            aResult = (*iEntry)->maToken;
+    }
+    return aResult;
+}
+
+
+
+
+String MasterPageContainer::GetURLForToken (
+    MasterPageContainer::Token aToken)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+        return pDescriptor->msURL;
+    else
+        return String();
+}
+
+
+
+
+String MasterPageContainer::GetPageNameForToken (
+    MasterPageContainer::Token aToken)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+        return pDescriptor->msPageName;
+    else
+        return String();
+}
+
+
+
+
+String MasterPageContainer::GetStyleNameForToken (
+    MasterPageContainer::Token aToken)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+        return pDescriptor->msStyleName;
+    else
+        return String();
+}
+
+
+
+
+SdPage* MasterPageContainer::GetPageObjectForToken (
+    MasterPageContainer::Token aToken,
+    bool bLoad)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    SdPage* pPageObject = NULL;
+    SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+    {
+        pPageObject = pDescriptor->mpMasterPage;
+        if (pPageObject == NULL)
+        {
+            // 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::Origin MasterPageContainer::GetOriginForToken (Token aToken)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+        return pDescriptor->meOrigin;
+    else
+        return UNKNOWN;
+}
+
+
+
+
+sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+        return pDescriptor->mnTemplateIndex;
+    else
+        return -1;
+}
+
+
+
+
+SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken (
+    MasterPageContainer::Token aToken)
+{
+    const ::osl::MutexGuard aGuard (mpImpl->maMutex);
+
+    return mpImpl->GetDescriptor(aToken);
+}
+
+
+
+void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken)
+{
+    mpImpl->InvalidatePreview(aToken);
+}
+
+
+
+
+Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken)
+{
+    return mpImpl->GetPreviewForToken(aToken,mePreviewSize);
+}
+
+
+
+
+MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken)
+{
+    return mpImpl->GetPreviewState(aToken);
+}
+
+
+
+
+bool MasterPageContainer::RequestPreview (Token aToken)
+{
+    return mpImpl->RequestPreview(aToken);
+}
+
+
+
+
+//==== Implementation ================================================
+
+MasterPageContainer::Implementation::Implementation (void)
+    : maMutex(),
+      maContainer(),
+	  meInitializationState(NOT_INITIALIZED),
+      mpRequestQueue(NULL),
+      mxModel(NULL),
+      mpDocument(NULL),
+      maPreviewRenderer(),
+      mbFirstPageObjectSeen(false),
+      maLargePreviewBeingCreated(),
+      maSmallPreviewBeingCreated(),
+      maLargePreviewNotAvailable(),
+      maSmallPreviewNotAvailable(),
+      maChangeListeners(),
+      maSmallPreviewSizePixel(),
+      maLargePreviewSizePixel(),
+      mbPageRatioKnown(false),
+      mbContainerCleaningPending(true)
+
+{
+    UpdatePreviewSizePixel();
+}
+
+
+
+
+MasterPageContainer::Implementation::~Implementation (void)
+{
+    // 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);
+
+    mpRequestQueue.reset();
+
+    uno::Reference<util::XCloseable> xCloseable (mxModel, uno::UNO_QUERY);
+    if (xCloseable.is())
+    {
+        try
+        {
+            xCloseable->close(true);
+        }
+        catch (::com::sun::star::util::CloseVetoException aException)
+        {
+        }
+    }
+    mxModel = NULL;
+}
+
+
+
+
+void MasterPageContainer::Implementation::LateInit (void)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    if (meInitializationState == NOT_INITIALIZED)
+    {
+        meInitializationState = INITIALIZING;
+
+        OSL_ASSERT(Instance().get()==this);
+        mpRequestQueue.reset(MasterPageContainerQueue::Create(
+            ::boost::shared_ptr<MasterPageContainerQueue::ContainerAdapter>(Instance())));
+
+        mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create(
+            ::boost::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)),
+            5,
+            50);
+
+        meInitializationState = INITIALIZED;
+    }
+}
+
+
+
+
+void MasterPageContainer::Implementation::AddChangeListener (const Link& rLink)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    ::std::vector<Link>::iterator iListener (
+        ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
+    if (iListener == maChangeListeners.end())
+        maChangeListeners.push_back(rLink);
+
+}
+
+
+
+
+void MasterPageContainer::Implementation::RemoveChangeListener (const Link& rLink)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    ::std::vector<Link>::iterator iListener (
+        ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
+    if (iListener != maChangeListeners.end())
+        maChangeListeners.erase(iListener);
+}
+
+
+
+
+void MasterPageContainer::Implementation::UpdatePreviewSizePixel (void)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    // The default aspect ratio is 4:3
+    int nWidth (4);
+    int nHeight (3);
+    
+    // Search for the first entry with an existing master page.
+    MasterPageContainerType::const_iterator iDescriptor;
+    MasterPageContainerType::const_iterator iContainerEnd(maContainer.end());
+    for (iDescriptor=maContainer.begin(); iDescriptor!=iContainerEnd; ++iDescriptor)
+        if (*iDescriptor!=NULL && (*iDescriptor)->mpMasterPage != NULL)
+        {
+            Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize());
+            nWidth = aPageSize.Width();
+            nHeight = aPageSize.Height();
+            mbFirstPageObjectSeen = true;
+            break;
+        }
+
+    maSmallPreviewSizePixel.Width() = SMALL_PREVIEW_WIDTH;
+    maLargePreviewSizePixel.Width() = LARGE_PREVIEW_WIDTH;
+
+    int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
+    int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
+
+    if (nNewSmallHeight!=maSmallPreviewSizePixel.Height()
+        || nNewLargeHeight!=maLargePreviewSizePixel.Height())
+    {
+        maSmallPreviewSizePixel.Height() = nNewSmallHeight;
+        maLargePreviewSizePixel.Height() = nNewLargeHeight;
+        FireContainerChange(
+            MasterPageContainerChangeEvent::SIZE_CHANGED,
+            NIL_TOKEN);
+    }
+}
+
+
+
+
+Size MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const
+{
+    if (eSize == SMALL)
+        return maSmallPreviewSizePixel;
+    else
+        return maLargePreviewSizePixel;
+}
+
+
+
+
+IMPL_LINK(MasterPageContainer::Implementation,AsynchronousNotifyCallback, EventData*, pData)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    if (pData != NULL)
+    {
+        FireContainerChange(pData->first, pData->second, false);
+        delete pData;
+    }
+
+    return 0;
+}
+
+
+
+
+MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage (
+    const SharedMasterPageDescriptor& rpDescriptor)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    Token aResult (NIL_TOKEN);
+
+    // 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.get()==NULL
+            && rpDescriptor->msURL.getLength()==0);
+
+        if ( ! bIgnore)
+        {
+            if (mbContainerCleaningPending)
+                CleanContainer();
+            
+            aResult = maContainer.size();
+            rpDescriptor->SetToken(aResult);
+
+            // 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)
+            {
+                case TEMPLATE:
+                case DEFAULT:
+                    ++rpDescriptor->mnUseCount;
+                    break;
+
+                default:
+                    break;
+            }
+            
+            maContainer.push_back(rpDescriptor);
+            aEntry = maContainer.end()-1;
+            
+            FireContainerChange(MasterPageContainerChangeEvent::CHILD_ADDED,aResult);
+        }
+    }
+    else
+    {
+        // Update an existing MasterPageDescriptor.
+        aResult = (*aEntry)->maToken;
+        ::std::auto_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes(
+            (*aEntry)->Update(*rpDescriptor));
+        if (pEventTypes.get()!=NULL && pEventTypes->size()>0)
+        {
+            // One or more aspects of the descriptor have changed.  Send
+            // appropriate events to the listeners.
+            UpdateDescriptor(*aEntry,false,false, true);
+            
+            std::vector<MasterPageContainerChangeEvent::EventType>::const_iterator iEventType;
+            for (iEventType=pEventTypes->begin(); iEventType!=pEventTypes->end(); ++iEventType)
+            {
+                FireContainerChange(
+                    *iEventType,
+                    (*aEntry)->maToken,
+                    false);
+            }
+        }
+    }
+
+    return aResult;
+}
+
+
+
+
+bool MasterPageContainer::Implementation::HasToken (Token aToken) const
+{
+    return aToken>=0
+        && (unsigned)aToken<maContainer.size()
+        && maContainer[aToken].get()!=NULL;
+}
+
+
+
+
+const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (
+    Token aToken) const
+{
+    if (aToken>=0 && (unsigned)aToken<maContainer.size())
+        return maContainer[aToken];
+    else
+        return SharedMasterPageDescriptor();
+}
+
+
+
+
+SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken)
+{
+    if (aToken>=0 && (unsigned)aToken<maContainer.size())
+        return maContainer[aToken];
+    else
+        return SharedMasterPageDescriptor();
+}
+
+
+
+
+void MasterPageContainer::Implementation::InvalidatePreview (Token aToken)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken));
+    if (pDescriptor.get() != NULL)
+    {
+        pDescriptor->maSmallPreview = Image();
+        pDescriptor->maLargePreview = Image();
+        RequestPreview(aToken);
+    }
+}
+
+
+
+
+Image MasterPageContainer::Implementation::GetPreviewForToken (
+    MasterPageContainer::Token aToken,
+    PreviewSize ePreviewSize)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    Image aPreview;
+    PreviewState ePreviewState (GetPreviewState(aToken));
+
+    SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
+    
+    // When the preview is missing but inexpensively creatable then do that
+    // now.
+    if (pDescriptor.get()!=NULL)
+    {
+        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:
+                aPreview = GetPreviewSubstitution(
+                    STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
+                    ePreviewSize);
+                break;
+
+            case PS_CREATABLE:
+                aPreview = GetPreviewSubstitution(
+                    STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
+                    ePreviewSize);
+                break;
+
+            case PS_NOT_AVAILABLE:
+                aPreview = GetPreviewSubstitution(
+                    STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION,
+                    ePreviewSize);
+                if (ePreviewSize == SMALL)
+                    pDescriptor->maSmallPreview = aPreview;
+                else
+                    pDescriptor->maLargePreview = aPreview;
+                break;
+        }
+    }
+    
+    return aPreview;
+}
+
+
+
+
+MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState (
+    Token aToken) const
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    PreviewState eState (PS_NOT_AVAILABLE);
+
+    SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+    {
+        if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
+            eState = PS_AVAILABLE;
+        else if (pDescriptor->mpPreviewProvider.get() != NULL)
+        {
+            // 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;
+    }
+
+    return eState;
+}
+
+
+
+
+bool MasterPageContainer::Implementation::RequestPreview (Token aToken)
+{
+    SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
+    if (pDescriptor.get() != NULL)
+        return mpRequestQueue->RequestPreview(pDescriptor);
+    else
+        return false;
+}
+
+
+
+
+Reference<frame::XModel> MasterPageContainer::Implementation::GetModel (void)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    if ( ! mxModel.is())
+    {
+        // Get the desktop a s service factory.
+        ::rtl::OUString sDesktopServiceName (
+            RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop"));
+        uno::Reference<frame::XComponentLoader> xDesktop (
+            ::comphelper::getProcessServiceFactory()->createInstance(
+                sDesktopServiceName), 
+            uno::UNO_QUERY);
+
+        // Create a new model.
+        ::rtl::OUString sModelServiceName (
+            RTL_CONSTASCII_USTRINGPARAM(
+                "com.sun.star.presentation.PresentationDocument"));
+        mxModel = uno::Reference<frame::XModel>(
+            ::comphelper::getProcessServiceFactory()->createInstance(
+                sModelServiceName),
+            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 (xUnoTunnel.is())
+        {
+            mpDocument = reinterpret_cast<SdXImpressDocument*>(
+                xUnoTunnel->getSomething(
+                    SdXImpressDocument::getUnoTunnelId()))->GetDoc();
+        }
+
+        // Create a default page.
+        uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY);
+        if (xSlideSupplier.is())
+        {
+            uno::Reference<drawing::XDrawPages> xSlides (
+                xSlideSupplier->getDrawPages(), uno::UNO_QUERY);
+            if (xSlides.is())
+            {
+                sal_Int32 nIndex (0);
+                uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(nIndex));
+                uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY);
+                if (xProperties.is())
+                    xProperties->setPropertyValue(
+                        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Layout")),
+                        makeAny((sal_Int16)AUTOLAYOUT_TITLE));
+            }
+        }
+    }
+    return mxModel;
+}
+
+
+
+
+SdDrawDocument* MasterPageContainer::Implementation::GetDocument (void)
+{
+    GetModel();
+    return mpDocument;
+}
+
+
+
+
+Image MasterPageContainer::Implementation::GetPreviewSubstitution (
+    sal_uInt16 nId,
+    PreviewSize ePreviewSize)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    Image aPreview;
+    
+    switch (nId)
+    {
+        case STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION:
+        {
+            Image& rPreview (ePreviewSize==SMALL
+                ? maSmallPreviewBeingCreated
+                : maLargePreviewBeingCreated);
+            if (rPreview.GetSizePixel().Width() == 0)
+            {
+                rPreview = maPreviewRenderer.RenderSubstitution(
+                    ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
+                    SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION));
+            }
+            aPreview = rPreview;
+        }
+        break;
+
+        case STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION:
+        {
+            Image& rPreview (ePreviewSize==SMALL
+                ? maSmallPreviewNotAvailable
+                : maLargePreviewNotAvailable);
+            if (rPreview.GetSizePixel().Width() == 0)
+            {
+                rPreview = maPreviewRenderer.RenderSubstitution(
+                    ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
+                    SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION));
+            }
+            aPreview = rPreview;
+        }
+        break;
+    }
+
+    return aPreview;
+}
+
+
+
+
+void MasterPageContainer::Implementation::CleanContainer (void)
+{
+    // 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].get()==NULL)
+        --nIndex;
+    maContainer.resize(++nIndex);
+}
+
+
+
+
+void MasterPageContainer::Implementation::FireContainerChange (
+    MasterPageContainerChangeEvent::EventType eType,
+    Token aToken,
+    bool bNotifyAsynchronously)
+{
+    if (bNotifyAsynchronously)
+    {
+        Application::PostUserEvent(
+            LINK(this,Implementation,AsynchronousNotifyCallback),
+            new EventData(eType,aToken));
+    }
+    else
+    {
+        ::std::vector<Link> aCopy(maChangeListeners.begin(),maChangeListeners.end());
+        ::std::vector<Link>::iterator iListener;
+        MasterPageContainerChangeEvent aEvent;
+        aEvent.meEventType = eType;
+        aEvent.maChildToken = aToken;
+        for (iListener=aCopy.begin(); iListener!=aCopy.end(); ++iListener)
+            iListener->Call(&aEvent);
+    }
+}
+
+
+
+
+bool MasterPageContainer::Implementation::UpdateDescriptor (
+    const SharedMasterPageDescriptor& rpDescriptor,
+    bool bForcePageObject,
+    bool bForcePreview,
+    bool bSendEvents)
+{
+    const ::osl::MutexGuard aGuard (maMutex);
+
+    // 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==NULL);
+
+    // 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();
+    bool bPageObjectModified (rpDescriptor->UpdatePageObject(
+        (bForcePageObject ? -1 : nCostThreshold),
+        mpDocument));
+    if (bPageObjectModified && bSendEvents)
+        FireContainerChange(
+            MasterPageContainerChangeEvent::DATA_CHANGED,
+            rpDescriptor->maToken);
+    if (bPageObjectModified && ! mbFirstPageObjectSeen)
+        UpdatePreviewSizePixel();
+
+    // Update the preview.
+    bool bPreviewModified (rpDescriptor->UpdatePreview(
+        (bForcePreview ? -1 : nCostThreshold),
+        maSmallPreviewSizePixel,
+        maLargePreviewSizePixel,
+        maPreviewRenderer));
+
+    if (bPreviewModified && bSendEvents)
+        FireContainerChange(
+            MasterPageContainerChangeEvent::PREVIEW_CHANGED,
+            rpDescriptor->maToken);
+
+    return bPageObjectModified || bPreviewModified;
+}
+
+
+
+
+void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken)
+{
+    if (aToken>=0 && (unsigned)aToken<maContainer.size())
+    {
+        maContainer[aToken].reset();
+        mbContainerCleaningPending = true;
+    }
+}
+
+
+
+
+void MasterPageContainer::Implementation::FillingDone (void)
+{
+    mpRequestQueue->ProcessAllRequests();
+}
+
+
+
+} } // end of namespace sd::sidebar

Added: openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainer.hxx
URL: http://svn.apache.org/viewvc/openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainer.hxx?rev=1447641&view=auto
==============================================================================
--- openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainer.hxx (added)
+++ openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainer.hxx Tue Feb 19 09:09:02 2013
@@ -0,0 +1,214 @@
+/**************************************************************
+ * 
+ * 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
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+#ifndef SD_SIDEBAR_PANELS_MASTER_PAGE_CONTAINER_HXX
+#define SD_SIDEBAR_PANELS_MASTER_PAGE_CONTAINER_HXX
+
+#include "MasterPageContainerProviders.hxx"
+
+#include <osl/mutex.hxx>
+#include <tools/string.hxx>
+#include <vcl/image.hxx>
+#include <memory>
+#include "PreviewRenderer.hxx"
+#include <com/sun/star/frame/XModel.hpp>
+#include <vcl/timer.hxx>
+#include "tools/SdGlobalResourceContainer.hxx"
+
+#include <boost/shared_ptr.hpp>
+
+class SdPage;
+class SdDrawDocument;
+class SfxObjectShellLock;
+
+namespace sd {
+class DrawDocShell;
+}
+
+namespace sd { namespace sidebar {
+
+class MasterPageDescriptor;
+
+/** This container manages the master pages used by the MasterPagesSelector
+    controls.  It uses internally a singleton implementation object.
+    Therefore, all MasterPageContainer object operator on the same set of
+    master pages.  Each MasterPageContainer, however, has its own
+    PreviewSize value and thus can independantly switch between large and
+    small previews.
+    
+    The container maintains its own document to store master page objects.
+    
+    For each master page container stores its URL, preview bitmap, page
+    name, and, if available, the page object.
+    
+    Entries are accessed via a Token, which is mostly a numerical index but
+    whose values do not neccessarily have to be consecutive.
+*/
+class MasterPageContainer
+{
+public:
+    typedef int Token;
+    static const Token NIL_TOKEN = -1;
+
+    MasterPageContainer (void);
+    virtual ~MasterPageContainer (void);
+
+    void AddChangeListener (const Link& rLink);
+    void RemoveChangeListener (const Link& rLink);
+
+    enum PreviewSize { SMALL, LARGE };
+    /** There are two different preview sizes, a small one and a large one.
+        Which one is used by the called container can be changed with this
+        method.
+        When the preview size is changed then all change listeners are
+        notified of this.
+    */
+    void SetPreviewSize (PreviewSize eSize);
+
+    /** Returns the preview size.
+    */
+    PreviewSize GetPreviewSize (void) const;
+
+    /** Return the preview size in pixels.
+    */
+    Size GetPreviewSizePixel (void) const;
+
+    enum PreviewState { PS_AVAILABLE, PS_CREATABLE, PS_PREPARING, PS_NOT_AVAILABLE };
+    PreviewState GetPreviewState (Token aToken);
+
+    /** This method is typically called for entries in the container for
+        which GetPreviewState() returns OS_CREATABLE.  The creation of the
+        preview is then scheduled to be executed asynchronously at a later
+        point in time.  When the preview is available the change listeners
+        will be notified.
+    */
+    bool RequestPreview (Token aToken);
+
+    /** Each entry of the container is either the first page of a template
+        document or is a master page of an Impress document. 
+    */
+    enum Origin {
+        MASTERPAGE,  // Master page of a document.
+        TEMPLATE,    // First page of a template file.
+        DEFAULT,     // Empty master page with default style.
+        UNKNOWN
+    };
+
+    /** Put the master page identified and described by the given parameters
+        into the container.  When there already is a master page with the
+        given URL, page name, or object pointer (when that is not NULL) then
+        the existing entry is replaced/updated by the given one.  Otherwise
+        a new entry is inserted.
+    */
+    Token PutMasterPage (const ::boost::shared_ptr<MasterPageDescriptor>& rDescriptor);
+    void AcquireToken (Token aToken);
+    void ReleaseToken (Token aToken);
+
+    /** This and the GetTokenForIndex() methods can be used to iterate over
+        all members of the container.
+    */
+    int GetTokenCount (void) const;
+
+    /** Determine whether the container has a member for the given token.
+    */
+    bool HasToken (Token aToken) const;
+    
+    /** Return a token for an index in the range 
+        0 <= index < GetTokenCount().
+    */
+    Token GetTokenForIndex (int nIndex);
+
+    Token GetTokenForURL (const String& sURL);
+    Token GetTokenForStyleName (const String& sStyleName);
+    Token GetTokenForPageObject (const SdPage* pPage);
+
+    String GetURLForToken (Token aToken);
+    String GetPageNameForToken (Token aToken);
+    String GetStyleNameForToken (Token aToken);
+    SdPage* GetPageObjectForToken (Token aToken, bool bLoad=true);
+    Origin GetOriginForToken (Token aToken);
+    sal_Int32 GetTemplateIndexForToken (Token aToken);
+    ::boost::shared_ptr<MasterPageDescriptor> GetDescriptorForToken (Token aToken);
+    
+    void InvalidatePreview (Token aToken);
+
+    /** Return a preview for the specified token.  When the preview is not
+        present then the PreviewProvider associated with the token is
+        executed only when that is not expensive.  It is the responsibility
+        of the caller to call RequestPreview() to do the same
+        (asynchronously) for expensive PreviewProviders.
+        Call GetPreviewState() to find out if that is necessary.
+        @param aToken
+            This token specifies for which master page to return the prview.
+            Tokens are returned for example by the GetTokenFor...() methods.
+        @return
+            The returned image is the requested preview or a substitution.
+    */
+    Image GetPreviewForToken (Token aToken);
+
+private:
+    class Implementation;
+    ::boost::shared_ptr<Implementation> mpImpl;
+    PreviewSize mePreviewSize;
+
+    /** Retrieve the preview of the document specified by the given URL.
+    */
+    static BitmapEx LoadPreviewFromURL (const ::rtl::OUString& aURL);
+};
+
+
+
+
+/** For some changes to the set of master pages in a MasterPageContainer or
+    to the data stored for each master page one or more events are sent to
+    registered listeners.
+    Each event has an event type and a token that tells the listener where
+    the change took place.
+*/
+class MasterPageContainerChangeEvent
+{
+public:
+    enum EventType {
+        // A master page was added to the container.
+        CHILD_ADDED,
+        // A master page was removed from the container.
+        CHILD_REMOVED,
+        // The preview of a master page has changed.
+        PREVIEW_CHANGED,
+        // The size of a preview has changed.
+        SIZE_CHANGED,
+        // Some of the data stored for a master page has changed.
+        DATA_CHANGED,
+        // The TemplateIndex of a master page has changed.
+        INDEX_CHANGED,
+        // More than one entries changed their TemplateIndex
+        INDEXES_CHANGED
+    } meEventType;
+
+    // Token of the container entry whose data changed or which was added or
+    // removed.
+    MasterPageContainer::Token maChildToken;
+};
+
+
+} } // end of namespace sd::sidebar
+
+#endif

Added: openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerFiller.cxx
URL: http://svn.apache.org/viewvc/openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerFiller.cxx?rev=1447641&view=auto
==============================================================================
--- openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerFiller.cxx (added)
+++ openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerFiller.cxx Tue Feb 19 09:09:02 2013
@@ -0,0 +1,191 @@
+/**************************************************************
+ * 
+ * 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
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "MasterPageContainerFiller.hxx"
+
+#include "MasterPageDescriptor.hxx"
+#include "MasterPageContainerProviders.hxx"
+#include "TemplateScanner.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+namespace sd { namespace sidebar {
+
+MasterPageContainerFiller::MasterPageContainerFiller (ContainerAdapter& rpAdapter)
+    : mrContainerAdapter(rpAdapter),
+      meState(INITIALIZE_TEMPLATE_SCANNER),
+      mpScannerTask(),
+      mpLastAddedEntry(NULL),
+      mnIndex(1)
+{
+    // Add one entry for the default master page.  We use temporarily the
+    // DefaultPagePreviewProvider to prevent the rendering (and the
+    // expensive creation) of the default page.  It is replaced later on by
+    // another.
+    SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor(
+        MasterPageContainer::DEFAULT,
+        0,
+        String(),
+        String(),
+        String(),
+        false,
+        ::boost::shared_ptr<PageObjectProvider>(new DefaultPageObjectProvider()),
+        ::boost::shared_ptr<PreviewProvider>(new PagePreviewProvider())));
+    mrContainerAdapter.PutMasterPage(pDescriptor);
+}
+
+
+
+
+MasterPageContainerFiller::~MasterPageContainerFiller (void)
+{
+}
+
+
+
+
+void MasterPageContainerFiller::RunNextStep (void)
+{
+    switch (meState)
+    {
+        case INITIALIZE_TEMPLATE_SCANNER:
+            mpScannerTask.reset(new TemplateScanner());
+            meState = SCAN_TEMPLATE;
+            break;
+
+        case SCAN_TEMPLATE:
+            meState = ScanTemplate();
+            break;
+            
+        case ADD_TEMPLATE:
+            meState = AddTemplate();
+            break;
+            
+        case DONE:
+        case ERROR:
+        default:
+            break;
+    }
+
+    // When the state has just been set to DONE or ERROR then tell the
+    // container that no more templates will be coming and stop the
+    // scanning.
+    switch (meState)
+    {
+        case DONE:
+        case ERROR:
+            if (mpScannerTask.get() != NULL)
+            {
+                mrContainerAdapter.FillingDone();
+                mpScannerTask.reset();
+            }
+		default:
+			break;
+    }
+}
+
+
+
+
+bool MasterPageContainerFiller::HasNextStep (void)
+{
+    switch (meState)
+    {
+        case DONE:
+        case ERROR:
+            return false;
+            
+        default:
+            return true;
+    }
+}
+
+
+
+
+MasterPageContainerFiller::State MasterPageContainerFiller::ScanTemplate (void)
+{
+    State eState (ERROR);
+
+    if (mpScannerTask.get() != NULL)
+    {
+        if (mpScannerTask->HasNextStep())
+        {
+            mpScannerTask->RunNextStep();
+            if (mpScannerTask->GetLastAddedEntry() != mpLastAddedEntry)
+            {
+                mpLastAddedEntry = mpScannerTask->GetLastAddedEntry();
+                if (mpLastAddedEntry != NULL)
+                    eState = ADD_TEMPLATE;
+                else
+                    eState = SCAN_TEMPLATE;
+            }
+            else
+                eState = SCAN_TEMPLATE;
+        }
+        else
+            eState = DONE;
+    }
+
+    return eState;
+}
+
+
+
+
+MasterPageContainerFiller::State MasterPageContainerFiller::AddTemplate (void)
+{
+    if (mpLastAddedEntry != NULL)
+    {
+        SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor(
+            MasterPageContainer::TEMPLATE,
+            mnIndex,
+            mpLastAddedEntry->msPath,
+            mpLastAddedEntry->msTitle,
+            String(),
+            false,
+            ::boost::shared_ptr<PageObjectProvider>(
+                new TemplatePageObjectProvider(mpLastAddedEntry->msPath)),
+            ::boost::shared_ptr<PreviewProvider>(
+                new TemplatePreviewProvider(mpLastAddedEntry->msPath))));
+        // For user supplied templates we use a different preview provider:
+        // The preview in the document shows not only shapes on the master
+        // page but also shapes on the foreground.  This is misleading and
+        // therefore these previews are discarded and created directly from
+        // the page objects.
+        if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER)
+            pDescriptor->mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>(
+                new PagePreviewProvider());
+
+        mrContainerAdapter.PutMasterPage(pDescriptor);
+        ++mnIndex;
+    }
+
+    return SCAN_TEMPLATE;
+}
+
+
+
+} } // end of namespace sd::sidebar

Added: openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerFiller.hxx
URL: http://svn.apache.org/viewvc/openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerFiller.hxx?rev=1447641&view=auto
==============================================================================
--- openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerFiller.hxx (added)
+++ openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerFiller.hxx Tue Feb 19 09:09:02 2013
@@ -0,0 +1,89 @@
+/**************************************************************
+ * 
+ * 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
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+#ifndef SD_SIDEBAR_PANELS_MASTER_PAGE_CONTAINER_FILLER_HXX
+#define SD_SIDEBAR_PANELS_MASTER_PAGE_CONTAINER_FILLER_HXX
+
+#include "MasterPageContainer.hxx"
+#include "MasterPageDescriptor.hxx"
+#include "tools/AsynchronousTask.hxx"
+
+namespace sd {
+class TemplateScanner;
+class TemplateEntry;
+}
+
+namespace sd { namespace sidebar {
+
+/** Fill a MasterPageContainer with information about the available master
+    pages.  These are provided by one default page and from the existing
+    Impress templates.  This is done asynchronously.
+*/
+class MasterPageContainerFiller
+    : public ::sd::tools::AsynchronousTask
+{
+public:
+    class ContainerAdapter
+    {
+    public:
+        virtual MasterPageContainer::Token PutMasterPage (
+            const SharedMasterPageDescriptor& rpDescriptor) = 0;
+        /** This method is called when all Impress templates have been added
+            to the container via the PutMasterPage() method.
+        */
+        virtual void FillingDone (void) = 0;
+    };
+    
+    MasterPageContainerFiller (ContainerAdapter& rContainerAdapter);
+    virtual ~MasterPageContainerFiller (void);
+    
+    /** Run the next step of the task.  After HasNextStep() returns false
+        this method should ignore further calls.
+    */
+    virtual void RunNextStep (void);
+
+    /** Return <TRUE/> when there is at least one more step to execute.
+        When the task has been executed completely then <FALSE/> is
+        returned.
+    */
+    virtual bool HasNextStep (void);
+
+private:
+    ContainerAdapter& mrContainerAdapter;
+    // Remember what the next step has to do.
+    enum State {
+        INITIALIZE_TEMPLATE_SCANNER,
+        SCAN_TEMPLATE,
+        ADD_TEMPLATE,
+        ERROR,
+        DONE
+    } meState;
+    ::std::auto_ptr<TemplateScanner> mpScannerTask;
+    const TemplateEntry* mpLastAddedEntry;
+    int mnIndex;
+    
+    State ScanTemplate (void);
+    State AddTemplate (void);
+};
+
+} } // end of namespace sd::sidebar
+
+#endif

Added: openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerProviders.cxx
URL: http://svn.apache.org/viewvc/openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerProviders.cxx?rev=1447641&view=auto
==============================================================================
--- openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerProviders.cxx (added)
+++ openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerProviders.cxx Tue Feb 19 09:09:02 2013
@@ -0,0 +1,420 @@
+/**************************************************************
+ * 
+ * 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
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "MasterPageContainerProviders.hxx"
+
+#include "DrawDocShell.hxx"
+#include "drawdoc.hxx"
+#include "PreviewRenderer.hxx"
+#include <comphelper/processfactory.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <unotools/ucbstreamhelper.hxx>
+#include <vcl/image.hxx>
+#include <vcl/pngread.hxx>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <tools/diagnose_ex.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace sd { namespace sidebar {
+
+
+//===== PagePreviewProvider ===================================================
+
+PagePreviewProvider::PagePreviewProvider (void)
+{
+}
+
+
+
+
+Image PagePreviewProvider::operator () (
+    int nWidth,
+    SdPage* pPage,
+    ::sd::PreviewRenderer& rRenderer)
+{
+    Image aPreview;
+    
+    if (pPage != NULL)
+    {
+        // Use the given renderer to create a preview of the given page
+        // object.
+        aPreview = rRenderer.RenderPage(
+            pPage,
+            nWidth,
+            String::CreateFromAscii(""),
+            false);
+    }
+
+    return aPreview;
+}
+
+
+
+
+int PagePreviewProvider::GetCostIndex (void)
+{
+    return 5;
+}
+
+
+
+
+bool PagePreviewProvider::NeedsPageObject (void)
+{
+    return true;
+}
+
+
+
+
+//===== TemplatePreviewProvider ===============================================
+
+TemplatePreviewProvider::TemplatePreviewProvider (const ::rtl::OUString& rsURL)
+    : msURL(rsURL)
+{
+}
+
+
+
+
+Image TemplatePreviewProvider::operator() (
+    int nWidth,
+    SdPage* pPage,
+    ::sd::PreviewRenderer& rRenderer)
+{
+    // Unused parameters.
+    (void)nWidth;
+    (void)pPage; 
+    (void)rRenderer;
+    
+    // Load the thumbnail from a template document.
+	uno::Reference<io::XInputStream> xIStream;
+
+    uno::Reference< lang::XMultiServiceFactory > xServiceManager (
+        ::comphelper::getProcessServiceFactory());
+	if (xServiceManager.is())
+	{
+		try
+        {
+			uno::Reference<lang::XSingleServiceFactory> xStorageFactory(
+				xServiceManager->createInstance( 
+                    ::rtl::OUString::createFromAscii(
+                        "com.sun.star.embed.StorageFactory")),
+				uno::UNO_QUERY);
+		
+			if (xStorageFactory.is())
+			{
+				uno::Sequence<uno::Any> aArgs (2);
+				aArgs[0] <<= msURL;
+				aArgs[1] <<= embed::ElementModes::READ;
+				uno::Reference<embed::XStorage> xDocStorage (
+                    xStorageFactory->createInstanceWithArguments(aArgs),
+                    uno::UNO_QUERY);
+
+                try
+                {
+                    if (xDocStorage.is())
+                    {
+                        uno::Reference<embed::XStorage> xStorage (
+                            xDocStorage->openStorageElement(
+                                ::rtl::OUString::createFromAscii("Thumbnails"),
+                                embed::ElementModes::READ));
+                        if (xStorage.is())
+                        {
+                            uno::Reference<io::XStream> xThumbnailCopy (
+                                xStorage->cloneStreamElement(
+                                    ::rtl::OUString::createFromAscii(
+                                        "thumbnail.png")));
+                            if (xThumbnailCopy.is())
+                                xIStream = xThumbnailCopy->getInputStream();
+                        }
+                    }
+                }
+                catch (uno::Exception& rException)
+                {
+                    OSL_TRACE (
+                        "caught exception while trying to access Thumbnail/thumbnail.png of %s: %s",
+                        ::rtl::OUStringToOString(msURL,
+                            RTL_TEXTENCODING_UTF8).getStr(),
+                        ::rtl::OUStringToOString(rException.Message,
+                            RTL_TEXTENCODING_UTF8).getStr());
+                }
+
+                try
+                {
+                    // An (older) implementation had a bug - The storage
+                    // name was "Thumbnail" instead of "Thumbnails".  The
+                    // old name is still used as fallback but this code can
+                    // be removed soon.
+                    if ( ! xIStream.is())
+                    {
+                        uno::Reference<embed::XStorage> xStorage (
+                            xDocStorage->openStorageElement(
+                                ::rtl::OUString::createFromAscii("Thumbnail"),
+                                embed::ElementModes::READ));
+                        if (xStorage.is())
+                        {
+                            uno::Reference<io::XStream> xThumbnailCopy (
+                                xStorage->cloneStreamElement(
+                                    ::rtl::OUString::createFromAscii(
+                                        "thumbnail.png")));
+                            if (xThumbnailCopy.is())
+                                xIStream = xThumbnailCopy->getInputStream();
+                        }
+					}
+                }
+                catch (uno::Exception& rException)
+                {
+                    OSL_TRACE (
+                        "caught exception while trying to access Thumbnails/thumbnail.png of %s: %s",
+                        ::rtl::OUStringToOString(msURL,
+                            RTL_TEXTENCODING_UTF8).getStr(),
+                        ::rtl::OUStringToOString(rException.Message,
+                            RTL_TEXTENCODING_UTF8).getStr());
+                }
+			}
+		}
+		catch (uno::Exception& rException)
+		{
+            OSL_TRACE (
+                "caught exception while trying to access tuhmbnail of %s: %s",
+                ::rtl::OUStringToOString(msURL,
+                    RTL_TEXTENCODING_UTF8).getStr(),
+                ::rtl::OUStringToOString(rException.Message,
+                    RTL_TEXTENCODING_UTF8).getStr());
+        }
+	}
+
+    // Extract the image from the stream.
+    BitmapEx aThumbnail;
+	if (xIStream.is())
+    {
+        ::std::auto_ptr<SvStream> pStream (
+            ::utl::UcbStreamHelper::CreateStream (xIStream));
+        ::vcl::PNGReader aReader (*pStream);
+        aThumbnail = aReader.Read ();
+    }
+
+    // Note that the preview is returned without scaling it to the desired
+    // width.  This gives the caller the chance to take advantage of a
+    // possibly larger resolution then was asked for.
+    return aThumbnail;
+}
+
+
+
+
+int TemplatePreviewProvider::GetCostIndex (void)
+{
+    return 10;
+}
+
+
+
+
+bool TemplatePreviewProvider::NeedsPageObject (void)
+{
+    return false;
+}
+
+
+
+
+//===== TemplatePageObjectProvider =============================================
+
+TemplatePageObjectProvider::TemplatePageObjectProvider (const ::rtl::OUString& rsURL)
+    : msURL(rsURL),
+      mxDocumentShell()
+{
+}
+
+
+
+
+SdPage* TemplatePageObjectProvider::operator() (SdDrawDocument* pContainerDocument)
+{
+    // Unused parameters.
+    (void)pContainerDocument;
+    
+    SdPage* pPage = NULL;
+    
+    mxDocumentShell = NULL;
+    ::sd::DrawDocShell* pDocumentShell = NULL;
+    try
+    {
+        // Load the template document and return its first page.
+        pDocumentShell = LoadDocument (msURL);
+        if (pDocumentShell != NULL)
+        {
+            SdDrawDocument* pDocument = pDocumentShell->GetDoc();
+            if (pDocument != NULL)
+            {
+                pPage = pDocument->GetMasterSdPage(0, PK_STANDARD);
+                // In order to make the newly loaded master page deletable
+                // when copied into documents it is marked as no "precious".
+                // When it is modified then it is marked as "precious".
+                if (pPage != NULL)
+                    pPage->SetPrecious(false);
+            }
+        }
+    }
+    catch (uno::RuntimeException)
+    {
+        DBG_UNHANDLED_EXCEPTION();
+        pPage = NULL;
+    }
+
+    return pPage;
+}
+
+
+
+
+::sd::DrawDocShell* TemplatePageObjectProvider::LoadDocument (const ::rtl::OUString& sFileName)
+{
+	SfxApplication* pSfxApp = SFX_APP();
+    SfxItemSet* pSet = new SfxAllItemSet (pSfxApp->GetPool());
+    pSet->Put (SfxBoolItem (SID_TEMPLATE, sal_True));
+    pSet->Put (SfxBoolItem (SID_PREVIEW, sal_True));
+    if (pSfxApp->LoadTemplate (mxDocumentShell, sFileName, sal_True, pSet))
+    {
+        mxDocumentShell = NULL;
+    }
+    SfxObjectShell* pShell = mxDocumentShell;
+    return PTR_CAST(::sd::DrawDocShell,pShell);
+}
+
+
+
+
+int TemplatePageObjectProvider::GetCostIndex (void)
+{
+    return 20;
+}
+
+
+
+
+bool TemplatePageObjectProvider::operator== (const PageObjectProvider& rProvider)
+{
+    const TemplatePageObjectProvider* pTemplatePageObjectProvider
+        = dynamic_cast<const TemplatePageObjectProvider*>(&rProvider);
+    if (pTemplatePageObjectProvider != NULL)
+        return (msURL == pTemplatePageObjectProvider->msURL);
+    else
+        return false;
+}
+
+
+
+
+//===== DefaultPageObjectProvider ==============================================
+
+DefaultPageObjectProvider::DefaultPageObjectProvider (void)
+{
+}
+
+
+
+
+SdPage* DefaultPageObjectProvider::operator () (SdDrawDocument* pContainerDocument)
+{
+    SdPage* pLocalMasterPage = NULL;
+    if (pContainerDocument != NULL)
+    {
+        sal_Int32 nIndex (0);
+        SdPage* pLocalSlide = pContainerDocument->GetSdPage((sal_uInt16)nIndex, PK_STANDARD);
+        if (pLocalSlide!=NULL && pLocalSlide->TRG_HasMasterPage())
+            pLocalMasterPage = dynamic_cast<SdPage*>(&pLocalSlide->TRG_GetMasterPage());
+    }
+
+    if (pLocalMasterPage == NULL)
+    {
+        DBG_ASSERT(false, "can not create master page for slide");
+    }
+
+    return pLocalMasterPage;
+}
+
+
+
+
+int DefaultPageObjectProvider::GetCostIndex (void)
+{
+    return 15;
+}
+
+
+
+
+bool DefaultPageObjectProvider::operator== (const PageObjectProvider& rProvider)
+{
+    return (dynamic_cast<const DefaultPageObjectProvider*>(&rProvider) != NULL);
+}
+
+
+
+
+//===== ExistingPageProvider ==================================================
+
+ExistingPageProvider::ExistingPageProvider (SdPage* pPage)
+    : mpPage(pPage)
+{
+}
+
+
+
+
+SdPage* ExistingPageProvider::operator() (SdDrawDocument* pDocument)
+{
+    (void)pDocument; // Unused parameter.
+    
+    return mpPage;
+}
+
+
+
+
+int ExistingPageProvider::GetCostIndex (void)
+{
+    return 0;
+}
+
+
+
+
+bool ExistingPageProvider::operator== (const PageObjectProvider& rProvider)
+{
+    const ExistingPageProvider* pExistingPageProvider
+        = dynamic_cast<const ExistingPageProvider*>(&rProvider);
+    if (pExistingPageProvider != NULL)
+        return (mpPage == pExistingPageProvider->mpPage);
+    else
+        return false;
+}
+
+
+} } // end of namespace sd::sidebar

Added: openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerProviders.hxx
URL: http://svn.apache.org/viewvc/openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerProviders.hxx?rev=1447641&view=auto
==============================================================================
--- openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerProviders.hxx (added)
+++ openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerProviders.hxx Tue Feb 19 09:09:02 2013
@@ -0,0 +1,183 @@
+/**************************************************************
+ * 
+ * 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
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+#ifndef SD_SIDEBAR_PANELS_MASTER_PAGE_CONTAINER_PROVIDERS_HXX
+#define SD_SIDEBAR_PANELS_MASTER_PAGE_CONTAINER_PROVIDERS_HXX
+
+#include <rtl/ustring.hxx>
+#include <sfx2/objsh.hxx>
+
+class Image;
+class SdDrawDocument;
+class SdPage;
+namespace sd { class PreviewRenderer; }
+namespace sd { class DrawDocShell; }
+
+
+namespace sd { namespace sidebar {
+
+
+/** Interface for a provider of page objects.  It is used by the
+    MasterPageDescriptor to create master page objects on demand.
+*/
+class PageObjectProvider
+{
+public:
+    /** Return a master page either by returning an already existing one, by
+        creating a new page, or by loading a document.
+        @param pDocument
+            The document of the MasterPageContainer.  It may be used to
+            create new pages.
+    */
+    virtual SdPage* operator() (SdDrawDocument* pDocument) = 0;
+
+    /** An abstract value for the expected cost of providing a master page
+        object.
+        @return
+            A value of 0 represents for the lowest cost, i.e. an almost
+            immediate return.  Positive values stand for higher costs.
+            Negative values are not supported.
+    */
+    virtual int GetCostIndex (void) = 0;
+
+    virtual bool operator== (const PageObjectProvider& rProvider) = 0;
+};
+
+
+
+
+class PreviewProvider
+{
+public:
+    /** Create a preview image in the specified width.
+        @param nWidth
+            Requested width of the preview.  The calling method can cope
+            with other sizes as well but the resulting image quality is
+            better when the returned image has the requested size.
+        @param pPage
+            Page object for which a preview is requested.  This may be NULL
+            when the page object is expensive to get and the PreviewProvider
+            does not need this object (NeedsPageObject() returns false.)
+        @param rRenderer
+            This PreviewRenderer may be used by the PreviewProvider to
+            create a preview image.
+    */
+    virtual Image operator() (int nWidth, SdPage* pPage, ::sd::PreviewRenderer& rRenderer) = 0;
+
+    /** Return a value that indicates how expensive the creation of a
+        preview image is.  The higher the returned value the more expensive
+        is the preview creation.  Return 0 when the preview is already
+        present and can be returned immediately.
+    */
+    virtual int GetCostIndex (void) = 0;
+
+    /** Return whether the page object passed is necessary to create a
+        preview.
+    */
+    virtual bool NeedsPageObject (void) = 0;
+};
+
+
+
+
+/** Provide previews of existing page objects by rendering them.
+*/
+class PagePreviewProvider : public PreviewProvider
+{
+public:
+    PagePreviewProvider (void);
+    virtual Image operator () (int nWidth, SdPage* pPage, ::sd::PreviewRenderer& rRenderer);
+    virtual int GetCostIndex (void);
+    virtual bool NeedsPageObject (void);
+private:
+};
+
+
+
+
+/** Provide master page objects for template documents for which only the
+    URL is given.
+*/
+class TemplatePageObjectProvider : public PageObjectProvider
+{
+public:
+    TemplatePageObjectProvider (const ::rtl::OUString& rsURL);
+    virtual ~TemplatePageObjectProvider (void) {};
+    virtual SdPage* operator () (SdDrawDocument* pDocument);
+    virtual int GetCostIndex (void);
+    virtual bool operator== (const PageObjectProvider& rProvider);
+private:
+    ::rtl::OUString msURL;
+    SfxObjectShellLock mxDocumentShell;
+    ::sd::DrawDocShell* LoadDocument (const ::rtl::OUString& sFileName);
+};
+
+
+
+
+/** Provide previews for template documents by loading the thumbnails from
+    the documents.
+*/
+class TemplatePreviewProvider : public PreviewProvider
+{
+public:
+    TemplatePreviewProvider (const ::rtl::OUString& rsURL);
+    virtual ~TemplatePreviewProvider (void) {};
+    virtual Image operator() (int nWidth, SdPage* pPage, ::sd::PreviewRenderer& rRenderer);
+    virtual int GetCostIndex (void);
+    virtual bool NeedsPageObject (void);
+private:
+    ::rtl::OUString msURL;
+};
+
+
+
+
+/** Create an empty default master page.
+*/
+class DefaultPageObjectProvider : public PageObjectProvider
+{
+public:
+    DefaultPageObjectProvider (void);
+    virtual SdPage* operator () (SdDrawDocument* pDocument);
+    virtual int GetCostIndex (void);
+    virtual bool operator== (const PageObjectProvider& rProvider);
+};
+
+
+
+/** This implementation of the PageObjectProvider simply returns an already
+    existing master page object.
+*/
+class ExistingPageProvider : public PageObjectProvider
+{
+public:
+    ExistingPageProvider (SdPage* pPage);
+    virtual SdPage* operator() (SdDrawDocument* pDocument);
+    virtual int GetCostIndex (void);
+    virtual bool operator== (const PageObjectProvider& rProvider);
+private:
+    SdPage* mpPage;
+};
+
+} } // end of namespace sd::sidebar
+
+#endif

Added: openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerQueue.cxx
URL: http://svn.apache.org/viewvc/openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerQueue.cxx?rev=1447641&view=auto
==============================================================================
--- openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerQueue.cxx (added)
+++ openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerQueue.cxx Tue Feb 19 09:09:02 2013
@@ -0,0 +1,297 @@
+/**************************************************************
+ * 
+ * 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
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "MasterPageContainerQueue.hxx"
+
+#include "tools/IdleDetection.hxx"
+
+#include <set>
+
+namespace sd { namespace sidebar {
+
+const sal_Int32 MasterPageContainerQueue::snDelayedCreationTimeout (15);
+const sal_Int32 MasterPageContainerQueue::snDelayedCreationTimeoutWhenNotIdle (100);
+const sal_Int32 MasterPageContainerQueue::snMasterPagePriorityBoost (5);
+const sal_Int32 MasterPageContainerQueue::snWaitForMoreRequestsPriorityThreshold (-10);
+sal_uInt32 MasterPageContainerQueue::snWaitForMoreRequestsCount(15);
+
+//===== MasterPageContainerQueue::PreviewCreationRequest ======================
+
+class MasterPageContainerQueue::PreviewCreationRequest
+{
+public:
+    PreviewCreationRequest (const SharedMasterPageDescriptor& rpDescriptor, int nPriority)
+        : mpDescriptor(rpDescriptor),
+          mnPriority(nPriority)
+    {}
+    SharedMasterPageDescriptor mpDescriptor;
+    int mnPriority;
+    class Compare {public:
+        bool operator() (const PreviewCreationRequest& r1,const PreviewCreationRequest& r2)
+        {
+            if (r1.mnPriority != r2.mnPriority)
+            {
+                // Prefer requests with higher priority.
+                return r1.mnPriority > r2.mnPriority;
+            }
+            else
+            {
+                // Prefer tokens that have been earlier created (those with lower
+                // value).
+                return r1.mpDescriptor->maToken < r2.mpDescriptor->maToken;
+            }
+        }
+    };
+    class CompareToken {public:
+        MasterPageContainer::Token maToken;
+        CompareToken(MasterPageContainer::Token aToken) : maToken(aToken) {}
+        bool operator() (const PreviewCreationRequest& rRequest)
+        {     return maToken==rRequest.mpDescriptor->maToken; }
+    };
+};
+
+
+
+
+//===== MasterPageContainerQueue::RequestQueue ================================
+
+class MasterPageContainerQueue::RequestQueue
+    : public ::std::set<PreviewCreationRequest,PreviewCreationRequest::Compare>
+{
+public:
+    RequestQueue (void) {}
+};
+
+
+
+
+//===== MasterPageContainerQueue ==============================================
+
+MasterPageContainerQueue* MasterPageContainerQueue::Create (
+    const ::boost::weak_ptr<ContainerAdapter>& rpContainer)
+{
+    MasterPageContainerQueue* pQueue = new MasterPageContainerQueue(rpContainer);
+    pQueue->LateInit();
+    return pQueue;
+}
+
+
+
+
+MasterPageContainerQueue::MasterPageContainerQueue (
+    const ::boost::weak_ptr<ContainerAdapter>& rpContainer)
+    : mpWeakContainer(rpContainer),
+      mpRequestQueue(new RequestQueue()),
+      maDelayedPreviewCreationTimer(),
+      mnRequestsServedCount(0)
+{
+}
+
+
+
+
+MasterPageContainerQueue::~MasterPageContainerQueue (void)
+{
+    maDelayedPreviewCreationTimer.Stop();
+    while ( ! mpRequestQueue->empty())
+        mpRequestQueue->erase(mpRequestQueue->begin());
+}
+
+
+
+
+void MasterPageContainerQueue::LateInit (void)
+{
+    // Set up the timer for the delayed creation of preview bitmaps.
+    maDelayedPreviewCreationTimer.SetTimeout (snDelayedCreationTimeout);
+    Link aLink (LINK(this,MasterPageContainerQueue,DelayedPreviewCreation));
+    maDelayedPreviewCreationTimer.SetTimeoutHdl(aLink);
+}
+
+
+
+
+bool MasterPageContainerQueue::RequestPreview (const SharedMasterPageDescriptor& rpDescriptor)
+{
+    bool bSuccess (false);
+    if (rpDescriptor.get() != NULL
+        && rpDescriptor->maLargePreview.GetSizePixel().Width() == 0)
+    {
+        sal_Int32 nPriority (CalculatePriority(rpDescriptor));
+        
+        // Add a new or replace an existing request.
+        RequestQueue::iterator iRequest (::std::find_if(
+            mpRequestQueue->begin(),
+            mpRequestQueue->end(),
+            PreviewCreationRequest::CompareToken(rpDescriptor->maToken)));
+        // When a request for the same token exists then the lowest of the
+        // two priorities is used.
+        if (iRequest != mpRequestQueue->end())
+            if (iRequest->mnPriority < nPriority)
+            {
+                mpRequestQueue->erase(iRequest);
+                iRequest = mpRequestQueue->end();
+            }
+
+        // Add a new request when none exists (or has just been erased).
+        if (iRequest == mpRequestQueue->end())
+        {
+            mpRequestQueue->insert(PreviewCreationRequest(rpDescriptor,nPriority));
+            maDelayedPreviewCreationTimer.Start();
+            bSuccess = true;
+        }
+    }
+    return bSuccess;
+}
+
+
+
+
+sal_Int32 MasterPageContainerQueue::CalculatePriority (
+    const SharedMasterPageDescriptor& rpDescriptor) const
+{
+    sal_Int32 nPriority;
+
+    // The cost is used as a starting value.
+    int nCost (0);
+    if (rpDescriptor->mpPreviewProvider.get() != NULL)
+    {
+        nCost = rpDescriptor->mpPreviewProvider->GetCostIndex();
+        if (rpDescriptor->mpPreviewProvider->NeedsPageObject())
+            if (rpDescriptor->mpPageObjectProvider.get() != NULL)
+                nCost += rpDescriptor->mpPageObjectProvider->GetCostIndex();
+    }
+
+    // Its negative value is used so that requests with a low cost are
+    // preferred over those with high costs.
+    nPriority = -nCost;
+
+    // Add a term that introduces an order based on the appearance in the
+    // AllMasterPagesSelector.
+    nPriority -= rpDescriptor->maToken / 3;
+    
+    // Process requests for the CurrentMasterPagesSelector first.
+    if (rpDescriptor->meOrigin == MasterPageContainer::MASTERPAGE)
+        nPriority += snMasterPagePriorityBoost;
+
+    return nPriority;
+}
+
+
+
+
+IMPL_LINK(MasterPageContainerQueue, DelayedPreviewCreation, Timer*, pTimer)
+{
+    bool bIsShowingFullScreenShow (false);
+    bool bWaitForMoreRequests (false);
+
+    do
+    {
+        if (mpRequestQueue->size() == 0)
+            break;
+
+        // First check whether the system is idle.
+        sal_Int32 nIdleState (tools::IdleDetection::GetIdleState());
+        if (nIdleState != tools::IdleDetection::IDET_IDLE)
+        {
+            if ((nIdleState&tools::IdleDetection::IDET_FULL_SCREEN_SHOW_ACTIVE) != 0)
+                bIsShowingFullScreenShow = true;
+            break;
+        }
+
+        PreviewCreationRequest aRequest (*mpRequestQueue->begin());
+
+        // Check if the request should really be processed right now.
+        // Reasons to not do it are when its cost is high and not many other
+        // requests have been inserted into the queue that would otherwise
+        // be processed first.
+        if (aRequest.mnPriority < snWaitForMoreRequestsPriorityThreshold
+            && (mnRequestsServedCount+mpRequestQueue->size() < snWaitForMoreRequestsCount))
+        {
+            // Wait for more requests before this one is processed.  Note
+            // that the queue processing is not started anew when this
+            // method is left.  That is done when the next request is
+            // inserted.
+            bWaitForMoreRequests = true;
+            break;
+        }
+
+        mpRequestQueue->erase(mpRequestQueue->begin());
+        
+        if (aRequest.mpDescriptor.get() != NULL)
+        {
+            mnRequestsServedCount += 1;
+            if ( ! mpWeakContainer.expired())
+            {
+                ::boost::shared_ptr<ContainerAdapter> pContainer (mpWeakContainer);
+                if (pContainer.get() != NULL)
+                    pContainer->UpdateDescriptor(aRequest.mpDescriptor,false,true,true);
+            }
+        }
+    }
+    while (false);
+    
+    if (mpRequestQueue->size() > 0 && ! bWaitForMoreRequests)
+    {
+        int nTimeout (snDelayedCreationTimeout);
+        if (bIsShowingFullScreenShow)
+            nTimeout = snDelayedCreationTimeoutWhenNotIdle;
+        maDelayedPreviewCreationTimer.SetTimeout(nTimeout);
+        pTimer->Start();
+    }
+
+    return 0;
+}
+
+
+
+
+bool MasterPageContainerQueue::HasRequest (MasterPageContainer::Token aToken) const
+{
+    RequestQueue::iterator iRequest (::std::find_if(
+        mpRequestQueue->begin(),
+        mpRequestQueue->end(),
+        PreviewCreationRequest::CompareToken(aToken)));
+    return (iRequest != mpRequestQueue->end());
+}
+
+
+
+
+bool MasterPageContainerQueue::IsEmpty (void) const
+{
+    return mpRequestQueue->empty();
+}
+
+
+
+
+void MasterPageContainerQueue::ProcessAllRequests (void)
+{
+    snWaitForMoreRequestsCount = 0;
+    if (mpRequestQueue->size() > 0)
+        maDelayedPreviewCreationTimer.Start();
+}
+
+
+} } // end of namespace sd::sidebar

Added: openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerQueue.hxx
URL: http://svn.apache.org/viewvc/openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerQueue.hxx?rev=1447641&view=auto
==============================================================================
--- openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerQueue.hxx (added)
+++ openoffice/branches/sidebar/main/sd/source/ui/sidebar/panels/MasterPageContainerQueue.hxx Tue Feb 19 09:09:02 2013
@@ -0,0 +1,130 @@
+/**************************************************************
+ * 
+ * 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
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+#ifndef SD_SIDEBAR_PANELS_MASTER_PAGE_CONTAINER_QUEUE_HXX
+#define SD_SIDEBAR_PANELS_MASTER_PAGE_CONTAINER_QUEUE_HXX
+
+#include "MasterPageContainer.hxx"
+#include "MasterPageDescriptor.hxx"
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+namespace sd { namespace sidebar {
+
+
+/** The queue stores and processes all requests from a MasterPageContainer
+    for the creation of previews.
+    The order of request processing and its timing is controlled by a
+    heuristic that uses values given with each request and which is
+    controlled by various parameters that are described below.
+*/
+class MasterPageContainerQueue
+{
+public:
+    class ContainerAdapter { public:
+        virtual bool UpdateDescriptor (
+            const SharedMasterPageDescriptor& rpDescriptor,
+            bool bForcePageObject,
+            bool bForcePreview,
+            bool bSendEvents) = 0;
+    };
+
+    static MasterPageContainerQueue* Create (
+        const ::boost::weak_ptr<ContainerAdapter>& rpContainer);
+    virtual ~MasterPageContainerQueue (void);
+
+    /** This method is typically called for entries in the container for
+        which GetPreviewState() returns OS_CREATABLE.  The creation of the
+        preview is then scheduled to be executed asynchronously at a later
+        point in time.  When the preview is available the change listeners
+        will be notified.
+    */
+    bool RequestPreview (const SharedMasterPageDescriptor& rDescriptor);
+
+    /** Return <TRUE/> when there is a request currently in the queue for
+        the given token.
+    */
+    bool HasRequest (MasterPageContainer::Token aToken) const;
+
+    /** Return <TRUE/> when there is at least one request in the queue.
+    */
+    bool IsEmpty (void) const;
+
+    /** After this call the queue does not wait anymore for requests with
+        higher priority when only a small number of requests with lower
+        priority are present.  This method should be called when all
+        templates are inserted into the MasterPageContainer.
+    */
+    void ProcessAllRequests (void);
+    
+private:
+    ::boost::weak_ptr<ContainerAdapter> mpWeakContainer;
+    class PreviewCreationRequest;
+    class RequestQueue;
+    ::boost::scoped_ptr<RequestQueue> mpRequestQueue;
+    Timer maDelayedPreviewCreationTimer;
+    sal_uInt32 mnRequestsServedCount;
+
+    // There are a couple of values that define various aspects of the
+    // heuristic that defines the order and timing in which requests for
+    // preview creation are processed.
+    
+    /** The time to wait (in milliseconds) between the creation of previews.
+    */
+    static const sal_Int32 snDelayedCreationTimeout;
+
+    /** The time to wait when the system is not idle.
+    */
+    static const sal_Int32 snDelayedCreationTimeoutWhenNotIdle;
+    
+    /** Requests for previews of master pages in a document have their
+        priority increased by this value.
+    */
+    static const sal_Int32 snMasterPagePriorityBoost;
+
+    /** When only requests which a priority lower than this threshold exist
+        and not many requests have been made yet then wait with processing
+        them until more requests are present.
+    */
+    static const sal_Int32 snWaitForMoreRequestsPriorityThreshold;
+
+    /** When only requests which a priority lower than a threshold exist
+        and not more requests than this number have been made or already
+        processed then wait with processing them until more requests are
+        present.
+    */
+    static sal_uInt32 snWaitForMoreRequestsCount;
+    
+    MasterPageContainerQueue (const ::boost::weak_ptr<ContainerAdapter>& rpContainer);
+    void LateInit (void);
+
+    /** Calculate the priority that defines the order in which requests
+        are processed.
+    */
+    sal_Int32 CalculatePriority (const SharedMasterPageDescriptor& rDescriptor) const;
+    
+    DECL_LINK(DelayedPreviewCreation, Timer *);
+};
+
+} } // end of namespace sd::sidebar
+
+#endif