LibreOffice Module sd (master) 1
PresenterSlideSorter.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <utility>
21#include <vcl/settings.hxx>
22
24#include "PresenterButton.hxx"
28#include "PresenterPaneBase.hxx"
32#include <DrawController.hxx>
33#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
34#include <com/sun/star/rendering/XBitmapCanvas.hpp>
35#include <com/sun/star/rendering/CompositeOperation.hpp>
36#include <com/sun/star/rendering/TextDirection.hpp>
37#include <algorithm>
38#include <math.h>
39
40using namespace ::com::sun::star;
41using namespace ::com::sun::star::uno;
43
44namespace {
45 const sal_Int32 gnVerticalGap (10);
46 const sal_Int32 gnVerticalBorder (10);
47 const sal_Int32 gnHorizontalGap (10);
48 const sal_Int32 gnHorizontalBorder (10);
49
50 const double gnMinimalPreviewWidth (200);
51 const double gnPreferredPreviewWidth (300);
52 const double gnMaximalPreviewWidth (400);
53 const sal_Int32 gnPreferredColumnCount (6);
54 const double gnMinimalHorizontalPreviewGap(15);
55 const double gnPreferredHorizontalPreviewGap(25);
56 const double gnMaximalHorizontalPreviewGap(50);
57 const double gnPreferredVerticalPreviewGap(25);
58
59 const sal_Int32 gnHorizontalLabelBorder (3);
60 const sal_Int32 gnHorizontalLabelPadding (5);
61
62 const sal_Int32 gnVerticalButtonPadding (gnVerticalGap);
63}
64
65namespace sdext::presenter {
66
67namespace {
68 sal_Int32 round (const double nValue) { return sal::static_int_cast<sal_Int32>(0.5 + nValue); }
69 sal_Int32 floor (const double nValue) { return sal::static_int_cast<sal_Int32>(nValue); }
70}
71
72//===== PresenterSlideSorter::Layout ==========================================
73
75{
76public:
77 explicit Layout (::rtl::Reference<PresenterScrollBar> xVerticalScrollBar);
78
79 void Update (const geometry::RealRectangle2D& rBoundingBox, const double nSlideAspectRatio);
80 void SetupVisibleArea();
81 void UpdateScrollBars();
82 bool IsScrollBarNeeded (const sal_Int32 nSlideCount);
83 geometry::RealPoint2D GetLocalPosition (const geometry::RealPoint2D& rWindowPoint) const;
84 geometry::RealPoint2D GetWindowPosition(const geometry::RealPoint2D& rLocalPoint) const;
85 sal_Int32 GetColumn (const geometry::RealPoint2D& rLocalPoint) const;
86 sal_Int32 GetRow (const geometry::RealPoint2D& rLocalPoint,
87 const bool bReturnInvalidValue = false) const;
88 sal_Int32 GetSlideIndexForPosition (const css::geometry::RealPoint2D& rPoint) const;
89 css::geometry::RealPoint2D GetPoint (
90 const sal_Int32 nSlideIndex,
91 const sal_Int32 nRelativeHorizontalPosition,
92 const sal_Int32 nRelativeVerticalPosition) const;
93 css::awt::Rectangle GetBoundingBox (const sal_Int32 nSlideIndex) const;
94 void ForAllVisibleSlides (const ::std::function<void (sal_Int32)>& rAction);
95 sal_Int32 GetFirstVisibleSlideIndex() const;
96 sal_Int32 GetLastVisibleSlideIndex() const;
97 bool SetHorizontalOffset (const double nOffset);
98 bool SetVerticalOffset (const double nOffset);
99
100 css::geometry::RealRectangle2D maBoundingBox;
101 css::geometry::IntegerSize2D maPreviewSize;
105 sal_Int32 mnVerticalGap;
108 sal_Int32 mnRowCount;
109 sal_Int32 mnColumnCount;
110 sal_Int32 mnSlideCount;
115
116private:
118
119 sal_Int32 GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const;
120 sal_Int32 GetRow (const sal_Int32 nSlideIndex) const;
121 sal_Int32 GetColumn (const sal_Int32 nSlideIndex) const;
122};
123
124//==== PresenterSlideSorter::MouseOverManager =================================
125
127{
128public:
130 const Reference<container::XIndexAccess>& rxSlides,
131 const std::shared_ptr<PresenterTheme>& rpTheme,
132 const Reference<awt::XWindow>& rxInvalidateTarget,
133 std::shared_ptr<PresenterPaintManager> xPaintManager);
136
137 void Paint (
138 const sal_Int32 nSlideIndex,
139 const Reference<rendering::XCanvas>& rxCanvas,
140 const Reference<rendering::XPolyPolygon2D>& rxClip);
141
142 void SetSlide (
143 const sal_Int32 nSlideIndex,
144 const awt::Rectangle& rBox);
145
146private:
147 Reference<rendering::XCanvas> mxCanvas;
148 const Reference<container::XIndexAccess> mxSlides;
153 sal_Int32 mnSlideIndex;
154 awt::Rectangle maSlideBoundingBox;
155 OUString msText;
156 Reference<rendering::XBitmap> mxBitmap;
157 Reference<awt::XWindow> mxInvalidateTarget;
158 std::shared_ptr<PresenterPaintManager> mpPaintManager;
159
160 void SetCanvas (
161 const Reference<rendering::XCanvas>& rxCanvas);
165 Reference<rendering::XBitmap> CreateBitmap (
166 const OUString& rsText,
167 const sal_Int32 nMaximalWidth) const;
168 void Invalidate();
169 geometry::IntegerSize2D CalculateLabelSize (
170 const OUString& rsText) const;
171 OUString GetFittingText (const OUString& rsText, const double nMaximalWidth) const;
173 const Reference<rendering::XCanvas>& rxCanvas,
174 const geometry::IntegerSize2D& rSize) const;
175};
176
177//==== PresenterSlideSorter::CurrentSlideFrameRenderer ========================
178
180{
181public:
183 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
184 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas);
185
187 const awt::Rectangle& rSlideBoundingBox,
188 const Reference<rendering::XCanvas>& rxCanvas,
189 const geometry::RealRectangle2D& rClipBox);
190
193 awt::Rectangle GetBoundingBox (
194 const awt::Rectangle& rSlideBoundingBox);
195
196private:
205 sal_Int32 mnTopFrameSize;
209
210 static void PaintBitmapOnce(
211 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
212 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
213 const Reference<rendering::XPolyPolygon2D>& rxClip,
214 const double nX,
215 const double nY);
216 static void PaintBitmapTiled(
217 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
218 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
219 const geometry::RealRectangle2D& rClipBox,
220 const double nX,
221 const double nY,
222 const double nWidth,
223 const double nHeight);
224};
225
226//===== PresenterSlideSorter ==================================================
227
229 const Reference<uno::XComponentContext>& rxContext,
230 const Reference<XResourceId>& rxViewId,
231 const rtl::Reference<::sd::DrawController>& rxController,
232 const ::rtl::Reference<PresenterController>& rpPresenterController)
234 mxComponentContext(rxContext),
235 mxViewId(rxViewId),
236 mpPresenterController(rpPresenterController),
237 mxSlideShowController(mpPresenterController->GetSlideShowController()),
238 mbIsLayoutPending(true),
239 mnSlideIndexMousePressed(-1),
240 mnCurrentSlideIndex(-1),
241 mnSeparatorY(0),
242 maSeparatorColor(0x00ffffff)
243{
244 if ( ! rxContext.is()
245 || ! rxViewId.is()
246 || ! rxController.is()
247 || ! rpPresenterController)
248 {
249 throw lang::IllegalArgumentException();
250 }
251
252 if ( ! mxSlideShowController.is())
253 throw RuntimeException();
254
255 try
256 {
257 // Get pane and window.
258 Reference<XConfigurationController> xCC (
259 rxController->getConfigurationController(), UNO_SET_THROW);
260 Reference<lang::XMultiComponentFactory> xFactory (
261 mxComponentContext->getServiceManager(), UNO_SET_THROW);
262
263 mxPane.set(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
264 mxWindow = mxPane->getWindow();
265
266 // Add window listener.
267 mxWindow->addWindowListener(this);
268 mxWindow->addPaintListener(this);
269 mxWindow->addMouseListener(this);
270 mxWindow->addMouseMotionListener(this);
271 mxWindow->setVisible(true);
272
273 // Remember the current slide.
274 mnCurrentSlideIndex = mxSlideShowController->getCurrentSlideIndex();
275
276 // Create the scroll bar.
279 rxContext,
280 mxWindow,
281 mpPresenterController->GetPaintManager(),
282 [this] (double const offset) { return this->SetVerticalOffset(offset); }));
283
285 rxContext,
287 mpPresenterController->GetTheme(),
288 mxWindow,
289 mxCanvas,
290 "SlideSorterCloser");
291
292 if (mpPresenterController->GetTheme() != nullptr)
293 {
295 mpPresenterController->GetTheme()->GetFont("ButtonFont"));
296 if (pFont)
297 maSeparatorColor = pFont->mnColor;
298 }
299
300 // Create the layout.
301 mpLayout = std::make_shared<Layout>(mpVerticalScrollBar);
302
303 // Create the preview cache.
304 mxPreviewCache.set(
305 xFactory->createInstanceWithContext(
306 "com.sun.star.drawing.PresenterPreviewCache",
308 UNO_QUERY_THROW);
309 Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY);
310 mxPreviewCache->setDocumentSlides(xSlides, rxController->getModel());
311 mxPreviewCache->addPreviewCreationNotifyListener(this);
312 if (xSlides.is())
313 {
314 mpLayout->mnSlideCount = xSlides->getCount();
315 }
316
317 // Create the mouse over manager.
319 Reference<container::XIndexAccess>(mxSlideShowController, UNO_QUERY),
320 mpPresenterController->GetTheme(),
321 mxWindow,
322 mpPresenterController->GetPaintManager()));
323
324 // Listen for changes of the current slide.
325 rxController->addPropertyChangeListener(
326 "CurrentPage",
327 this);
328
329 // Move the current slide in the center of the window.
330 const awt::Rectangle aCurrentSlideBBox (mpLayout->GetBoundingBox(mnCurrentSlideIndex));
331 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
332 SetHorizontalOffset(aCurrentSlideBBox.X - aWindowBox.Width/2.0);
333 }
334 catch (RuntimeException&)
335 {
336 disposing();
337 throw;
338 }
339}
340
342{
343}
344
346{
347 mxComponentContext = nullptr;
348 mxViewId = nullptr;
349 mxPane = nullptr;
350
351 if (mpVerticalScrollBar.is())
352 {
353 Reference<lang::XComponent> xComponent = mpVerticalScrollBar;
354 mpVerticalScrollBar = nullptr;
355 if (xComponent.is())
356 xComponent->dispose();
357 }
358 if (mpCloseButton.is())
359 {
360 Reference<lang::XComponent> xComponent = mpCloseButton;
361 mpCloseButton = nullptr;
362 if (xComponent.is())
363 xComponent->dispose();
364 }
365
366 if (mxCanvas.is())
367 {
368 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
369 if (xComponent.is())
370 xComponent->removeEventListener(static_cast<awt::XWindowListener*>(this));
371 mxCanvas = nullptr;
372 }
373 mpPresenterController = nullptr;
374 mxSlideShowController = nullptr;
375 mpLayout.reset();
376 mpMouseOverManager.reset();
377
378 if (mxPreviewCache.is())
379 {
380 mxPreviewCache->removePreviewCreationNotifyListener(this);
381
382 Reference<XComponent> xComponent (mxPreviewCache, UNO_QUERY);
383 mxPreviewCache = nullptr;
384 if (xComponent.is())
385 xComponent->dispose();
386 }
387
388 if (mxWindow.is())
389 {
390 mxWindow->removeWindowListener(this);
391 mxWindow->removePaintListener(this);
392 mxWindow->removeMouseListener(this);
393 mxWindow->removeMouseMotionListener(this);
394 }
395}
396
397//----- lang::XEventListener --------------------------------------------------
398
399void SAL_CALL PresenterSlideSorter::disposing (const lang::EventObject& rEventObject)
400{
401 if (rEventObject.Source == mxWindow)
402 {
403 mxWindow = nullptr;
404 dispose();
405 }
406 else if (rEventObject.Source == mxPreviewCache)
407 {
408 mxPreviewCache = nullptr;
409 dispose();
410 }
411 else if (rEventObject.Source == mxCanvas)
412 {
413 mxCanvas = nullptr;
414 mbIsLayoutPending = true;
415
416 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
417 }
418}
419
420//----- XWindowListener -------------------------------------------------------
421
422void SAL_CALL PresenterSlideSorter::windowResized (const awt::WindowEvent&)
423{
425 mbIsLayoutPending = true;
426 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
427}
428
429void SAL_CALL PresenterSlideSorter::windowMoved (const awt::WindowEvent&)
430{
432}
433
434void SAL_CALL PresenterSlideSorter::windowShown (const lang::EventObject&)
435{
437 mbIsLayoutPending = true;
438 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
439}
440
441void SAL_CALL PresenterSlideSorter::windowHidden (const lang::EventObject&)
442{
444}
445
446//----- XPaintListener --------------------------------------------------------
447
448void SAL_CALL PresenterSlideSorter::windowPaint (const css::awt::PaintEvent& rEvent)
449{
450 // Deactivated views must not be painted.
451 if ( ! mbIsPresenterViewActive)
452 return;
453
454 Paint(rEvent.UpdateRect);
455
456 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
457 if (xSpriteCanvas.is())
458 xSpriteCanvas->updateScreen(false);
459}
460
461//----- XMouseListener --------------------------------------------------------
462
463void SAL_CALL PresenterSlideSorter::mousePressed (const css::awt::MouseEvent& rEvent)
464{
465 css::awt::MouseEvent rTemp =rEvent;
468 awt::Rectangle aBox = mxWindow->getPosSize();
469 rTemp.X=aBox.Width-rEvent.X;
470 }
471 const geometry::RealPoint2D aPosition(rTemp.X, rEvent.Y);
472 mnSlideIndexMousePressed = mpLayout->GetSlideIndexForPosition(aPosition);
473}
474
475void SAL_CALL PresenterSlideSorter::mouseReleased (const css::awt::MouseEvent& rEvent)
476{
477 css::awt::MouseEvent rTemp =rEvent;
480 awt::Rectangle aBox = mxWindow->getPosSize();
481 rTemp.X=aBox.Width-rEvent.X;
482 }
483 const geometry::RealPoint2D aPosition(rTemp.X, rEvent.Y);
484 const sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));
485
486 if (nSlideIndex != mnSlideIndexMousePressed || mnSlideIndexMousePressed < 0)
487 return;
488
489 switch (rEvent.ClickCount)
490 {
491 case 1:
492 default:
493 GotoSlide(nSlideIndex);
494 break;
495
496 case 2:
497 OSL_ASSERT(mpPresenterController);
498 OSL_ASSERT(mpPresenterController->GetWindowManager());
499 mpPresenterController->GetWindowManager()->SetSlideSorterState(false);
500 GotoSlide(nSlideIndex);
501 break;
502 }
503}
504
505void SAL_CALL PresenterSlideSorter::mouseEntered (const css::awt::MouseEvent&) {}
506
507void SAL_CALL PresenterSlideSorter::mouseExited (const css::awt::MouseEvent&)
508{
510 if (mpMouseOverManager != nullptr)
511 mpMouseOverManager->SetSlide(mnSlideIndexMousePressed, awt::Rectangle(0,0,0,0));
512}
513
514//----- XMouseMotionListener --------------------------------------------------
515
516void SAL_CALL PresenterSlideSorter::mouseMoved (const css::awt::MouseEvent& rEvent)
517{
518 if (mpMouseOverManager == nullptr)
519 return;
520
521 css::awt::MouseEvent rTemp =rEvent;
524 awt::Rectangle aBox = mxWindow->getPosSize();
525 rTemp.X=aBox.Width-rEvent.X;
526 }
527 const geometry::RealPoint2D aPosition(rTemp.X, rEvent.Y);
528 sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));
529
530 if (nSlideIndex < 0)
531 {
533 mpMouseOverManager->SetSlide(nSlideIndex, awt::Rectangle(0,0,0,0));
534 }
535 else
536 {
537 mpMouseOverManager->SetSlide(
538 nSlideIndex,
539 mpLayout->GetBoundingBox(nSlideIndex));
540 }
541}
542
543void SAL_CALL PresenterSlideSorter::mouseDragged (const css::awt::MouseEvent&) {}
544
545//----- XResourceId -----------------------------------------------------------
546
547Reference<XResourceId> SAL_CALL PresenterSlideSorter::getResourceId()
548{
550 return mxViewId;
551}
552
554{
555 return false;
556}
557
558//----- XPropertyChangeListener -----------------------------------------------
559
561 const css::beans::PropertyChangeEvent&)
562{}
563
564//----- XSlidePreviewCacheListener --------------------------------------------
565
567 sal_Int32 nSlideIndex)
568{
569 OSL_ASSERT(mpLayout != nullptr);
570
571 awt::Rectangle aBBox (mpLayout->GetBoundingBox(nSlideIndex));
572 mpPresenterController->GetPaintManager()->Invalidate(mxWindow, aBBox, true);
573}
574
575//----- XDrawView -------------------------------------------------------------
576
577void SAL_CALL PresenterSlideSorter::setCurrentPage (const Reference<drawing::XDrawPage>&)
578{
580 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
581
582 if (!mxSlideShowController.is())
583 return;
584
585 const sal_Int32 nNewCurrentSlideIndex (mxSlideShowController->getCurrentSlideIndex());
586 if (nNewCurrentSlideIndex == mnCurrentSlideIndex)
587 return;
588
589 mnCurrentSlideIndex = nNewCurrentSlideIndex;
590
591 // Request a repaint of the previous current slide to hide its
592 // current slide indicator.
593 mpPresenterController->GetPaintManager()->Invalidate(
594 mxWindow,
596
597 // Request a repaint of the new current slide to show its
598 // current slide indicator.
600 mpLayout->GetBoundingBox(mnCurrentSlideIndex));
601 mpPresenterController->GetPaintManager()->Invalidate(
602 mxWindow,
604}
605
606Reference<drawing::XDrawPage> SAL_CALL PresenterSlideSorter::getCurrentPage()
607{
609 return nullptr;
610}
611
612
614{
615 if ( ! mxWindow.is())
616 return;
617
618 mbIsLayoutPending = false;
619
620 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
621 sal_Int32 nLeftBorderWidth (aWindowBox.X);
622
623 // Get border width.
625 mpPresenterController->GetPaneContainer()->FindViewURL(
626 mxViewId->getResourceURL()));
627 do
628 {
629 if (!pPane)
630 break;
631 if ( ! pPane->mxPane.is())
632 break;
633
634 Reference<drawing::framework::XPaneBorderPainter> xBorderPainter (
635 pPane->mxPane->GetPaneBorderPainter());
636 if ( ! xBorderPainter.is())
637 break;
638 xBorderPainter->addBorder (
639 mxViewId->getAnchor()->getResourceURL(),
640 awt::Rectangle(0, 0, aWindowBox.Width, aWindowBox.Height),
641 drawing::framework::BorderType_INNER_BORDER);
642 }
643 while(false);
644
645 // Place vertical separator.
646 mnSeparatorY = aWindowBox.Height - mpCloseButton->GetSize().Height - gnVerticalButtonPadding;
647
648 PlaceCloseButton(pPane, aWindowBox, nLeftBorderWidth);
649
650 geometry::RealRectangle2D aUpperBox(
653 aWindowBox.Width - 2*gnHorizontalBorder,
654 mnSeparatorY - gnVerticalGap);
655
656 // Determine whether the scroll bar has to be displayed.
657 aUpperBox = PlaceScrollBars(aUpperBox);
658
659 mpLayout->Update(aUpperBox, GetSlideAspectRatio());
660 mpLayout->SetupVisibleArea();
661 mpLayout->UpdateScrollBars();
662
663 // Tell the preview cache about some of the values.
664 mxPreviewCache->setPreviewSize(mpLayout->maPreviewSize);
665 mxPreviewCache->setVisibleRange(
666 mpLayout->GetFirstVisibleSlideIndex(),
667 mpLayout->GetLastVisibleSlideIndex());
668
669 // Clear the frame polygon so that it is re-created on the next paint.
670 mxPreviewFrame = nullptr;
671}
672
673geometry::RealRectangle2D PresenterSlideSorter::PlaceScrollBars (
674 const geometry::RealRectangle2D& rUpperBox)
675{
676 mpLayout->Update(rUpperBox, GetSlideAspectRatio());
677 bool bIsScrollBarNeeded (false);
678 Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY_THROW);
679 bIsScrollBarNeeded = mpLayout->IsScrollBarNeeded(xSlides->getCount());
681 {
682 if (bIsScrollBarNeeded)
683 {
685 {
686 mpVerticalScrollBar->SetPosSize(geometry::RealRectangle2D(
687 rUpperBox.X1,
688 rUpperBox.Y1,
689 rUpperBox.X1 + mpVerticalScrollBar->GetSize(),
690 rUpperBox.Y2));
691 mpVerticalScrollBar->SetVisible(true);
692 // Reduce area covered by the scroll bar from the available
693 // space.
694 return geometry::RealRectangle2D(
695 rUpperBox.X1 + gnHorizontalGap + mpVerticalScrollBar->GetSize(),
696 rUpperBox.Y1,
697 rUpperBox.X2,
698 rUpperBox.Y2);
699 }
700 else
701 {
702 // if it's not RTL place vertical scroll bar at right border.
703 mpVerticalScrollBar->SetPosSize(geometry::RealRectangle2D(
704 rUpperBox.X2 - mpVerticalScrollBar->GetSize(),
705 rUpperBox.Y1,
706 rUpperBox.X2,
707 rUpperBox.Y2));
708 mpVerticalScrollBar->SetVisible(true);
709 // Reduce area covered by the scroll bar from the available
710 // space.
711 return geometry::RealRectangle2D(
712 rUpperBox.X1,
713 rUpperBox.Y1,
714 rUpperBox.X2 - mpVerticalScrollBar->GetSize() - gnHorizontalGap,
715 rUpperBox.Y2);
716 }
717 }
718 else
719 mpVerticalScrollBar->SetVisible(false);
720 }
721 return rUpperBox;
722}
723
726 const awt::Rectangle& rCenterBox,
727 const sal_Int32 nLeftBorderWidth)
728{
729 // Place button. When the callout is near the center then the button is
730 // centered over the callout. Otherwise it is centered with respect to
731 // the whole window.
732 sal_Int32 nCloseButtonCenter (rCenterBox.Width/2);
733 if (rpPane && rpPane->mxPane.is())
734 {
735 const sal_Int32 nCalloutCenter (-nLeftBorderWidth);
736 const sal_Int32 nDistanceFromWindowCenter (abs(nCalloutCenter - rCenterBox.Width/2));
737 const sal_Int32 nButtonWidth (mpCloseButton->GetSize().Width);
738 const static sal_Int32 nMaxDistanceForCalloutCentering (nButtonWidth * 2);
739 if (nDistanceFromWindowCenter < nMaxDistanceForCalloutCentering)
740 {
741 if (nCalloutCenter < nButtonWidth/2)
742 nCloseButtonCenter = nButtonWidth/2;
743 else if (nCalloutCenter > rCenterBox.Width-nButtonWidth/2)
744 nCloseButtonCenter = rCenterBox.Width-nButtonWidth/2;
745 else
746 nCloseButtonCenter = nCalloutCenter;
747 }
748 }
749 mpCloseButton->SetCenter(geometry::RealPoint2D(
750 nCloseButtonCenter,
751 rCenterBox.Height - mpCloseButton->GetSize().Height/ 2));
752}
753
755 const Reference<rendering::XCanvas>& rxCanvas,
756 const awt::Rectangle& rUpdateBox)
757{
758 OSL_ASSERT(rxCanvas.is());
759
760 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
761 mpPresenterController->GetCanvasHelper()->Paint(
762 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
763 rxCanvas,
764 rUpdateBox,
765 awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
766 awt::Rectangle());
767}
768
770{
771 double nSlideAspectRatio (28.0/21.0);
772
773 try
774 {
775 Reference<container::XIndexAccess> xSlides(mxSlideShowController, UNO_QUERY_THROW);
776 if (mxSlideShowController.is() && xSlides->getCount()>0)
777 {
778 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
779 sal_Int32 nWidth (28000);
780 sal_Int32 nHeight (21000);
781 if ((xProperties->getPropertyValue("Width") >>= nWidth)
782 && (xProperties->getPropertyValue("Height") >>= nHeight)
783 && nHeight > 0)
784 {
785 nSlideAspectRatio = double(nWidth) / double(nHeight);
786 }
787 }
788 }
789 catch (RuntimeException&)
790 {
791 OSL_ASSERT(false);
792 }
793
794 return nSlideAspectRatio;
795}
796
797Reference<rendering::XBitmap> PresenterSlideSorter::GetPreview (const sal_Int32 nSlideIndex)
798{
799 if (nSlideIndex < 0 || nSlideIndex>=mpLayout->mnSlideCount)
800 return nullptr;
801 else if (mxPane.is())
802 return mxPreviewCache->getSlidePreview(nSlideIndex, mxPane->getCanvas());
803 else
804 return nullptr;
805}
806
808 const Reference<rendering::XCanvas>& rxCanvas,
809 const css::awt::Rectangle& rUpdateBox,
810 const sal_Int32 nSlideIndex)
811{
812 OSL_ASSERT(rxCanvas.is());
813
814 geometry::IntegerSize2D aSize (mpLayout->maPreviewSize);
815
817 rUpdateBox,
818 mpLayout->GetBoundingBox(nSlideIndex)))
819 {
820 return;
821 }
822
823 Reference<rendering::XBitmap> xPreview (GetPreview(nSlideIndex));
824 bool isRTL = AllSettings::GetLayoutRTL();
825
826 const geometry::RealPoint2D aTopLeft (
827 mpLayout->GetWindowPosition(
828 mpLayout->GetPoint(nSlideIndex, isRTL?1:-1, -1)));
829
830 PresenterBitmapContainer aContainer (
831 "PresenterScreenSettings/ScrollBar/Bitmaps",
832 std::shared_ptr<PresenterBitmapContainer>(),
834 rxCanvas);
835 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
836 Reference<drawing::XDrawPage> xPage( xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY);
837 bool bTransition = PresenterController::HasTransition(xPage);
838 bool bCustomAnimation = PresenterController::HasCustomAnimation(xPage);
839
840 // Create clip rectangle as intersection of the current update area and
841 // the bounding box of all previews.
842 geometry::RealRectangle2D aBoundingBox (mpLayout->maBoundingBox);
843 aBoundingBox.Y2 += 1;
844 const geometry::RealRectangle2D aClipBox (
847 aBoundingBox));
848 Reference<rendering::XPolyPolygon2D> xClip (
849 PresenterGeometryHelper::CreatePolygon(aClipBox, rxCanvas->getDevice()));
850
851 const rendering::ViewState aViewState (geometry::AffineMatrix2D(1,0,0, 0,1,0), xClip);
852
853 rendering::RenderState aRenderState (
854 geometry::AffineMatrix2D(
855 1, 0, aTopLeft.X,
856 0, 1, aTopLeft.Y),
857 nullptr,
858 Sequence<double>(4),
859 rendering::CompositeOperation::SOURCE);
860
861 // Emphasize the current slide.
862 if (nSlideIndex == mnCurrentSlideIndex)
863 {
864 if (mpCurrentSlideFrameRenderer != nullptr)
865 {
866 const awt::Rectangle aSlideBoundingBox(
867 sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.X),
868 sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.Y),
869 aSize.Width,
870 aSize.Height);
872 = mpCurrentSlideFrameRenderer->GetBoundingBox(aSlideBoundingBox);
873 mpCurrentSlideFrameRenderer->PaintCurrentSlideFrame (
874 aSlideBoundingBox,
875 mxCanvas,
876 aClipBox);
877 }
878 }
879
880 // Paint the preview.
881 if (xPreview.is())
882 {
883 aSize = xPreview->getSize();
884 if (aSize.Width > 0 && aSize.Height > 0)
885 {
886 rxCanvas->drawBitmap(xPreview, aViewState, aRenderState);
887 if( bCustomAnimation )
888 {
889 const awt::Rectangle aAnimationPreviewBox(aTopLeft.X+3, aTopLeft.Y+aSize.Height-40, 0, 0);
890 SharedBitmapDescriptor aAnimationDescriptor = aContainer.GetBitmap("Animation");
891 Reference<rendering::XBitmap> xAnimationIcon (aAnimationDescriptor->GetNormalBitmap());
892 rendering::RenderState aAnimationRenderState (
893 geometry::AffineMatrix2D(
894 1, 0, aAnimationPreviewBox.X,
895 0, 1, aAnimationPreviewBox.Y),
896 nullptr,
897 Sequence<double>(4),
898 rendering::CompositeOperation::SOURCE);
899 rxCanvas->drawBitmap(xAnimationIcon, aViewState, aAnimationRenderState);
900 }
901 if( bTransition )
902 {
903 const awt::Rectangle aTransitionPreviewBox(aTopLeft.X+3, aTopLeft.Y+aSize.Height-20, 0, 0);
904 SharedBitmapDescriptor aTransitionDescriptor = aContainer.GetBitmap("Transition");
905 Reference<rendering::XBitmap> xTransitionIcon (aTransitionDescriptor->GetNormalBitmap());
906 rendering::RenderState aTransitionRenderState (
907 geometry::AffineMatrix2D(
908 1, 0, aTransitionPreviewBox.X,
909 0, 1, aTransitionPreviewBox.Y),
910 nullptr,
911 Sequence<double>(4),
912 rendering::CompositeOperation::SOURCE);
913 rxCanvas->drawBitmap(xTransitionIcon, aViewState, aTransitionRenderState);
914 }
915 }
916 }
917
918 // Create a polygon that is used to paint a frame around previews. Its
919 // coordinates are chosen in the local coordinate system of a preview.
920 if ( ! mxPreviewFrame.is())
922 awt::Rectangle(-1, -1, aSize.Width+2, aSize.Height+2),
923 rxCanvas->getDevice());
924
925 // Paint a border around the preview.
926 if (mxPreviewFrame.is())
927 {
928 const util::Color aFrameColor (0x00000000);
929 PresenterCanvasHelper::SetDeviceColor(aRenderState, aFrameColor);
930 rxCanvas->drawPolyPolygon(mxPreviewFrame, aViewState, aRenderState);
931 }
932
933 // Paint mouse over effect.
934 mpMouseOverManager->Paint(nSlideIndex, mxCanvas, xClip);
935}
936
937void PresenterSlideSorter::Paint (const awt::Rectangle& rUpdateBox)
938{
939 const bool bCanvasChanged ( ! mxCanvas.is());
940 if ( ! ProvideCanvas())
941 return;
942
943 if (mpLayout->mnRowCount<=0 || mpLayout->mnColumnCount<=0)
944 {
945 OSL_ASSERT(mpLayout->mnRowCount>0 || mpLayout->mnColumnCount>0);
946 return;
947 }
948
949 ClearBackground(mxCanvas, rUpdateBox);
950
951 // Give the canvas to the controls.
952 if (bCanvasChanged)
953 {
954 if (mpVerticalScrollBar.is())
955 mpVerticalScrollBar->SetCanvas(mxCanvas);
956 if (mpCloseButton.is())
957 mpCloseButton->SetCanvas(mxCanvas, mxWindow);
958 }
959
960 // Now that the controls have a canvas we can do the layouting.
962 UpdateLayout();
963
964 // Paint the horizontal separator.
965 rendering::RenderState aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0),
966 nullptr, Sequence<double>(4), rendering::CompositeOperation::SOURCE);
968 mxCanvas->drawLine(
969 geometry::RealPoint2D(0, mnSeparatorY),
970 geometry::RealPoint2D(mxWindow->getPosSize().Width, mnSeparatorY),
971 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
972 aRenderState);
973
974 // Paint the slides.
976 rUpdateBox,
978 {
979 mpLayout->ForAllVisibleSlides(
980 [this, &rUpdateBox] (sal_Int32 const nIndex) {
981 return this->PaintPreview(this->mxCanvas, rUpdateBox, nIndex);
982 });
983 }
984
985 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
986 if (xSpriteCanvas.is())
987 xSpriteCanvas->updateScreen(false);
988}
989
991{
992 if (mpLayout->SetHorizontalOffset(nXOffset))
993 {
994 mxPreviewCache->setVisibleRange(
995 mpLayout->GetFirstVisibleSlideIndex(),
996 mpLayout->GetLastVisibleSlideIndex());
997
998 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
999 }
1000}
1001
1003{
1004 if (mpLayout->SetVerticalOffset(nYOffset))
1005 {
1006 mxPreviewCache->setVisibleRange(
1007 mpLayout->GetFirstVisibleSlideIndex(),
1008 mpLayout->GetLastVisibleSlideIndex());
1009
1010 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
1011 }
1012}
1013
1014void PresenterSlideSorter::GotoSlide (const sal_Int32 nSlideIndex)
1015{
1016 mxSlideShowController->gotoSlideIndex(nSlideIndex);
1017}
1018
1020{
1021 if ( ! mxCanvas.is())
1022 {
1023 if (mxPane.is())
1024 mxCanvas = mxPane->getCanvas();
1025
1026 // Register as event listener so that we are informed when the
1027 // canvas is disposed (and we have to fetch another one).
1028 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
1029 if (xComponent.is())
1030 xComponent->addEventListener(static_cast<awt::XWindowListener*>(this));
1031
1033 std::make_shared<CurrentSlideFrameRenderer>(mxComponentContext, mxCanvas);
1034 }
1035 return mxCanvas.is();
1036}
1037
1039{
1040 if (rBHelper.bDisposed || rBHelper.bInDispose)
1041 {
1042 throw lang::DisposedException (
1043 "PresenterSlideSorter has been already disposed",
1044 static_cast<uno::XWeak*>(this));
1045 }
1046}
1047
1048//===== PresenterSlideSorter::Layout ==========================================
1049
1051 ::rtl::Reference<PresenterScrollBar> xVerticalScrollBar)
1052 : mnHorizontalOffset(0),
1054 mnHorizontalGap(0),
1055 mnVerticalGap(0),
1056 mnHorizontalBorder(0),
1057 mnVerticalBorder(0),
1058 mnRowCount(1),
1059 mnColumnCount(1),
1060 mnSlideCount(0),
1061 mnFirstVisibleColumn(-1),
1062 mnLastVisibleColumn(-1),
1063 mnFirstVisibleRow(-1),
1064 mnLastVisibleRow(-1),
1065 mpVerticalScrollBar(std::move(xVerticalScrollBar))
1066{
1067}
1068
1070 const geometry::RealRectangle2D& rBoundingBox,
1071 const double nSlideAspectRatio)
1072{
1073 maBoundingBox = rBoundingBox;
1074
1075 mnHorizontalBorder = gnHorizontalBorder;
1076 mnVerticalBorder = gnVerticalBorder;
1077
1078 const double nWidth (rBoundingBox.X2 - rBoundingBox.X1 - 2*mnHorizontalBorder);
1079 const double nHeight (rBoundingBox.Y2 - rBoundingBox.Y1 - 2*mnVerticalBorder);
1080 if (nWidth<=0 || nHeight<=0)
1081 return;
1082
1083 double nPreviewWidth;
1084
1085 // Determine column count, preview width, and horizontal gap (borders
1086 // are half the gap). Try to use the preferred values. Try more to
1087 // stay in the valid intervals. This last constraint may be not
1088 // fulfilled in some cases.
1089 const double nElementWidth = nWidth / gnPreferredColumnCount;
1090 if (nElementWidth < gnMinimalPreviewWidth + gnMinimalHorizontalPreviewGap)
1091 {
1092 // The preferred column count is too large.
1093 // Can we use the preferred preview width?
1094 if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
1095 {
1096 // Yes.
1097 nPreviewWidth = gnPreferredPreviewWidth;
1098 mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
1099 / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
1100 mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1101 }
1102 else
1103 {
1104 // No. Set the column count to 1 and adapt preview width and
1105 // gap.
1106 mnColumnCount = 1;
1107 mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
1108 if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
1109 nPreviewWidth = nWidth - gnMinimalHorizontalPreviewGap;
1110 else
1111 nPreviewWidth = ::std::max(gnMinimalPreviewWidth, nWidth-mnHorizontalGap);
1112 }
1113 }
1114 else if (nElementWidth > gnMaximalPreviewWidth + gnMaximalHorizontalPreviewGap)
1115 {
1116 // The preferred column count is too small.
1117 nPreviewWidth = gnPreferredPreviewWidth;
1118 mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
1119 / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
1120 mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1121 }
1122 else
1123 {
1124 // The preferred column count is possible. Determine gap and
1125 // preview width.
1126 mnColumnCount = gnPreferredColumnCount;
1127 if (nElementWidth - gnPreferredPreviewWidth < gnMinimalHorizontalPreviewGap)
1128 {
1129 // Use the minimal gap and adapt the preview width.
1130 mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
1131 nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
1132 }
1133 else if (nElementWidth - gnPreferredPreviewWidth <= gnMaximalHorizontalPreviewGap)
1134 {
1135 // Use the maximal gap and adapt the preview width.
1136 mnHorizontalGap = round(gnMaximalHorizontalPreviewGap);
1137 nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
1138 }
1139 else
1140 {
1141 // Use the preferred preview width and adapt the gap.
1142 nPreviewWidth = gnPreferredPreviewWidth;
1143 mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1144 }
1145 }
1146
1147 // Now determine the row count, preview height, and vertical gap.
1148 const double nPreviewHeight = nPreviewWidth / nSlideAspectRatio;
1149 mnRowCount = ::std::max(
1150 sal_Int32(1),
1151 sal_Int32(ceil((nHeight+gnPreferredVerticalPreviewGap)
1152 / (nPreviewHeight + gnPreferredVerticalPreviewGap))));
1153 mnVerticalGap = round(gnPreferredVerticalPreviewGap);
1154
1155 maPreviewSize = geometry::IntegerSize2D(floor(nPreviewWidth), floor(nPreviewHeight));
1156
1157 // Reset the offset.
1158 mnVerticalOffset = 0;
1159 mnHorizontalOffset = round(-(nWidth
1160 - mnColumnCount*maPreviewSize.Width
1161 - (mnColumnCount-1)*mnHorizontalGap)
1162 / 2);
1163}
1164
1166{
1167 geometry::RealPoint2D aPoint (GetLocalPosition(
1168 geometry::RealPoint2D(maBoundingBox.X1, maBoundingBox.Y1)));
1169 mnFirstVisibleColumn = 0;
1170 mnFirstVisibleRow = ::std::max(sal_Int32(0), GetRow(aPoint));
1171
1172 aPoint = GetLocalPosition(geometry::RealPoint2D( maBoundingBox.X2, maBoundingBox.Y2));
1173 mnLastVisibleColumn = mnColumnCount - 1;
1174 mnLastVisibleRow = GetRow(aPoint, true);
1175}
1176
1177bool PresenterSlideSorter::Layout::IsScrollBarNeeded (const sal_Int32 nSlideCount)
1178{
1179 geometry::RealPoint2D aBottomRight = GetPoint(
1180 mnColumnCount * (GetRow(nSlideCount)+1) - 1, +1, +1);
1181 return aBottomRight.X > maBoundingBox.X2-maBoundingBox.X1
1182 || aBottomRight.Y > maBoundingBox.Y2-maBoundingBox.Y1;
1183}
1184
1186 const geometry::RealPoint2D& rWindowPoint) const
1187{
1189 {
1190 return css::geometry::RealPoint2D(
1191 -rWindowPoint.X + maBoundingBox.X2 + mnHorizontalOffset,
1192 rWindowPoint.Y - maBoundingBox.Y1 + mnVerticalOffset);
1193 }
1194 else
1195 {
1196 return css::geometry::RealPoint2D(
1197 rWindowPoint.X - maBoundingBox.X1 + mnHorizontalOffset,
1198 rWindowPoint.Y - maBoundingBox.Y1 + mnVerticalOffset);
1199 }
1200}
1201
1203 const geometry::RealPoint2D& rLocalPoint) const
1204{
1206 {
1207 return css::geometry::RealPoint2D(
1208 -rLocalPoint.X + mnHorizontalOffset + maBoundingBox.X2,
1209 rLocalPoint.Y - mnVerticalOffset + maBoundingBox.Y1);
1210 }
1211 else
1212 {
1213 return css::geometry::RealPoint2D(
1214 rLocalPoint.X - mnHorizontalOffset + maBoundingBox.X1,
1215 rLocalPoint.Y - mnVerticalOffset + maBoundingBox.Y1);
1216 }
1217}
1218
1220 const css::geometry::RealPoint2D& rLocalPoint) const
1221{
1222 const sal_Int32 nColumn(floor(
1223 (rLocalPoint.X + mnHorizontalGap/2.0) / (maPreviewSize.Width+mnHorizontalGap)));
1224 if (nColumn>=mnFirstVisibleColumn && nColumn<=mnLastVisibleColumn)
1225 {
1226 return nColumn;
1227 }
1228 else
1229 return -1;
1230}
1231
1233 const css::geometry::RealPoint2D& rLocalPoint,
1234 const bool bReturnInvalidValue) const
1235{
1236 const sal_Int32 nRow (floor(
1237 (rLocalPoint.Y + mnVerticalGap/2.0) / (maPreviewSize.Height+mnVerticalGap)));
1238 if (bReturnInvalidValue
1239 || (nRow>=mnFirstVisibleRow && nRow<=mnLastVisibleRow))
1240 {
1241 return nRow;
1242 }
1243 else
1244 return -1;
1245}
1246
1248 const css::geometry::RealPoint2D& rWindowPoint) const
1249{
1250 if ( ! PresenterGeometryHelper::IsInside(maBoundingBox, rWindowPoint))
1251 return -1;
1252
1253 const css::geometry::RealPoint2D aLocalPosition (GetLocalPosition(rWindowPoint));
1254 const sal_Int32 nColumn (GetColumn(aLocalPosition));
1255 const sal_Int32 nRow (GetRow(aLocalPosition));
1256
1257 if (nColumn < 0 || nRow < 0)
1258 return -1;
1259 else
1260 {
1261 sal_Int32 nIndex (GetIndex(nRow, nColumn));
1262 if (nIndex >= mnSlideCount)
1263 return -1;
1264 else
1265 return nIndex;
1266 }
1267}
1268
1270 const sal_Int32 nSlideIndex,
1271 const sal_Int32 nRelativeHorizontalPosition,
1272 const sal_Int32 nRelativeVerticalPosition) const
1273{
1274 sal_Int32 nColumn (GetColumn(nSlideIndex));
1275 sal_Int32 nRow (GetRow(nSlideIndex));
1276
1277 geometry::RealPoint2D aPosition (
1278 mnHorizontalBorder + nColumn*(maPreviewSize.Width+mnHorizontalGap),
1279 mnVerticalBorder + nRow*(maPreviewSize.Height+mnVerticalGap));
1280
1281 if (nRelativeHorizontalPosition >= 0)
1282 {
1283 if (nRelativeHorizontalPosition > 0)
1284 aPosition.X += maPreviewSize.Width;
1285 else
1286 aPosition.X += maPreviewSize.Width / 2.0;
1287 }
1288 if (nRelativeVerticalPosition >= 0)
1289 {
1290 if (nRelativeVerticalPosition > 0)
1291 aPosition.Y += maPreviewSize.Height;
1292 else
1293 aPosition.Y += maPreviewSize.Height / 2.0;
1294 }
1295
1296 return aPosition;
1297}
1298
1299awt::Rectangle PresenterSlideSorter::Layout::GetBoundingBox (const sal_Int32 nSlideIndex) const
1300{
1301 bool isRTL = AllSettings::GetLayoutRTL();
1302 const geometry::RealPoint2D aWindowPosition(GetWindowPosition(GetPoint(nSlideIndex, isRTL?1:-1, -1)));
1304 geometry::RealRectangle2D(
1305 aWindowPosition.X,
1306 aWindowPosition.Y,
1307 aWindowPosition.X + maPreviewSize.Width,
1308 aWindowPosition.Y + maPreviewSize.Height));
1309}
1310
1312 const ::std::function<void (sal_Int32)>& rAction)
1313{
1314 for (sal_Int32 nRow=mnFirstVisibleRow; nRow<=mnLastVisibleRow; ++nRow)
1315 {
1316 for (sal_Int32 nColumn=mnFirstVisibleColumn; nColumn<=mnLastVisibleColumn; ++nColumn)
1317 {
1318 const sal_Int32 nSlideIndex (GetIndex(nRow, nColumn));
1319 if (nSlideIndex >= mnSlideCount)
1320 return;
1321 rAction(nSlideIndex);
1322 }
1323 }
1324}
1325
1327{
1328 return GetIndex(mnFirstVisibleRow, mnFirstVisibleColumn);
1329}
1330
1332{
1333 return ::std::min(
1334 GetIndex(mnLastVisibleRow, mnLastVisibleColumn),
1335 mnSlideCount);
1336}
1337
1339{
1340 if (mnHorizontalOffset != nOffset)
1341 {
1342 mnHorizontalOffset = round(nOffset);
1343 SetupVisibleArea();
1344 UpdateScrollBars();
1345 return true;
1346 }
1347 else
1348 return false;
1349}
1350
1352{
1353 if (mnVerticalOffset != nOffset)
1354 {
1355 mnVerticalOffset = round(nOffset);
1356 SetupVisibleArea();
1357 UpdateScrollBars();
1358 return true;
1359 }
1360 else
1361 return false;
1362}
1363
1365{
1366 sal_Int32 nTotalRowCount = sal_Int32(ceil(double(mnSlideCount) / double(mnColumnCount)));
1367
1369 {
1370 mpVerticalScrollBar->SetTotalSize(
1371 nTotalRowCount * maPreviewSize.Height
1372 + (nTotalRowCount-1) * mnVerticalGap
1373 + 2*mnVerticalGap);
1374 mpVerticalScrollBar->SetThumbPosition(mnVerticalOffset, false);
1375 mpVerticalScrollBar->SetThumbSize(maBoundingBox.Y2 - maBoundingBox.Y1 + 1);
1376 mpVerticalScrollBar->SetLineHeight(maPreviewSize.Height);
1377 }
1378
1379 // No place yet for the vertical scroll bar.
1380}
1381
1383 const sal_Int32 nRow,
1384 const sal_Int32 nColumn) const
1385{
1386 return nRow * mnColumnCount + nColumn;
1387}
1388
1389sal_Int32 PresenterSlideSorter::Layout::GetRow (const sal_Int32 nSlideIndex) const
1390{
1391 return nSlideIndex / mnColumnCount;
1392}
1393
1394sal_Int32 PresenterSlideSorter::Layout::GetColumn (const sal_Int32 nSlideIndex) const
1395{
1396 return nSlideIndex % mnColumnCount;
1397}
1398
1399//===== PresenterSlideSorter::MouseOverManager ================================
1400
1402 const Reference<container::XIndexAccess>& rxSlides,
1403 const std::shared_ptr<PresenterTheme>& rpTheme,
1404 const Reference<awt::XWindow>& rxInvalidateTarget,
1405 std::shared_ptr<PresenterPaintManager> xPaintManager)
1406 : mxSlides(rxSlides),
1407 mnSlideIndex(-1),
1408 mxInvalidateTarget(rxInvalidateTarget),
1409 mpPaintManager(std::move(xPaintManager))
1410{
1411 if (rpTheme != nullptr)
1412 {
1413 std::shared_ptr<PresenterBitmapContainer> pBitmaps (rpTheme->GetBitmapContainer());
1414 if (pBitmaps != nullptr)
1415 {
1416 mpLeftLabelBitmap = pBitmaps->GetBitmap("LabelLeft");
1417 mpCenterLabelBitmap = pBitmaps->GetBitmap("LabelCenter");
1418 mpRightLabelBitmap = pBitmaps->GetBitmap("LabelRight");
1419 }
1420
1421 mpFont = rpTheme->GetFont("SlideSorterLabelFont");
1422 }
1423}
1424
1426 const sal_Int32 nSlideIndex,
1427 const Reference<rendering::XCanvas>& rxCanvas,
1428 const Reference<rendering::XPolyPolygon2D>& rxClip)
1429{
1430 if (nSlideIndex != mnSlideIndex)
1431 return;
1432
1433 if (mxCanvas != rxCanvas)
1434 SetCanvas(rxCanvas);
1435 if (rxCanvas == nullptr)
1436 return;
1437
1438 if ( ! mxBitmap.is())
1439 mxBitmap = CreateBitmap(msText, maSlideBoundingBox.Width);
1440 if (!mxBitmap.is())
1441 return;
1442
1443 geometry::IntegerSize2D aSize (mxBitmap->getSize());
1444 const double nXOffset (maSlideBoundingBox.X
1445 + (maSlideBoundingBox.Width - aSize.Width) / 2.0);
1446 const double nYOffset (maSlideBoundingBox.Y
1447 + (maSlideBoundingBox.Height - aSize.Height) / 2.0);
1448 rxCanvas->drawBitmap(
1449 mxBitmap,
1450 rendering::ViewState(
1451 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1452 rxClip),
1453 rendering::RenderState(
1454 geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset),
1455 nullptr,
1456 Sequence<double>(4),
1457 rendering::CompositeOperation::SOURCE));
1458}
1459
1461 const Reference<rendering::XCanvas>& rxCanvas)
1462{
1463 mxCanvas = rxCanvas;
1464 if (mpFont)
1465 mpFont->PrepareFont(mxCanvas);
1466}
1467
1469 const sal_Int32 nSlideIndex,
1470 const awt::Rectangle& rBox)
1471{
1472 if (mnSlideIndex == nSlideIndex)
1473 return;
1474
1475 mnSlideIndex = -1;
1476 Invalidate();
1477
1478 maSlideBoundingBox = rBox;
1479 mnSlideIndex = nSlideIndex;
1480
1481 if (nSlideIndex >= 0)
1482 {
1483 if (mxSlides)
1484 {
1485 msText.clear();
1486
1487 Reference<beans::XPropertySet> xSlideProperties(mxSlides->getByIndex(nSlideIndex), UNO_QUERY);
1488 if (xSlideProperties.is())
1489 xSlideProperties->getPropertyValue("LinkDisplayName") >>= msText;
1490
1491 if (msText.isEmpty())
1492 msText = "Slide " + OUString::number(nSlideIndex + 1);
1493 }
1494 }
1495 else
1496 {
1497 msText.clear();
1498 }
1499 mxBitmap = nullptr;
1500
1501 Invalidate();
1502}
1503
1505 const OUString& rsText,
1506 const sal_Int32 nMaximalWidth) const
1507{
1508 if ( ! mxCanvas.is())
1509 return nullptr;
1510
1511 if (!mpFont || !mpFont->mxFont.is())
1512 return nullptr;
1513
1514 // Long text has to be shortened.
1515 const OUString sText (GetFittingText(rsText, nMaximalWidth
1516 - 2*gnHorizontalLabelBorder
1517 - 2*gnHorizontalLabelPadding));
1518
1519 // Determine the size of the label. Its height is defined by the
1520 // bitmaps that are used to paints its background. The width is defined
1521 // by the text.
1522 geometry::IntegerSize2D aLabelSize (CalculateLabelSize(sText));
1523
1524 // Create a new bitmap that will contain the complete label.
1525 Reference<rendering::XBitmap> xBitmap (
1526 mxCanvas->getDevice()->createCompatibleAlphaBitmap(aLabelSize));
1527
1528 if ( ! xBitmap.is())
1529 return nullptr;
1530
1531 Reference<rendering::XBitmapCanvas> xBitmapCanvas (xBitmap, UNO_QUERY);
1532 if ( ! xBitmapCanvas.is())
1533 return nullptr;
1534
1535 // Paint the background.
1536 PaintButtonBackground(xBitmapCanvas, aLabelSize);
1537
1538 // Paint the text.
1539 if (!sText.isEmpty())
1540 {
1541
1542 const rendering::StringContext aContext (sText, 0, sText.getLength());
1543 const Reference<rendering::XTextLayout> xLayout (mpFont->mxFont->createTextLayout(
1544 aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0));
1545 const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds());
1546
1547 const double nXOffset = (aLabelSize.Width - aTextBBox.X2 + aTextBBox.X1) / 2;
1548 const double nYOffset = aLabelSize.Height
1549 - (aLabelSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y2;
1550
1551 const rendering::ViewState aViewState(
1552 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1553 nullptr);
1554
1555 rendering::RenderState aRenderState (
1556 geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset),
1557 nullptr,
1558 Sequence<double>(4),
1559 rendering::CompositeOperation::SOURCE);
1560 PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
1561
1562 xBitmapCanvas->drawTextLayout (
1563 xLayout,
1564 aViewState,
1565 aRenderState);
1566 }
1567
1568 return xBitmap;
1569}
1570
1572 const OUString& rsText,
1573 const double nMaximalWidth) const
1574{
1575 const double nTextWidth (
1576 PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText).Width);
1577 if (nTextWidth > nMaximalWidth)
1578 {
1579 // Text is too wide. Shorten it by removing characters from the end
1580 // and replacing them by ellipses.
1581
1582 // Guess a start value of the final string length.
1583 double nBestWidth (0);
1584 OUString sBestCandidate;
1585 sal_Int32 nLength (round(rsText.getLength() * nMaximalWidth / nTextWidth));
1586 static constexpr OUStringLiteral sEllipses (u"...");
1587 while (true)
1588 {
1589 const OUString sCandidate (rsText.subView(0,nLength) + sEllipses);
1590 const double nWidth (
1591 PresenterCanvasHelper::GetTextSize(mpFont->mxFont, sCandidate).Width);
1592 if (nWidth > nMaximalWidth)
1593 {
1594 // Candidate still too wide, shorten it.
1595 nLength -= 1;
1596 if (nLength <= 0)
1597 break;
1598 }
1599 else if (nWidth < nMaximalWidth)
1600 {
1601 // Candidate short enough.
1602 if (nWidth > nBestWidth)
1603 {
1604 // Best length so far.
1605 sBestCandidate = sCandidate;
1606 nBestWidth = nWidth;
1607 nLength += 1;
1608 if (nLength >= rsText.getLength())
1609 break;
1610 }
1611 else
1612 break;
1613 }
1614 else
1615 {
1616 // Candidate is exactly as long as it may be. Use it
1617 // without looking any further.
1618 sBestCandidate = sCandidate;
1619 break;
1620 }
1621 }
1622 return sBestCandidate;
1623 }
1624 else
1625 return rsText;
1626}
1627
1629 const OUString& rsText) const
1630{
1631 // Height is specified by the label bitmaps.
1632 sal_Int32 nHeight (32);
1633 if (mpCenterLabelBitmap)
1634 {
1635 Reference<rendering::XBitmap> xBitmap (mpCenterLabelBitmap->GetNormalBitmap());
1636 if (xBitmap.is())
1637 nHeight = xBitmap->getSize().Height;
1638 }
1639
1640 // Width is specified by text width and maximal width.
1641 const geometry::RealSize2D aTextSize (
1643
1644 const sal_Int32 nWidth (round(aTextSize.Width + 2*gnHorizontalLabelPadding));
1645
1646 return geometry::IntegerSize2D(nWidth, nHeight);
1647}
1648
1650 const Reference<rendering::XCanvas>& rxCanvas,
1651 const geometry::IntegerSize2D& rSize) const
1652{
1653 // Get the bitmaps for painting the label background.
1654 Reference<rendering::XBitmap> xLeftLabelBitmap;
1655 if (mpLeftLabelBitmap)
1656 xLeftLabelBitmap = mpLeftLabelBitmap->GetNormalBitmap();
1657
1658 Reference<rendering::XBitmap> xCenterLabelBitmap;
1659 if (mpCenterLabelBitmap)
1660 xCenterLabelBitmap = mpCenterLabelBitmap->GetNormalBitmap();
1661
1662 Reference<rendering::XBitmap> xRightLabelBitmap;
1663 if (mpRightLabelBitmap)
1664 xRightLabelBitmap = mpRightLabelBitmap->GetNormalBitmap();
1665
1667 rxCanvas,
1668 awt::Rectangle(0,0, rSize.Width,rSize.Height),
1669 awt::Rectangle(0,0, rSize.Width,rSize.Height),
1670 xLeftLabelBitmap,
1671 xCenterLabelBitmap,
1672 xRightLabelBitmap);
1673}
1674
1676{
1677 if (mpPaintManager != nullptr)
1678 mpPaintManager->Invalidate(mxInvalidateTarget, maSlideBoundingBox, true);
1679}
1680
1681//===== PresenterSlideSorter::CurrentSlideFrameRenderer =======================
1682
1684 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
1685 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas)
1686 : mnTopFrameSize(0),
1687 mnLeftFrameSize(0),
1688 mnRightFrameSize(0),
1689 mnBottomFrameSize(0)
1690{
1691 PresenterConfigurationAccess aConfiguration (
1692 rxContext,
1693 "/org.openoffice.Office.PresenterScreen/",
1695 Reference<container::XHierarchicalNameAccess> xBitmaps (
1696 aConfiguration.GetConfigurationNode(
1697 "PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps"),
1698 UNO_QUERY);
1699 if ( ! xBitmaps.is())
1700 return;
1701
1702 PresenterBitmapContainer aContainer (
1703 "PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps",
1704 std::shared_ptr<PresenterBitmapContainer>(),
1705 rxContext,
1706 rxCanvas);
1707
1708 mpTopLeft = aContainer.GetBitmap("TopLeft");
1709 mpTop = aContainer.GetBitmap("Top");
1710 mpTopRight = aContainer.GetBitmap("TopRight");
1711 mpLeft = aContainer.GetBitmap("Left");
1712 mpRight = aContainer.GetBitmap("Right");
1713 mpBottomLeft = aContainer.GetBitmap("BottomLeft");
1714 mpBottom = aContainer.GetBitmap("Bottom");
1715 mpBottomRight = aContainer.GetBitmap("BottomRight");
1716
1717 // Determine size of frame.
1718 if (mpTop)
1719 mnTopFrameSize = mpTop->mnHeight;
1720 if (mpLeft)
1721 mnLeftFrameSize = mpLeft->mnWidth;
1722 if (mpRight)
1723 mnRightFrameSize = mpRight->mnWidth;
1724 if (mpBottom)
1725 mnBottomFrameSize = mpBottom->mnHeight;
1726
1727 if (mpTopLeft)
1728 {
1729 mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopLeft->mnHeight);
1730 mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpTopLeft->mnWidth);
1731 }
1732 if (mpTopRight)
1733 {
1734 mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopRight->mnHeight);
1735 mnRightFrameSize = ::std::max(mnRightFrameSize, mpTopRight->mnWidth);
1736 }
1737 if (mpBottomLeft)
1738 {
1739 mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpBottomLeft->mnWidth);
1740 mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomLeft->mnHeight);
1741 }
1742 if (mpBottomRight)
1743 {
1744 mnRightFrameSize = ::std::max(mnRightFrameSize, mpBottomRight->mnWidth);
1745 mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomRight->mnHeight);
1746 }
1747}
1748
1750 const awt::Rectangle& rSlideBoundingBox,
1751 const Reference<rendering::XCanvas>& rxCanvas,
1752 const geometry::RealRectangle2D& rClipBox)
1753{
1754 if ( ! rxCanvas.is())
1755 return;
1756
1757 const Reference<rendering::XPolyPolygon2D> xClip (
1758 PresenterGeometryHelper::CreatePolygon(rClipBox, rxCanvas->getDevice()));
1759
1760 if (mpTop)
1761 {
1762 PaintBitmapTiled(
1763 mpTop->GetNormalBitmap(),
1764 rxCanvas,
1765 rClipBox,
1766 rSlideBoundingBox.X,
1767 rSlideBoundingBox.Y - mpTop->mnHeight,
1768 rSlideBoundingBox.Width,
1769 mpTop->mnHeight);
1770 }
1771 if (mpLeft)
1772 {
1773 PaintBitmapTiled(
1774 mpLeft->GetNormalBitmap(),
1775 rxCanvas,
1776 rClipBox,
1777 rSlideBoundingBox.X - mpLeft->mnWidth,
1778 rSlideBoundingBox.Y,
1779 mpLeft->mnWidth,
1780 rSlideBoundingBox.Height);
1781 }
1782 if (mpRight)
1783 {
1784 PaintBitmapTiled(
1785 mpRight->GetNormalBitmap(),
1786 rxCanvas,
1787 rClipBox,
1788 rSlideBoundingBox.X + rSlideBoundingBox.Width,
1789 rSlideBoundingBox.Y,
1790 mpRight->mnWidth,
1791 rSlideBoundingBox.Height);
1792 }
1793 if (mpBottom)
1794 {
1795 PaintBitmapTiled(
1796 mpBottom->GetNormalBitmap(),
1797 rxCanvas,
1798 rClipBox,
1799 rSlideBoundingBox.X,
1800 rSlideBoundingBox.Y + rSlideBoundingBox.Height,
1801 rSlideBoundingBox.Width,
1802 mpBottom->mnHeight);
1803 }
1804 if (mpTopLeft)
1805 {
1806 PaintBitmapOnce(
1807 mpTopLeft->GetNormalBitmap(),
1808 rxCanvas,
1809 xClip,
1810 rSlideBoundingBox.X - mpTopLeft->mnWidth,
1811 rSlideBoundingBox.Y - mpTopLeft->mnHeight);
1812 }
1813 if (mpTopRight)
1814 {
1815 PaintBitmapOnce(
1816 mpTopRight->GetNormalBitmap(),
1817 rxCanvas,
1818 xClip,
1819 rSlideBoundingBox.X + rSlideBoundingBox.Width,
1820 rSlideBoundingBox.Y - mpTopRight->mnHeight);
1821 }
1822 if (mpBottomLeft)
1823 {
1824 PaintBitmapOnce(
1825 mpBottomLeft->GetNormalBitmap(),
1826 rxCanvas,
1827 xClip,
1828 rSlideBoundingBox.X - mpBottomLeft->mnWidth,
1829 rSlideBoundingBox.Y + rSlideBoundingBox.Height);
1830 }
1831 if (mpBottomRight)
1832 {
1833 PaintBitmapOnce(
1834 mpBottomRight->GetNormalBitmap(),
1835 rxCanvas,
1836 xClip,
1837 rSlideBoundingBox.X + rSlideBoundingBox.Width,
1838 rSlideBoundingBox.Y + rSlideBoundingBox.Height);
1839 }
1840}
1841
1843 const awt::Rectangle& rSlideBoundingBox)
1844{
1845 return awt::Rectangle(
1846 rSlideBoundingBox.X - mnLeftFrameSize,
1847 rSlideBoundingBox.Y - mnTopFrameSize,
1848 rSlideBoundingBox.Width + mnLeftFrameSize + mnRightFrameSize,
1849 rSlideBoundingBox.Height + mnTopFrameSize + mnBottomFrameSize);
1850}
1851
1853 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
1854 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
1855 const Reference<rendering::XPolyPolygon2D>& rxClip,
1856 const double nX,
1857 const double nY)
1858{
1859 OSL_ASSERT(rxCanvas.is());
1860 if ( ! rxBitmap.is())
1861 return;
1862
1863 const rendering::ViewState aViewState(
1864 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1865 rxClip);
1866
1867 const rendering::RenderState aRenderState (
1868 geometry::AffineMatrix2D(
1869 1, 0, nX,
1870 0, 1, nY),
1871 nullptr,
1872 Sequence<double>(4),
1873 rendering::CompositeOperation::SOURCE);
1874
1875 rxCanvas->drawBitmap(
1876 rxBitmap,
1877 aViewState,
1878 aRenderState);
1879}
1880
1882 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
1883 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
1884 const geometry::RealRectangle2D& rClipBox,
1885 const double nX0,
1886 const double nY0,
1887 const double nWidth,
1888 const double nHeight)
1889{
1890 OSL_ASSERT(rxCanvas.is());
1891 if ( ! rxBitmap.is())
1892 return;
1893
1894 geometry::IntegerSize2D aSize (rxBitmap->getSize());
1895
1896 const rendering::ViewState aViewState(
1897 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1900 rClipBox,
1901 geometry::RealRectangle2D(nX0,nY0,nX0+nWidth,nY0+nHeight)),
1902 rxCanvas->getDevice()));
1903
1904 rendering::RenderState aRenderState (
1905 geometry::AffineMatrix2D(
1906 1, 0, nX0,
1907 0, 1, nY0),
1908 nullptr,
1909 Sequence<double>(4),
1910 rendering::CompositeOperation::SOURCE);
1911
1912 const double nX1 = nX0 + nWidth;
1913 const double nY1 = nY0 + nHeight;
1914 for (double nY=nY0; nY<nY1; nY+=aSize.Height)
1915 for (double nX=nX0; nX<nX1; nX+=aSize.Width)
1916 {
1917 aRenderState.AffineTransform.m02 = nX;
1918 aRenderState.AffineTransform.m12 = nY;
1919 rxCanvas->drawBitmap(
1920 rxBitmap,
1921 aViewState,
1922 aRenderState);
1923 }
1924}
1925
1926} // end of namespace ::sdext::presenter
1927
1928/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double mnVerticalOffset
const OUString msText
SharedBitmapDescriptor mpBottomRight
SharedBitmapDescriptor mpLeft
SharedBitmapDescriptor mpRight
SharedBitmapDescriptor mpTop
PresenterTheme::SharedFontDescriptor mpFont
SharedBitmapDescriptor mpTopRight
SharedBitmapDescriptor mpTopLeft
SharedBitmapDescriptor mpBottomLeft
SharedBitmapDescriptor mpBottom
rtl::Reference< PresenterController > mpPresenterController
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
static bool GetLayoutRTL()
Manage a set of bitmap groups as they are used for buttons: three bitmaps, one for the normal state,...
std::shared_ptr< BitmapDescriptor > GetBitmap(const OUString &rsName) const
Return the bitmap set that is associated with the given name.
static ::rtl::Reference< PresenterButton > Create(const css::uno::Reference< css::uno::XComponentContext > &rxComponentContext, const ::rtl::Reference< PresenterController > &rpPresenterController, const std::shared_ptr< PresenterTheme > &rpTheme, const css::uno::Reference< css::awt::XWindow > &rxParentWindow, const css::uno::Reference< css::rendering::XCanvas > &rxParentCanvas, const OUString &rsConfigurationName)
static css::geometry::RealSize2D GetTextSize(const css::uno::Reference< css::rendering::XCanvasFont > &rxFont, const OUString &rsText)
static void SetDeviceColor(css::rendering::RenderState &rRenderState, const css::util::Color aColor)
This class gives access to the configuration.
css::uno::Any GetConfigurationNode(const OUString &rsPathToNode)
Return a configuration node below the root of the called object.
static bool HasTransition(css::uno::Reference< css::drawing::XDrawPage > const &rxPage)
static bool HasCustomAnimation(css::uno::Reference< css::drawing::XDrawPage > const &rxPage)
static bool AreRectanglesDisjoint(const css::awt::Rectangle &rBox1, const css::awt::Rectangle &rBox2)
static bool IsInside(const css::geometry::RealRectangle2D &rBox, const css::geometry::RealPoint2D &rPoint)
static css::awt::Rectangle Intersection(const css::awt::Rectangle &rBox1, const css::awt::Rectangle &rBox2)
static css::uno::Reference< css::rendering::XPolyPolygon2D > CreatePolygon(const css::awt::Rectangle &rBox, const css::uno::Reference< css::rendering::XGraphicDevice > &rxDevice)
static css::awt::Rectangle ConvertRectangle(const css::geometry::RealRectangle2D &rBox)
Return the bounding box with integer coordinates of the given rectangle.
std::shared_ptr< PaneDescriptor > SharedPaneDescriptor
static void PaintBitmapTiled(const css::uno::Reference< css::rendering::XBitmap > &rxBitmap, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const geometry::RealRectangle2D &rClipBox, const double nX, const double nY, const double nWidth, const double nHeight)
awt::Rectangle GetBoundingBox(const awt::Rectangle &rSlideBoundingBox)
Enlarge the given rectangle to include the current slide indicator.
void PaintCurrentSlideFrame(const awt::Rectangle &rSlideBoundingBox, const Reference< rendering::XCanvas > &rxCanvas, const geometry::RealRectangle2D &rClipBox)
static void PaintBitmapOnce(const css::uno::Reference< css::rendering::XBitmap > &rxBitmap, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const Reference< rendering::XPolyPolygon2D > &rxClip, const double nX, const double nY)
CurrentSlideFrameRenderer(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas)
css::geometry::RealPoint2D GetPoint(const sal_Int32 nSlideIndex, const sal_Int32 nRelativeHorizontalPosition, const sal_Int32 nRelativeVerticalPosition) const
bool IsScrollBarNeeded(const sal_Int32 nSlideCount)
void Update(const geometry::RealRectangle2D &rBoundingBox, const double nSlideAspectRatio)
sal_Int32 GetIndex(const sal_Int32 nRow, const sal_Int32 nColumn) const
geometry::RealPoint2D GetLocalPosition(const geometry::RealPoint2D &rWindowPoint) const
void ForAllVisibleSlides(const ::std::function< void(sal_Int32)> &rAction)
sal_Int32 GetColumn(const geometry::RealPoint2D &rLocalPoint) const
::rtl::Reference< PresenterScrollBar > mpVerticalScrollBar
geometry::RealPoint2D GetWindowPosition(const geometry::RealPoint2D &rLocalPoint) const
sal_Int32 GetSlideIndexForPosition(const css::geometry::RealPoint2D &rPoint) const
sal_Int32 GetRow(const geometry::RealPoint2D &rLocalPoint, const bool bReturnInvalidValue=false) const
Layout(::rtl::Reference< PresenterScrollBar > xVerticalScrollBar)
css::awt::Rectangle GetBoundingBox(const sal_Int32 nSlideIndex) const
MouseOverManager(const Reference< container::XIndexAccess > &rxSlides, const std::shared_ptr< PresenterTheme > &rpTheme, const Reference< awt::XWindow > &rxInvalidateTarget, std::shared_ptr< PresenterPaintManager > xPaintManager)
MouseOverManager & operator=(const MouseOverManager &)=delete
void SetCanvas(const Reference< rendering::XCanvas > &rxCanvas)
Reference< rendering::XBitmap > CreateBitmap(const OUString &rsText, const sal_Int32 nMaximalWidth) const
Create a bitmap that shows the given text and is not wider than the given maximal width.
OUString GetFittingText(const OUString &rsText, const double nMaximalWidth) const
void SetSlide(const sal_Int32 nSlideIndex, const awt::Rectangle &rBox)
std::shared_ptr< PresenterPaintManager > mpPaintManager
const Reference< container::XIndexAccess > mxSlides
void PaintButtonBackground(const Reference< rendering::XCanvas > &rxCanvas, const geometry::IntegerSize2D &rSize) const
geometry::IntegerSize2D CalculateLabelSize(const OUString &rsText) const
void Paint(const sal_Int32 nSlideIndex, const Reference< rendering::XCanvas > &rxCanvas, const Reference< rendering::XPolyPolygon2D > &rxClip)
void PaintPreview(const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rUpdateBox, const sal_Int32 nSlideIndex)
::rtl::Reference< PresenterController > mpPresenterController
std::shared_ptr< CurrentSlideFrameRenderer > mpCurrentSlideFrameRenderer
css::uno::Reference< css::rendering::XBitmap > GetPreview(const sal_Int32 nSlideIndex)
css::uno::Reference< css::rendering::XPolyPolygon2D > mxPreviewFrame
void Paint(const css::awt::Rectangle &rUpdateBox)
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
virtual void SAL_CALL mouseReleased(const css::awt::MouseEvent &rEvent) override
virtual void SAL_CALL windowPaint(const css::awt::PaintEvent &rEvent) override
virtual void SAL_CALL mousePressed(const css::awt::MouseEvent &rEvent) override
virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL getCurrentPage() override
virtual void SAL_CALL mouseEntered(const css::awt::MouseEvent &rEvent) override
virtual void SAL_CALL windowShown(const css::lang::EventObject &rEvent) override
std::unique_ptr< MouseOverManager > mpMouseOverManager
virtual void SAL_CALL windowMoved(const css::awt::WindowEvent &rEvent) override
css::uno::Reference< css::drawing::XSlidePreviewCache > mxPreviewCache
virtual void SAL_CALL mouseDragged(const css::awt::MouseEvent &rEvent) override
void PlaceCloseButton(const PresenterPaneContainer::SharedPaneDescriptor &rpPane, const css::awt::Rectangle &rCenterBox, const sal_Int32 nLeftFrameWidth)
css::uno::Reference< css::drawing::framework::XPane > mxPane
css::uno::Reference< css::awt::XWindow > mxWindow
void ClearBackground(const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rRedrawArea)
css::uno::Reference< css::drawing::framework::XResourceId > mxViewId
css::uno::Reference< css::presentation::XSlideShowController > mxSlideShowController
virtual void SAL_CALL mouseMoved(const css::awt::MouseEvent &rEvent) override
css::geometry::RealRectangle2D PlaceScrollBars(const css::geometry::RealRectangle2D &rUpperBox)
virtual sal_Bool SAL_CALL isAnchorOnly() override
virtual void SAL_CALL notifyPreviewCreation(sal_Int32 nSlideIndex) override
css::uno::Reference< css::rendering::XCanvas > mxCanvas
::rtl::Reference< PresenterButton > mpCloseButton
void GotoSlide(const sal_Int32 nSlideIndex)
virtual void SAL_CALL mouseExited(const css::awt::MouseEvent &rEvent) override
virtual void SAL_CALL windowResized(const css::awt::WindowEvent &rEvent) override
virtual css::uno::Reference< css::drawing::framework::XResourceId > SAL_CALL getResourceId() override
void SetHorizontalOffset(const double nXOffset)
virtual void SAL_CALL disposing() override
::rtl::Reference< PresenterScrollBar > mpVerticalScrollBar
virtual void SAL_CALL setCurrentPage(const css::uno::Reference< css::drawing::XDrawPage > &rxSlide) override
virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent &rEvent) override
virtual void SAL_CALL windowHidden(const css::lang::EventObject &rEvent) override
PresenterSlideSorter(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::drawing::framework::XResourceId > &rxViewId, const rtl::Reference<::sd::DrawController > &rxController, const ::rtl::Reference< PresenterController > &rpPresenterController)
std::shared_ptr< FontDescriptor > SharedFontDescriptor
static void PaintHorizontalBitmapComposite(const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rRepaintBox, const css::awt::Rectangle &rBoundingBox, const css::uno::Reference< css::rendering::XBitmap > &rxLeftBitmap, const css::uno::Reference< css::rendering::XBitmap > &rxRepeatableCenterBitmap, const css::uno::Reference< css::rendering::XBitmap > &rxRightBitmap)
VclPtr< VirtualDevice > mxBitmap
float u
Reference< XSingleServiceFactory > xFactory
std::mutex m_aMutex
sal_Int32 nIndex
css::uno::Reference< css::presentation::XSlideShowController > GetSlideShowController(const css::uno::Reference< css::frame::XController > &rxController)
Return the slide show controller of a running presentation that has the same document as the given fr...
cppu::WeakComponentImplHelper< css::drawing::framework::XView, css::awt::XWindowListener, css::awt::XPaintListener, css::beans::XPropertyChangeListener, css::drawing::XSlidePreviewCacheListener, css::awt::XMouseListener, css::awt::XMouseMotionListener, css::drawing::XDrawView > PresenterSlideSorterInterfaceBase
const double gnHorizontalBorder(15)
std::shared_ptr< PresenterBitmapContainer::BitmapDescriptor > SharedBitmapDescriptor
const double gnVerticalBorder(5)
void dispose()
SwNodeOffset abs(const SwNodeOffset &a)
const tools::Long nButtonWidth
unsigned char sal_Bool
sal_Int32 nLength