Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "MasterPageContainerQueue.hxx"
22 :
23 : #include "tools/IdleDetection.hxx"
24 :
25 : #include <set>
26 :
27 : namespace sd { namespace toolpanel { namespace controls {
28 :
29 : const sal_Int32 MasterPageContainerQueue::snDelayedCreationTimeout (15);
30 : const sal_Int32 MasterPageContainerQueue::snDelayedCreationTimeoutWhenNotIdle (100);
31 : const sal_Int32 MasterPageContainerQueue::snMasterPagePriorityBoost (5);
32 : const sal_Int32 MasterPageContainerQueue::snWaitForMoreRequestsPriorityThreshold (-10);
33 : sal_uInt32 MasterPageContainerQueue::snWaitForMoreRequestsCount(15);
34 :
35 : //===== MasterPageContainerQueue::PreviewCreationRequest ======================
36 :
37 0 : class MasterPageContainerQueue::PreviewCreationRequest
38 : {
39 : public:
40 0 : PreviewCreationRequest (const SharedMasterPageDescriptor& rpDescriptor, int nPriority)
41 : : mpDescriptor(rpDescriptor),
42 0 : mnPriority(nPriority)
43 0 : {}
44 : SharedMasterPageDescriptor mpDescriptor;
45 : int mnPriority;
46 : class Compare
47 : {
48 : public:
49 0 : bool operator() (const PreviewCreationRequest& r1,const PreviewCreationRequest& r2) const
50 : {
51 0 : if (r1.mnPriority != r2.mnPriority)
52 : {
53 : // Prefer requests with higher priority.
54 0 : return r1.mnPriority > r2.mnPriority;
55 : }
56 : else
57 : {
58 : // Prefer tokens that have been earlier created (those with lower
59 : // value).
60 0 : return r1.mpDescriptor->maToken < r2.mpDescriptor->maToken;
61 : }
62 : }
63 : };
64 : class CompareToken
65 : {
66 : public:
67 : MasterPageContainer::Token maToken;
68 0 : CompareToken(MasterPageContainer::Token aToken) : maToken(aToken) {}
69 0 : bool operator() (const PreviewCreationRequest& rRequest) const
70 0 : { return maToken==rRequest.mpDescriptor->maToken; }
71 : };
72 : };
73 :
74 :
75 :
76 :
77 : //===== MasterPageContainerQueue::RequestQueue ================================
78 :
79 0 : class MasterPageContainerQueue::RequestQueue
80 : : public ::std::set<PreviewCreationRequest,PreviewCreationRequest::Compare>
81 : {
82 : public:
83 0 : RequestQueue (void) {}
84 : };
85 :
86 :
87 :
88 :
89 : //===== MasterPageContainerQueue ==============================================
90 :
91 0 : MasterPageContainerQueue* MasterPageContainerQueue::Create (
92 : const ::boost::weak_ptr<ContainerAdapter>& rpContainer)
93 : {
94 0 : MasterPageContainerQueue* pQueue = new MasterPageContainerQueue(rpContainer);
95 0 : pQueue->LateInit();
96 0 : return pQueue;
97 : }
98 :
99 :
100 :
101 :
102 0 : MasterPageContainerQueue::MasterPageContainerQueue (
103 : const ::boost::weak_ptr<ContainerAdapter>& rpContainer)
104 : : mpWeakContainer(rpContainer),
105 0 : mpRequestQueue(new RequestQueue()),
106 : maDelayedPreviewCreationTimer(),
107 0 : mnRequestsServedCount(0)
108 : {
109 0 : }
110 :
111 :
112 :
113 :
114 0 : MasterPageContainerQueue::~MasterPageContainerQueue (void)
115 : {
116 0 : maDelayedPreviewCreationTimer.Stop();
117 0 : while ( ! mpRequestQueue->empty())
118 0 : mpRequestQueue->erase(mpRequestQueue->begin());
119 0 : }
120 :
121 :
122 :
123 :
124 0 : void MasterPageContainerQueue::LateInit (void)
125 : {
126 : // Set up the timer for the delayed creation of preview bitmaps.
127 0 : maDelayedPreviewCreationTimer.SetTimeout (snDelayedCreationTimeout);
128 0 : Link aLink (LINK(this,MasterPageContainerQueue,DelayedPreviewCreation));
129 0 : maDelayedPreviewCreationTimer.SetTimeoutHdl(aLink);
130 0 : }
131 :
132 :
133 :
134 :
135 0 : bool MasterPageContainerQueue::RequestPreview (const SharedMasterPageDescriptor& rpDescriptor)
136 : {
137 0 : bool bSuccess (false);
138 0 : if (rpDescriptor.get() != NULL
139 0 : && rpDescriptor->maLargePreview.GetSizePixel().Width() == 0)
140 : {
141 0 : sal_Int32 nPriority (CalculatePriority(rpDescriptor));
142 :
143 : // Add a new or replace an existing request.
144 : RequestQueue::iterator iRequest (::std::find_if(
145 0 : mpRequestQueue->begin(),
146 0 : mpRequestQueue->end(),
147 0 : PreviewCreationRequest::CompareToken(rpDescriptor->maToken)));
148 : // When a request for the same token exists then the lowest of the
149 : // two priorities is used.
150 0 : if (iRequest != mpRequestQueue->end())
151 0 : if (iRequest->mnPriority < nPriority)
152 : {
153 0 : mpRequestQueue->erase(iRequest);
154 0 : iRequest = mpRequestQueue->end();
155 : }
156 :
157 : // Add a new request when none exists (or has just been erased).
158 0 : if (iRequest == mpRequestQueue->end())
159 : {
160 0 : mpRequestQueue->insert(PreviewCreationRequest(rpDescriptor,nPriority));
161 0 : maDelayedPreviewCreationTimer.Start();
162 0 : bSuccess = true;
163 : }
164 : }
165 0 : return bSuccess;
166 : }
167 :
168 :
169 :
170 :
171 0 : sal_Int32 MasterPageContainerQueue::CalculatePriority (
172 : const SharedMasterPageDescriptor& rpDescriptor) const
173 : {
174 : sal_Int32 nPriority;
175 :
176 : // The cost is used as a starting value.
177 0 : int nCost (0);
178 0 : if (rpDescriptor->mpPreviewProvider.get() != NULL)
179 : {
180 0 : nCost = rpDescriptor->mpPreviewProvider->GetCostIndex();
181 0 : if (rpDescriptor->mpPreviewProvider->NeedsPageObject())
182 0 : if (rpDescriptor->mpPageObjectProvider.get() != NULL)
183 0 : nCost += rpDescriptor->mpPageObjectProvider->GetCostIndex();
184 : }
185 :
186 : // Its negative value is used so that requests with a low cost are
187 : // preferred over those with high costs.
188 0 : nPriority = -nCost;
189 :
190 : // Add a term that introduces an order based on the appearance in the
191 : // AllMasterPagesSelector.
192 0 : nPriority -= rpDescriptor->maToken / 3;
193 :
194 : // Process requests for the CurrentMasterPagesSelector first.
195 0 : if (rpDescriptor->meOrigin == MasterPageContainer::MASTERPAGE)
196 0 : nPriority += snMasterPagePriorityBoost;
197 :
198 0 : return nPriority;
199 : }
200 :
201 :
202 :
203 :
204 0 : IMPL_LINK(MasterPageContainerQueue, DelayedPreviewCreation, Timer*, pTimer)
205 : {
206 0 : bool bIsShowingFullScreenShow (false);
207 0 : bool bWaitForMoreRequests (false);
208 :
209 : do
210 : {
211 0 : if (mpRequestQueue->empty())
212 : break;
213 :
214 : // First check whether the system is idle.
215 0 : sal_Int32 nIdleState (tools::IdleDetection::GetIdleState());
216 0 : if (nIdleState != tools::IdleDetection::IDET_IDLE)
217 : {
218 0 : if ((nIdleState&tools::IdleDetection::IDET_FULL_SCREEN_SHOW_ACTIVE) != 0)
219 0 : bIsShowingFullScreenShow = true;
220 : break;
221 : }
222 :
223 0 : PreviewCreationRequest aRequest (*mpRequestQueue->begin());
224 :
225 : // Check if the request should really be processed right now.
226 : // Reasons to not do it are when its cost is high and not many other
227 : // requests have been inserted into the queue that would otherwise
228 : // be processed first.
229 0 : if (aRequest.mnPriority < snWaitForMoreRequestsPriorityThreshold
230 0 : && (mnRequestsServedCount+mpRequestQueue->size() < snWaitForMoreRequestsCount))
231 : {
232 : // Wait for more requests before this one is processed. Note
233 : // that the queue processing is not started anew when this
234 : // method is left. That is done when the next request is
235 : // inserted.
236 0 : bWaitForMoreRequests = true;
237 : break;
238 : }
239 :
240 0 : mpRequestQueue->erase(mpRequestQueue->begin());
241 :
242 0 : if (aRequest.mpDescriptor.get() != NULL)
243 : {
244 0 : mnRequestsServedCount += 1;
245 0 : if ( ! mpWeakContainer.expired())
246 : {
247 0 : ::boost::shared_ptr<ContainerAdapter> pContainer (mpWeakContainer);
248 0 : if (pContainer.get() != NULL)
249 0 : pContainer->UpdateDescriptor(aRequest.mpDescriptor,false,true,true);
250 : }
251 0 : }
252 : }
253 : while (false);
254 :
255 0 : if (mpRequestQueue->size() > 0 && ! bWaitForMoreRequests)
256 : {
257 0 : int nTimeout (snDelayedCreationTimeout);
258 0 : if (bIsShowingFullScreenShow)
259 0 : nTimeout = snDelayedCreationTimeoutWhenNotIdle;
260 0 : maDelayedPreviewCreationTimer.SetTimeout(nTimeout);
261 0 : pTimer->Start();
262 : }
263 :
264 0 : return 0;
265 : }
266 :
267 :
268 :
269 :
270 0 : bool MasterPageContainerQueue::HasRequest (MasterPageContainer::Token aToken) const
271 : {
272 : RequestQueue::iterator iRequest (::std::find_if(
273 0 : mpRequestQueue->begin(),
274 0 : mpRequestQueue->end(),
275 0 : PreviewCreationRequest::CompareToken(aToken)));
276 0 : return (iRequest != mpRequestQueue->end());
277 : }
278 :
279 :
280 :
281 :
282 0 : bool MasterPageContainerQueue::IsEmpty (void) const
283 : {
284 0 : return mpRequestQueue->empty();
285 : }
286 :
287 :
288 :
289 :
290 0 : void MasterPageContainerQueue::ProcessAllRequests (void)
291 : {
292 0 : snWaitForMoreRequestsCount = 0;
293 0 : if (mpRequestQueue->size() > 0)
294 0 : maDelayedPreviewCreationTimer.Start();
295 0 : }
296 :
297 :
298 : } } } // end of namespace ::sd::toolpanel::controls
299 :
300 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|