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