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