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