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