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 "controller/SlideSorterController.hxx"
27 
28 #include "SlideSorter.hxx"
29 #include "controller/SlsPageSelector.hxx"
30 #include "controller/SlsSelectionFunction.hxx"
31 #include "controller/SlsProperties.hxx"
32 #include "controller/SlsCurrentSlideManager.hxx"
33 #include "SlsListener.hxx"
34 #include "controller/SlsFocusManager.hxx"
35 #include "SlsSelectionCommand.hxx"
36 #include "controller/SlsAnimator.hxx"
37 #include "controller/SlsClipboard.hxx"
38 #include "controller/SlsInsertionIndicatorHandler.hxx"
39 #include "controller/SlsScrollBarManager.hxx"
40 #include "controller/SlsSelectionManager.hxx"
41 #include "controller/SlsSlotManager.hxx"
42 #include "controller/SlsTransferableData.hxx"
43 #include "controller/SlsVisibleAreaManager.hxx"
44 #include "model/SlideSorterModel.hxx"
45 #include "model/SlsPageEnumerationProvider.hxx"
46 #include "model/SlsPageDescriptor.hxx"
47 #include "view/SlideSorterView.hxx"
48 #include "view/SlsLayouter.hxx"
49 #include "view/SlsFontProvider.hxx"
50 #include "view/SlsPageObjectLayouter.hxx"
51 #include "view/SlsPageObjectPainter.hxx"
52 #include "view/SlsTheme.hxx"
53 #include "view/SlsToolTip.hxx"
54 #include "cache/SlsPageCache.hxx"
55 #include "cache/SlsPageCacheManager.hxx"
56 
57 #include "drawdoc.hxx"
58 #include "DrawViewShell.hxx"
59 #include "TextLogger.hxx"
60 #include "ViewShellBase.hxx"
61 #include "Window.hxx"
62 #include "FrameView.hxx"
63 #include "DrawDocShell.hxx"
64 #include "sdpage.hxx"
65 #include "res_bmp.hrc"
66 #include "sdresid.hxx"
67 #include "strings.hrc"
68 #include "app.hrc"
69 #include "glob.hrc"
70 #include "sdmod.hxx"
71 #include "sdxfer.hxx"
72 #include "FrameView.hxx"
73 #include "ViewShellHint.hxx"
74 #include "AccessibleSlideSorterView.hxx"
75 #include "AccessibleSlideSorterObject.hxx"
76 
77 #include <vcl/window.hxx>
78 #include <svx/svdopage.hxx>
79 #include <svx/svxids.hrc>
80 #include <svx/ruler.hxx>
81 #include <svx/zoomitem.hxx>
82 #include <svtools/tabbar.hxx>
83 #include <sfx2/request.hxx>
84 #include <sfx2/viewfrm.hxx>
85 #include <sfx2/dispatch.hxx>
86 #include <tools/link.hxx>
87 #include <vcl/svapp.hxx>
88 
89 #include <com/sun/star/lang/XComponent.hpp>
90 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
91 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
92 #include <com/sun/star/drawing/XDrawPages.hpp>
93 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
94 
95 using namespace ::com::sun::star;
96 using namespace ::com::sun::star::uno;
97 using namespace ::sd::slidesorter::model;
98 using namespace ::sd::slidesorter::view;
99 using namespace ::sd::slidesorter::controller;
100 using namespace ::basegfx;
101 
102 namespace sd { namespace slidesorter { namespace controller {
103 
104 
SlideSorterController(SlideSorter & rSlideSorter)105 SlideSorterController::SlideSorterController (SlideSorter& rSlideSorter)
106     : mrSlideSorter(rSlideSorter),
107       mrModel(mrSlideSorter.GetModel()),
108       mrView(mrSlideSorter.GetView()),
109       mpPageSelector(),
110       mpFocusManager(),
111       mpSlotManager(),
112       mpClipboard(),
113       mpScrollBarManager(),
114       mpCurrentSlideManager(),
115       mpSelectionManager(),
116       mpInsertionIndicatorHandler(new InsertionIndicatorHandler(rSlideSorter)),
117       mpAnimator(new Animator(rSlideSorter)),
118       mpVisibleAreaManager(new VisibleAreaManager(rSlideSorter)),
119       mpListener(),
120       mnModelChangeLockCount(0),
121       mbIsForcedRearrangePending(false),
122       mbPreModelChangeDone(false),
123       mbPostModelChangePending(false),
124       maSelectionBeforeSwitch(),
125       mnCurrentPageBeforeSwitch(0),
126       mpEditModeChangeMasterPage(NULL),
127       maTotalWindowArea(),
128       mnPaintEntranceCount(0),
129       mbIsContextMenuOpen(false)
130 {
131     SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
132     OSL_ASSERT(pWindow);
133     if (pWindow)
134     {
135         // The whole background is painted by the view and controls.
136         ::Window* pParentWindow = pWindow->GetParent();
137         OSL_ASSERT(pParentWindow!=NULL);
138         pParentWindow->SetBackground (Wallpaper());
139 
140         // Connect the view with the window that has been created by our base
141         // class.
142         pWindow->SetBackground(Wallpaper());
143         pWindow->SetCenterAllowed(false);
144         pWindow->SetMapMode(MapMode(MAP_PIXEL));
145         pWindow->SetViewSize(mrView.GetModelArea().GetSize());
146     }
147 }
148 
149 
150 
151 
Init(void)152 void SlideSorterController::Init (void)
153 {
154     mpCurrentSlideManager.reset(new CurrentSlideManager(mrSlideSorter));
155     mpPageSelector.reset(new PageSelector(mrSlideSorter));
156     mpFocusManager.reset(new FocusManager(mrSlideSorter));
157     mpSlotManager.reset(new SlotManager(mrSlideSorter));
158     mpClipboard.reset(new Clipboard(mrSlideSorter));
159     mpScrollBarManager.reset(new ScrollBarManager(mrSlideSorter));
160     mpSelectionManager.reset(new SelectionManager(mrSlideSorter));
161 
162     mpScrollBarManager->LateInitialization();
163 
164     // Create the selection function.
165     SfxRequest aRequest (
166         SID_OBJECT_SELECT,
167         0,
168         mrModel.GetDocument()->GetItemPool());
169     mrSlideSorter.SetCurrentFunction(CreateSelectionFunction(aRequest));
170 
171     mpListener = new Listener(mrSlideSorter);
172 
173     mpPageSelector->GetCoreSelection();
174     GetSelectionManager()->SelectionHasChanged();
175 }
176 
177 
178 
179 
~SlideSorterController(void)180 SlideSorterController::~SlideSorterController (void)
181 {
182     try
183     {
184         uno::Reference<lang::XComponent> xComponent (
185             static_cast<XWeak*>(mpListener.get()), uno::UNO_QUERY);
186         if (xComponent.is())
187             xComponent->dispose();
188     }
189     catch( uno::Exception& e )
190     {
191         (void)e;
192         DBG_ERROR( "sd::SlideSorterController::~SlideSorterController(), exception caught!" );
193     }
194 
195     // dispose should have been called by now so that nothing is to be done
196     // to shut down cleanly.
197 }
198 
199 
200 
201 
Dispose(void)202 void SlideSorterController::Dispose (void)
203 {
204     mpInsertionIndicatorHandler->End(Animator::AM_Immediate);
205     mpSelectionManager.reset();
206     mpAnimator->Dispose();
207 }
208 
209 
210 
211 
GetPageAt(const Point & aWindowPosition)212 model::SharedPageDescriptor SlideSorterController::GetPageAt (
213     const Point& aWindowPosition)
214 {
215     sal_Int32 nHitPageIndex (mrView.GetPageIndexAtPoint(aWindowPosition));
216     model::SharedPageDescriptor pDescriptorAtPoint;
217     if (nHitPageIndex >= 0)
218     {
219         pDescriptorAtPoint = mrModel.GetPageDescriptor(nHitPageIndex);
220 
221         // Depending on a property we may have to check that the mouse is no
222         // just over the page object but over the preview area.
223         if (pDescriptorAtPoint
224             && mrSlideSorter.GetProperties()->IsOnlyPreviewTriggersMouseOver()
225             && ! pDescriptorAtPoint->HasState(PageDescriptor::ST_Selected))
226         {
227             // Make sure that the mouse is over the preview area.
228             if ( ! mrView.GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
229                 pDescriptorAtPoint,
230                 view::PageObjectLayouter::Preview,
231                 view::PageObjectLayouter::WindowCoordinateSystem).IsInside(aWindowPosition))
232             {
233                 pDescriptorAtPoint.reset();
234             }
235         }
236     }
237 
238     return pDescriptorAtPoint;
239 }
240 
241 
242 
243 
GetPageSelector(void)244 PageSelector& SlideSorterController::GetPageSelector (void)
245 {
246     OSL_ASSERT(mpPageSelector.get()!=NULL);
247     return *mpPageSelector.get();
248 }
249 
250 
251 
252 
GetFocusManager(void)253 FocusManager& SlideSorterController::GetFocusManager (void)
254 {
255     OSL_ASSERT(mpFocusManager.get()!=NULL);
256     return *mpFocusManager.get();
257 }
258 
259 
260 
261 
GetClipboard(void)262 Clipboard& SlideSorterController::GetClipboard (void)
263 {
264     OSL_ASSERT(mpClipboard.get()!=NULL);
265     return *mpClipboard.get();
266 }
267 
268 
269 
270 
GetScrollBarManager(void)271 ScrollBarManager& SlideSorterController::GetScrollBarManager (void)
272 {
273     OSL_ASSERT(mpScrollBarManager.get()!=NULL);
274     return *mpScrollBarManager.get();
275 }
276 
277 
278 
279 
GetCurrentSlideManager(void) const280 ::boost::shared_ptr<CurrentSlideManager> SlideSorterController::GetCurrentSlideManager (void) const
281 {
282     OSL_ASSERT(mpCurrentSlideManager.get()!=NULL);
283     return mpCurrentSlideManager;
284 }
285 
286 
287 
288 
GetSlotManager(void) const289 ::boost::shared_ptr<SlotManager> SlideSorterController::GetSlotManager (void) const
290 {
291     OSL_ASSERT(mpSlotManager.get()!=NULL);
292     return mpSlotManager;
293 }
294 
295 
296 
297 
GetSelectionManager(void) const298 ::boost::shared_ptr<SelectionManager> SlideSorterController::GetSelectionManager (void) const
299 {
300     OSL_ASSERT(mpSelectionManager.get()!=NULL);
301     return mpSelectionManager;
302 }
303 
304 
305 
306 
307 ::boost::shared_ptr<InsertionIndicatorHandler>
GetInsertionIndicatorHandler(void) const308     SlideSorterController::GetInsertionIndicatorHandler (void) const
309 {
310     OSL_ASSERT(mpInsertionIndicatorHandler.get()!=NULL);
311     return mpInsertionIndicatorHandler;
312 }
313 
314 
315 
316 
Paint(const Rectangle & rBBox,::Window * pWindow)317 void SlideSorterController::Paint (
318     const Rectangle& rBBox,
319     ::Window* pWindow)
320 {
321     if (mnPaintEntranceCount == 0)
322     {
323         ++mnPaintEntranceCount;
324 
325         try
326         {
327             mrView.CompleteRedraw(pWindow, Region(rBBox), 0);
328         }
329         catch (const Exception&)
330         {
331             // Ignore all exceptions.
332         }
333 
334         --mnPaintEntranceCount;
335     }
336 }
337 
338 
339 
340 
FuTemporary(SfxRequest & rRequest)341 void SlideSorterController::FuTemporary (SfxRequest& rRequest)
342 {
343     mpSlotManager->FuTemporary (rRequest);
344 }
345 
346 
347 
348 
FuPermanent(SfxRequest & rRequest)349 void SlideSorterController::FuPermanent (SfxRequest &rRequest)
350 {
351     mpSlotManager->FuPermanent (rRequest);
352 }
353 
354 
355 
356 
FuSupport(SfxRequest & rRequest)357 void SlideSorterController::FuSupport (SfxRequest &rRequest)
358 {
359     mpSlotManager->FuSupport (rRequest);
360 }
361 
362 
363 
364 
Command(const CommandEvent & rEvent,::sd::Window * pWindow)365 bool SlideSorterController::Command (
366     const CommandEvent& rEvent,
367     ::sd::Window* pWindow)
368 {
369     bool bEventHasBeenHandled = false;
370 
371     if (pWindow == NULL)
372         return false;
373 
374     ViewShell* pViewShell = mrSlideSorter.GetViewShell();
375     if (pViewShell == NULL)
376         return false;
377 
378     switch (rEvent.GetCommand())
379     {
380         case COMMAND_CONTEXTMENU:
381         {
382             SdPage* pPage = NULL;
383             sal_uInt16 nPopupId;
384 
385             model::PageEnumeration aSelectedPages (
386                 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
387             if (aSelectedPages.HasMoreElements())
388                 pPage = aSelectedPages.GetNextElement()->GetPage();
389 
390             // Choose the popup menu depending on a) the type of the main
391             // view shell, b) the edit mode, and c) on whether the selection
392             // is empty or not.
393             ViewShell::ShellType eMainViewShellType (ViewShell::ST_NONE);
394             ::boost::shared_ptr<ViewShell> pMainViewShell (
395                 pViewShell->GetViewShellBase().GetMainViewShell());
396             if (pMainViewShell.get() != NULL)
397                 eMainViewShellType = pMainViewShell->GetShellType();
398             switch (eMainViewShellType)
399             {
400                 case ViewShell::ST_DRAW:
401                     if (pPage != NULL)
402                         nPopupId = RID_SLIDE_SORTER_DRAW_SEL_POPUP;
403                     else
404                         nPopupId = RID_SLIDE_SORTER_DRAW_NOSEL_POPUP;
405                     break;
406 
407                 default:
408                     if (mrModel.GetEditMode() == EM_PAGE)
409                         if (pPage != NULL)
410                             nPopupId = RID_SLIDE_SORTER_IMPRESS_SEL_POPUP;
411                         else
412                             nPopupId = RID_SLIDE_SORTER_IMPRESS_NOSEL_POPUP;
413                     else
414                         if (pPage != NULL)
415                             nPopupId = RID_SLIDE_SORTER_MASTER_SEL_POPUP;
416                         else
417                             nPopupId = RID_SLIDE_SORTER_MASTER_NOSEL_POPUP;
418             }
419             ::boost::scoped_ptr<InsertionIndicatorHandler::ForceShowContext> pContext;
420             if (pPage == NULL)
421             {
422                 // When there is no selection, then we show the insertion
423                 // indicator so that the user knows where a page insertion
424                 // would take place.
425                 mpInsertionIndicatorHandler->Start(false);
426                 mpInsertionIndicatorHandler->UpdateIndicatorIcon(SD_MOD()->pTransferClip);
427                 mpInsertionIndicatorHandler->UpdatePosition(
428                     pWindow->PixelToLogic(rEvent.GetMousePosPixel()),
429                     InsertionIndicatorHandler::MoveMode);
430                 pContext.reset(new InsertionIndicatorHandler::ForceShowContext(
431                     mpInsertionIndicatorHandler));
432             }
433 
434             pWindow->ReleaseMouse();
435 
436             Point aMenuLocation (0,0);
437             if (rEvent.IsMouseEvent())
438             {
439                 // We have to explicitly specify the location of the menu
440                 // when the slide sorter is placed in an undocked child
441                 // menu.  But when it is docked it does not hurt, so we
442                 // specify the location always.
443                 aMenuLocation = rEvent.GetMousePosPixel();
444             }
445             else
446             {
447                 // The event is not a mouse event.  Use the center of the
448                 // focused page as top left position of the context menu.
449                 model::SharedPageDescriptor pDescriptor (
450                     GetFocusManager().GetFocusedPageDescriptor());
451                 if (pDescriptor.get() != NULL)
452                 {
453                     Rectangle aBBox (
454                         mrView.GetLayouter().GetPageObjectLayouter()->GetBoundingBox (
455                             pDescriptor,
456                             PageObjectLayouter::PageObject,
457                             PageObjectLayouter::ModelCoordinateSystem));
458                     aMenuLocation = aBBox.Center();
459                 }
460             }
461 
462             mbIsContextMenuOpen = true;
463             if (pViewShell != NULL)
464             {
465                 SfxDispatcher* pDispatcher = pViewShell->GetDispatcher();
466                 if (pDispatcher != NULL)
467                 {
468                     pDispatcher->ExecutePopup(
469                         SdResId(nPopupId),
470                         pWindow,
471                         &aMenuLocation);
472                     mrSlideSorter.GetView().UpdatePageUnderMouse(false);
473                     ::rtl::Reference<SelectionFunction> pFunction(GetCurrentSelectionFunction());
474                     if (pFunction.is())
475                         pFunction->ResetMouseAnchor();
476                 }
477             }
478             mbIsContextMenuOpen = false;
479             if (pPage == NULL)
480             {
481                 // Remember the position of the insertion indicator before
482                 // it is hidden, so that a pending slide insertion slot call
483                 // finds the right place to insert a new slide.
484                 GetSelectionManager()->SetInsertionPosition(
485                     GetInsertionIndicatorHandler()->GetInsertionPageIndex());
486             }
487             pContext.reset();
488             bEventHasBeenHandled = true;
489         }
490         break;
491 
492         case COMMAND_WHEEL:
493         {
494             const CommandWheelData* pData = rEvent.GetWheelData();
495             if (pData == NULL)
496                 return false;
497             if (pData->IsMod1())
498             {
499                 // We do not support zooming with control+mouse wheel.
500                 return false;
501             }
502             // Determine whether to scroll horizontally or vertically.  This
503             // depends on the orientation of the scroll bar and the
504             // IsHoriz() flag of the event.
505             if ((mrSlideSorter.GetView().GetOrientation()==view::Layouter::HORIZONTAL)
506                 == pData->IsHorz())
507             {
508                 GetScrollBarManager().Scroll(
509                     ScrollBarManager::Orientation_Vertical,
510                     ScrollBarManager::Unit_Slide,
511                     -pData->GetNotchDelta());
512             }
513             else
514             {
515                 GetScrollBarManager().Scroll(
516                     ScrollBarManager::Orientation_Horizontal,
517                     ScrollBarManager::Unit_Slide,
518                     -pData->GetNotchDelta());
519             }
520             mrSlideSorter.GetView().UpdatePageUnderMouse(rEvent.GetMousePosPixel(), false);
521 
522             bEventHasBeenHandled = true;
523         }
524         break;
525 	}
526 
527     return bEventHasBeenHandled;
528 }
529 
530 
531 
532 
LockModelChange(void)533 void SlideSorterController::LockModelChange (void)
534 {
535     mnModelChangeLockCount += 1;
536 }
537 
538 
539 
540 
UnlockModelChange(void)541 void SlideSorterController::UnlockModelChange (void)
542 {
543     mnModelChangeLockCount -= 1;
544     if (mnModelChangeLockCount==0 && mbPostModelChangePending)
545     {
546         PostModelChange();
547     }
548 }
549 
550 
551 
552 
PreModelChange(void)553 void SlideSorterController::PreModelChange (void)
554 {
555     // Prevent PreModelChange to execute more than once per model lock.
556     if (mbPostModelChangePending)
557         return;
558     mbPreModelChangeDone = true;
559 
560     if (mrSlideSorter.GetViewShell() != NULL)
561         mrSlideSorter.GetViewShell()->Broadcast(
562             ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START));
563 
564     GetCurrentSlideManager()->PrepareModelChange();
565 
566     if (mrSlideSorter.GetContentWindow())
567         mrView.PreModelChange();
568 
569     mbPostModelChangePending = true;
570 }
571 
572 
573 
574 
PostModelChange(void)575 void SlideSorterController::PostModelChange (void)
576 {
577     mbPostModelChangePending = false;
578     mrModel.Resync();
579 
580     SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
581     if (pWindow)
582     {
583         GetCurrentSlideManager()->HandleModelChange();
584 
585         mrView.PostModelChange ();
586 
587         pWindow->SetViewOrigin (Point (0,0));
588         pWindow->SetViewSize (mrView.GetModelArea().GetSize());
589 
590         // The visibility of the scroll bars may have to be changed.  Then
591         // the size of the view has to change, too.  Let Rearrange() handle
592         // that.
593         Rearrange(mbIsForcedRearrangePending);
594     }
595 
596     if (mrSlideSorter.GetViewShell() != NULL)
597         mrSlideSorter.GetViewShell()->Broadcast(
598             ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END));
599 }
600 
601 
602 
603 
HandleModelChange(void)604 void SlideSorterController::HandleModelChange (void)
605 {
606     // Ignore this call when the document is not in a valid state, i.e. has
607     // not the same number of regular and notes pages.
608     bool bIsDocumentValid = (mrModel.GetDocument()->GetPageCount() % 2 == 1);
609 
610     if (bIsDocumentValid)
611     {
612         ModelChangeLock aLock (*this);
613         PreModelChange();
614     }
615 }
616 
617 
618 
619 
IMPL_LINK(SlideSorterController,WindowEventHandler,VclWindowEvent *,pEvent)620 IMPL_LINK(SlideSorterController, WindowEventHandler, VclWindowEvent*, pEvent)
621 {
622     if (pEvent != NULL)
623     {
624         ::Window* pWindow = pEvent->GetWindow();
625         SharedSdWindow pActiveWindow (mrSlideSorter.GetContentWindow());
626         switch (pEvent->GetId())
627         {
628             case VCLEVENT_WINDOW_ACTIVATE:
629             case VCLEVENT_WINDOW_SHOW:
630                 if (pActiveWindow && pWindow == pActiveWindow->GetParent())
631                     mrView.RequestRepaint();
632                 break;
633 
634             case VCLEVENT_WINDOW_HIDE:
635                 if (pActiveWindow && pWindow == pActiveWindow->GetParent())
636                     mrView.SetPageUnderMouse(SharedPageDescriptor());
637                 break;
638 
639             case VCLEVENT_WINDOW_GETFOCUS:
640                 if (pActiveWindow)
641                     if (pWindow == pActiveWindow.get())
642                         GetFocusManager().ShowFocus(false);
643                 break;
644 
645             case VCLEVENT_WINDOW_LOSEFOCUS:
646                 if (pActiveWindow && pWindow == pActiveWindow.get())
647                 {
648                     GetFocusManager().HideFocus();
649                     mrView.GetToolTip().Hide();
650 
651                     // Select the current slide so that it is properly
652                     // visualized when the focus is moved to the edit view.
653                     GetPageSelector().SelectPage(GetCurrentSlideManager()->GetCurrentSlide());
654                 }
655                 break;
656 
657             case VCLEVENT_APPLICATION_DATACHANGED:
658             {
659                 // Invalidate the preview cache.
660                 cache::PageCacheManager::Instance()->InvalidateAllCaches();
661 
662                 // Update the draw mode.
663                 sal_uLong nDrawMode (Application::GetSettings().GetStyleSettings().GetHighContrastMode()
664                     ? ViewShell::OUTPUT_DRAWMODE_CONTRAST
665                     : ViewShell::OUTPUT_DRAWMODE_COLOR);
666                 if (mrSlideSorter.GetViewShell() != NULL)
667                     mrSlideSorter.GetViewShell()->GetFrameView()->SetDrawMode(nDrawMode);
668                 if( bool(pActiveWindow) )
669                     pActiveWindow->SetDrawMode(nDrawMode);
670                 mrView.HandleDrawModeChange();
671 
672                 // When the system font has changed a layout has to be done.
673                 mrView.Resize();
674                 FontProvider::Instance().Invalidate();
675 
676                 // Update theme colors.
677                 mrSlideSorter.GetProperties()->HandleDataChangeEvent();
678                 mrSlideSorter.GetTheme()->Update(mrSlideSorter.GetProperties());
679                 mrView.HandleDataChangeEvent();
680             }
681             break;
682 
683             default:
684                 break;
685         }
686     }
687 
688     return sal_True;
689 }
690 
691 
692 
693 
GetCtrlState(SfxItemSet & rSet)694 void SlideSorterController::GetCtrlState (SfxItemSet& rSet)
695 {
696 	if (rSet.GetItemState(SID_RELOAD) != SFX_ITEM_UNKNOWN)
697 	{
698 		// "Letzte Version" vom SFx en/disablen lassen
699         SfxViewFrame* pSlideViewFrame = SfxViewFrame::Current();
700 		DBG_ASSERT(pSlideViewFrame!=NULL,
701             "SlideSorterController::GetCtrlState: ViewFrame not found");
702 		if (pSlideViewFrame)
703 		{
704 			pSlideViewFrame->GetSlotState (SID_RELOAD, NULL, &rSet);
705 		}
706 		else		// MI sagt: kein MDIFrame --> disablen
707 		{
708 			rSet.DisableItem(SID_RELOAD);
709 		}
710 	}
711 
712     // Output quality.
713 	if (rSet.GetItemState(SID_OUTPUT_QUALITY_COLOR)==SFX_ITEM_AVAILABLE
714         ||rSet.GetItemState(SID_OUTPUT_QUALITY_GRAYSCALE)==SFX_ITEM_AVAILABLE
715         ||rSet.GetItemState(SID_OUTPUT_QUALITY_BLACKWHITE)==SFX_ITEM_AVAILABLE
716         ||rSet.GetItemState(SID_OUTPUT_QUALITY_CONTRAST)==SFX_ITEM_AVAILABLE)
717 	{
718 		if (mrSlideSorter.GetContentWindow())
719 		{
720 			sal_uLong nMode = mrSlideSorter.GetContentWindow()->GetDrawMode();
721 			sal_uInt16 nQuality = 0;
722 
723 			switch (nMode)
724 			{
725 				case ViewShell::OUTPUT_DRAWMODE_COLOR:
726 					nQuality = 0;
727 					break;
728 				case ViewShell::OUTPUT_DRAWMODE_GRAYSCALE:
729 					nQuality = 1;
730 					break;
731 				case ViewShell::OUTPUT_DRAWMODE_BLACKWHITE:
732 					nQuality = 2;
733 					break;
734 				case ViewShell::OUTPUT_DRAWMODE_CONTRAST:
735 					nQuality = 3;
736 					break;
737 			}
738 
739 			rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_COLOR,
740 					(sal_Bool)(nQuality==0)));
741 			rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_GRAYSCALE,
742 					(sal_Bool)(nQuality==1)));
743 			rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_BLACKWHITE,
744 					(sal_Bool)(nQuality==2)));
745 			rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_CONTRAST,
746 					(sal_Bool)(nQuality==3)));
747 		}
748 	}
749 
750 	if (rSet.GetItemState(SID_MAIL_SCROLLBODY_PAGEDOWN) == SFX_ITEM_AVAILABLE)
751 	{
752 		rSet.Put (SfxBoolItem( SID_MAIL_SCROLLBODY_PAGEDOWN, sal_True));
753 	}
754 }
755 
756 
757 
758 
GetStatusBarState(SfxItemSet & rSet)759 void SlideSorterController::GetStatusBarState (SfxItemSet& rSet)
760 {
761     mpSlotManager->GetStatusBarState (rSet);
762 }
763 
764 
765 
766 
ExecCtrl(SfxRequest & rRequest)767 void SlideSorterController::ExecCtrl (SfxRequest& rRequest)
768 {
769     mpSlotManager->ExecCtrl (rRequest);
770 }
771 
772 
773 
774 
GetAttrState(SfxItemSet & rSet)775 void SlideSorterController::GetAttrState (SfxItemSet& rSet)
776 {
777     mpSlotManager->GetAttrState (rSet);
778 }
779 
780 
781 
782 
ExecStatusBar(SfxRequest &)783 void SlideSorterController::ExecStatusBar (SfxRequest& )
784 {
785 }
786 
787 
788 
789 
UpdateAllPages(void)790 void SlideSorterController::UpdateAllPages (void)
791 {
792     // Do a redraw.
793     mrSlideSorter.GetContentWindow()->Invalidate();
794 }
795 
796 
797 
798 
Resize(const Rectangle & rAvailableSpace)799 Rectangle SlideSorterController::Resize (const Rectangle& rAvailableSpace)
800 {
801     Rectangle aContentArea (rAvailableSpace);
802 
803     if (maTotalWindowArea != rAvailableSpace)
804     {
805         maTotalWindowArea = rAvailableSpace;
806         aContentArea = Rearrange(true);
807     }
808 
809     return aContentArea;
810 }
811 
812 
813 
814 
Rearrange(bool bForce)815 Rectangle  SlideSorterController::Rearrange (bool bForce)
816 {
817     Rectangle aNewContentArea (maTotalWindowArea);
818 
819     if (aNewContentArea.IsEmpty())
820         return aNewContentArea;
821 
822     if (mnModelChangeLockCount>0)
823     {
824         mbIsForcedRearrangePending |= bForce;
825         return aNewContentArea;
826     }
827     else
828         mbIsForcedRearrangePending = false;
829 
830     SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
831     if (pWindow)
832     {
833         if (bForce)
834             mrView.UpdateOrientation();
835 
836         // Place the scroll bars.
837         aNewContentArea = GetScrollBarManager().PlaceScrollBars(
838             maTotalWindowArea,
839             mrView.GetOrientation() != view::Layouter::VERTICAL,
840             mrView.GetOrientation() != view::Layouter::HORIZONTAL);
841 
842         bool bSizeHasChanged (false);
843         // Only when bForce is not true we have to test for a size change in
844         // order to determine whether the window and the view have to be resized.
845         if ( ! bForce)
846         {
847             Rectangle aCurrentContentArea (pWindow->GetPosPixel(), pWindow->GetOutputSizePixel());
848             bSizeHasChanged = (aNewContentArea != aCurrentContentArea);
849         }
850         if (bForce || bSizeHasChanged)
851         {
852             // The browser window gets the remaining space.
853             pWindow->SetPosSizePixel (aNewContentArea.TopLeft(), aNewContentArea.GetSize());
854             mrView.Resize();
855         }
856 
857         // Adapt the scroll bars to the new zoom factor of the browser
858         // window and the arrangement of the page objects.
859         GetScrollBarManager().UpdateScrollBars(false, !bForce);
860 
861         // Keep the current slide in the visible area.
862         GetVisibleAreaManager().RequestCurrentSlideVisible();
863 
864         mrView.RequestRepaint();
865     }
866 
867     return aNewContentArea;
868 }
869 
870 
871 
872 
CreateSelectionFunction(SfxRequest & rRequest)873 FunctionReference SlideSorterController::CreateSelectionFunction (SfxRequest& rRequest)
874 {
875 	FunctionReference xFunc( SelectionFunction::Create(mrSlideSorter, rRequest) );
876     return xFunc;
877 }
878 
879 
880 
881 
GetCurrentSelectionFunction(void)882 ::rtl::Reference<SelectionFunction> SlideSorterController::GetCurrentSelectionFunction (void)
883 {
884 	FunctionReference pFunction (mrSlideSorter.GetViewShell()->GetCurrentFunction());
885     return ::rtl::Reference<SelectionFunction>(dynamic_cast<SelectionFunction*>(pFunction.get()));
886 }
887 
888 
889 
890 
PrepareEditModeChange(void)891 void SlideSorterController::PrepareEditModeChange (void)
892 {
893     //  Before we throw away the page descriptors we prepare for selecting
894     //  descriptors in the other mode and for restoring the current
895     //  selection when switching back to the current mode.
896     if (mrModel.GetEditMode() == EM_PAGE)
897     {
898         maSelectionBeforeSwitch.clear();
899 
900         // Search for the first selected page and determine the master page
901         // used by its page object.  It will be selected after the switch.
902         // In the same loop the current selection is stored.
903         PageEnumeration aSelectedPages (
904             PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
905         while (aSelectedPages.HasMoreElements())
906         {
907             SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
908             SdPage* pPage = pDescriptor->GetPage();
909             // Remember the master page of the first selected descriptor.
910             if (pPage!=NULL && mpEditModeChangeMasterPage==NULL)
911                 mpEditModeChangeMasterPage = &static_cast<SdPage&>(
912                     pPage->TRG_GetMasterPage());
913 
914             maSelectionBeforeSwitch.push_back(pPage);
915         }
916 
917         // Remember the current page.
918         if (mrSlideSorter.GetViewShell() != NULL)
919             mnCurrentPageBeforeSwitch = (mrSlideSorter.GetViewShell()->GetViewShellBase()
920             .GetMainViewShell()->GetActualPage()->GetPageNum()-1)/2;
921     }
922 }
923 
924 
925 
926 
ChangeEditMode(EditMode eEditMode)927 bool SlideSorterController::ChangeEditMode (EditMode eEditMode)
928 {
929     bool bResult (false);
930     if (mrModel.GetEditMode() != eEditMode)
931     {
932         ModelChangeLock aLock (*this);
933         PreModelChange();
934         // Do the actual edit mode switching.
935         bResult = mrModel.SetEditMode(eEditMode);
936         if (bResult)
937             HandleModelChange();
938     }
939     return bResult;
940 }
941 
942 
943 
944 
FinishEditModeChange(void)945 void SlideSorterController::FinishEditModeChange (void)
946 {
947     if (mrModel.GetEditMode() == EM_MASTERPAGE)
948     {
949         mpPageSelector->DeselectAllPages();
950 
951         // Search for the master page that was determined in
952         // PrepareEditModeChange() and make it the current page.
953         PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
954         while (aAllPages.HasMoreElements())
955         {
956             SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
957             if (pDescriptor->GetPage() == mpEditModeChangeMasterPage)
958             {
959                 GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
960                 mpPageSelector->SelectPage(pDescriptor);
961                 break;
962             }
963         }
964     }
965     else
966     {
967         PageSelector::BroadcastLock aBroadcastLock (*mpPageSelector);
968 
969         SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(mnCurrentPageBeforeSwitch));
970         GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
971 
972         // Restore the selection.
973         mpPageSelector->DeselectAllPages();
974         ::std::vector<SdPage*>::iterator iPage;
975         for (iPage=maSelectionBeforeSwitch.begin();
976              iPage!=maSelectionBeforeSwitch.end();
977              ++iPage)
978         {
979             mpPageSelector->SelectPage(*iPage);
980         }
981         maSelectionBeforeSwitch.clear( );
982     }
983     mpEditModeChangeMasterPage = NULL;
984 }
985 
986 
987 
988 
PageNameHasChanged(int nPageIndex,const String & rsOldName)989 void SlideSorterController::PageNameHasChanged (int nPageIndex, const String& rsOldName)
990 {
991     // Request a repaint for the page object whose name has changed.
992     model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
993     if (pDescriptor.get() != NULL)
994         mrView.RequestRepaint(pDescriptor);
995 
996     // Get a pointer to the corresponding accessible object and notify
997     // that of the name change.
998     do
999     {
1000         SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
1001         if ( ! pWindow)
1002             break;
1003 
1004         ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
1005             xAccessible (pWindow->GetAccessible(sal_False));
1006         if ( ! xAccessible.is())
1007             break;
1008 
1009         // Now comes a small hack.  We assume that the accessible object is
1010         // an instantiation of AccessibleSlideSorterView and cast it to that
1011         // class.  The cleaner alternative to this cast would be a new member
1012         // in which we would store the last AccessibleSlideSorterView object
1013         // created by SlideSorterViewShell::CreateAccessibleDocumentView().
1014         // But then there is no guaranty that the accessible object obtained
1015         // from the window really is that instance last created by
1016         // CreateAccessibleDocumentView().
1017         // However, the dynamic cast together with the check of the result
1018         // being NULL should be safe enough.
1019         ::accessibility::AccessibleSlideSorterView* pAccessibleView
1020               = dynamic_cast< ::accessibility::AccessibleSlideSorterView*>(xAccessible.get());
1021         if (pAccessibleView == NULL)
1022             break;
1023 
1024         ::accessibility::AccessibleSlideSorterObject* pChild
1025               = pAccessibleView->GetAccessibleChildImplementation(nPageIndex);
1026         if (pChild == NULL || pChild->GetPage() == NULL)
1027             break;
1028 
1029         ::rtl::OUString sOldName (rsOldName);
1030         ::rtl::OUString sNewName (pChild->GetPage()->GetName());
1031         pChild->FireAccessibleEvent(
1032             ::com::sun::star::accessibility::AccessibleEventId::NAME_CHANGED,
1033             makeAny(sOldName),
1034             makeAny(sNewName));
1035     }
1036     while (false);
1037 }
1038 
1039 
1040 
1041 
IsContextMenuOpen(void) const1042 bool SlideSorterController::IsContextMenuOpen (void) const
1043 {
1044     return mbIsContextMenuOpen;
1045 }
1046 
1047 
1048 
1049 
SetDocumentSlides(const Reference<container::XIndexAccess> & rxSlides)1050 void SlideSorterController::SetDocumentSlides (const Reference<container::XIndexAccess>& rxSlides)
1051 {
1052     if (mrModel.GetDocumentSlides() != rxSlides)
1053     {
1054         ModelChangeLock aLock (*this);
1055         PreModelChange();
1056 
1057         mrModel.SetDocumentSlides(rxSlides);
1058     }
1059 }
1060 
1061 
1062 
1063 
GetAnimator(void) const1064 ::boost::shared_ptr<Animator> SlideSorterController::GetAnimator (void) const
1065 {
1066     return mpAnimator;
1067 }
1068 
1069 
1070 
1071 
GetVisibleAreaManager(void) const1072 VisibleAreaManager& SlideSorterController::GetVisibleAreaManager (void) const
1073 {
1074     OSL_ASSERT(mpVisibleAreaManager);
1075     return *mpVisibleAreaManager;
1076 }
1077 
1078 
1079 
1080 
CheckForMasterPageAssignment(void)1081 void SlideSorterController::CheckForMasterPageAssignment (void)
1082 {
1083     if (mrModel.GetPageCount()%2==0)
1084         return;
1085     PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
1086     while (aAllPages.HasMoreElements())
1087     {
1088         SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
1089         if (pDescriptor->UpdateMasterPage())
1090         {
1091             mrView.GetPreviewCache()->InvalidatePreviewBitmap (
1092                 pDescriptor->GetPage(),
1093                 true);
1094         }
1095     }
1096 }
1097 
1098 
1099 
1100 
CheckForSlideTransitionAssignment(void)1101 void SlideSorterController::CheckForSlideTransitionAssignment (void)
1102 {
1103     if (mrModel.GetPageCount()%2==0)
1104         return;
1105     PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
1106     while (aAllPages.HasMoreElements())
1107     {
1108         SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
1109         if (pDescriptor->UpdateTransitionFlag())
1110         {
1111             mrView.GetPreviewCache()->InvalidatePreviewBitmap (
1112                 pDescriptor->GetPage(),
1113                 true);
1114         }
1115     }
1116 }
1117 
1118 
1119 
1120 
1121 //===== SlideSorterController::ModelChangeLock ================================
1122 
ModelChangeLock(SlideSorterController & rController)1123 SlideSorterController::ModelChangeLock::ModelChangeLock (
1124     SlideSorterController& rController)
1125     : mpController(&rController)
1126 {
1127     mpController->LockModelChange();
1128 }
1129 
1130 
1131 
1132 
~ModelChangeLock(void)1133 SlideSorterController::ModelChangeLock::~ModelChangeLock (void)
1134 {
1135     Release();
1136 }
1137 
1138 
1139 
1140 
Release(void)1141 void SlideSorterController::ModelChangeLock::Release (void)
1142 {
1143     if (mpController != NULL)
1144     {
1145         mpController->UnlockModelChange();
1146         mpController = NULL;
1147     }
1148 }
1149 
1150 } } } // end of namespace ::sd::slidesorter
1151