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 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 63 CurrentSlideManager::~CurrentSlideManager (void) 64 { 65 } 66 67 68 69 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 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 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 120 bool CurrentSlideManager::IsCurrentSlideIsValid (void) 121 { 122 return mnCurrentSlideIndex >= 0 && mnCurrentSlideIndex<mrSlideSorter.GetModel().GetPageCount(); 123 } 124 125 126 127 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 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 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 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 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 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 271 SharedPageDescriptor CurrentSlideManager::GetCurrentSlide (void) 272 { 273 return mpCurrentSlide; 274 } 275 276 277 278 279 void CurrentSlideManager::PrepareModelChange (void) 280 { 281 mpCurrentSlide.reset(); 282 } 283 284 285 286 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 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