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