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 #include "precompiled_sd.hxx"
25 
26 #include "SlideSorter.hxx"
27 #include "model/SlideSorterModel.hxx"
28 #include "model/SlsPageDescriptor.hxx"
29 #include "controller/SlsPageSelector.hxx"
30 #include "controller/SlideSorterController.hxx"
31 #include "controller/SlsCurrentSlideManager.hxx"
32 #include "controller/SlsFocusManager.hxx"
33 #include "view/SlideSorterView.hxx"
34 #include "ViewShellBase.hxx"
35 #include "ViewShell.hxx"
36 #include "DrawViewShell.hxx"
37 #include "sdpage.hxx"
38 #include "FrameView.hxx"
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::uno;
43 
44 using namespace ::sd::slidesorter::model;
45 
46 
47 namespace sd { namespace slidesorter { namespace controller {
48 
49 
CurrentSlideManager(SlideSorter & rSlideSorter)50 CurrentSlideManager::CurrentSlideManager (SlideSorter& rSlideSorter)
51     : mrSlideSorter(rSlideSorter),
52       mnCurrentSlideIndex(-1),
53       mpCurrentSlide(),
54       maSwitchPageDelayTimer()
55 {
56     maSwitchPageDelayTimer.SetTimeout(100);
57     maSwitchPageDelayTimer.SetTimeoutHdl(LINK(this,CurrentSlideManager,SwitchPageCallback));
58 }
59 
60 
61 
62 
~CurrentSlideManager(void)63 CurrentSlideManager::~CurrentSlideManager (void)
64 {
65 }
66 
67 
68 
69 
NotifyCurrentSlideChange(const SdPage * pPage)70 void CurrentSlideManager::NotifyCurrentSlideChange (const SdPage* pPage)
71 {
72     if (pPage != NULL)
73         NotifyCurrentSlideChange(
74             mrSlideSorter.GetModel().GetIndex(
75                 Reference<drawing::XDrawPage>(
76                     const_cast<SdPage*>(pPage)->getUnoPage(),
77                     UNO_QUERY)));
78     else
79         NotifyCurrentSlideChange(-1);
80 }
81 
82 
83 
84 
NotifyCurrentSlideChange(const sal_Int32 nSlideIndex)85 void CurrentSlideManager::NotifyCurrentSlideChange (const sal_Int32 nSlideIndex)
86 {
87     if (mnCurrentSlideIndex != nSlideIndex)
88     {
89         PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter.GetController().GetPageSelector());
90 
91         mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
92 
93         ReleaseCurrentSlide();
94         AcquireCurrentSlide(nSlideIndex);
95 
96         // Update the selection.
97         if (mpCurrentSlide)
98         {
99             mrSlideSorter.GetController().GetPageSelector().SelectPage(mpCurrentSlide);
100             mrSlideSorter.GetController().GetFocusManager().SetFocusedPage(mpCurrentSlide);
101         }
102     }
103 }
104 
105 
106 
107 
ReleaseCurrentSlide(void)108 void CurrentSlideManager::ReleaseCurrentSlide (void)
109 {
110     if (mpCurrentSlide.get() != NULL)
111         mrSlideSorter.GetView().SetState(mpCurrentSlide, PageDescriptor::ST_Current, false);
112 
113     mpCurrentSlide.reset();
114     mnCurrentSlideIndex = -1;
115 }
116 
117 
118 
119 
IsCurrentSlideIsValid(void)120 bool CurrentSlideManager::IsCurrentSlideIsValid (void)
121 {
122     return mnCurrentSlideIndex >= 0 && mnCurrentSlideIndex<mrSlideSorter.GetModel().GetPageCount();
123 }
124 
125 
126 
127 
AcquireCurrentSlide(const sal_Int32 nSlideIndex)128 void CurrentSlideManager::AcquireCurrentSlide (const sal_Int32 nSlideIndex)
129 {
130     mnCurrentSlideIndex = nSlideIndex;
131 
132     if (IsCurrentSlideIsValid())
133     {
134         // Get a descriptor for the XDrawPage reference.  Note that the
135         // given XDrawPage may or may not be member of the slide sorter
136         // document.
137         mpCurrentSlide = mrSlideSorter.GetModel().GetPageDescriptor(mnCurrentSlideIndex);
138         if (mpCurrentSlide.get() != NULL)
139             mrSlideSorter.GetView().SetState(mpCurrentSlide, PageDescriptor::ST_Current, true);
140     }
141 }
142 
143 
144 
145 
SwitchCurrentSlide(const sal_Int32 nSlideIndex,const bool bUpdateSelection)146 void CurrentSlideManager::SwitchCurrentSlide (
147     const sal_Int32 nSlideIndex,
148     const bool bUpdateSelection)
149 {
150     SwitchCurrentSlide(mrSlideSorter.GetModel().GetPageDescriptor(nSlideIndex), bUpdateSelection);
151 }
152 
153 
154 
155 
SwitchCurrentSlide(const SharedPageDescriptor & rpDescriptor,const bool bUpdateSelection)156 void CurrentSlideManager::SwitchCurrentSlide (
157     const SharedPageDescriptor& rpDescriptor,
158     const bool bUpdateSelection)
159 {
160     if (rpDescriptor.get() != NULL && mpCurrentSlide!=rpDescriptor)
161     {
162         ReleaseCurrentSlide();
163         AcquireCurrentSlide((rpDescriptor->GetPage()->GetPageNum()-1)/2);
164 
165         ViewShell* pViewShell = mrSlideSorter.GetViewShell();
166         if (pViewShell != NULL && pViewShell->IsMainViewShell())
167         {
168             // The slide sorter is the main view.
169             FrameView* pFrameView = pViewShell->GetFrameView();
170             if (pFrameView != NULL)
171                 pFrameView->SetSelectedPage(sal::static_int_cast<sal_uInt16>(mnCurrentSlideIndex));
172             mrSlideSorter.GetController().GetPageSelector().SetCoreSelection();
173         }
174 
175         // We do not tell the XController/ViewShellBase about the new
176         // slide right away.  This is done asynchronously after a short
177         // delay to allow for more slide switches in the slide sorter.
178         // This goes under the assumption that slide switching inside
179         // the slide sorter is fast (no expensive redraw of the new page
180         // (unless the preview of the new slide is not yet preset)) and
181         // that slide switching in the edit view is slow (all shapes of
182         // the new slide have to be repainted.)
183         maSwitchPageDelayTimer.Start();
184 
185         // We have to store the (index of the) new current slide at
186         // the tab control because there are other asynchronous
187         // notifications of the slide switching that otherwise
188         // overwrite the correct value.
189         SetCurrentSlideAtTabControl(mpCurrentSlide);
190 
191         if (bUpdateSelection)
192         {
193             mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
194             mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
195         }
196         mrSlideSorter.GetController().GetFocusManager().SetFocusedPage(rpDescriptor);
197     }
198 }
199 
200 
201 
202 
SetCurrentSlideAtViewShellBase(const SharedPageDescriptor & rpDescriptor)203 void CurrentSlideManager::SetCurrentSlideAtViewShellBase (const SharedPageDescriptor& rpDescriptor)
204 {
205     OSL_ASSERT(rpDescriptor.get() != NULL);
206 
207     ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
208     if (pBase != NULL)
209     {
210         DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(
211             pBase->GetMainViewShell().get());
212         if (pDrawViewShell != NULL)
213         {
214             sal_uInt16 nPageNumber = (rpDescriptor->GetPage()->GetPageNum()-1)/2;
215             pDrawViewShell->SwitchPage(nPageNumber);
216             pDrawViewShell->GetPageTabControl()->SetCurPageId(nPageNumber+1);
217         }
218     }
219 }
220 
221 
222 
223 
SetCurrentSlideAtTabControl(const SharedPageDescriptor & rpDescriptor)224 void CurrentSlideManager::SetCurrentSlideAtTabControl (const SharedPageDescriptor& rpDescriptor)
225 {
226     OSL_ASSERT(rpDescriptor.get() != NULL);
227 
228     ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
229     if (pBase != NULL)
230     {
231         ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
232             ::boost::dynamic_pointer_cast<DrawViewShell>(pBase->GetMainViewShell()));
233         if (pDrawViewShell)
234         {
235             sal_uInt16 nPageNumber = (rpDescriptor->GetPage()->GetPageNum()-1)/2;
236             pDrawViewShell->GetPageTabControl()->SetCurPageId(nPageNumber+1);
237         }
238     }
239 }
240 
241 
242 
243 
SetCurrentSlideAtXController(const SharedPageDescriptor & rpDescriptor)244 void CurrentSlideManager::SetCurrentSlideAtXController (const SharedPageDescriptor& rpDescriptor)
245 {
246     OSL_ASSERT(rpDescriptor.get() != NULL);
247 
248     try
249     {
250         Reference<beans::XPropertySet> xSet (mrSlideSorter.GetXController(), UNO_QUERY);
251         if (xSet.is())
252         {
253             Any aPage;
254             aPage <<= rpDescriptor->GetPage()->getUnoPage();
255             xSet->setPropertyValue (
256                 String::CreateFromAscii("CurrentPage"),
257                 aPage);
258         }
259     }
260     catch (Exception aException)
261     {
262         // We have not been able to set the current page at the main view.
263         // This is sad but still leaves us in a valid state.  Therefore,
264         // this exception is silently ignored.
265     }
266 }
267 
268 
269 
270 
GetCurrentSlide(void)271 SharedPageDescriptor CurrentSlideManager::GetCurrentSlide (void)
272 {
273     return mpCurrentSlide;
274 }
275 
276 
277 
278 
PrepareModelChange(void)279 void CurrentSlideManager::PrepareModelChange (void)
280 {
281     mpCurrentSlide.reset();
282 }
283 
284 
285 
286 
HandleModelChange(void)287 void CurrentSlideManager::HandleModelChange (void)
288 {
289     if (mnCurrentSlideIndex >= 0)
290     {
291         mpCurrentSlide = mrSlideSorter.GetModel().GetPageDescriptor(mnCurrentSlideIndex);
292         if (mpCurrentSlide.get() != NULL)
293             mrSlideSorter.GetView().SetState(mpCurrentSlide, PageDescriptor::ST_Current, true);
294     }
295 }
296 
297 
298 
299 
IMPL_LINK(CurrentSlideManager,SwitchPageCallback,void *,EMPTYARG)300 IMPL_LINK(CurrentSlideManager, SwitchPageCallback, void*, EMPTYARG)
301 {
302     if (mpCurrentSlide)
303     {
304         // Set current page.  At the moment we have to do this in two
305         // different ways.  The UNO way is the preferable one but, alas,
306         // it does not work always correctly (after some kinds of model
307         // changes).  Therefore, we call DrawViewShell::SwitchPage(),
308         // too.
309         ViewShell* pViewShell = mrSlideSorter.GetViewShell();
310         if (pViewShell==NULL || ! pViewShell->IsMainViewShell())
311             SetCurrentSlideAtViewShellBase(mpCurrentSlide);
312         SetCurrentSlideAtXController(mpCurrentSlide);
313     }
314 
315     return 1;
316 }
317 
318 } } } // end of namespace ::sd::slidesorter::controller
319