Bump version to 5.0-14
[LibreOffice.git] / sdext / source / presenter / PresenterSlideSorter.cxx
blobc1024c600706524db64e60b3160d91b969825885
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "vcl/svapp.hxx"
21 #include "vcl/settings.hxx"
23 #include "PresenterSlideSorter.hxx"
24 #include "PresenterButton.hxx"
25 #include "PresenterCanvasHelper.hxx"
26 #include "PresenterGeometryHelper.hxx"
27 #include "PresenterHelper.hxx"
28 #include "PresenterPaintManager.hxx"
29 #include "PresenterPaneBase.hxx"
30 #include "PresenterScrollBar.hxx"
31 #include "PresenterUIPainter.hxx"
32 #include "PresenterWindowManager.hxx"
33 #include <com/sun/star/awt/PosSize.hpp>
34 #include <com/sun/star/awt/XWindowPeer.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/container/XNamed.hpp>
37 #include <com/sun/star/drawing/XSlideSorterBase.hpp>
38 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
39 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
40 #include <com/sun/star/rendering/XBitmapCanvas.hpp>
41 #include <com/sun/star/rendering/CompositeOperation.hpp>
42 #include <com/sun/star/rendering/TextDirection.hpp>
43 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
44 #include <com/sun/star/util/Color.hpp>
45 #include <algorithm>
46 #include <math.h>
47 #include <boost/bind.hpp>
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::drawing::framework;
53 namespace {
54 const static sal_Int32 gnVerticalGap (10);
55 const static sal_Int32 gnVerticalBorder (10);
56 const static sal_Int32 gnHorizontalGap (10);
57 const static sal_Int32 gnHorizontalBorder (10);
59 const static double gnMinimalPreviewWidth (200);
60 const static double gnPreferredPreviewWidth (300);
61 const static double gnMaximalPreviewWidth (400);
62 const static sal_Int32 gnPreferredColumnCount (6);
63 const static double gnMinimalHorizontalPreviewGap(15);
64 const static double gnPreferredHorizontalPreviewGap(25);
65 const static double gnMaximalHorizontalPreviewGap(50);
66 const static double gnPreferredVerticalPreviewGap(25);
68 const static sal_Int32 gnHorizontalLabelBorder (3);
69 const static sal_Int32 gnHorizontalLabelPadding (5);
71 const static sal_Int32 gnVerticalButtonPadding (gnVerticalGap);
74 namespace sdext { namespace presenter {
76 namespace {
77 sal_Int32 round (const double nValue) { return sal::static_int_cast<sal_Int32>(0.5 + nValue); }
78 sal_Int32 floor (const double nValue) { return sal::static_int_cast<sal_Int32>(nValue); }
81 //===== PresenterSlideSorter::Layout ==========================================
83 class PresenterSlideSorter::Layout
85 public:
86 Layout (const ::rtl::Reference<PresenterScrollBar>& rpVerticalScrollBar);
88 void Update (const geometry::RealRectangle2D& rBoundingBox, const double nSlideAspectRatio);
89 void SetupVisibleArea();
90 void UpdateScrollBars();
91 bool IsScrollBarNeeded (const sal_Int32 nSlideCount);
92 geometry::RealPoint2D GetLocalPosition (const geometry::RealPoint2D& rWindowPoint) const;
93 geometry::RealPoint2D GetWindowPosition(const geometry::RealPoint2D& rLocalPoint) const;
94 sal_Int32 GetColumn (const geometry::RealPoint2D& rLocalPoint,
95 const bool bReturnInvalidValue = false) const;
96 sal_Int32 GetRow (const geometry::RealPoint2D& rLocalPoint,
97 const bool bReturnInvalidValue = false) const;
98 sal_Int32 GetSlideIndexForPosition (const css::geometry::RealPoint2D& rPoint) const;
99 css::geometry::RealPoint2D GetPoint (
100 const sal_Int32 nSlideIndex,
101 const sal_Int32 nRelativeHorizontalPosition,
102 const sal_Int32 nRelativeVerticalPosition) const;
103 css::awt::Rectangle GetBoundingBox (const sal_Int32 nSlideIndex) const;
104 void ForAllVisibleSlides (const ::boost::function<void(sal_Int32)>& rAction);
105 sal_Int32 GetFirstVisibleSlideIndex() const;
106 sal_Int32 GetLastVisibleSlideIndex() const;
107 bool SetHorizontalOffset (const double nOffset);
108 bool SetVerticalOffset (const double nOffset);
110 css::geometry::RealRectangle2D maBoundingBox;
111 css::geometry::IntegerSize2D maPreviewSize;
112 sal_Int32 mnHorizontalOffset;
113 sal_Int32 mnVerticalOffset;
114 sal_Int32 mnHorizontalGap;
115 sal_Int32 mnVerticalGap;
116 sal_Int32 mnHorizontalBorder;
117 sal_Int32 mnVerticalBorder;
118 sal_Int32 mnRowCount;
119 sal_Int32 mnColumnCount;
120 sal_Int32 mnSlideCount;
121 sal_Int32 mnSlideIndexAtMouse;
122 sal_Int32 mnFirstVisibleColumn;
123 sal_Int32 mnLastVisibleColumn;
124 sal_Int32 mnFirstVisibleRow;
125 sal_Int32 mnLastVisibleRow;
127 private:
128 ::rtl::Reference<PresenterScrollBar> mpVerticalScrollBar;
130 sal_Int32 GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const;
131 sal_Int32 GetRow (const sal_Int32 nSlideIndex) const;
132 sal_Int32 GetColumn (const sal_Int32 nSlideIndex) const;
135 //==== PresenterSlideSorter::MouseOverManager =================================
137 class PresenterSlideSorter::MouseOverManager
138 : ::boost::noncopyable
140 public:
141 MouseOverManager (
142 const Reference<container::XIndexAccess>& rxSlides,
143 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
144 const Reference<awt::XWindow>& rxInvalidateTarget,
145 const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager);
146 ~MouseOverManager();
148 void Paint (
149 const sal_Int32 nSlideIndex,
150 const Reference<rendering::XCanvas>& rxCanvas,
151 const Reference<rendering::XPolyPolygon2D>& rxClip);
153 void SetSlide (
154 const sal_Int32 nSlideIndex,
155 const awt::Rectangle& rBox);
157 private:
158 Reference<rendering::XCanvas> mxCanvas;
159 const Reference<container::XIndexAccess> mxSlides;
160 SharedBitmapDescriptor mpLeftLabelBitmap;
161 SharedBitmapDescriptor mpCenterLabelBitmap;
162 SharedBitmapDescriptor mpRightLabelBitmap;
163 PresenterTheme::SharedFontDescriptor mpFont;
164 sal_Int32 mnSlideIndex;
165 awt::Rectangle maSlideBoundingBox;
166 OUString msText;
167 Reference<rendering::XBitmap> mxBitmap;
168 Reference<awt::XWindow> mxInvalidateTarget;
169 ::boost::shared_ptr<PresenterPaintManager> mpPaintManager;
171 void SetCanvas (
172 const Reference<rendering::XCanvas>& rxCanvas);
173 /** Create a bitmap that shows the given text and is not wider than the
174 given maximal width.
176 Reference<rendering::XBitmap> CreateBitmap (
177 const OUString& rsText,
178 const sal_Int32 nMaximalWidth) const;
179 void Invalidate();
180 geometry::IntegerSize2D CalculateLabelSize (
181 const OUString& rsText) const;
182 OUString GetFittingText (const OUString& rsText, const double nMaximalWidth) const;
183 void PaintButtonBackground (
184 const Reference<rendering::XCanvas>& rxCanvas,
185 const geometry::IntegerSize2D& rSize) const;
188 //==== PresenterSlideSorter::CurrentSlideFrameRenderer ========================
190 class PresenterSlideSorter::CurrentSlideFrameRenderer
192 public:
193 CurrentSlideFrameRenderer (
194 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
195 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas);
196 ~CurrentSlideFrameRenderer();
198 void PaintCurrentSlideFrame (
199 const awt::Rectangle& rSlideBoundingBox,
200 const Reference<rendering::XCanvas>& rxCanvas,
201 const geometry::RealRectangle2D& rClipBox);
203 /** Enlarge the given rectangle to include the current slide indicator.
205 awt::Rectangle GetBoundingBox (
206 const awt::Rectangle& rSlideBoundingBox);
208 private:
209 SharedBitmapDescriptor mpTopLeft;
210 SharedBitmapDescriptor mpTop;
211 SharedBitmapDescriptor mpTopRight;
212 SharedBitmapDescriptor mpLeft;
213 SharedBitmapDescriptor mpRight;
214 SharedBitmapDescriptor mpBottomLeft;
215 SharedBitmapDescriptor mpBottom;
216 SharedBitmapDescriptor mpBottomRight;
217 sal_Int32 mnTopFrameSize;
218 sal_Int32 mnLeftFrameSize;
219 sal_Int32 mnRightFrameSize;
220 sal_Int32 mnBottomFrameSize;
222 static void PaintBitmapOnce(
223 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
224 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
225 const Reference<rendering::XPolyPolygon2D>& rxClip,
226 const double nX,
227 const double nY);
228 static void PaintBitmapTiled(
229 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
230 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
231 const geometry::RealRectangle2D& rClipBox,
232 const double nX,
233 const double nY,
234 const double nWidth,
235 const double nHeight);
238 //===== PresenterSlideSorter ==================================================
240 PresenterSlideSorter::PresenterSlideSorter (
241 const Reference<uno::XComponentContext>& rxContext,
242 const Reference<XResourceId>& rxViewId,
243 const Reference<frame::XController>& rxController,
244 const ::rtl::Reference<PresenterController>& rpPresenterController)
245 : PresenterSlideSorterInterfaceBase(m_aMutex),
246 mxComponentContext(rxContext),
247 mxViewId(rxViewId),
248 mxPane(),
249 mxCanvas(),
250 mxWindow(),
251 mpPresenterController(rpPresenterController),
252 mxSlideShowController(mpPresenterController->GetSlideShowController()),
253 mxPreviewCache(),
254 mbIsPaintPending(true),
255 mbIsLayoutPending(true),
256 mpLayout(),
257 mpVerticalScrollBar(),
258 mpCloseButton(),
259 mpMouseOverManager(),
260 mnSlideIndexMousePressed(-1),
261 mnCurrentSlideIndex(-1),
262 mnSeparatorY(0),
263 maSeparatorColor(0x00ffffff),
264 maCloseButtonCenter(),
265 maCurrentSlideFrameBoundingBox(),
266 mpCurrentSlideFrameRenderer(),
267 mxPreviewFrame()
269 if ( ! rxContext.is()
270 || ! rxViewId.is()
271 || ! rxController.is()
272 || rpPresenterController.get()==NULL)
274 throw lang::IllegalArgumentException();
277 if ( ! mxSlideShowController.is())
278 throw RuntimeException();
282 // Get pane and window.
283 Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
284 Reference<XConfigurationController> xCC (
285 xCM->getConfigurationController(), UNO_QUERY_THROW);
286 Reference<lang::XMultiComponentFactory> xFactory (
287 mxComponentContext->getServiceManager(), UNO_QUERY_THROW);
289 mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
290 mxWindow = mxPane->getWindow();
292 // Add window listener.
293 mxWindow->addWindowListener(this);
294 mxWindow->addPaintListener(this);
295 mxWindow->addMouseListener(this);
296 mxWindow->addMouseMotionListener(this);
297 mxWindow->setVisible(sal_True);
299 // Remember the current slide.
300 mnCurrentSlideIndex = mxSlideShowController->getCurrentSlideIndex();
302 // Create the scroll bar.
303 mpVerticalScrollBar = ::rtl::Reference<PresenterScrollBar>(
304 new PresenterVerticalScrollBar(
305 rxContext,
306 mxWindow,
307 mpPresenterController->GetPaintManager(),
308 ::boost::bind(&PresenterSlideSorter::SetVerticalOffset,this,_1)));
310 mpCloseButton = PresenterButton::Create(
311 rxContext,
312 mpPresenterController,
313 mpPresenterController->GetTheme(),
314 mxWindow,
315 mxCanvas,
316 "SlideSorterCloser");
318 if (mpPresenterController->GetTheme().get() != NULL)
320 PresenterTheme::SharedFontDescriptor pFont (
321 mpPresenterController->GetTheme()->GetFont("ButtonFont"));
322 if (pFont.get() != NULL)
323 maSeparatorColor = pFont->mnColor;
326 // Create the layout.
327 mpLayout.reset(new Layout(mpVerticalScrollBar));
329 // Create the preview cache.
330 mxPreviewCache = Reference<drawing::XSlidePreviewCache>(
331 xFactory->createInstanceWithContext(
332 OUString("com.sun.star.drawing.PresenterPreviewCache"),
333 mxComponentContext),
334 UNO_QUERY_THROW);
335 Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY);
336 mxPreviewCache->setDocumentSlides(xSlides, rxController->getModel());
337 mxPreviewCache->addPreviewCreationNotifyListener(this);
338 if (xSlides.is())
340 mpLayout->mnSlideCount = xSlides->getCount();
343 // Create the mouse over manager.
344 mpMouseOverManager.reset(new MouseOverManager(
345 Reference<container::XIndexAccess>(mxSlideShowController, UNO_QUERY),
346 mpPresenterController->GetTheme(),
347 mxWindow,
348 mpPresenterController->GetPaintManager()));
350 // Listen for changes of the current slide.
351 Reference<beans::XPropertySet> xControllerProperties (rxController, UNO_QUERY_THROW);
352 xControllerProperties->addPropertyChangeListener(
353 OUString("CurrentPage"),
354 this);
356 // Move the current slide in the center of the window.
357 const awt::Rectangle aCurrentSlideBBox (mpLayout->GetBoundingBox(mnCurrentSlideIndex));
358 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
359 SetHorizontalOffset(aCurrentSlideBBox.X - aWindowBox.Width/2.0);
361 catch (RuntimeException&)
363 disposing();
364 throw;
368 PresenterSlideSorter::~PresenterSlideSorter()
372 void SAL_CALL PresenterSlideSorter::disposing()
374 mxComponentContext = NULL;
375 mxViewId = NULL;
376 mxPane = NULL;
378 if (mpVerticalScrollBar.is())
380 Reference<lang::XComponent> xComponent (
381 static_cast<XWeak*>(mpVerticalScrollBar.get()), UNO_QUERY);
382 mpVerticalScrollBar = NULL;
383 if (xComponent.is())
384 xComponent->dispose();
386 if (mpCloseButton.is())
388 Reference<lang::XComponent> xComponent (
389 static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY);
390 mpCloseButton = NULL;
391 if (xComponent.is())
392 xComponent->dispose();
395 if (mxCanvas.is())
397 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
398 if (xComponent.is())
399 xComponent->removeEventListener(static_cast<awt::XWindowListener*>(this));
400 mxCanvas = NULL;
402 mpPresenterController = NULL;
403 mxSlideShowController = NULL;
404 mpLayout.reset();
405 mpMouseOverManager.reset();
407 if (mxPreviewCache.is())
409 mxPreviewCache->removePreviewCreationNotifyListener(this);
411 Reference<XComponent> xComponent (mxPreviewCache, UNO_QUERY);
412 mxPreviewCache = NULL;
413 if (xComponent.is())
414 xComponent->dispose();
417 if (mxWindow.is())
419 mxWindow->removeWindowListener(this);
420 mxWindow->removePaintListener(this);
421 mxWindow->removeMouseListener(this);
422 mxWindow->removeMouseMotionListener(this);
426 void PresenterSlideSorter::SetActiveState (const bool bIsActive)
428 (void)bIsActive;
431 //----- lang::XEventListener --------------------------------------------------
433 void SAL_CALL PresenterSlideSorter::disposing (const lang::EventObject& rEventObject)
434 throw (RuntimeException, std::exception)
436 if (rEventObject.Source == mxWindow)
438 mxWindow = NULL;
439 dispose();
441 else if (rEventObject.Source == mxPreviewCache)
443 mxPreviewCache = NULL;
444 dispose();
446 else if (rEventObject.Source == mxCanvas)
448 mxCanvas = NULL;
449 mbIsLayoutPending = true;
450 mbIsPaintPending = true;
452 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
456 //----- XWindowListener -------------------------------------------------------
458 void SAL_CALL PresenterSlideSorter::windowResized (const awt::WindowEvent& rEvent)
459 throw (uno::RuntimeException, std::exception)
461 (void)rEvent;
462 ThrowIfDisposed();
463 mbIsLayoutPending = true;
464 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
467 void SAL_CALL PresenterSlideSorter::windowMoved (const awt::WindowEvent& rEvent)
468 throw (uno::RuntimeException, std::exception)
470 (void)rEvent;
471 ThrowIfDisposed();
474 void SAL_CALL PresenterSlideSorter::windowShown (const lang::EventObject& rEvent)
475 throw (uno::RuntimeException, std::exception)
477 (void)rEvent;
478 ThrowIfDisposed();
479 mbIsLayoutPending = true;
480 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
483 void SAL_CALL PresenterSlideSorter::windowHidden (const lang::EventObject& rEvent)
484 throw (uno::RuntimeException, std::exception)
486 (void)rEvent;
487 ThrowIfDisposed();
490 //----- XPaintListener --------------------------------------------------------
492 void SAL_CALL PresenterSlideSorter::windowPaint (const css::awt::PaintEvent& rEvent)
493 throw (RuntimeException, std::exception)
495 (void)rEvent;
497 // Deactivated views must not be painted.
498 if ( ! mbIsPresenterViewActive)
499 return;
501 Paint(rEvent.UpdateRect);
503 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
504 if (xSpriteCanvas.is())
505 xSpriteCanvas->updateScreen(sal_False);
508 //----- XMouseListener --------------------------------------------------------
510 void SAL_CALL PresenterSlideSorter::mousePressed (const css::awt::MouseEvent& rEvent)
511 throw(css::uno::RuntimeException, std::exception)
513 css::awt::MouseEvent rTemp =rEvent;
514 /// check whether RTL interface or not
515 if(AllSettings::GetLayoutRTL()){
516 awt::Rectangle aBox = mxWindow->getPosSize();
517 rTemp.X=aBox.Width-rEvent.X;
519 const geometry::RealPoint2D aPosition(rTemp.X, rEvent.Y);
520 mnSlideIndexMousePressed = mpLayout->GetSlideIndexForPosition(aPosition);
523 void SAL_CALL PresenterSlideSorter::mouseReleased (const css::awt::MouseEvent& rEvent)
524 throw(css::uno::RuntimeException, std::exception)
526 css::awt::MouseEvent rTemp =rEvent;
527 /// check whether RTL interface or not
528 if(AllSettings::GetLayoutRTL()){
529 awt::Rectangle aBox = mxWindow->getPosSize();
530 rTemp.X=aBox.Width-rEvent.X;
532 const geometry::RealPoint2D aPosition(rTemp.X, rEvent.Y);
533 const sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));
535 if (nSlideIndex == mnSlideIndexMousePressed && mnSlideIndexMousePressed >= 0)
537 switch (rEvent.ClickCount)
539 case 1:
540 default:
541 GotoSlide(nSlideIndex);
542 break;
544 case 2:
545 OSL_ASSERT(mpPresenterController.get()!=NULL);
546 OSL_ASSERT(mpPresenterController->GetWindowManager().get()!=NULL);
547 mpPresenterController->GetWindowManager()->SetSlideSorterState(false);
548 GotoSlide(nSlideIndex);
549 break;
554 void SAL_CALL PresenterSlideSorter::mouseEntered (const css::awt::MouseEvent& rEvent)
555 throw(css::uno::RuntimeException, std::exception)
557 (void)rEvent;
560 void SAL_CALL PresenterSlideSorter::mouseExited (const css::awt::MouseEvent& rEvent)
561 throw(css::uno::RuntimeException, std::exception)
563 (void)rEvent;
564 mnSlideIndexMousePressed = -1;
565 if (mpMouseOverManager.get() != NULL)
566 mpMouseOverManager->SetSlide(mnSlideIndexMousePressed, awt::Rectangle(0,0,0,0));
569 //----- XMouseMotionListener --------------------------------------------------
571 void SAL_CALL PresenterSlideSorter::mouseMoved (const css::awt::MouseEvent& rEvent)
572 throw (css::uno::RuntimeException, std::exception)
574 if (mpMouseOverManager.get() != NULL)
576 css::awt::MouseEvent rTemp =rEvent;
577 /// check whether RTL interface or not
578 if(AllSettings::GetLayoutRTL()){
579 awt::Rectangle aBox = mxWindow->getPosSize();
580 rTemp.X=aBox.Width-rEvent.X;
582 const geometry::RealPoint2D aPosition(rTemp.X, rEvent.Y);
583 sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));
585 if (nSlideIndex < 0)
586 mnSlideIndexMousePressed = -1;
588 if (nSlideIndex < 0)
590 mpMouseOverManager->SetSlide(nSlideIndex, awt::Rectangle(0,0,0,0));
592 else
594 mpMouseOverManager->SetSlide(
595 nSlideIndex,
596 mpLayout->GetBoundingBox(nSlideIndex));
601 void SAL_CALL PresenterSlideSorter::mouseDragged (const css::awt::MouseEvent& rEvent)
602 throw (css::uno::RuntimeException, std::exception)
604 (void)rEvent;
607 //----- XResourceId -----------------------------------------------------------
609 Reference<XResourceId> SAL_CALL PresenterSlideSorter::getResourceId()
610 throw (RuntimeException, std::exception)
612 ThrowIfDisposed();
613 return mxViewId;
616 sal_Bool SAL_CALL PresenterSlideSorter::isAnchorOnly()
617 throw (RuntimeException, std::exception)
619 return false;
622 //----- XPropertyChangeListener -----------------------------------------------
624 void SAL_CALL PresenterSlideSorter::propertyChange (
625 const css::beans::PropertyChangeEvent& rEvent)
626 throw(css::uno::RuntimeException, std::exception)
628 (void)rEvent;
631 //----- XSlidePreviewCacheListener --------------------------------------------
633 void SAL_CALL PresenterSlideSorter::notifyPreviewCreation (
634 sal_Int32 nSlideIndex)
635 throw(css::uno::RuntimeException, std::exception)
637 OSL_ASSERT(mpLayout.get()!=NULL);
639 awt::Rectangle aBBox (mpLayout->GetBoundingBox(nSlideIndex));
640 mpPresenterController->GetPaintManager()->Invalidate(mxWindow, aBBox, true);
643 //----- XDrawView -------------------------------------------------------------
645 void SAL_CALL PresenterSlideSorter::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
646 throw (RuntimeException, std::exception)
648 (void)rxSlide;
650 ThrowIfDisposed();
651 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
653 if (mxSlideShowController.is())
655 const sal_Int32 nNewCurrentSlideIndex (mxSlideShowController->getCurrentSlideIndex());
656 if (nNewCurrentSlideIndex != mnCurrentSlideIndex)
658 mnCurrentSlideIndex = nNewCurrentSlideIndex;
660 // Request a repaint of the previous current slide to hide its
661 // current slide indicator.
662 mpPresenterController->GetPaintManager()->Invalidate(
663 mxWindow,
664 maCurrentSlideFrameBoundingBox);
666 // Request a repaint of the new current slide to show its
667 // current slide indicator.
668 maCurrentSlideFrameBoundingBox = mpCurrentSlideFrameRenderer->GetBoundingBox(
669 mpLayout->GetBoundingBox(mnCurrentSlideIndex));
670 mpPresenterController->GetPaintManager()->Invalidate(
671 mxWindow,
672 maCurrentSlideFrameBoundingBox);
677 Reference<drawing::XDrawPage> SAL_CALL PresenterSlideSorter::getCurrentPage()
678 throw (RuntimeException, std::exception)
680 ThrowIfDisposed();
681 return NULL;
686 void PresenterSlideSorter::UpdateLayout()
688 if ( ! mxWindow.is())
689 return;
691 mbIsLayoutPending = false;
692 mbIsPaintPending = true;
694 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
695 awt::Rectangle aCenterBox (aWindowBox);
696 sal_Int32 nLeftBorderWidth (aWindowBox.X);
698 // Get border width.
699 PresenterPaneContainer::SharedPaneDescriptor pPane (
700 mpPresenterController->GetPaneContainer()->FindViewURL(
701 mxViewId->getResourceURL()));
704 if (pPane.get() == NULL)
705 break;
706 if ( ! pPane->mxPane.is())
707 break;
709 Reference<drawing::framework::XPaneBorderPainter> xBorderPainter (
710 pPane->mxPane->GetPaneBorderPainter());
711 if ( ! xBorderPainter.is())
712 break;
713 aCenterBox = xBorderPainter->addBorder (
714 mxViewId->getAnchor()->getResourceURL(),
715 awt::Rectangle(0, 0, aWindowBox.Width, aWindowBox.Height),
716 drawing::framework::BorderType_INNER_BORDER);
718 while(false);
720 // Place vertical separator.
721 mnSeparatorY = aWindowBox.Height - mpCloseButton->GetSize().Height - gnVerticalButtonPadding;
723 PlaceCloseButton(pPane, aWindowBox, nLeftBorderWidth);
725 geometry::RealRectangle2D aUpperBox(
726 gnHorizontalBorder,
727 gnVerticalBorder,
728 aWindowBox.Width - 2*gnHorizontalBorder,
729 mnSeparatorY - gnVerticalGap);
731 // Determine whether the scroll bar has to be displayed.
732 aUpperBox = PlaceScrollBars(aUpperBox);
734 mpLayout->Update(aUpperBox, GetSlideAspectRatio());
735 mpLayout->SetupVisibleArea();
736 mpLayout->UpdateScrollBars();
738 // Tell the preview cache about some of the values.
739 mxPreviewCache->setPreviewSize(mpLayout->maPreviewSize);
740 mxPreviewCache->setVisibleRange(
741 mpLayout->GetFirstVisibleSlideIndex(),
742 mpLayout->GetLastVisibleSlideIndex());
744 // Clear the frame polygon so that it is re-created on the next paint.
745 mxPreviewFrame = NULL;
748 geometry::RealRectangle2D PresenterSlideSorter::PlaceScrollBars (
749 const geometry::RealRectangle2D& rUpperBox)
751 mpLayout->Update(rUpperBox, GetSlideAspectRatio());
752 bool bIsScrollBarNeeded (false);
753 Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY_THROW);
754 if (xSlides.is())
755 bIsScrollBarNeeded = mpLayout->IsScrollBarNeeded(xSlides->getCount());
756 if (mpVerticalScrollBar.get() != NULL)
758 if (bIsScrollBarNeeded)
760 if(AllSettings::GetLayoutRTL())
762 mpVerticalScrollBar->SetPosSize(geometry::RealRectangle2D(
763 rUpperBox.X1,
764 rUpperBox.Y1,
765 rUpperBox.X1 + mpVerticalScrollBar->GetSize(),
766 rUpperBox.Y2));
767 mpVerticalScrollBar->SetVisible(true);
768 // Reduce area covered by the scroll bar from the available
769 // space.
770 return geometry::RealRectangle2D(
771 rUpperBox.X1 + gnHorizontalGap + mpVerticalScrollBar->GetSize(),
772 rUpperBox.Y1,
773 rUpperBox.X2,
774 rUpperBox.Y2);
776 else
778 // if its not RTL place vertical scroll bar at right border.
779 mpVerticalScrollBar->SetPosSize(geometry::RealRectangle2D(
780 rUpperBox.X2 - mpVerticalScrollBar->GetSize(),
781 rUpperBox.Y1,
782 rUpperBox.X2,
783 rUpperBox.Y2));
784 mpVerticalScrollBar->SetVisible(true);
785 // Reduce area covered by the scroll bar from the available
786 // space.
787 return geometry::RealRectangle2D(
788 rUpperBox.X1,
789 rUpperBox.Y1,
790 rUpperBox.X2 - mpVerticalScrollBar->GetSize() - gnHorizontalGap,
791 rUpperBox.Y2);
794 else
795 mpVerticalScrollBar->SetVisible(false);
797 return rUpperBox;
800 void PresenterSlideSorter::PlaceCloseButton (
801 const PresenterPaneContainer::SharedPaneDescriptor& rpPane,
802 const awt::Rectangle& rCenterBox,
803 const sal_Int32 nLeftBorderWidth)
805 // Place button. When the callout is near the center then the button is
806 // centered over the callout. Otherwise it is centered with respect to
807 // the whole window.
808 sal_Int32 nCloseButtonCenter (rCenterBox.Width/2);
809 if (rpPane.get() != NULL && rpPane->mxPane.is())
811 const sal_Int32 nCalloutCenter (rpPane->mxPane->GetCalloutAnchor().X - nLeftBorderWidth);
812 const sal_Int32 nDistanceFromWindowCenter (abs(nCalloutCenter - rCenterBox.Width/2));
813 const sal_Int32 nButtonWidth (mpCloseButton->GetSize().Width);
814 const static sal_Int32 nMaxDistanceForCalloutCentering (nButtonWidth * 2);
815 if (nDistanceFromWindowCenter < nMaxDistanceForCalloutCentering)
817 if (nCalloutCenter < nButtonWidth/2)
818 nCloseButtonCenter = nButtonWidth/2;
819 else if (nCalloutCenter > rCenterBox.Width-nButtonWidth/2)
820 nCloseButtonCenter = rCenterBox.Width-nButtonWidth/2;
821 else
822 nCloseButtonCenter = nCalloutCenter;
825 mpCloseButton->SetCenter(geometry::RealPoint2D(
826 nCloseButtonCenter,
827 rCenterBox.Height - mpCloseButton->GetSize().Height/ 2));
830 void PresenterSlideSorter::ClearBackground (
831 const Reference<rendering::XCanvas>& rxCanvas,
832 const awt::Rectangle& rUpdateBox)
834 OSL_ASSERT(rxCanvas.is());
836 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
837 mpPresenterController->GetCanvasHelper()->Paint(
838 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
839 rxCanvas,
840 rUpdateBox,
841 awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
842 awt::Rectangle());
845 double PresenterSlideSorter::GetSlideAspectRatio() const
847 double nSlideAspectRatio (28.0/21.0);
851 Reference<container::XIndexAccess> xSlides(mxSlideShowController, UNO_QUERY_THROW);
852 if (mxSlideShowController.is() && xSlides->getCount()>0)
854 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
855 sal_Int32 nWidth (28000);
856 sal_Int32 nHeight (21000);
857 if ((xProperties->getPropertyValue("Width") >>= nWidth)
858 && (xProperties->getPropertyValue("Height") >>= nHeight)
859 && nHeight > 0)
861 nSlideAspectRatio = double(nWidth) / double(nHeight);
865 catch (RuntimeException&)
867 OSL_ASSERT(false);
870 return nSlideAspectRatio;
873 Reference<rendering::XBitmap> PresenterSlideSorter::GetPreview (const sal_Int32 nSlideIndex)
875 if (nSlideIndex < 0 || nSlideIndex>=mpLayout->mnSlideCount)
876 return NULL;
877 else if (mxPane.is())
878 return mxPreviewCache->getSlidePreview(nSlideIndex, mxPane->getCanvas());
879 else
880 return NULL;
883 void PresenterSlideSorter::PaintPreview (
884 const Reference<rendering::XCanvas>& rxCanvas,
885 const css::awt::Rectangle& rUpdateBox,
886 const sal_Int32 nSlideIndex)
888 OSL_ASSERT(rxCanvas.is());
890 geometry::IntegerSize2D aSize (mpLayout->maPreviewSize);
892 if (PresenterGeometryHelper::AreRectanglesDisjoint(
893 rUpdateBox,
894 mpLayout->GetBoundingBox(nSlideIndex)))
896 return;
899 Reference<rendering::XBitmap> xPreview (GetPreview(nSlideIndex));
900 bool isRTL = AllSettings::GetLayoutRTL();
902 const geometry::RealPoint2D aTopLeft (
903 mpLayout->GetWindowPosition(
904 mpLayout->GetPoint(nSlideIndex, isRTL?1:-1, -1)));
906 PresenterBitmapContainer aContainer (
907 "PresenterScreenSettings/ScrollBar/Bitmaps",
908 ::boost::shared_ptr<PresenterBitmapContainer>(),
909 mxComponentContext,
910 rxCanvas);
911 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
912 Reference<drawing::XDrawPage> xPage = Reference<drawing::XDrawPage>(
913 xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY);
914 bool bTransition = PresenterController::HasTransition(xPage);
915 bool bCustomAnimation = PresenterController::HasCustomAnimation(xPage);
917 // Create clip rectangle as intersection of the current update area and
918 // the bounding box of all previews.
919 geometry::RealRectangle2D aBoundingBox (mpLayout->maBoundingBox);
920 aBoundingBox.Y2 += 1;
921 const geometry::RealRectangle2D aClipBox (
922 PresenterGeometryHelper::Intersection(
923 PresenterGeometryHelper::ConvertRectangle(rUpdateBox),
924 aBoundingBox));
925 Reference<rendering::XPolyPolygon2D> xClip (
926 PresenterGeometryHelper::CreatePolygon(aClipBox, rxCanvas->getDevice()));
928 const rendering::ViewState aViewState (geometry::AffineMatrix2D(1,0,0, 0,1,0), xClip);
930 rendering::RenderState aRenderState (
931 geometry::AffineMatrix2D(
932 1, 0, aTopLeft.X,
933 0, 1, aTopLeft.Y),
934 NULL,
935 Sequence<double>(4),
936 rendering::CompositeOperation::SOURCE);
938 // Emphasize the current slide.
939 if (nSlideIndex == mnCurrentSlideIndex)
941 if (mpCurrentSlideFrameRenderer.get() != NULL)
943 const awt::Rectangle aSlideBoundingBox(
944 sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.X),
945 sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.Y),
946 aSize.Width,
947 aSize.Height);
948 maCurrentSlideFrameBoundingBox
949 = mpCurrentSlideFrameRenderer->GetBoundingBox(aSlideBoundingBox);
950 mpCurrentSlideFrameRenderer->PaintCurrentSlideFrame (
951 aSlideBoundingBox,
952 mxCanvas,
953 aClipBox);
957 // Paint the preview.
958 if (xPreview.is())
960 aSize = xPreview->getSize();
961 if (aSize.Width > 0 && aSize.Height > 0)
963 rxCanvas->drawBitmap(xPreview, aViewState, aRenderState);
964 if( bCustomAnimation )
966 const awt::Rectangle aAnimationPreviewBox(aTopLeft.X+3, aTopLeft.Y+aSize.Height-40, 0, 0);
967 SharedBitmapDescriptor aAnimationDescriptor = aContainer.GetBitmap("Animation");
968 Reference<rendering::XBitmap> xAnimationIcon (aAnimationDescriptor->GetNormalBitmap());
969 rendering::RenderState aAnimationRenderState (
970 geometry::AffineMatrix2D(
971 1, 0, aAnimationPreviewBox.X,
972 0, 1, aAnimationPreviewBox.Y),
973 NULL,
974 Sequence<double>(4),
975 rendering::CompositeOperation::SOURCE);
976 rxCanvas->drawBitmap(xAnimationIcon, aViewState, aAnimationRenderState);
978 if( bTransition )
980 const awt::Rectangle aTransitionPreviewBox(aTopLeft.X+3, aTopLeft.Y+aSize.Height-20, 0, 0);
981 SharedBitmapDescriptor aTransitionDescriptor = aContainer.GetBitmap("Transition");
982 Reference<rendering::XBitmap> xTransitionIcon (aTransitionDescriptor->GetNormalBitmap());
983 rendering::RenderState aTransitionRenderState (
984 geometry::AffineMatrix2D(
985 1, 0, aTransitionPreviewBox.X,
986 0, 1, aTransitionPreviewBox.Y),
987 NULL,
988 Sequence<double>(4),
989 rendering::CompositeOperation::SOURCE);
990 rxCanvas->drawBitmap(xTransitionIcon, aViewState, aTransitionRenderState);
995 // Create a polygon that is used to paint a frame around previews. Its
996 // coordinates are chosen in the local coordinate system of a preview.
997 if ( ! mxPreviewFrame.is())
998 mxPreviewFrame = PresenterGeometryHelper::CreatePolygon(
999 awt::Rectangle(-1, -1, aSize.Width+2, aSize.Height+2),
1000 rxCanvas->getDevice());
1002 // Paint a border around the preview.
1003 if (mxPreviewFrame.is())
1005 const geometry::RealRectangle2D aBox (0, 0, aSize.Width, aSize.Height);
1006 const util::Color aFrameColor (0x00000000);
1007 PresenterCanvasHelper::SetDeviceColor(aRenderState, aFrameColor);
1008 rxCanvas->drawPolyPolygon(mxPreviewFrame, aViewState, aRenderState);
1011 // Paint mouse over effect.
1012 mpMouseOverManager->Paint(nSlideIndex, mxCanvas, xClip);
1015 void PresenterSlideSorter::Paint (const awt::Rectangle& rUpdateBox)
1017 const bool bCanvasChanged ( ! mxCanvas.is());
1018 if ( ! ProvideCanvas())
1019 return;
1021 if (mpLayout->mnRowCount<=0 || mpLayout->mnColumnCount<=0)
1023 OSL_ASSERT(mpLayout->mnRowCount>0 || mpLayout->mnColumnCount>0);
1024 return;
1027 mbIsPaintPending = false;
1029 ClearBackground(mxCanvas, rUpdateBox);
1031 // Give the canvas to the controls.
1032 if (bCanvasChanged)
1034 if (mpVerticalScrollBar.is())
1035 mpVerticalScrollBar->SetCanvas(mxCanvas);
1036 if (mpCloseButton.is())
1037 mpCloseButton->SetCanvas(mxCanvas, mxWindow);
1040 // Now that the controls have a canvas we can do the layouting.
1041 if (mbIsLayoutPending)
1042 UpdateLayout();
1044 // Paint the horizontal separator.
1045 rendering::RenderState aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0),
1046 NULL, Sequence<double>(4), rendering::CompositeOperation::SOURCE);
1047 PresenterCanvasHelper::SetDeviceColor(aRenderState, maSeparatorColor);
1048 mxCanvas->drawLine(
1049 geometry::RealPoint2D(0, mnSeparatorY),
1050 geometry::RealPoint2D(mxWindow->getPosSize().Width, mnSeparatorY),
1051 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL),
1052 aRenderState);
1054 // Paint the slides.
1055 if ( ! PresenterGeometryHelper::AreRectanglesDisjoint(
1056 rUpdateBox,
1057 PresenterGeometryHelper::ConvertRectangle(mpLayout->maBoundingBox)))
1059 mpLayout->ForAllVisibleSlides(
1060 ::boost::bind(&PresenterSlideSorter::PaintPreview, this, mxCanvas, rUpdateBox, _1));
1063 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
1064 if (xSpriteCanvas.is())
1065 xSpriteCanvas->updateScreen(sal_False);
1068 void PresenterSlideSorter::SetHorizontalOffset (const double nXOffset)
1070 if (mpLayout->SetHorizontalOffset(nXOffset))
1072 mxPreviewCache->setVisibleRange(
1073 mpLayout->GetFirstVisibleSlideIndex(),
1074 mpLayout->GetLastVisibleSlideIndex());
1076 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
1080 void PresenterSlideSorter::SetVerticalOffset (const double nYOffset)
1082 if (mpLayout->SetVerticalOffset(nYOffset))
1084 mxPreviewCache->setVisibleRange(
1085 mpLayout->GetFirstVisibleSlideIndex(),
1086 mpLayout->GetLastVisibleSlideIndex());
1088 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
1092 void PresenterSlideSorter::GotoSlide (const sal_Int32 nSlideIndex)
1094 mxSlideShowController->gotoSlideIndex(nSlideIndex);
1097 bool PresenterSlideSorter::ProvideCanvas()
1099 if ( ! mxCanvas.is())
1101 if (mxPane.is())
1102 mxCanvas = mxPane->getCanvas();
1104 // Register as event listener so that we are informed when the
1105 // canvas is disposed (and we have to fetch another one).
1106 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
1107 if (xComponent.is())
1108 xComponent->addEventListener(static_cast<awt::XWindowListener*>(this));
1110 mpCurrentSlideFrameRenderer.reset(
1111 new CurrentSlideFrameRenderer(mxComponentContext, mxCanvas));
1113 return mxCanvas.is();
1116 void PresenterSlideSorter::ThrowIfDisposed()
1117 throw (lang::DisposedException)
1119 if (rBHelper.bDisposed || rBHelper.bInDispose)
1121 throw lang::DisposedException (
1122 OUString(
1123 "PresenterSlideSorter has been already disposed"),
1124 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1128 //===== PresenterSlideSorter::Layout ==========================================
1130 PresenterSlideSorter::Layout::Layout (
1131 const ::rtl::Reference<PresenterScrollBar>& rpVerticalScrollBar)
1132 : maBoundingBox(),
1133 maPreviewSize(),
1134 mnHorizontalOffset(0),
1135 mnVerticalOffset(0),
1136 mnHorizontalGap(0),
1137 mnVerticalGap(0),
1138 mnHorizontalBorder(0),
1139 mnVerticalBorder(0),
1140 mnRowCount(1),
1141 mnColumnCount(1),
1142 mnSlideCount(0),
1143 mnSlideIndexAtMouse(-1),
1144 mnFirstVisibleColumn(-1),
1145 mnLastVisibleColumn(-1),
1146 mnFirstVisibleRow(-1),
1147 mnLastVisibleRow(-1),
1148 mpVerticalScrollBar(rpVerticalScrollBar)
1152 void PresenterSlideSorter::Layout::Update (
1153 const geometry::RealRectangle2D& rBoundingBox,
1154 const double nSlideAspectRatio)
1156 maBoundingBox = rBoundingBox;
1158 mnHorizontalBorder = gnHorizontalBorder;
1159 mnVerticalBorder = gnVerticalBorder;
1161 const double nWidth (rBoundingBox.X2 - rBoundingBox.X1 - 2*mnHorizontalBorder);
1162 const double nHeight (rBoundingBox.Y2 - rBoundingBox.Y1 - 2*mnVerticalBorder);
1163 if (nWidth<=0 || nHeight<=0)
1164 return;
1166 double nPreviewWidth;
1168 // Determine column count, preview width, and horizontal gap (borders
1169 // are half the gap). Try to use the preferred values. Try more to
1170 // stay in the valid intervalls. This last constraint may be not
1171 // fulfilled in some cases.
1172 const double nElementWidth = nWidth / gnPreferredColumnCount;
1173 if (nElementWidth < gnMinimalPreviewWidth + gnMinimalHorizontalPreviewGap)
1175 // The preferred column count is too large.
1176 // Can we use the preferred preview width?
1177 if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
1179 // Yes.
1180 nPreviewWidth = gnPreferredPreviewWidth;
1181 mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
1182 / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
1183 mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1185 else
1187 // No. Set the column count to 1 and adapt preview width and
1188 // gap.
1189 mnColumnCount = 1;
1190 mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
1191 if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
1192 nPreviewWidth = nWidth - gnMinimalHorizontalPreviewGap;
1193 else
1194 nPreviewWidth = ::std::max(gnMinimalPreviewWidth, nWidth-mnHorizontalGap);
1197 else if (nElementWidth > gnMaximalPreviewWidth + gnMaximalHorizontalPreviewGap)
1199 // The preferred column count is too small.
1200 nPreviewWidth = gnPreferredPreviewWidth;
1201 mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
1202 / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
1203 mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1205 else
1207 // The preferred column count is possible. Determine gap and
1208 // preview width.
1209 mnColumnCount = gnPreferredColumnCount;
1210 if (nElementWidth - gnPreferredPreviewWidth < gnMinimalHorizontalPreviewGap)
1212 // Use the minimal gap and adapt the preview width.
1213 mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
1214 nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
1216 else if (nElementWidth - gnPreferredPreviewWidth <= gnMaximalHorizontalPreviewGap)
1218 // Use the maximal gap and adapt the preview width.
1219 mnHorizontalGap = round(gnMaximalHorizontalPreviewGap);
1220 nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
1222 else
1224 // Use the preferred preview width and adapt the gap.
1225 nPreviewWidth = gnPreferredPreviewWidth;
1226 mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1230 // Now determine the row count, preview height, and vertical gap.
1231 const double nPreviewHeight = nPreviewWidth / nSlideAspectRatio;
1232 mnRowCount = ::std::max(
1233 sal_Int32(1),
1234 sal_Int32(ceil((nHeight+gnPreferredVerticalPreviewGap)
1235 / (nPreviewHeight + gnPreferredVerticalPreviewGap))));
1236 mnVerticalGap = round(gnPreferredVerticalPreviewGap);
1238 maPreviewSize = geometry::IntegerSize2D(floor(nPreviewWidth), floor(nPreviewHeight));
1240 // Reset the offset.
1241 mnVerticalOffset = 0;
1242 mnHorizontalOffset = round(-(nWidth
1243 - mnColumnCount*maPreviewSize.Width
1244 - (mnColumnCount-1)*mnHorizontalGap)
1245 / 2);
1248 void PresenterSlideSorter::Layout::SetupVisibleArea()
1250 geometry::RealPoint2D aPoint (GetLocalPosition(
1251 geometry::RealPoint2D(maBoundingBox.X1, maBoundingBox.Y1)));
1252 mnFirstVisibleColumn = 0;
1253 mnFirstVisibleRow = ::std::max(sal_Int32(0), GetRow(aPoint));
1255 aPoint = GetLocalPosition(geometry::RealPoint2D( maBoundingBox.X2, maBoundingBox.Y2));
1256 mnLastVisibleColumn = mnColumnCount - 1;
1257 mnLastVisibleRow = GetRow(aPoint, true);
1260 bool PresenterSlideSorter::Layout::IsScrollBarNeeded (const sal_Int32 nSlideCount)
1262 geometry::RealPoint2D aBottomRight;
1263 aBottomRight = GetPoint(
1264 mnColumnCount * (GetRow(nSlideCount)+1) - 1, +1, +1);
1265 return aBottomRight.X > maBoundingBox.X2-maBoundingBox.X1
1266 || aBottomRight.Y > maBoundingBox.Y2-maBoundingBox.Y1;
1269 geometry::RealPoint2D PresenterSlideSorter::Layout::GetLocalPosition(
1270 const geometry::RealPoint2D& rWindowPoint) const
1272 if(AllSettings::GetLayoutRTL())
1274 return css::geometry::RealPoint2D(
1275 -rWindowPoint.X + maBoundingBox.X2 + mnHorizontalOffset,
1276 rWindowPoint.Y - maBoundingBox.Y1 + mnVerticalOffset);
1278 else
1280 return css::geometry::RealPoint2D(
1281 rWindowPoint.X - maBoundingBox.X1 + mnHorizontalOffset,
1282 rWindowPoint.Y - maBoundingBox.Y1 + mnVerticalOffset);
1286 geometry::RealPoint2D PresenterSlideSorter::Layout::GetWindowPosition(
1287 const geometry::RealPoint2D& rLocalPoint) const
1289 if(AllSettings::GetLayoutRTL())
1291 return css::geometry::RealPoint2D(
1292 -rLocalPoint.X + mnHorizontalOffset + maBoundingBox.X2,
1293 rLocalPoint.Y - mnVerticalOffset + maBoundingBox.Y1);
1295 else
1297 return css::geometry::RealPoint2D(
1298 rLocalPoint.X - mnHorizontalOffset + maBoundingBox.X1,
1299 rLocalPoint.Y - mnVerticalOffset + maBoundingBox.Y1);
1303 sal_Int32 PresenterSlideSorter::Layout::GetColumn (
1304 const css::geometry::RealPoint2D& rLocalPoint,
1305 const bool bReturnInvalidValue) const
1307 const sal_Int32 nColumn(floor(
1308 (rLocalPoint.X + mnHorizontalGap/2.0) / (maPreviewSize.Width+mnHorizontalGap)));
1309 if (bReturnInvalidValue
1310 || (nColumn>=mnFirstVisibleColumn && nColumn<=mnLastVisibleColumn))
1312 return nColumn;
1314 else
1315 return -1;
1318 sal_Int32 PresenterSlideSorter::Layout::GetRow (
1319 const css::geometry::RealPoint2D& rLocalPoint,
1320 const bool bReturnInvalidValue) const
1322 const sal_Int32 nRow (floor(
1323 (rLocalPoint.Y + mnVerticalGap/2.0) / (maPreviewSize.Height+mnVerticalGap)));
1324 if (bReturnInvalidValue
1325 || (nRow>=mnFirstVisibleRow && nRow<=mnLastVisibleRow))
1327 return nRow;
1329 else
1330 return -1;
1333 sal_Int32 PresenterSlideSorter::Layout::GetSlideIndexForPosition (
1334 const css::geometry::RealPoint2D& rWindowPoint) const
1336 if ( ! PresenterGeometryHelper::IsInside(maBoundingBox, rWindowPoint))
1337 return -1;
1339 const css::geometry::RealPoint2D aLocalPosition (GetLocalPosition(rWindowPoint));
1340 const sal_Int32 nColumn (GetColumn(aLocalPosition));
1341 const sal_Int32 nRow (GetRow(aLocalPosition));
1343 if (nColumn < 0 || nRow < 0)
1344 return -1;
1345 else
1347 sal_Int32 nIndex (GetIndex(nRow, nColumn));
1348 if (nIndex >= mnSlideCount)
1349 return -1;
1350 else
1351 return nIndex;
1355 geometry::RealPoint2D PresenterSlideSorter::Layout::GetPoint (
1356 const sal_Int32 nSlideIndex,
1357 const sal_Int32 nRelativeHorizontalPosition,
1358 const sal_Int32 nRelativeVerticalPosition) const
1360 sal_Int32 nColumn (GetColumn(nSlideIndex));
1361 sal_Int32 nRow (GetRow(nSlideIndex));
1363 geometry::RealPoint2D aPosition (
1364 mnHorizontalBorder + nColumn*(maPreviewSize.Width+mnHorizontalGap),
1365 mnVerticalBorder + nRow*(maPreviewSize.Height+mnVerticalGap));
1367 if (nRelativeHorizontalPosition >= 0)
1369 if (nRelativeHorizontalPosition > 0)
1370 aPosition.X += maPreviewSize.Width;
1371 else
1372 aPosition.X += maPreviewSize.Width / 2.0;
1374 if (nRelativeVerticalPosition >= 0)
1376 if (nRelativeVerticalPosition > 0)
1377 aPosition.Y += maPreviewSize.Height;
1378 else
1379 aPosition.Y += maPreviewSize.Height / 2.0;
1382 return aPosition;
1385 awt::Rectangle PresenterSlideSorter::Layout::GetBoundingBox (const sal_Int32 nSlideIndex) const
1387 bool isRTL = AllSettings::GetLayoutRTL();
1388 const geometry::RealPoint2D aWindowPosition(GetWindowPosition(GetPoint(nSlideIndex, isRTL?1:-1, -1)));
1389 return PresenterGeometryHelper::ConvertRectangle(
1390 geometry::RealRectangle2D(
1391 aWindowPosition.X,
1392 aWindowPosition.Y,
1393 aWindowPosition.X + maPreviewSize.Width,
1394 aWindowPosition.Y + maPreviewSize.Height));
1397 void PresenterSlideSorter::Layout::ForAllVisibleSlides (const ::boost::function<void(sal_Int32)>& rAction)
1399 for (sal_Int32 nRow=mnFirstVisibleRow; nRow<=mnLastVisibleRow; ++nRow)
1401 for (sal_Int32 nColumn=mnFirstVisibleColumn; nColumn<=mnLastVisibleColumn; ++nColumn)
1403 const sal_Int32 nSlideIndex (GetIndex(nRow, nColumn));
1404 if (nSlideIndex >= mnSlideCount)
1405 return;
1406 rAction(nSlideIndex);
1411 sal_Int32 PresenterSlideSorter::Layout::GetFirstVisibleSlideIndex() const
1413 return GetIndex(mnFirstVisibleRow, mnFirstVisibleColumn);
1416 sal_Int32 PresenterSlideSorter::Layout::GetLastVisibleSlideIndex() const
1418 return ::std::min(
1419 GetIndex(mnLastVisibleRow, mnLastVisibleColumn),
1420 mnSlideCount);
1423 bool PresenterSlideSorter::Layout::SetHorizontalOffset (const double nOffset)
1425 if (mnHorizontalOffset != nOffset)
1427 mnHorizontalOffset = round(nOffset);
1428 SetupVisibleArea();
1429 UpdateScrollBars();
1430 return true;
1432 else
1433 return false;
1436 bool PresenterSlideSorter::Layout::SetVerticalOffset (const double nOffset)
1438 if (mnVerticalOffset != nOffset)
1440 mnVerticalOffset = round(nOffset);
1441 SetupVisibleArea();
1442 UpdateScrollBars();
1443 return true;
1445 else
1446 return false;
1449 void PresenterSlideSorter::Layout::UpdateScrollBars()
1451 sal_Int32 nTotalRowCount (0);
1452 nTotalRowCount = sal_Int32(ceil(double(mnSlideCount) / double(mnColumnCount)));
1454 if (mpVerticalScrollBar.get() != NULL)
1456 mpVerticalScrollBar->SetTotalSize(
1457 nTotalRowCount * maPreviewSize.Height
1458 + (nTotalRowCount-1) * mnVerticalGap
1459 + 2*mnVerticalGap);
1460 mpVerticalScrollBar->SetThumbPosition(mnVerticalOffset, false);
1461 mpVerticalScrollBar->SetThumbSize(maBoundingBox.Y2 - maBoundingBox.Y1 + 1);
1462 mpVerticalScrollBar->SetLineHeight(maPreviewSize.Height);
1465 // No place yet for the vertical scroll bar.
1468 sal_Int32 PresenterSlideSorter::Layout::GetIndex (
1469 const sal_Int32 nRow,
1470 const sal_Int32 nColumn) const
1472 return nRow * mnColumnCount + nColumn;
1475 sal_Int32 PresenterSlideSorter::Layout::GetRow (const sal_Int32 nSlideIndex) const
1477 return nSlideIndex / mnColumnCount;
1480 sal_Int32 PresenterSlideSorter::Layout::GetColumn (const sal_Int32 nSlideIndex) const
1482 return nSlideIndex % mnColumnCount;
1485 //===== PresenterSlideSorter::MouseOverManager ================================
1487 PresenterSlideSorter::MouseOverManager::MouseOverManager (
1488 const Reference<container::XIndexAccess>& rxSlides,
1489 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
1490 const Reference<awt::XWindow>& rxInvalidateTarget,
1491 const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager)
1492 : mxCanvas(),
1493 mxSlides(rxSlides),
1494 mpLeftLabelBitmap(),
1495 mpCenterLabelBitmap(),
1496 mpRightLabelBitmap(),
1497 mpFont(),
1498 mnSlideIndex(-1),
1499 maSlideBoundingBox(),
1500 mxInvalidateTarget(rxInvalidateTarget),
1501 mpPaintManager(rpPaintManager)
1503 if (rpTheme.get()!=NULL)
1505 ::boost::shared_ptr<PresenterBitmapContainer> pBitmaps (rpTheme->GetBitmapContainer());
1506 if (pBitmaps.get() != NULL)
1508 mpLeftLabelBitmap = pBitmaps->GetBitmap("LabelLeft");
1509 mpCenterLabelBitmap = pBitmaps->GetBitmap("LabelCenter");
1510 mpRightLabelBitmap = pBitmaps->GetBitmap("LabelRight");
1513 mpFont = rpTheme->GetFont("SlideSorterLabelFont");
1517 PresenterSlideSorter::MouseOverManager::~MouseOverManager()
1521 void PresenterSlideSorter::MouseOverManager::Paint (
1522 const sal_Int32 nSlideIndex,
1523 const Reference<rendering::XCanvas>& rxCanvas,
1524 const Reference<rendering::XPolyPolygon2D>& rxClip)
1526 if (nSlideIndex != mnSlideIndex)
1527 return;
1529 if (mxCanvas != rxCanvas)
1530 SetCanvas(rxCanvas);
1531 if (rxCanvas != NULL)
1533 if ( ! mxBitmap.is())
1534 mxBitmap = CreateBitmap(msText, maSlideBoundingBox.Width);
1535 if (mxBitmap.is())
1537 geometry::IntegerSize2D aSize (mxBitmap->getSize());
1538 const double nXOffset (maSlideBoundingBox.X
1539 + (maSlideBoundingBox.Width - aSize.Width) / 2.0);
1540 const double nYOffset (maSlideBoundingBox.Y
1541 + (maSlideBoundingBox.Height - aSize.Height) / 2.0);
1542 rxCanvas->drawBitmap(
1543 mxBitmap,
1544 rendering::ViewState(
1545 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1546 rxClip),
1547 rendering::RenderState(
1548 geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset),
1549 NULL,
1550 Sequence<double>(4),
1551 rendering::CompositeOperation::SOURCE));
1556 void PresenterSlideSorter::MouseOverManager::SetCanvas (
1557 const Reference<rendering::XCanvas>& rxCanvas)
1559 mxCanvas = rxCanvas;
1560 if (mpFont.get() != NULL)
1561 mpFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY));
1564 void PresenterSlideSorter::MouseOverManager::SetSlide (
1565 const sal_Int32 nSlideIndex,
1566 const awt::Rectangle& rBox)
1568 if (mnSlideIndex == nSlideIndex)
1569 return;
1571 mnSlideIndex = -1;
1572 Invalidate();
1574 maSlideBoundingBox = rBox;
1575 mnSlideIndex = nSlideIndex;
1577 if (nSlideIndex >= 0)
1579 if (mxSlides.get() != NULL)
1581 msText.clear();
1583 Reference<beans::XPropertySet> xSlideProperties(mxSlides->getByIndex(nSlideIndex), UNO_QUERY);
1584 if (xSlideProperties.is())
1585 xSlideProperties->getPropertyValue("LinkDisplayName") >>= msText;
1587 if (msText.isEmpty())
1588 msText = "Slide " + OUString::number(nSlideIndex + 1);
1591 else
1593 msText.clear();
1595 mxBitmap = NULL;
1597 Invalidate();
1600 Reference<rendering::XBitmap> PresenterSlideSorter::MouseOverManager::CreateBitmap (
1601 const OUString& rsText,
1602 const sal_Int32 nMaximalWidth) const
1604 if ( ! mxCanvas.is())
1605 return NULL;
1607 if (mpFont.get()==NULL || !mpFont->mxFont.is())
1608 return NULL;
1610 // Long text has to be shortened.
1611 const OUString sText (GetFittingText(rsText, nMaximalWidth
1612 - 2*gnHorizontalLabelBorder
1613 - 2*gnHorizontalLabelPadding));
1615 // Determine the size of the label. Its height is defined by the
1616 // bitmaps that are used to paints its background. The width is defined
1617 // by the text.
1618 geometry::IntegerSize2D aLabelSize (CalculateLabelSize(sText));
1620 // Create a new bitmap that will contain the complete label.
1621 Reference<rendering::XBitmap> xBitmap (
1622 mxCanvas->getDevice()->createCompatibleAlphaBitmap(aLabelSize));
1624 if ( ! xBitmap.is())
1625 return NULL;
1627 Reference<rendering::XBitmapCanvas> xBitmapCanvas (xBitmap, UNO_QUERY);
1628 if ( ! xBitmapCanvas.is())
1629 return NULL;
1631 // Paint the background.
1632 PaintButtonBackground(xBitmapCanvas, aLabelSize);
1634 // Paint the text.
1635 if (!sText.isEmpty())
1638 const rendering::StringContext aContext (sText, 0, sText.getLength());
1639 const Reference<rendering::XTextLayout> xLayout (mpFont->mxFont->createTextLayout(
1640 aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0));
1641 const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds());
1643 const double nXOffset = (aLabelSize.Width - aTextBBox.X2 + aTextBBox.X1) / 2;
1644 const double nYOffset = aLabelSize.Height
1645 - (aLabelSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y2;
1647 const rendering::ViewState aViewState(
1648 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1649 NULL);
1651 rendering::RenderState aRenderState (
1652 geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset),
1653 NULL,
1654 Sequence<double>(4),
1655 rendering::CompositeOperation::SOURCE);
1656 PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
1658 xBitmapCanvas->drawTextLayout (
1659 xLayout,
1660 aViewState,
1661 aRenderState);
1664 return xBitmap;
1667 OUString PresenterSlideSorter::MouseOverManager::GetFittingText (
1668 const OUString& rsText,
1669 const double nMaximalWidth) const
1671 const double nTextWidth (
1672 PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText).Width);
1673 if (nTextWidth > nMaximalWidth)
1675 // Text is too wide. Shorten it by removing characters from the end
1676 // and replacing them by ellipses.
1678 // Guess a start value of the final string length.
1679 double nBestWidth (0);
1680 OUString sBestCandidate;
1681 sal_Int32 nLength (round(rsText.getLength() * nMaximalWidth / nTextWidth));
1682 const OUString sEllipses ("...");
1683 while (true)
1685 const OUString sCandidate (rsText.copy(0,nLength) + sEllipses);
1686 const double nWidth (
1687 PresenterCanvasHelper::GetTextSize(mpFont->mxFont, sCandidate).Width);
1688 if (nWidth > nMaximalWidth)
1690 // Candidate still too wide, shorten it.
1691 nLength -= 1;
1692 if (nLength <= 0)
1693 break;
1695 else if (nWidth < nMaximalWidth)
1697 // Candidate short enough.
1698 if (nWidth > nBestWidth)
1700 // Best length so far.
1701 sBestCandidate = sCandidate;
1702 nBestWidth = nWidth;
1703 nLength += 1;
1704 if (nLength >= rsText.getLength())
1705 break;
1707 else
1708 break;
1710 else
1712 // Candidate is exactly as long as it may be. Use it
1713 // without looking any further.
1714 sBestCandidate = sCandidate;
1715 break;
1718 return sBestCandidate;
1720 else
1721 return rsText;
1724 geometry::IntegerSize2D PresenterSlideSorter::MouseOverManager::CalculateLabelSize (
1725 const OUString& rsText) const
1727 // Height is specified by the label bitmaps.
1728 sal_Int32 nHeight (32);
1729 if (mpCenterLabelBitmap.get() != NULL)
1731 Reference<rendering::XBitmap> xBitmap (mpCenterLabelBitmap->GetNormalBitmap());
1732 if (xBitmap.is())
1733 nHeight = xBitmap->getSize().Height;
1736 // Width is specified by text width and maximal width.
1737 const geometry::RealSize2D aTextSize (
1738 PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText));
1740 const sal_Int32 nWidth (round(aTextSize.Width + 2*gnHorizontalLabelPadding));
1742 return geometry::IntegerSize2D(nWidth, nHeight);
1745 void PresenterSlideSorter::MouseOverManager::PaintButtonBackground (
1746 const Reference<rendering::XCanvas>& rxCanvas,
1747 const geometry::IntegerSize2D& rSize) const
1749 // Get the bitmaps for painting the label background.
1750 Reference<rendering::XBitmap> xLeftLabelBitmap;
1751 if (mpLeftLabelBitmap.get() != NULL)
1752 xLeftLabelBitmap = mpLeftLabelBitmap->GetNormalBitmap();
1754 Reference<rendering::XBitmap> xCenterLabelBitmap;
1755 if (mpCenterLabelBitmap.get() != NULL)
1756 xCenterLabelBitmap = mpCenterLabelBitmap->GetNormalBitmap();
1758 Reference<rendering::XBitmap> xRightLabelBitmap;
1759 if (mpRightLabelBitmap.get() != NULL)
1760 xRightLabelBitmap = mpRightLabelBitmap->GetNormalBitmap();
1762 PresenterUIPainter::PaintHorizontalBitmapComposite (
1763 Reference<rendering::XCanvas>(rxCanvas, UNO_QUERY),
1764 awt::Rectangle(0,0, rSize.Width,rSize.Height),
1765 awt::Rectangle(0,0, rSize.Width,rSize.Height),
1766 xLeftLabelBitmap,
1767 xCenterLabelBitmap,
1768 xRightLabelBitmap);
1771 void PresenterSlideSorter::MouseOverManager::Invalidate()
1773 if (mpPaintManager.get() != NULL)
1774 mpPaintManager->Invalidate(mxInvalidateTarget, maSlideBoundingBox, true);
1777 //===== PresenterSlideSorter::CurrentSlideFrameRenderer =======================
1779 PresenterSlideSorter::CurrentSlideFrameRenderer::CurrentSlideFrameRenderer (
1780 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
1781 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas)
1782 : mpTopLeft(),
1783 mpTop(),
1784 mpTopRight(),
1785 mpLeft(),
1786 mpRight(),
1787 mpBottomLeft(),
1788 mpBottom(),
1789 mpBottomRight(),
1790 mnTopFrameSize(0),
1791 mnLeftFrameSize(0),
1792 mnRightFrameSize(0),
1793 mnBottomFrameSize(0)
1795 PresenterConfigurationAccess aConfiguration (
1796 rxContext,
1797 OUString("/org.openoffice.Office.PresenterScreen/"),
1798 PresenterConfigurationAccess::READ_ONLY);
1799 Reference<container::XHierarchicalNameAccess> xBitmaps (
1800 aConfiguration.GetConfigurationNode(
1801 "PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps"),
1802 UNO_QUERY);
1803 if ( ! xBitmaps.is())
1804 return;
1806 PresenterBitmapContainer aContainer (
1807 "PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps",
1808 ::boost::shared_ptr<PresenterBitmapContainer>(),
1809 rxContext,
1810 rxCanvas);
1812 mpTopLeft = aContainer.GetBitmap("TopLeft");
1813 mpTop = aContainer.GetBitmap("Top");
1814 mpTopRight = aContainer.GetBitmap("TopRight");
1815 mpLeft = aContainer.GetBitmap("Left");
1816 mpRight = aContainer.GetBitmap("Right");
1817 mpBottomLeft = aContainer.GetBitmap("BottomLeft");
1818 mpBottom = aContainer.GetBitmap("Bottom");
1819 mpBottomRight = aContainer.GetBitmap("BottomRight");
1821 // Determine size of frame.
1822 if (mpTop.get() != NULL)
1823 mnTopFrameSize = mpTop->mnHeight;
1824 if (mpLeft.get() != NULL)
1825 mnLeftFrameSize = mpLeft->mnWidth;
1826 if (mpRight.get() != NULL)
1827 mnRightFrameSize = mpRight->mnWidth;
1828 if (mpBottom.get() != NULL)
1829 mnBottomFrameSize = mpBottom->mnHeight;
1831 if (mpTopLeft.get() != NULL)
1833 mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopLeft->mnHeight);
1834 mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpTopLeft->mnWidth);
1836 if (mpTopRight.get() != NULL)
1838 mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopRight->mnHeight);
1839 mnRightFrameSize = ::std::max(mnRightFrameSize, mpTopRight->mnWidth);
1841 if (mpBottomLeft.get() != NULL)
1843 mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpBottomLeft->mnWidth);
1844 mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomLeft->mnHeight);
1846 if (mpBottomRight.get() != NULL)
1848 mnRightFrameSize = ::std::max(mnRightFrameSize, mpBottomRight->mnWidth);
1849 mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomRight->mnHeight);
1853 PresenterSlideSorter::CurrentSlideFrameRenderer::~CurrentSlideFrameRenderer()
1857 void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintCurrentSlideFrame (
1858 const awt::Rectangle& rSlideBoundingBox,
1859 const Reference<rendering::XCanvas>& rxCanvas,
1860 const geometry::RealRectangle2D& rClipBox)
1862 if ( ! rxCanvas.is())
1863 return;
1865 const Reference<rendering::XPolyPolygon2D> xClip (
1866 PresenterGeometryHelper::CreatePolygon(rClipBox, rxCanvas->getDevice()));
1868 if (mpTop.get() != NULL)
1870 PaintBitmapTiled(
1871 mpTop->GetNormalBitmap(),
1872 rxCanvas,
1873 rClipBox,
1874 rSlideBoundingBox.X,
1875 rSlideBoundingBox.Y - mpTop->mnHeight,
1876 rSlideBoundingBox.Width,
1877 mpTop->mnHeight);
1879 if (mpLeft.get() != NULL)
1881 PaintBitmapTiled(
1882 mpLeft->GetNormalBitmap(),
1883 rxCanvas,
1884 rClipBox,
1885 rSlideBoundingBox.X - mpLeft->mnWidth,
1886 rSlideBoundingBox.Y,
1887 mpLeft->mnWidth,
1888 rSlideBoundingBox.Height);
1890 if (mpRight.get() != NULL)
1892 PaintBitmapTiled(
1893 mpRight->GetNormalBitmap(),
1894 rxCanvas,
1895 rClipBox,
1896 rSlideBoundingBox.X + rSlideBoundingBox.Width,
1897 rSlideBoundingBox.Y,
1898 mpRight->mnWidth,
1899 rSlideBoundingBox.Height);
1901 if (mpBottom.get() != NULL)
1903 PaintBitmapTiled(
1904 mpBottom->GetNormalBitmap(),
1905 rxCanvas,
1906 rClipBox,
1907 rSlideBoundingBox.X,
1908 rSlideBoundingBox.Y + rSlideBoundingBox.Height,
1909 rSlideBoundingBox.Width,
1910 mpBottom->mnHeight);
1912 if (mpTopLeft.get() != NULL)
1914 PaintBitmapOnce(
1915 mpTopLeft->GetNormalBitmap(),
1916 rxCanvas,
1917 xClip,
1918 rSlideBoundingBox.X - mpTopLeft->mnWidth,
1919 rSlideBoundingBox.Y - mpTopLeft->mnHeight);
1921 if (mpTopRight.get() != NULL)
1923 PaintBitmapOnce(
1924 mpTopRight->GetNormalBitmap(),
1925 rxCanvas,
1926 xClip,
1927 rSlideBoundingBox.X + rSlideBoundingBox.Width,
1928 rSlideBoundingBox.Y - mpTopLeft->mnHeight);
1930 if (mpBottomLeft.get() != NULL)
1932 PaintBitmapOnce(
1933 mpBottomLeft->GetNormalBitmap(),
1934 rxCanvas,
1935 xClip,
1936 rSlideBoundingBox.X - mpBottomLeft->mnWidth,
1937 rSlideBoundingBox.Y + rSlideBoundingBox.Height);
1939 if (mpBottomRight.get() != NULL)
1941 PaintBitmapOnce(
1942 mpBottomRight->GetNormalBitmap(),
1943 rxCanvas,
1944 xClip,
1945 rSlideBoundingBox.X + rSlideBoundingBox.Width,
1946 rSlideBoundingBox.Y + rSlideBoundingBox.Height);
1950 awt::Rectangle PresenterSlideSorter::CurrentSlideFrameRenderer::GetBoundingBox (
1951 const awt::Rectangle& rSlideBoundingBox)
1953 return awt::Rectangle(
1954 rSlideBoundingBox.X - mnLeftFrameSize,
1955 rSlideBoundingBox.Y - mnTopFrameSize,
1956 rSlideBoundingBox.Width + mnLeftFrameSize + mnRightFrameSize,
1957 rSlideBoundingBox.Height + mnTopFrameSize + mnBottomFrameSize);
1960 void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintBitmapOnce(
1961 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
1962 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
1963 const Reference<rendering::XPolyPolygon2D>& rxClip,
1964 const double nX,
1965 const double nY)
1967 OSL_ASSERT(rxCanvas.is());
1968 if ( ! rxBitmap.is())
1969 return;
1971 const rendering::ViewState aViewState(
1972 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1973 rxClip);
1975 const rendering::RenderState aRenderState (
1976 geometry::AffineMatrix2D(
1977 1, 0, nX,
1978 0, 1, nY),
1979 NULL,
1980 Sequence<double>(4),
1981 rendering::CompositeOperation::SOURCE);
1983 rxCanvas->drawBitmap(
1984 rxBitmap,
1985 aViewState,
1986 aRenderState);
1989 void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintBitmapTiled(
1990 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
1991 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
1992 const geometry::RealRectangle2D& rClipBox,
1993 const double nX0,
1994 const double nY0,
1995 const double nWidth,
1996 const double nHeight)
1998 OSL_ASSERT(rxCanvas.is());
1999 if ( ! rxBitmap.is())
2000 return;
2002 geometry::IntegerSize2D aSize (rxBitmap->getSize());
2004 const rendering::ViewState aViewState(
2005 geometry::AffineMatrix2D(1,0,0, 0,1,0),
2006 PresenterGeometryHelper::CreatePolygon(
2007 PresenterGeometryHelper::Intersection(
2008 rClipBox,
2009 geometry::RealRectangle2D(nX0,nY0,nX0+nWidth,nY0+nHeight)),
2010 rxCanvas->getDevice()));
2012 rendering::RenderState aRenderState (
2013 geometry::AffineMatrix2D(
2014 1, 0, nX0,
2015 0, 1, nY0),
2016 NULL,
2017 Sequence<double>(4),
2018 rendering::CompositeOperation::SOURCE);
2020 const double nX1 = nX0 + nWidth;
2021 const double nY1 = nY0 + nHeight;
2022 for (double nY=nY0; nY<nY1; nY+=aSize.Height)
2023 for (double nX=nX0; nX<nX1; nX+=aSize.Width)
2025 aRenderState.AffineTransform.m02 = nX;
2026 aRenderState.AffineTransform.m12 = nY;
2027 rxCanvas->drawBitmap(
2028 rxBitmap,
2029 aViewState,
2030 aRenderState);
2034 } } // end of namespace ::sdext::presenter
2036 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */