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