blob: c34a317175d38d198a5ab6d76940555aafcc2132 [file] [log] [blame]
/**************************************************************
*
* 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