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: 43 PreviewCreationRequest (const SharedMasterPageDescriptor& rpDescriptor, int nPriority) 44 : mpDescriptor(rpDescriptor), 45 mnPriority(nPriority) 46 {} 47 SharedMasterPageDescriptor mpDescriptor; 48 int mnPriority; 49 class Compare {public: 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; 67 CompareToken(MasterPageContainer::Token aToken) : maToken(aToken) {} 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: 82 RequestQueue (void) {} 83 }; 84 85 86 87 88 //===== MasterPageContainerQueue ============================================== 89 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 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 113 MasterPageContainerQueue::~MasterPageContainerQueue (void) 114 { 115 maDelayedPreviewCreationTimer.Stop(); 116 while ( ! mpRequestQueue->empty()) 117 mpRequestQueue->erase(mpRequestQueue->begin()); 118 } 119 120 121 122 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 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 170 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 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 269 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 281 bool MasterPageContainerQueue::IsEmpty (void) const 282 { 283 return mpRequestQueue->empty(); 284 } 285 286 287 288 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