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