1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 #include "precompiled_slideshow.hxx" 28 29 #include "screenupdater.hxx" 30 #include "listenercontainer.hxx" 31 32 #include <boost/bind.hpp> 33 #include <vector> 34 #include <algorithm> 35 36 namespace { 37 class UpdateLock : public ::slideshow::internal::ScreenUpdater::UpdateLock 38 { 39 public: 40 UpdateLock (::slideshow::internal::ScreenUpdater& rUpdater, const bool bStartLocked); 41 virtual ~UpdateLock (void); 42 virtual void Activate (void); 43 private: 44 ::slideshow::internal::ScreenUpdater& mrUpdater; 45 bool mbIsActivated; 46 }; 47 } 48 49 namespace slideshow 50 { 51 namespace internal 52 { 53 typedef std::vector< 54 std::pair<UnoViewSharedPtr,bool> > UpdateRequestVector; 55 56 struct ScreenUpdater::ImplScreenUpdater 57 { 58 /** List of registered ViewUpdaters, to consult for necessary 59 updates 60 */ 61 ThreadUnsafeListenerContainer< 62 ViewUpdateSharedPtr, 63 std::vector<ViewUpdateSharedPtr> > maUpdaters; 64 65 /// Views that have been notified for update 66 UpdateRequestVector maViewUpdateRequests; 67 68 /// List of View. Used to issue screen updates on. 69 UnoViewContainer const& mrViewContainer; 70 71 /// True, if a notifyUpdate() for all views has been issued. 72 bool mbUpdateAllRequest; 73 74 /// True, if at least one notifyUpdate() call had bViewClobbered set 75 bool mbViewClobbered; 76 77 /// The screen is updated only when mnLockCount==0 78 sal_Int32 mnLockCount; 79 80 explicit ImplScreenUpdater( UnoViewContainer const& rViewContainer ) : 81 maUpdaters(), 82 maViewUpdateRequests(), 83 mrViewContainer(rViewContainer), 84 mbUpdateAllRequest(false), 85 mbViewClobbered(false), 86 mnLockCount(0) 87 {} 88 }; 89 90 ScreenUpdater::ScreenUpdater( UnoViewContainer const& rViewContainer ) : 91 mpImpl(new ImplScreenUpdater(rViewContainer) ) 92 { 93 } 94 95 ScreenUpdater::~ScreenUpdater() 96 { 97 // outline because of pimpl 98 } 99 100 void ScreenUpdater::notifyUpdate() 101 { 102 mpImpl->mbUpdateAllRequest = true; 103 } 104 105 void ScreenUpdater::notifyUpdate( const UnoViewSharedPtr& rView, 106 bool bViewClobbered ) 107 { 108 mpImpl->maViewUpdateRequests.push_back( 109 std::make_pair(rView, bViewClobbered) ); 110 111 if( bViewClobbered ) 112 mpImpl->mbViewClobbered = true; 113 } 114 115 void ScreenUpdater::commitUpdates() 116 { 117 if (mpImpl->mnLockCount > 0) 118 return; 119 120 // cases: 121 // 122 // (a) no update necessary at all 123 // 124 // (b) no ViewUpdate-generated update 125 // I. update all views requested -> for_each( mrViewContainer ) 126 // II. update some views requested -> for_each( maViewUpdateRequests ) 127 // 128 // (c) ViewUpdate-triggered update - update all views 129 // 130 131 // any ViewUpdate-triggered updates? 132 const bool bViewUpdatesNeeded( 133 mpImpl->maUpdaters.apply( 134 boost::mem_fn(&ViewUpdate::needsUpdate)) ); 135 136 if( bViewUpdatesNeeded ) 137 { 138 mpImpl->maUpdaters.applyAll( 139 boost::mem_fn((bool (ViewUpdate::*)())&ViewUpdate::update) ); 140 } 141 142 if( bViewUpdatesNeeded || 143 mpImpl->mbUpdateAllRequest ) 144 { 145 // unconditionally update all views 146 std::for_each( mpImpl->mrViewContainer.begin(), 147 mpImpl->mrViewContainer.end(), 148 mpImpl->mbViewClobbered ? 149 boost::mem_fn(&View::paintScreen) : 150 boost::mem_fn(&View::updateScreen) ); 151 } 152 else if( !mpImpl->maViewUpdateRequests.empty() ) 153 { 154 // update notified views only 155 UpdateRequestVector::const_iterator aIter( 156 mpImpl->maViewUpdateRequests.begin() ); 157 const UpdateRequestVector::const_iterator aEnd( 158 mpImpl->maViewUpdateRequests.end() ); 159 while( aIter != aEnd ) 160 { 161 // TODO(P1): this is O(n^2) in the number of views, if 162 // lots of views notify updates. 163 const UnoViewVector::const_iterator aEndOfViews( 164 mpImpl->mrViewContainer.end() ); 165 UnoViewVector::const_iterator aFoundView; 166 if( (aFoundView=std::find(mpImpl->mrViewContainer.begin(), 167 aEndOfViews, 168 aIter->first)) != aEndOfViews ) 169 { 170 if( aIter->second ) 171 (*aFoundView)->paintScreen(); // force-paint 172 else 173 (*aFoundView)->updateScreen(); // update changes only 174 } 175 176 ++aIter; 177 } 178 } 179 180 // done - clear requests 181 mpImpl->mbViewClobbered = false; 182 mpImpl->mbUpdateAllRequest = false; 183 UpdateRequestVector().swap( mpImpl->maViewUpdateRequests ); 184 } 185 186 void ScreenUpdater::addViewUpdate( ViewUpdateSharedPtr const& rViewUpdate ) 187 { 188 mpImpl->maUpdaters.add( rViewUpdate ); 189 } 190 191 void ScreenUpdater::removeViewUpdate( ViewUpdateSharedPtr const& rViewUpdate ) 192 { 193 mpImpl->maUpdaters.remove( rViewUpdate ); 194 } 195 196 void ScreenUpdater::requestImmediateUpdate() 197 { 198 if (mpImpl->mnLockCount > 0) 199 return; 200 201 // TODO(F2): This will interfere with other updates, since it 202 // happens out-of-sync with main animation loop. Might cause 203 // artifacts. 204 std::for_each( mpImpl->mrViewContainer.begin(), 205 mpImpl->mrViewContainer.end(), 206 boost::mem_fn(&View::updateScreen) ); 207 } 208 209 void ScreenUpdater::lockUpdates (void) 210 { 211 ++mpImpl->mnLockCount; 212 OSL_ASSERT(mpImpl->mnLockCount>0); 213 } 214 215 void ScreenUpdater::unlockUpdates (void) 216 { 217 OSL_ASSERT(mpImpl->mnLockCount>0); 218 if (mpImpl->mnLockCount > 0) 219 { 220 --mpImpl->mnLockCount; 221 if (mpImpl->mnLockCount) 222 commitUpdates(); 223 } 224 } 225 226 ::boost::shared_ptr<ScreenUpdater::UpdateLock> ScreenUpdater::createLock (const bool bStartLocked) 227 { 228 return ::boost::shared_ptr<ScreenUpdater::UpdateLock>(new ::UpdateLock(*this, bStartLocked)); 229 } 230 231 232 } // namespace internal 233 } // namespace slideshow 234 235 namespace { 236 237 UpdateLock::UpdateLock ( 238 ::slideshow::internal::ScreenUpdater& rUpdater, 239 const bool bStartLocked) 240 : mrUpdater(rUpdater), 241 mbIsActivated(false) 242 { 243 if (bStartLocked) 244 Activate(); 245 } 246 247 248 249 250 UpdateLock::~UpdateLock (void) 251 { 252 if (mbIsActivated) 253 mrUpdater.unlockUpdates(); 254 } 255 256 257 258 259 void UpdateLock::Activate (void) 260 { 261 if ( ! mbIsActivated) 262 { 263 mbIsActivated = true; 264 mrUpdater.lockUpdates(); 265 } 266 } 267 268 } 269