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