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