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 :
21 : #include "view/SlideSorterView.hxx"
22 :
23 : #include "ViewShellBase.hxx"
24 : #include "SlideSorter.hxx"
25 : #include "SlideSorterViewShell.hxx"
26 : #include "ViewShell.hxx"
27 : #include "SlsViewCacheContext.hxx"
28 : #include "SlsLayeredDevice.hxx"
29 : #include "view/SlsLayouter.hxx"
30 : #include "view/SlsPageObjectLayouter.hxx"
31 : #include "view/SlsPageObjectPainter.hxx"
32 : #include "view/SlsILayerPainter.hxx"
33 : #include "view/SlsToolTip.hxx"
34 : #include "controller/SlideSorterController.hxx"
35 : #include "controller/SlsProperties.hxx"
36 : #include "controller/SlsClipboard.hxx"
37 : #include "model/SlideSorterModel.hxx"
38 : #include "model/SlsPageEnumerationProvider.hxx"
39 : #include "model/SlsPageDescriptor.hxx"
40 : #include "cache/SlsPageCache.hxx"
41 : #include "cache/SlsPageCacheManager.hxx"
42 : #include "cache/SlsCacheContext.hxx"
43 : #include "taskpane/SlideSorterCacheDisplay.hxx"
44 : #include "DrawDocShell.hxx"
45 : #include "PaneDockingWindow.hxx"
46 :
47 : #include "drawdoc.hxx"
48 : #include "sdpage.hxx"
49 : #include "Window.hxx"
50 : #include "sdresid.hxx"
51 : #include "glob.hrc"
52 :
53 : #include <svl/itempool.hxx>
54 : #include <svx/svdpagv.hxx>
55 : #include <svx/svdopage.hxx>
56 : #include <svx/xlndsit.hxx>
57 : #include <svx/xlnclit.hxx>
58 : #include <vcl/svapp.hxx>
59 : #include <vcl/scrbar.hxx>
60 : #include <vcl/settings.hxx>
61 :
62 : #include <tools/poly.hxx>
63 : #include <vcl/lineinfo.hxx>
64 : #include <algorithm>
65 : #include <svx/sdrpagewindow.hxx>
66 : #include <basegfx/matrix/b2dhommatrix.hxx>
67 : #include <basegfx/polygon/b2dpolygontools.hxx>
68 : #include <basegfx/polygon/b2dpolygon.hxx>
69 : #include <drawinglayer/geometry/viewinformation2d.hxx>
70 : #include <canvas/elapsedtime.hxx>
71 :
72 : //#define DEBUG_TIMING
73 : #ifdef DEBUG_TIMING
74 : #include <vector>
75 : #endif
76 : #include <boost/foreach.hpp>
77 :
78 :
79 : using namespace std;
80 : using namespace ::sd::slidesorter::model;
81 : using namespace ::drawinglayer::primitive2d;
82 :
83 :
84 : namespace sd { namespace slidesorter { namespace view {
85 :
86 : namespace {
87 : /** Wrapper around the SlideSorterView that supports the IPainter
88 : interface and that allows the LayeredDevice to hold the
89 : SlideSorterView (held as scoped_ptr by the SlideSorter) as
90 : shared_ptr.
91 : */
92 : class Painter : public ILayerPainter
93 : {
94 : public:
95 0 : Painter (SlideSorterView& rView) : mrView(rView) {}
96 0 : virtual ~Painter (void) {}
97 :
98 0 : virtual void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea) SAL_OVERRIDE
99 : {
100 0 : mrView.Paint(rDevice,rRepaintArea);
101 0 : }
102 :
103 0 : virtual void SetLayerInvalidator (const SharedILayerInvalidator&) SAL_OVERRIDE {}
104 :
105 : private:
106 : SlideSorterView& mrView;
107 : };
108 : }
109 :
110 :
111 :
112 : class BackgroundPainter
113 : : public ILayerPainter,
114 : public ::boost::noncopyable
115 : {
116 : public:
117 0 : BackgroundPainter (const Color aBackgroundColor) : maBackgroundColor(aBackgroundColor) {}
118 0 : virtual ~BackgroundPainter (void) {}
119 :
120 0 : virtual void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea) SAL_OVERRIDE
121 : {
122 0 : rDevice.SetFillColor(maBackgroundColor);
123 0 : rDevice.SetLineColor();
124 0 : rDevice.DrawRect(rRepaintArea);
125 0 : }
126 :
127 0 : virtual void SetLayerInvalidator (const SharedILayerInvalidator&) SAL_OVERRIDE {}
128 :
129 0 : void SetColor (const Color aColor) { maBackgroundColor = aColor; }
130 :
131 : private:
132 : Color maBackgroundColor;
133 : };
134 :
135 :
136 :
137 0 : TYPEINIT1(SlideSorterView, ::sd::View);
138 :
139 0 : SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter)
140 : : ::sd::View (
141 0 : *rSlideSorter.GetModel().GetDocument(),
142 0 : rSlideSorter.GetContentWindow().get(),
143 : rSlideSorter.GetViewShell()),
144 : mrSlideSorter(rSlideSorter),
145 0 : mrModel(rSlideSorter.GetModel()),
146 : mbIsDisposed(false),
147 0 : mpLayouter (new Layouter(rSlideSorter.GetContentWindow(), rSlideSorter.GetTheme())),
148 : mbPageObjectVisibilitiesValid (false),
149 : mpPreviewCache(),
150 0 : mpLayeredDevice(new LayeredDevice(rSlideSorter.GetContentWindow())),
151 : maVisiblePageRange(-1,-1),
152 : mbModelChangedWhileModifyEnabled(true),
153 : maPreviewSize(0,0),
154 : mbPreciousFlagUpdatePending(true),
155 : meOrientation(Layouter::GRID),
156 : mpProperties(rSlideSorter.GetProperties()),
157 : mpPageUnderMouse(),
158 : mnButtonUnderMouse(-1),
159 : mpPageObjectPainter(),
160 : mpSelectionPainter(),
161 : mpBackgroundPainter(
162 0 : new BackgroundPainter(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background))),
163 0 : mpToolTip(new ToolTip(mrSlideSorter)),
164 : mbIsRearrangePending(true),
165 0 : maVisibilityChangeListeners()
166 : {
167 : // Hide the page that contains the page objects.
168 0 : SetPageVisible (false);
169 :
170 : // Register the background painter on level 1 to avoid the creation of a
171 : // background buffer.
172 0 : mpLayeredDevice->RegisterPainter(mpBackgroundPainter, 1);
173 :
174 : // Wrap a shared_ptr-held-wrapper around this view and register it as
175 : // painter at the layered device. There is no explicit destruction: in
176 : // the SlideSorterView destructor the layered device is destroyed and
177 : // with it the only reference to the wrapper which therefore is also
178 : // destroyed.
179 0 : SharedILayerPainter pPainter (new Painter(*this));
180 :
181 : // The painter is placed on level 1 to avoid buffering. This should be
182 : // a little faster during animations because the previews are painted
183 : // directly into the window, not via the buffer.
184 0 : mpLayeredDevice->RegisterPainter(pPainter, 1);
185 0 : }
186 :
187 :
188 :
189 :
190 0 : SlideSorterView::~SlideSorterView (void)
191 : {
192 0 : if ( ! mbIsDisposed)
193 : {
194 : OSL_ASSERT(mbIsDisposed);
195 0 : Dispose();
196 : }
197 0 : }
198 :
199 :
200 :
201 :
202 0 : void SlideSorterView::Init (void)
203 : {
204 0 : HandleModelChange();
205 0 : }
206 :
207 :
208 :
209 :
210 0 : void SlideSorterView::Dispose (void)
211 : {
212 0 : mpSelectionPainter.reset();
213 :
214 0 : mpLayeredDevice->Dispose();
215 0 : mpPreviewCache.reset();
216 :
217 0 : SetPageUnderMouse(SharedPageDescriptor());
218 :
219 : // Hide the page to avoid problems in the view when deleting
220 : // visualized objects
221 0 : HideSdrPage();
222 :
223 : // Deletion of the objects and the page will be done in SdrModel
224 : // destructor (as long as objects and pages are added)
225 :
226 : OSL_ASSERT(mpLayeredDevice.unique());
227 0 : mpLayeredDevice.reset();
228 :
229 0 : mbIsDisposed = true;
230 0 : }
231 :
232 :
233 :
234 :
235 0 : sal_Int32 SlideSorterView::GetPageIndexAtPoint (const Point& rWindowPosition) const
236 : {
237 0 : sal_Int32 nIndex (-1);
238 :
239 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
240 0 : if (pWindow)
241 : {
242 0 : nIndex = mpLayouter->GetIndexAtPoint(pWindow->PixelToLogic(rWindowPosition), false, false);
243 :
244 : // Clip the page index against the page count.
245 0 : if (nIndex >= mrModel.GetPageCount())
246 0 : nIndex = -1;
247 : }
248 :
249 0 : return nIndex;
250 : }
251 :
252 :
253 :
254 :
255 0 : Layouter& SlideSorterView::GetLayouter (void)
256 : {
257 0 : return *mpLayouter.get();
258 : }
259 :
260 :
261 :
262 :
263 0 : void SlideSorterView::ModelHasChanged (void)
264 : {
265 : // Ignore this call. Rely on hints sent by the model to get informed of
266 : // model changes.
267 0 : }
268 :
269 :
270 :
271 :
272 0 : void SlideSorterView::PreModelChange (void)
273 : {
274 : // Reset the slide under the mouse. It will be re-set in PostModelChange().
275 0 : SetPageUnderMouse(SharedPageDescriptor());
276 0 : }
277 :
278 :
279 :
280 :
281 0 : void SlideSorterView::PostModelChange (void)
282 : {
283 : // In PreModelChange() the page objects have been released. Here we
284 : // create new ones.
285 0 : ::osl::MutexGuard aGuard (mrModel.GetMutex());
286 :
287 : model::PageEnumeration aPageEnumeration (
288 0 : model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
289 :
290 : // The new page objects have to be scaled and positioned.
291 0 : RequestRearrange();
292 0 : RequestRepaint();
293 0 : }
294 :
295 :
296 :
297 :
298 : /** At the moment for every model change all page objects are destroyed and
299 : re-created again. This can be optimized by accepting hints that
300 : describe the type of change so that existing page objects can be
301 : reused.
302 : */
303 0 : void SlideSorterView::HandleModelChange (void)
304 : {
305 0 : PreModelChange ();
306 0 : PostModelChange();
307 0 : }
308 :
309 :
310 :
311 :
312 0 : void SlideSorterView::HandleDrawModeChange (void)
313 : {
314 : // Replace the preview cache with a new and empty one. The
315 : // PreviewRenderer that is used by the cache is replaced by this as
316 : // well.
317 0 : mpPreviewCache.reset();
318 0 : GetPreviewCache()->InvalidateCache(true);
319 :
320 0 : RequestRepaint();
321 0 : }
322 :
323 :
324 :
325 :
326 0 : void SlideSorterView::HandleDataChangeEvent (void)
327 : {
328 0 : GetPageObjectPainter()->SetTheme(mrSlideSorter.GetTheme());
329 :
330 : // Update the color used by the background painter.
331 : ::boost::shared_ptr<BackgroundPainter> pPainter (
332 0 : ::boost::dynamic_pointer_cast<BackgroundPainter>(mpBackgroundPainter));
333 0 : if (pPainter)
334 0 : pPainter->SetColor(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background));
335 :
336 0 : RequestRepaint();
337 0 : }
338 :
339 :
340 :
341 :
342 0 : void SlideSorterView::Resize (void)
343 : {
344 0 : UpdateOrientation();
345 :
346 0 : mpLayeredDevice->Resize();
347 0 : RequestRearrange();
348 0 : }
349 :
350 :
351 :
352 :
353 0 : void SlideSorterView::RequestRearrange (void)
354 : {
355 0 : mbIsRearrangePending = true;
356 0 : Rearrange();
357 0 : }
358 :
359 :
360 :
361 :
362 0 : void SlideSorterView::Rearrange (void)
363 : {
364 0 : if ( ! mbIsRearrangePending)
365 0 : return;
366 0 : if (mrModel.GetPageCount() <= 0)
367 0 : return;
368 :
369 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
370 0 : if ( ! pWindow)
371 0 : return;
372 0 : const Size aWindowSize (pWindow->GetSizePixel());
373 0 : if (aWindowSize.Width()<=0 || aWindowSize.Height()<=0)
374 0 : return;
375 :
376 : const bool bRearrangeSuccess (
377 : mpLayouter->Rearrange (
378 : meOrientation,
379 : aWindowSize,
380 0 : mrModel.GetPageDescriptor(0)->GetPage()->GetSize(),
381 0 : mrModel.GetPageCount()));
382 0 : if (bRearrangeSuccess)
383 : {
384 0 : mbIsRearrangePending = false;
385 0 : Layout();
386 0 : UpdatePageUnderMouse();
387 : // RequestRepaint();
388 0 : }
389 : }
390 :
391 :
392 :
393 :
394 0 : void SlideSorterView::UpdateOrientation (void)
395 : {
396 : // The layout of slides depends on whether the slide sorter is
397 : // displayed in the center or the side pane.
398 0 : if (mrSlideSorter.GetViewShell()->IsMainViewShell())
399 0 : SetOrientation(Layouter::GRID);
400 : else
401 : {
402 : // Get access to the docking window.
403 0 : ::Window* pWindow = mrSlideSorter.GetContentWindow().get();
404 0 : PaneDockingWindow* pDockingWindow = NULL;
405 0 : while (pWindow!=NULL && pDockingWindow==NULL)
406 : {
407 0 : pDockingWindow = dynamic_cast<PaneDockingWindow*>(pWindow);
408 0 : pWindow = pWindow->GetParent();
409 : }
410 :
411 0 : if (pDockingWindow != NULL)
412 : {
413 : const long nScrollBarSize (
414 0 : Application::GetSettings().GetStyleSettings().GetScrollBarSize());
415 0 : switch (pDockingWindow->GetOrientation())
416 : {
417 : case PaneDockingWindow::HorizontalOrientation:
418 0 : if (SetOrientation(Layouter::HORIZONTAL))
419 : {
420 0 : const Range aRange (mpLayouter->GetValidVerticalSizeRange());
421 : pDockingWindow->SetValidSizeRange(Range(
422 0 : aRange.Min() + nScrollBarSize,
423 0 : aRange.Max() + nScrollBarSize));
424 : }
425 0 : break;
426 :
427 : case PaneDockingWindow::VerticalOrientation:
428 0 : if (SetOrientation(Layouter::VERTICAL))
429 : {
430 0 : const Range aRange (mpLayouter->GetValidHorizontalSizeRange());
431 : pDockingWindow->SetValidSizeRange(Range(
432 0 : aRange.Min() + nScrollBarSize,
433 0 : aRange.Max() + nScrollBarSize));
434 : }
435 0 : break;
436 :
437 : case PaneDockingWindow::UnknownOrientation:
438 0 : if (SetOrientation(Layouter::GRID))
439 : {
440 0 : const sal_Int32 nAdditionalSize (10);
441 : pDockingWindow->SetMinOutputSizePixel(Size(
442 0 : mpLayouter->GetValidHorizontalSizeRange().Min()
443 0 : + nScrollBarSize
444 : + nAdditionalSize,
445 0 : mpLayouter->GetValidVerticalSizeRange().Min()
446 0 : + nScrollBarSize
447 0 : + nAdditionalSize));
448 : }
449 0 : return;
450 : }
451 : }
452 : else
453 : {
454 : // We are not placed in a docking window. One possible reason
455 : // is that the slide sorter is temporarily into a cache and was
456 : // reparented to a non-docking window.
457 0 : SetOrientation(Layouter::GRID);
458 : }
459 : }
460 : }
461 :
462 :
463 :
464 :
465 0 : void SlideSorterView::Layout ()
466 : {
467 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
468 0 : if (pWindow)
469 : {
470 : // Set the model area, i.e. the smallest rectangle that includes all
471 : // page objects.
472 0 : const Rectangle aViewBox (mpLayouter->GetTotalBoundingBox());
473 0 : pWindow->SetViewOrigin (aViewBox.TopLeft());
474 0 : pWindow->SetViewSize (aViewBox.GetSize());
475 :
476 : ::boost::shared_ptr<PageObjectLayouter> pPageObjectLayouter(
477 0 : mpLayouter->GetPageObjectLayouter());
478 0 : if (pPageObjectLayouter)
479 : {
480 : const Size aNewPreviewSize (mpLayouter->GetPageObjectLayouter()->GetSize(
481 : PageObjectLayouter::Preview,
482 0 : PageObjectLayouter::WindowCoordinateSystem));
483 0 : if (maPreviewSize != aNewPreviewSize && GetPreviewCache())
484 : {
485 0 : mpPreviewCache->ChangeSize(aNewPreviewSize, false);
486 0 : maPreviewSize = aNewPreviewSize;
487 : }
488 : }
489 :
490 : // Iterate over all page objects and place them relative to the
491 : // containing page.
492 : model::PageEnumeration aPageEnumeration (
493 0 : model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
494 0 : while (aPageEnumeration.HasMoreElements())
495 : {
496 0 : model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
497 0 : pDescriptor->SetBoundingBox(mpLayouter->GetPageObjectBox(pDescriptor->GetPageIndex()));
498 0 : }
499 :
500 0 : GetPageObjectPainter()->NotifyResize();
501 : }
502 :
503 0 : InvalidatePageObjectVisibilities ();
504 0 : }
505 :
506 :
507 :
508 :
509 0 : void SlideSorterView::InvalidatePageObjectVisibilities (void)
510 : {
511 0 : mbPageObjectVisibilitiesValid = false;
512 0 : }
513 :
514 :
515 :
516 :
517 0 : void SlideSorterView::DeterminePageObjectVisibilities (void)
518 : {
519 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
520 0 : if (pWindow)
521 : {
522 : // Set this flag to true here so that an invalidate during the
523 : // visibility calculation can correctly invalidate it again.
524 0 : mbPageObjectVisibilitiesValid = true;
525 :
526 0 : Rectangle aViewArea (pWindow->PixelToLogic(Rectangle(Point(0,0),pWindow->GetSizePixel())));
527 0 : const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(aViewArea));
528 : const Range aUnion(
529 0 : ::std::min(maVisiblePageRange.Min(), aRange.Min()),
530 0 : ::std::max(maVisiblePageRange.Max(), aRange.Max()));
531 :
532 : // For page objects that just dropped off the visible area we
533 : // decrease the priority of pending requests for preview bitmaps.
534 0 : if (maVisiblePageRange != aRange)
535 0 : mbPreciousFlagUpdatePending |= true;
536 :
537 0 : model::SharedPageDescriptor pDescriptor;
538 0 : for (int nIndex=aUnion.Min(); nIndex<=aUnion.Max(); nIndex++)
539 : {
540 0 : pDescriptor = mrModel.GetPageDescriptor(nIndex);
541 0 : if (pDescriptor.get() != NULL)
542 : SetState(
543 : pDescriptor,
544 : PageDescriptor::ST_Visible,
545 0 : aRange.IsInside(nIndex));
546 : }
547 :
548 : // Broadcast a change of the set of visible page objects.
549 0 : if (maVisiblePageRange != aRange)
550 : {
551 0 : maVisiblePageRange = aRange;
552 :
553 : // Tell the listeners that the visibility of some objects has
554 : // changed.
555 0 : ::std::vector<Link>& aChangeListeners (maVisibilityChangeListeners);
556 0 : for (::std::vector<Link>::const_iterator
557 0 : iLink(aChangeListeners.begin()),
558 0 : iEnd(aChangeListeners.end());
559 : iLink!=iEnd;
560 : ++iLink)
561 : {
562 0 : iLink->Call(NULL);
563 : }
564 : }
565 :
566 :
567 : // Restore the mouse over state.
568 0 : UpdatePageUnderMouse();
569 0 : }
570 0 : }
571 :
572 :
573 :
574 :
575 0 : void SlideSorterView::UpdatePreciousFlags (void)
576 : {
577 0 : if (mbPreciousFlagUpdatePending)
578 : {
579 0 : mbPreciousFlagUpdatePending = false;
580 :
581 0 : model::SharedPageDescriptor pDescriptor;
582 0 : ::boost::shared_ptr<cache::PageCache> pCache = GetPreviewCache();
583 0 : sal_Int32 nPageCount (mrModel.GetPageCount());
584 :
585 0 : for (int nIndex=0; nIndex<=nPageCount; ++nIndex)
586 : {
587 0 : pDescriptor = mrModel.GetPageDescriptor(nIndex);
588 0 : if (pDescriptor.get() != NULL)
589 : {
590 : pCache->SetPreciousFlag(
591 0 : pDescriptor->GetPage(),
592 0 : maVisiblePageRange.IsInside(nIndex));
593 : SSCD_SET_VISIBILITY(mrModel.GetDocument(), nIndex,
594 : maVisiblePageRange.IsInside(nIndex));
595 : }
596 : else
597 : {
598 : // At least one cache entry can not be updated. Remember to
599 : // repeat the whole updating later and leave the loop now.
600 0 : mbPreciousFlagUpdatePending = true;
601 0 : break;
602 : }
603 0 : }
604 : }
605 0 : }
606 :
607 :
608 :
609 :
610 0 : bool SlideSorterView::SetOrientation (const Layouter::Orientation eOrientation)
611 : {
612 0 : if (meOrientation != eOrientation)
613 : {
614 0 : meOrientation = eOrientation;
615 0 : return true;
616 : }
617 : else
618 0 : return false;
619 : }
620 :
621 :
622 :
623 :
624 0 : Layouter::Orientation SlideSorterView::GetOrientation (void) const
625 : {
626 0 : return meOrientation;
627 : }
628 :
629 :
630 :
631 :
632 0 : void SlideSorterView::RequestRepaint (void)
633 : {
634 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
635 0 : if (pWindow)
636 : {
637 : mpLayeredDevice->InvalidateAllLayers(
638 : Rectangle(
639 0 : pWindow->PixelToLogic(Point(0,0)),
640 0 : pWindow->PixelToLogic(pWindow->GetSizePixel())));
641 0 : pWindow->Invalidate();
642 0 : }
643 0 : }
644 :
645 :
646 :
647 :
648 0 : void SlideSorterView::RequestRepaint (const model::SharedPageDescriptor& rpDescriptor)
649 : {
650 0 : if (rpDescriptor)
651 0 : RequestRepaint(rpDescriptor->GetBoundingBox());
652 0 : }
653 :
654 :
655 :
656 :
657 0 : void SlideSorterView::RequestRepaint (const Rectangle& rRepaintBox)
658 : {
659 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
660 0 : if (pWindow)
661 : {
662 0 : mpLayeredDevice->InvalidateAllLayers(rRepaintBox);
663 0 : pWindow->Invalidate(rRepaintBox);
664 0 : }
665 0 : }
666 :
667 :
668 :
669 0 : void SlideSorterView::RequestRepaint (const Region& rRepaintRegion)
670 : {
671 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
672 0 : if (pWindow)
673 : {
674 0 : mpLayeredDevice->InvalidateAllLayers(rRepaintRegion);
675 0 : pWindow->Invalidate(rRepaintRegion);
676 0 : }
677 0 : }
678 :
679 :
680 :
681 :
682 0 : Rectangle SlideSorterView::GetModelArea (void)
683 : {
684 0 : return mpLayouter->GetTotalBoundingBox();
685 : }
686 :
687 :
688 : #ifdef DEBUG_TIMING
689 : static ::canvas::tools::ElapsedTime gaTimer;
690 : static const size_t gFrameTimeCount (10);
691 : static size_t gFrameTimeIndex (0);
692 : static ::std::vector<double> gFrameTimes (gFrameTimeCount, 0);
693 : static double gFrameTimeSum (0);
694 : static const Rectangle gFrameTimeBox (10,10,150,20);
695 : static double gnLastFrameStart = 0;
696 : #endif
697 :
698 0 : void SlideSorterView::CompleteRedraw (
699 : OutputDevice* pDevice,
700 : const Region& rPaintArea,
701 : sdr::contact::ViewObjectContactRedirector* pRedirector)
702 : {
703 : (void)pRedirector;
704 : #ifdef DEBUG_TIMING
705 : const double nStartTime (gaTimer.getElapsedTime());
706 : OSL_TRACE("SlideSorterView::CompleteRedraw start at %f, %s",
707 : nStartTime,
708 : mnLockRedrawSmph ? "locked" : "");
709 : #endif
710 :
711 0 : if (pDevice == NULL || pDevice!=mrSlideSorter.GetContentWindow().get())
712 0 : return;
713 :
714 : // The parent implementation of CompleteRedraw is called only when
715 : // painting is locked. We do all the painting ourself. When painting
716 : // is locked the parent implementation keeps track of the repaint
717 : // requests and later, when painting is unlocked, calls CompleteRedraw
718 : // for all missed repaints.
719 :
720 0 : if (mnLockRedrawSmph == 0)
721 : {
722 0 : mrSlideSorter.GetContentWindow()->IncrementLockCount();
723 0 : if (mpLayeredDevice->HandleMapModeChange())
724 0 : DeterminePageObjectVisibilities();
725 0 : mpLayeredDevice->Repaint(rPaintArea);
726 0 : mrSlideSorter.GetContentWindow()->DecrementLockCount();
727 : }
728 : else
729 : {
730 0 : maRedrawRegion.Union(rPaintArea);
731 : }
732 :
733 : #ifdef DEBUG_TIMING
734 : const double nEndTime (gaTimer.getElapsedTime());
735 : OSL_TRACE("SlideSorterView::CompleteRedraw end at %f after %fms", nEndTime, (nEndTime-nStartTime)*1000);
736 : gFrameTimeSum -= gFrameTimes[gFrameTimeIndex];
737 : gFrameTimes[gFrameTimeIndex] = nStartTime - gnLastFrameStart;
738 : gnLastFrameStart = nStartTime;
739 : gFrameTimeSum += gFrameTimes[gFrameTimeIndex];
740 : gFrameTimeIndex = (gFrameTimeIndex+1) % gFrameTimeCount;
741 :
742 :
743 : mrSlideSorter.GetContentWindow()->SetFillColor(COL_BLUE);
744 : mrSlideSorter.GetContentWindow()->DrawRect(gFrameTimeBox);
745 : mrSlideSorter.GetContentWindow()->SetTextColor(COL_WHITE);
746 : mrSlideSorter.GetContentWindow()->DrawText(
747 : gFrameTimeBox,
748 : OUString::number(1 / (gFrameTimeSum / gFrameTimeCount)),
749 : TEXT_DRAW_RIGHT | TEXT_DRAW_VCENTER);
750 : // mrSlideSorter.GetContentWindow()->Invalidate(gFrameTimeBox);
751 : #endif
752 : }
753 :
754 :
755 :
756 :
757 0 : void SlideSorterView::Paint (
758 : OutputDevice& rDevice,
759 : const Rectangle& rRepaintArea)
760 : {
761 0 : if ( ! mpPageObjectPainter)
762 0 : if ( ! GetPageObjectPainter())
763 0 : return;
764 :
765 : // Update the page visibilities when they have been invalidated.
766 0 : if ( ! mbPageObjectVisibilitiesValid)
767 0 : DeterminePageObjectVisibilities();
768 :
769 0 : if (mbPreciousFlagUpdatePending)
770 0 : UpdatePreciousFlags();
771 :
772 0 : if (mbIsRearrangePending)
773 0 : Rearrange();
774 :
775 : // Paint all page objects that are fully or partially inside the
776 : // repaint region.
777 0 : const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(rRepaintArea));
778 0 : for (sal_Int32 nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
779 : {
780 0 : model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
781 0 : if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
782 0 : continue;
783 :
784 0 : mpPageObjectPainter->PaintPageObject(rDevice, pDescriptor);
785 0 : }
786 : }
787 :
788 :
789 :
790 :
791 0 : void SlideSorterView::ConfigurationChanged (
792 : utl::ConfigurationBroadcaster* pBroadcaster,
793 : sal_uInt32 nHint)
794 : {
795 : // Some changes of the configuration (some of the colors for example)
796 : // may affect the previews. Throw away the old ones and create new ones.
797 0 : cache::PageCacheManager::Instance()->InvalidateAllCaches();
798 :
799 0 : ::sd::View::ConfigurationChanged(pBroadcaster, nHint);
800 0 : RequestRepaint();
801 :
802 0 : }
803 :
804 :
805 :
806 :
807 0 : ::boost::shared_ptr<cache::PageCache> SlideSorterView::GetPreviewCache (void)
808 : {
809 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
810 0 : if (pWindow && mpPreviewCache.get() == NULL)
811 : {
812 : mpPreviewCache.reset(
813 : new cache::PageCache(
814 0 : mpLayouter->GetPageObjectSize(),
815 : false,
816 0 : cache::SharedCacheContext(new ViewCacheContext(mrSlideSorter))));
817 : }
818 :
819 0 : return mpPreviewCache;
820 : }
821 :
822 :
823 :
824 :
825 0 : Pair SlideSorterView::GetVisiblePageRange (void)
826 : {
827 0 : if ( ! mbPageObjectVisibilitiesValid)
828 0 : DeterminePageObjectVisibilities();
829 0 : return maVisiblePageRange;
830 : }
831 :
832 :
833 :
834 :
835 0 : void SlideSorterView::AddVisibilityChangeListener (const Link& rListener)
836 : {
837 0 : if (::std::find (
838 : maVisibilityChangeListeners.begin(),
839 : maVisibilityChangeListeners.end(),
840 0 : rListener) == maVisibilityChangeListeners.end())
841 : {
842 0 : maVisibilityChangeListeners.push_back(rListener);
843 : }
844 0 : }
845 :
846 :
847 :
848 :
849 0 : void SlideSorterView::RemoveVisibilityChangeListener(const Link&rListener)
850 : {
851 : maVisibilityChangeListeners.erase (
852 : ::std::find (
853 : maVisibilityChangeListeners.begin(),
854 : maVisibilityChangeListeners.end(),
855 0 : rListener));
856 0 : }
857 :
858 :
859 :
860 :
861 0 : ToolTip& SlideSorterView::GetToolTip (void) const
862 : {
863 : OSL_ASSERT(mpToolTip);
864 0 : return *mpToolTip;
865 : }
866 :
867 :
868 :
869 :
870 0 : void SlideSorterView::DragFinished (sal_Int8 nDropAction)
871 : {
872 0 : mrSlideSorter.GetController().GetClipboard().DragFinished(nDropAction);
873 :
874 0 : View::DragFinished(nDropAction);
875 0 : }
876 :
877 :
878 :
879 :
880 0 : void SlideSorterView::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
881 : {
882 0 : ::sd::DrawDocShell* pDocShell = mrModel.GetDocument()->GetDocSh();
883 0 : if (pDocShell!=NULL && pDocShell->IsEnableSetModified())
884 0 : mbModelChangedWhileModifyEnabled = true;
885 :
886 0 : ::sd::View::Notify(rBroadcaster, rHint);
887 0 : }
888 :
889 :
890 :
891 :
892 0 : void SlideSorterView::UpdatePageUnderMouse ()
893 : {
894 0 : ::boost::shared_ptr<ScrollBar> pVScrollBar (mrSlideSorter.GetVerticalScrollBar());
895 0 : ::boost::shared_ptr<ScrollBar> pHScrollBar (mrSlideSorter.GetHorizontalScrollBar());
896 0 : if ((pVScrollBar && pVScrollBar->IsVisible() && pVScrollBar->IsTracking())
897 0 : || (pHScrollBar && pHScrollBar->IsVisible() && pHScrollBar->IsTracking()))
898 : {
899 : // One of the scroll bars is tracking mouse movement. Do not
900 : // highlight the slide under the mouse in this case.
901 0 : SetPageUnderMouse(SharedPageDescriptor());
902 0 : return;
903 : }
904 :
905 0 : SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
906 0 : if (pWindow && pWindow->IsVisible() && ! pWindow->IsMouseCaptured())
907 : {
908 0 : const Window::PointerState aPointerState (pWindow->GetPointerState());
909 0 : const Rectangle aWindowBox (pWindow->GetPosPixel(), pWindow->GetSizePixel());
910 0 : if (aWindowBox.IsInside(aPointerState.maPos))
911 : {
912 0 : UpdatePageUnderMouse(aPointerState.maPos);
913 0 : return;
914 : }
915 : }
916 :
917 0 : SetPageUnderMouse(SharedPageDescriptor());
918 : }
919 :
920 :
921 :
922 :
923 0 : void SlideSorterView::UpdatePageUnderMouse (
924 : const Point& rMousePosition)
925 : {
926 0 : SetPageUnderMouse(mrSlideSorter.GetController().GetPageAt(rMousePosition));
927 0 : }
928 :
929 :
930 :
931 :
932 0 : void SlideSorterView::SetPageUnderMouse (
933 : const model::SharedPageDescriptor& rpDescriptor)
934 : {
935 0 : if (mpPageUnderMouse != rpDescriptor)
936 : {
937 0 : if (mpPageUnderMouse)
938 0 : SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, false);
939 :
940 0 : mpPageUnderMouse = rpDescriptor;
941 :
942 0 : if (mpPageUnderMouse)
943 0 : SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, true);
944 :
945 : // Change the quick help text to display the name of the page under
946 : // the mouse.
947 0 : mpToolTip->SetPage(rpDescriptor);
948 : }
949 0 : }
950 :
951 :
952 :
953 :
954 0 : bool SlideSorterView::SetState (
955 : const model::SharedPageDescriptor& rpDescriptor,
956 : const PageDescriptor::State eState,
957 : const bool bStateValue)
958 : {
959 0 : model::SharedPageDescriptor pDescriptor (rpDescriptor);
960 0 : if ( ! pDescriptor)
961 0 : return false;
962 :
963 0 : const bool bModified (pDescriptor->SetState(eState, bStateValue));
964 0 : if ( ! bModified)
965 0 : return false;
966 :
967 : // When the page object is not visible (i.e. not on the screen then
968 : // nothing has to be painted.
969 0 : if (pDescriptor->HasState(PageDescriptor::ST_Visible))
970 : {
971 : // For most states a change of that state leads to visible
972 : // difference and we have to request a repaint.
973 0 : if (eState != PageDescriptor::ST_WasSelected)
974 0 : RequestRepaint(pDescriptor);
975 : }
976 :
977 0 : return bModified;
978 : }
979 :
980 :
981 :
982 :
983 0 : ::boost::shared_ptr<PageObjectPainter> SlideSorterView::GetPageObjectPainter (void)
984 : {
985 0 : if ( ! mpPageObjectPainter)
986 0 : mpPageObjectPainter.reset(new PageObjectPainter(mrSlideSorter));
987 0 : return mpPageObjectPainter;
988 : }
989 :
990 :
991 :
992 :
993 0 : ::boost::shared_ptr<LayeredDevice> SlideSorterView::GetLayeredDevice (void) const
994 : {
995 0 : return mpLayeredDevice;
996 : }
997 :
998 :
999 :
1000 :
1001 : //===== SlideSorterView::DrawLock =============================================
1002 :
1003 0 : SlideSorterView::DrawLock::DrawLock (SlideSorter& rSlideSorter)
1004 0 : : mrView(rSlideSorter.GetView()),
1005 0 : mpWindow(rSlideSorter.GetContentWindow())
1006 : {
1007 0 : if (mrView.mnLockRedrawSmph == 0)
1008 0 : mrView.maRedrawRegion.SetEmpty();
1009 0 : ++mrView.mnLockRedrawSmph;
1010 0 : }
1011 :
1012 :
1013 :
1014 :
1015 0 : SlideSorterView::DrawLock::~DrawLock (void)
1016 : {
1017 : OSL_ASSERT(mrView.mnLockRedrawSmph>0);
1018 0 : --mrView.mnLockRedrawSmph;
1019 0 : if (mrView.mnLockRedrawSmph == 0)
1020 0 : if (mpWindow)
1021 : {
1022 0 : mpWindow->Invalidate(mrView.maRedrawRegion);
1023 0 : mpWindow->Update();
1024 : }
1025 0 : }
1026 :
1027 :
1028 :
1029 :
1030 0 : void SlideSorterView::DrawLock::Dispose (void)
1031 : {
1032 0 : mpWindow.reset();
1033 0 : }
1034 :
1035 :
1036 : } } } // end of namespace ::sd::slidesorter::view
1037 :
1038 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|