1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "screenupdater.hxx"
21 #include "listenercontainer.hxx"
23 #include <osl/diagnose.h>
25 #include <boost/shared_ptr.hpp>
26 #include <boost/mem_fn.hpp>
31 class UpdateLock
: public ::slideshow::internal::ScreenUpdater::UpdateLock
34 UpdateLock (::slideshow::internal::ScreenUpdater
& rUpdater
, const bool bStartLocked
);
35 virtual ~UpdateLock();
36 virtual void Activate() SAL_OVERRIDE
;
38 ::slideshow::internal::ScreenUpdater
& mrUpdater
;
48 std::pair
<UnoViewSharedPtr
,bool> > UpdateRequestVector
;
50 struct ScreenUpdater::ImplScreenUpdater
52 /** List of registered ViewUpdaters, to consult for necessary
55 ThreadUnsafeListenerContainer
<
57 std::vector
<ViewUpdateSharedPtr
> > maUpdaters
;
59 /// Views that have been notified for update
60 UpdateRequestVector maViewUpdateRequests
;
62 /// List of View. Used to issue screen updates on.
63 UnoViewContainer
const& mrViewContainer
;
65 /// True, if a notifyUpdate() for all views has been issued.
66 bool mbUpdateAllRequest
;
68 /// True, if at least one notifyUpdate() call had bViewClobbered set
71 /// The screen is updated only when mnLockCount==0
72 sal_Int32 mnLockCount
;
74 explicit ImplScreenUpdater( UnoViewContainer
const& rViewContainer
) :
76 maViewUpdateRequests(),
77 mrViewContainer(rViewContainer
),
78 mbUpdateAllRequest(false),
79 mbViewClobbered(false),
84 ScreenUpdater::ScreenUpdater( UnoViewContainer
const& rViewContainer
) :
85 mpImpl(new ImplScreenUpdater(rViewContainer
) )
89 ScreenUpdater::~ScreenUpdater()
91 // outline because of pimpl
94 void ScreenUpdater::notifyUpdate()
96 mpImpl
->mbUpdateAllRequest
= true;
99 void ScreenUpdater::notifyUpdate( const UnoViewSharedPtr
& rView
,
100 bool bViewClobbered
)
102 mpImpl
->maViewUpdateRequests
.push_back(
103 std::make_pair(rView
, bViewClobbered
) );
106 mpImpl
->mbViewClobbered
= true;
109 void ScreenUpdater::commitUpdates()
111 if (mpImpl
->mnLockCount
> 0)
116 // (a) no update necessary at all
118 // (b) no ViewUpdate-generated update
119 // I. update all views requested -> for_each( mrViewContainer )
120 // II. update some views requested -> for_each( maViewUpdateRequests )
122 // (c) ViewUpdate-triggered update - update all views
125 // any ViewUpdate-triggered updates?
126 const bool bViewUpdatesNeeded(
127 mpImpl
->maUpdaters
.apply(
128 boost::mem_fn(&ViewUpdate::needsUpdate
)) );
130 if( bViewUpdatesNeeded
)
132 mpImpl
->maUpdaters
.applyAll(
133 boost::mem_fn((bool (ViewUpdate::*)())&ViewUpdate::update
) );
136 if( bViewUpdatesNeeded
||
137 mpImpl
->mbUpdateAllRequest
)
139 // unconditionally update all views
140 std::for_each( mpImpl
->mrViewContainer
.begin(),
141 mpImpl
->mrViewContainer
.end(),
142 mpImpl
->mbViewClobbered
?
143 boost::mem_fn(&View::paintScreen
) :
144 boost::mem_fn(&View::updateScreen
) );
146 else if( !mpImpl
->maViewUpdateRequests
.empty() )
148 // update notified views only
149 UpdateRequestVector::const_iterator
aIter(
150 mpImpl
->maViewUpdateRequests
.begin() );
151 const UpdateRequestVector::const_iterator
aEnd(
152 mpImpl
->maViewUpdateRequests
.end() );
153 while( aIter
!= aEnd
)
155 // TODO(P1): this is O(n^2) in the number of views, if
156 // lots of views notify updates.
157 const UnoViewVector::const_iterator
aEndOfViews(
158 mpImpl
->mrViewContainer
.end() );
159 UnoViewVector::const_iterator aFoundView
;
160 if( (aFoundView
=std::find(mpImpl
->mrViewContainer
.begin(),
162 aIter
->first
)) != aEndOfViews
)
165 (*aFoundView
)->paintScreen(); // force-paint
167 (*aFoundView
)->updateScreen(); // update changes only
174 // done - clear requests
175 mpImpl
->mbViewClobbered
= false;
176 mpImpl
->mbUpdateAllRequest
= false;
177 UpdateRequestVector().swap( mpImpl
->maViewUpdateRequests
);
180 void ScreenUpdater::addViewUpdate( ViewUpdateSharedPtr
const& rViewUpdate
)
182 mpImpl
->maUpdaters
.add( rViewUpdate
);
185 void ScreenUpdater::removeViewUpdate( ViewUpdateSharedPtr
const& rViewUpdate
)
187 mpImpl
->maUpdaters
.remove( rViewUpdate
);
190 void ScreenUpdater::requestImmediateUpdate()
192 if (mpImpl
->mnLockCount
> 0)
195 // TODO(F2): This will interfere with other updates, since it
196 // happens out-of-sync with main animation loop. Might cause
198 std::for_each( mpImpl
->mrViewContainer
.begin(),
199 mpImpl
->mrViewContainer
.end(),
200 boost::mem_fn(&View::updateScreen
) );
203 void ScreenUpdater::lockUpdates()
205 ++mpImpl
->mnLockCount
;
206 OSL_ASSERT(mpImpl
->mnLockCount
>0);
209 void ScreenUpdater::unlockUpdates()
211 OSL_ASSERT(mpImpl
->mnLockCount
>0);
212 if (mpImpl
->mnLockCount
> 0)
214 --mpImpl
->mnLockCount
;
215 if (mpImpl
->mnLockCount
)
220 ::boost::shared_ptr
<ScreenUpdater::UpdateLock
> ScreenUpdater::createLock (const bool bStartLocked
)
222 return ::boost::shared_ptr
<ScreenUpdater::UpdateLock
>(new ::UpdateLock(*this, bStartLocked
));
226 } // namespace internal
227 } // namespace slideshow
231 UpdateLock::UpdateLock (
232 ::slideshow::internal::ScreenUpdater
& rUpdater
,
233 const bool bStartLocked
)
234 : mrUpdater(rUpdater
),
244 UpdateLock::~UpdateLock()
247 mrUpdater
.unlockUpdates();
253 void UpdateLock::Activate()
255 if ( ! mbIsActivated
)
257 mbIsActivated
= true;
258 mrUpdater
.lockUpdates();
264 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */