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