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