update dev300-m58
[ooovba.git] / sdext / source / presenter / PresenterSlideSorter.cxx
blob6819e9d87ab0d6e3e40674be4130ae2106311382
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: PresenterSlideSorter.cxx,v $
11 * $Revision: 1.9 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_sdext.hxx"
35 #include "PresenterSlideSorter.hxx"
36 #include "PresenterButton.hxx"
37 #include "PresenterCanvasHelper.hxx"
38 #include "PresenterComponent.hxx"
39 #include "PresenterGeometryHelper.hxx"
40 #include "PresenterHelper.hxx"
41 #include "PresenterPaintManager.hxx"
42 #include "PresenterPaneBase.hxx"
43 #include "PresenterScrollBar.hxx"
44 #include "PresenterUIPainter.hxx"
45 #include "PresenterWindowManager.hxx"
46 #include <com/sun/star/awt/PosSize.hpp>
47 #include <com/sun/star/awt/XWindowPeer.hpp>
48 #include <com/sun/star/container/XNameAccess.hpp>
49 #include <com/sun/star/container/XNamed.hpp>
50 #include <com/sun/star/drawing/XSlideSorterBase.hpp>
51 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
52 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
53 #include <com/sun/star/rendering/CompositeOperation.hpp>
54 #include <com/sun/star/rendering/TextDirection.hpp>
55 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
56 #include <com/sun/star/util/Color.hpp>
57 #include <algorithm>
58 #include <math.h>
59 #include <boost/bind.hpp>
61 using namespace ::com::sun::star;
62 using namespace ::com::sun::star::uno;
63 using namespace ::com::sun::star::drawing::framework;
64 using ::rtl::OUString;
66 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
68 namespace {
69 const static sal_Int32 gnVerticalGap (10);
70 const static sal_Int32 gnVerticalBorder (10);
71 const static sal_Int32 gnHorizontalGap (10);
72 const static sal_Int32 gnHorizontalBorder (10);
74 const static double gnMinimalPreviewWidth (200);
75 const static double gnPreferredPreviewWidth (300);
76 const static double gnMaximalPreviewWidth (400);
77 const static sal_Int32 gnPreferredColumnCount (6);
78 const static double gnMinimalHorizontalPreviewGap(15);
79 const static double gnPreferredHorizontalPreviewGap(25);
80 const static double gnMaximalHorizontalPreviewGap(50);
81 const static double gnMinimalVerticalPreviewGap(15);
82 const static double gnPreferredVerticalPreviewGap(25);
83 const static double gnMaximalVerticalPreviewGap(50);
85 const static sal_Int32 gnHorizontalLabelBorder (3);
86 const static sal_Int32 gnHorizontalLabelPadding (5);
88 const static sal_Int32 gnVerticalButtonPadding (gnVerticalGap);
91 namespace sdext { namespace presenter {
93 namespace {
94 sal_Int32 round (const double nValue) { return sal::static_int_cast<sal_Int32>(0.5 + nValue); }
95 sal_Int32 floor (const double nValue) { return sal::static_int_cast<sal_Int32>(nValue); }
100 //===== PresenterSlideSorter::Layout ==========================================
102 class PresenterSlideSorter::Layout
104 public:
105 enum Orientation { Horizontal, Vertical };
106 Layout (
107 const Orientation eOrientation,
108 const ::rtl::Reference<PresenterScrollBar>& rpHorizontalScrollBar,
109 const ::rtl::Reference<PresenterScrollBar>& rpVerticalScrollBar);
111 void Update (const geometry::RealRectangle2D& rBoundingBox, const double nSlideAspectRatio);
112 void SetupVisibleArea (void);
113 void UpdateScrollBars (void);
114 bool IsScrollBarNeeded (const sal_Int32 nSlideCount);
115 geometry::RealPoint2D GetLocalPosition (const geometry::RealPoint2D& rWindowPoint) const;
116 geometry::RealPoint2D GetWindowPosition(const geometry::RealPoint2D& rLocalPoint) const;
117 sal_Int32 GetColumn (const geometry::RealPoint2D& rLocalPoint,
118 const bool bReturnInvalidValue = false) const;
119 sal_Int32 GetRow (const geometry::RealPoint2D& rLocalPoint,
120 const bool bReturnInvalidValue = false) const;
121 sal_Int32 GetSlideIndexForPosition (const css::geometry::RealPoint2D& rPoint) const;
122 css::geometry::RealPoint2D GetPoint (
123 const sal_Int32 nSlideIndex,
124 const sal_Int32 nRelativeHorizontalPosition,
125 const sal_Int32 nRelativeVerticalPosition) const;
126 css::awt::Rectangle GetBoundingBox (const sal_Int32 nSlideIndex) const;
127 void ForAllVisibleSlides (const ::boost::function<void(sal_Int32)>& rAction);
128 sal_Int32 GetFirstVisibleSlideIndex (void) const;
129 sal_Int32 GetLastVisibleSlideIndex (void) const;
130 bool SetHorizontalOffset (const double nOffset);
131 bool SetVerticalOffset (const double nOffset);
132 Orientation GetOrientation (void) const;
134 css::geometry::RealRectangle2D maBoundingBox;
135 css::geometry::IntegerSize2D maPreviewSize;
136 sal_Int32 mnHorizontalOffset;
137 sal_Int32 mnVerticalOffset;
138 sal_Int32 mnHorizontalGap;
139 sal_Int32 mnVerticalGap;
140 sal_Int32 mnHorizontalBorder;
141 sal_Int32 mnVerticalBorder;
142 sal_Int32 mnRowCount;
143 sal_Int32 mnColumnCount;
144 sal_Int32 mnSlideCount;
145 sal_Int32 mnSlideIndexAtMouse;
146 sal_Int32 mnFirstVisibleColumn;
147 sal_Int32 mnLastVisibleColumn;
148 sal_Int32 mnFirstVisibleRow;
149 sal_Int32 mnLastVisibleRow;
151 private:
152 Orientation meOrientation;
153 ::rtl::Reference<PresenterScrollBar> mpHorizontalScrollBar;
154 ::rtl::Reference<PresenterScrollBar> mpVerticalScrollBar;
156 sal_Int32 GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const;
157 sal_Int32 GetRow (const sal_Int32 nSlideIndex) const;
158 sal_Int32 GetColumn (const sal_Int32 nSlideIndex) const;
164 //==== PresenterSlideSorter::MouseOverManager =================================
166 class PresenterSlideSorter::MouseOverManager
167 : ::boost::noncopyable
169 public:
170 MouseOverManager (
171 const Reference<container::XIndexAccess>& rxSlides,
172 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
173 const Reference<awt::XWindow>& rxInvalidateTarget,
174 const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager);
175 ~MouseOverManager (void);
177 void Paint (
178 const sal_Int32 nSlideIndex,
179 const Reference<rendering::XCanvas>& rxCanvas,
180 const Reference<rendering::XPolyPolygon2D>& rxClip);
182 void SetSlide (
183 const sal_Int32 nSlideIndex,
184 const awt::Rectangle& rBox);
186 private:
187 Reference<rendering::XCanvas> mxCanvas;
188 const Reference<container::XIndexAccess> mxSlides;
189 SharedBitmapDescriptor mpLeftLabelBitmap;
190 SharedBitmapDescriptor mpCenterLabelBitmap;
191 SharedBitmapDescriptor mpRightLabelBitmap;
192 PresenterTheme::SharedFontDescriptor mpFont;
193 sal_Int32 mnSlideIndex;
194 awt::Rectangle maSlideBoundingBox;
195 OUString msText;
196 Reference<rendering::XBitmap> mxBitmap;
197 Reference<awt::XWindow> mxInvalidateTarget;
198 ::boost::shared_ptr<PresenterPaintManager> mpPaintManager;
200 void SetCanvas (
201 const Reference<rendering::XCanvas>& rxCanvas);
202 /** Create a bitmap that shows the given text and is not wider than the
203 given maximal width.
205 Reference<rendering::XBitmap> CreateBitmap (
206 const OUString& rsText,
207 const sal_Int32 nMaximalWidth) const;
208 void Invalidate (void);
209 geometry::IntegerSize2D CalculateLabelSize (
210 const OUString& rsText) const;
211 OUString GetFittingText (const OUString& rsText, const double nMaximalWidth) const;
212 void PaintButtonBackground (
213 const Reference<rendering::XBitmapCanvas>& rxCanvas,
214 const geometry::IntegerSize2D& rSize) const;
220 //==== PresenterSlideSorter::CurrentSlideFrameRenderer ========================
222 class PresenterSlideSorter::CurrentSlideFrameRenderer
224 public:
225 CurrentSlideFrameRenderer (
226 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
227 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas);
228 ~CurrentSlideFrameRenderer (void);
230 void PaintCurrentSlideFrame (
231 const awt::Rectangle& rSlideBoundingBox,
232 const Reference<rendering::XCanvas>& rxCanvas,
233 const geometry::RealRectangle2D& rClipBox);
235 /** Enlarge the given rectangle to include the current slide indicator.
237 awt::Rectangle GetBoundingBox (
238 const awt::Rectangle& rSlideBoundingBox);
240 private:
241 SharedBitmapDescriptor mpTopLeft;
242 SharedBitmapDescriptor mpTop;
243 SharedBitmapDescriptor mpTopRight;
244 SharedBitmapDescriptor mpLeft;
245 SharedBitmapDescriptor mpRight;
246 SharedBitmapDescriptor mpBottomLeft;
247 SharedBitmapDescriptor mpBottom;
248 SharedBitmapDescriptor mpBottomRight;
249 sal_Int32 mnTopFrameSize;
250 sal_Int32 mnLeftFrameSize;
251 sal_Int32 mnRightFrameSize;
252 sal_Int32 mnBottomFrameSize;
254 void PaintBitmapOnce(
255 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
256 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
257 const Reference<rendering::XPolyPolygon2D>& rxClip,
258 const double nX,
259 const double nY);
260 void PaintBitmapTiled(
261 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
262 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
263 const geometry::RealRectangle2D& rClipBox,
264 const double nX,
265 const double nY,
266 const double nWidth,
267 const double nHeight);
273 //===== PresenterSlideSorter ==================================================
275 PresenterSlideSorter::PresenterSlideSorter (
276 const Reference<uno::XComponentContext>& rxContext,
277 const Reference<XResourceId>& rxViewId,
278 const Reference<frame::XController>& rxController,
279 const ::rtl::Reference<PresenterController>& rpPresenterController)
280 : PresenterSlideSorterInterfaceBase(m_aMutex),
281 mxComponentContext(rxContext),
282 mxViewId(rxViewId),
283 mxPane(),
284 mxCanvas(),
285 mxWindow(),
286 mpPresenterController(rpPresenterController),
287 mxSlideShowController(mpPresenterController->GetSlideShowController()),
288 mxPreviewCache(),
289 mbIsPaintPending(true),
290 mbIsLayoutPending(true),
291 mpLayout(),
292 mpHorizontalScrollBar(),
293 mpVerticalScrollBar(),
294 mpCloseButton(),
295 mpMouseOverManager(),
296 mnSlideIndexMousePressed(-1),
297 mnCurrentSlideIndex(-1),
298 mnSeparatorY(0),
299 maSeparatorColor(0x00ffffff),
300 maCloseButtonCenter(),
301 maCurrentSlideFrameBoundingBox(),
302 mpCurrentSlideFrameRenderer(),
303 mxPreviewFrame()
305 if ( ! rxContext.is()
306 || ! rxViewId.is()
307 || ! rxController.is()
308 || rpPresenterController.get()==NULL)
310 throw lang::IllegalArgumentException();
313 if ( ! mxSlideShowController.is())
314 throw RuntimeException();
318 // Get pane and window.
319 Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
320 Reference<XConfigurationController> xCC (
321 xCM->getConfigurationController(), UNO_QUERY_THROW);
322 Reference<lang::XMultiComponentFactory> xFactory (
323 mxComponentContext->getServiceManager(), UNO_QUERY_THROW);
325 mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
326 mxWindow = mxPane->getWindow();
328 // Add window listener.
329 mxWindow->addWindowListener(this);
330 mxWindow->addPaintListener(this);
331 mxWindow->addMouseListener(this);
332 mxWindow->addMouseMotionListener(this);
333 mxWindow->setVisible(sal_True);
335 // Remember the current slide.
336 mnCurrentSlideIndex = mxSlideShowController->getCurrentSlideIndex();
338 // Set the orientation.
339 const bool bIsVertical (true);
341 // Create the scroll bar.
342 if (bIsVertical)
343 mpVerticalScrollBar = ::rtl::Reference<PresenterScrollBar>(
344 new PresenterVerticalScrollBar(
345 rxContext,
346 mxWindow,
347 mpPresenterController->GetPaintManager(),
348 ::boost::bind(&PresenterSlideSorter::SetVerticalOffset,this,_1)));
349 else
350 mpHorizontalScrollBar = ::rtl::Reference<PresenterScrollBar>(
351 new PresenterHorizontalScrollBar(
352 rxContext,
353 mxWindow,
354 mpPresenterController->GetPaintManager(),
355 ::boost::bind(&PresenterSlideSorter::SetHorizontalOffset,this,_1)));
356 mpCloseButton = PresenterButton::Create(
357 rxContext,
358 mpPresenterController,
359 mpPresenterController->GetTheme(),
360 mxWindow,
361 mxCanvas,
362 A2S("SlideSorterCloser"));
364 if (mpPresenterController->GetTheme().get() != NULL)
366 PresenterTheme::SharedFontDescriptor pFont (
367 mpPresenterController->GetTheme()->GetFont(A2S("ButtonFont")));
368 if (pFont.get() != NULL)
369 maSeparatorColor = pFont->mnColor;
372 // Create the layout.
373 mpLayout.reset(new Layout(
374 Layout::Vertical,
375 mpHorizontalScrollBar,
376 mpVerticalScrollBar));
378 // Create the preview cache.
379 mxPreviewCache = Reference<drawing::XSlidePreviewCache>(
380 xFactory->createInstanceWithContext(
381 OUString::createFromAscii("com.sun.star.drawing.PresenterPreviewCache"),
382 mxComponentContext),
383 UNO_QUERY_THROW);
384 Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY);
385 mxPreviewCache->setDocumentSlides(xSlides, rxController->getModel());
386 mxPreviewCache->addPreviewCreationNotifyListener(this);
387 if (xSlides.is())
389 mpLayout->mnSlideCount = xSlides->getCount();
392 // Create the mouse over manager.
393 mpMouseOverManager.reset(new MouseOverManager(
394 Reference<container::XIndexAccess>(mxSlideShowController, UNO_QUERY),
395 mpPresenterController->GetTheme(),
396 mxWindow,
397 mpPresenterController->GetPaintManager()));
399 // Listen for changes of the current slide.
400 Reference<beans::XPropertySet> xControllerProperties (rxController, UNO_QUERY_THROW);
401 xControllerProperties->addPropertyChangeListener(
402 OUString::createFromAscii("CurrentPage"),
403 this);
405 // Move the current slide in the center of the window.
406 const awt::Rectangle aCurrentSlideBBox (mpLayout->GetBoundingBox(mnCurrentSlideIndex));
407 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
408 SetHorizontalOffset(aCurrentSlideBBox.X - aWindowBox.Width/2.0);
410 catch (RuntimeException&)
412 disposing();
413 throw;
420 PresenterSlideSorter::~PresenterSlideSorter (void)
427 void SAL_CALL PresenterSlideSorter::disposing (void)
429 mxComponentContext = NULL;
430 mxViewId = NULL;
431 mxPane = NULL;
433 if (mpVerticalScrollBar.is())
435 Reference<lang::XComponent> xComponent (
436 static_cast<XWeak*>(mpVerticalScrollBar.get()), UNO_QUERY);
437 mpVerticalScrollBar = NULL;
438 if (xComponent.is())
439 xComponent->dispose();
441 if (mpHorizontalScrollBar.is())
443 Reference<lang::XComponent> xComponent (
444 static_cast<XWeak*>(mpHorizontalScrollBar.get()), UNO_QUERY);
445 mpHorizontalScrollBar = NULL;
446 if (xComponent.is())
447 xComponent->dispose();
449 if (mpCloseButton.is())
451 Reference<lang::XComponent> xComponent (
452 static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY);
453 mpCloseButton = NULL;
454 if (xComponent.is())
455 xComponent->dispose();
458 if (mxCanvas.is())
460 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
461 if (xComponent.is())
462 xComponent->removeEventListener(static_cast<awt::XWindowListener*>(this));
463 mxCanvas = NULL;
465 mpPresenterController = NULL;
466 mxSlideShowController = NULL;
467 mpLayout.reset();
468 mpMouseOverManager.reset();
470 if (mxPreviewCache.is())
472 mxPreviewCache->removePreviewCreationNotifyListener(this);
474 Reference<XComponent> xComponent (mxPreviewCache, UNO_QUERY);
475 mxPreviewCache = NULL;
476 if (xComponent.is())
477 xComponent->dispose();
480 if (mxWindow.is())
482 mxWindow->removeWindowListener(this);
483 mxWindow->removePaintListener(this);
484 mxWindow->removeMouseListener(this);
485 mxWindow->removeMouseMotionListener(this);
492 void PresenterSlideSorter::SetActiveState (const bool bIsActive)
494 (void)bIsActive;
500 //----- lang::XEventListener --------------------------------------------------
502 void SAL_CALL PresenterSlideSorter::disposing (const lang::EventObject& rEventObject)
503 throw (RuntimeException)
505 if (rEventObject.Source == mxWindow)
507 mxWindow = NULL;
508 dispose();
510 else if (rEventObject.Source == mxPreviewCache)
512 mxPreviewCache = NULL;
513 dispose();
515 else if (rEventObject.Source == mxCanvas)
517 mxCanvas = NULL;
518 if (mpHorizontalScrollBar.is())
519 mpHorizontalScrollBar->SetCanvas(NULL);
520 mbIsLayoutPending = true;
521 mbIsPaintPending = true;
523 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
530 //----- XWindowListener -------------------------------------------------------
532 void SAL_CALL PresenterSlideSorter::windowResized (const awt::WindowEvent& rEvent)
533 throw (uno::RuntimeException)
535 (void)rEvent;
536 ThrowIfDisposed();
537 mbIsLayoutPending = true;
538 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
544 void SAL_CALL PresenterSlideSorter::windowMoved (const awt::WindowEvent& rEvent)
545 throw (uno::RuntimeException)
547 (void)rEvent;
548 ThrowIfDisposed();
554 void SAL_CALL PresenterSlideSorter::windowShown (const lang::EventObject& rEvent)
555 throw (uno::RuntimeException)
557 (void)rEvent;
558 ThrowIfDisposed();
559 mbIsLayoutPending = true;
560 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
566 void SAL_CALL PresenterSlideSorter::windowHidden (const lang::EventObject& rEvent)
567 throw (uno::RuntimeException)
569 (void)rEvent;
570 ThrowIfDisposed();
576 //----- XPaintListener --------------------------------------------------------
578 void SAL_CALL PresenterSlideSorter::windowPaint (const css::awt::PaintEvent& rEvent)
579 throw (RuntimeException)
581 (void)rEvent;
583 // Deactivated views must not be painted.
584 if ( ! mbIsPresenterViewActive)
585 return;
587 Paint(rEvent.UpdateRect);
589 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
590 if (xSpriteCanvas.is())
591 xSpriteCanvas->updateScreen(sal_False);
597 //----- XMouseListener --------------------------------------------------------
599 void SAL_CALL PresenterSlideSorter::mousePressed (const css::awt::MouseEvent& rEvent)
600 throw(css::uno::RuntimeException)
602 const geometry::RealPoint2D aPosition (rEvent.X, rEvent.Y);
603 mnSlideIndexMousePressed = mpLayout->GetSlideIndexForPosition(aPosition);
609 void SAL_CALL PresenterSlideSorter::mouseReleased (const css::awt::MouseEvent& rEvent)
610 throw(css::uno::RuntimeException)
612 const geometry::RealPoint2D aPosition (rEvent.X, rEvent.Y);
613 const sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));
615 if (nSlideIndex == mnSlideIndexMousePressed && mnSlideIndexMousePressed >= 0)
617 switch (rEvent.ClickCount)
619 case 1:
620 default:
621 GotoSlide(nSlideIndex);
622 break;
624 case 2:
625 OSL_ASSERT(mpPresenterController.get()!=NULL);
626 OSL_ASSERT(mpPresenterController->GetWindowManager().get()!=NULL);
627 mpPresenterController->GetWindowManager()->SetSlideSorterState(false);
628 GotoSlide(nSlideIndex);
629 break;
637 void SAL_CALL PresenterSlideSorter::mouseEntered (const css::awt::MouseEvent& rEvent)
638 throw(css::uno::RuntimeException)
640 (void)rEvent;
646 void SAL_CALL PresenterSlideSorter::mouseExited (const css::awt::MouseEvent& rEvent)
647 throw(css::uno::RuntimeException)
649 (void)rEvent;
650 mnSlideIndexMousePressed = -1;
651 if (mpMouseOverManager.get() != NULL)
652 mpMouseOverManager->SetSlide(mnSlideIndexMousePressed, awt::Rectangle(0,0,0,0));
658 //----- XMouseMotionListener --------------------------------------------------
660 void SAL_CALL PresenterSlideSorter::mouseMoved (const css::awt::MouseEvent& rEvent)
661 throw (css::uno::RuntimeException)
663 if (mpMouseOverManager.get() != NULL)
665 const geometry::RealPoint2D aPosition (rEvent.X, rEvent.Y);
666 sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));
668 if (nSlideIndex < 0)
669 mnSlideIndexMousePressed = -1;
671 if (nSlideIndex < 0)
673 mpMouseOverManager->SetSlide(nSlideIndex, awt::Rectangle(0,0,0,0));
675 else
677 mpMouseOverManager->SetSlide(
678 nSlideIndex,
679 mpLayout->GetBoundingBox(nSlideIndex));
687 void SAL_CALL PresenterSlideSorter::mouseDragged (const css::awt::MouseEvent& rEvent)
688 throw (css::uno::RuntimeException)
690 (void)rEvent;
696 //----- XResourceId -----------------------------------------------------------
698 Reference<XResourceId> SAL_CALL PresenterSlideSorter::getResourceId (void)
699 throw (RuntimeException)
701 ThrowIfDisposed();
702 return mxViewId;
708 sal_Bool SAL_CALL PresenterSlideSorter::isAnchorOnly (void)
709 throw (RuntimeException)
711 return false;
717 //----- XPropertyChangeListener -----------------------------------------------
719 void SAL_CALL PresenterSlideSorter::propertyChange (
720 const css::beans::PropertyChangeEvent& rEvent)
721 throw(css::uno::RuntimeException)
723 (void)rEvent;
729 //----- XSlidePreviewCacheListener --------------------------------------------
731 void SAL_CALL PresenterSlideSorter::notifyPreviewCreation (
732 sal_Int32 nSlideIndex)
733 throw(css::uno::RuntimeException)
735 OSL_ASSERT(mpLayout.get()!=NULL);
737 awt::Rectangle aBBox (mpLayout->GetBoundingBox(nSlideIndex));
738 mpPresenterController->GetPaintManager()->Invalidate(mxWindow, aBBox, true);
744 //----- XDrawView -------------------------------------------------------------
746 void SAL_CALL PresenterSlideSorter::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
747 throw (RuntimeException)
749 (void)rxSlide;
751 ThrowIfDisposed();
752 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
754 if (mxSlideShowController.is())
756 const sal_Int32 nNewCurrentSlideIndex (mxSlideShowController->getCurrentSlideIndex());
757 if (nNewCurrentSlideIndex != mnCurrentSlideIndex)
759 mnCurrentSlideIndex = nNewCurrentSlideIndex;
761 // Request a repaint of the previous current slide to hide its
762 // current slide indicator.
763 mpPresenterController->GetPaintManager()->Invalidate(
764 mxWindow,
765 maCurrentSlideFrameBoundingBox);
767 // Request a repaint of the new current slide to show its
768 // current slide indicator.
769 maCurrentSlideFrameBoundingBox = mpCurrentSlideFrameRenderer->GetBoundingBox(
770 mpLayout->GetBoundingBox(mnCurrentSlideIndex));
771 mpPresenterController->GetPaintManager()->Invalidate(
772 mxWindow,
773 maCurrentSlideFrameBoundingBox);
781 Reference<drawing::XDrawPage> SAL_CALL PresenterSlideSorter::getCurrentPage (void)
782 throw (RuntimeException)
784 ThrowIfDisposed();
785 return NULL;
791 //-----------------------------------------------------------------------------
793 void PresenterSlideSorter::UpdateLayout (void)
795 if ( ! mxWindow.is())
796 return;
798 mbIsLayoutPending = false;
799 mbIsPaintPending = true;
801 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
802 awt::Rectangle aCenterBox (aWindowBox);
803 sal_Int32 nLeftBorderWidth (aWindowBox.X);
805 // Get border width.
806 PresenterPaneContainer::SharedPaneDescriptor pPane (
807 mpPresenterController->GetPaneContainer()->FindViewURL(
808 mxViewId->getResourceURL()));
811 if (pPane.get() == NULL)
812 break;
813 if ( ! pPane->mxPane.is())
814 break;
816 Reference<drawing::framework::XPaneBorderPainter> xBorderPainter (
817 pPane->mxPane->GetPaneBorderPainter());
818 if ( ! xBorderPainter.is())
819 break;
820 aCenterBox = xBorderPainter->addBorder (
821 mxViewId->getAnchor()->getResourceURL(),
822 awt::Rectangle(0, 0, aWindowBox.Width, aWindowBox.Height),
823 drawing::framework::BorderType_INNER_BORDER);
825 while(false);
827 // Place vertical separator.
828 mnSeparatorY = aWindowBox.Height - mpCloseButton->GetSize().Height - gnVerticalButtonPadding;
830 PlaceCloseButton(pPane, aWindowBox, nLeftBorderWidth);
832 geometry::RealRectangle2D aUpperBox(
833 gnHorizontalBorder,
834 gnVerticalBorder,
835 aWindowBox.Width - 2*gnHorizontalBorder,
836 mnSeparatorY - gnVerticalGap);
838 // Determine whether the scroll bar has to be displayed.
839 aUpperBox = PlaceScrollBars(aUpperBox);
841 mpLayout->Update(aUpperBox, GetSlideAspectRatio());
842 mpLayout->SetupVisibleArea();
843 mpLayout->UpdateScrollBars();
845 // Tell the preview cache about some of the values.
846 mxPreviewCache->setPreviewSize(mpLayout->maPreviewSize);
847 mxPreviewCache->setVisibleRange(
848 mpLayout->GetFirstVisibleSlideIndex(),
849 mpLayout->GetLastVisibleSlideIndex());
851 // Clear the frame polygon so that it is re-created on the next paint.
852 mxPreviewFrame = NULL;
858 geometry::RealRectangle2D PresenterSlideSorter::PlaceScrollBars (
859 const geometry::RealRectangle2D& rUpperBox)
861 mpLayout->Update(rUpperBox, GetSlideAspectRatio());
862 bool bIsScrollBarNeeded (false);
863 Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY_THROW);
864 if (xSlides.is())
865 bIsScrollBarNeeded = mpLayout->IsScrollBarNeeded(xSlides->getCount());
867 if (mpLayout->GetOrientation() == Layout::Vertical)
869 if (mpVerticalScrollBar.get() != NULL)
871 if (bIsScrollBarNeeded)
873 // Place vertical scroll bar at right border.
874 mpVerticalScrollBar->SetPosSize(geometry::RealRectangle2D(
875 rUpperBox.X2 - mpVerticalScrollBar->GetSize(),
876 rUpperBox.Y1,
877 rUpperBox.X2,
878 rUpperBox.Y2));
879 mpVerticalScrollBar->SetVisible(true);
881 // Reduce area covered by the scroll bar from the available
882 // space.
883 return geometry::RealRectangle2D(
884 rUpperBox.X1,
885 rUpperBox.Y1,
886 rUpperBox.X2 - mpVerticalScrollBar->GetSize() - gnHorizontalGap,
887 rUpperBox.Y2);
889 else
890 mpVerticalScrollBar->SetVisible(false);
893 else
895 if (mpHorizontalScrollBar.get() != NULL)
897 if (bIsScrollBarNeeded)
899 // Place horixontal scroll bar at the bottom.
900 mpHorizontalScrollBar->SetPosSize(geometry::RealRectangle2D(
901 rUpperBox.X1,
902 rUpperBox.Y2 - mpHorizontalScrollBar->GetSize(),
903 rUpperBox.X2,
904 rUpperBox.Y2));
905 mpHorizontalScrollBar->SetVisible(true);
907 // Reduce area covered by the scroll bar from the available
908 // space.
909 return geometry::RealRectangle2D(
910 rUpperBox.X1,
911 rUpperBox.Y1,
912 rUpperBox.X2,
913 rUpperBox.Y2 - mpHorizontalScrollBar->GetSize() - gnVerticalGap);
915 else
916 mpHorizontalScrollBar->SetVisible(false);
920 return rUpperBox;
926 void PresenterSlideSorter::PlaceCloseButton (
927 const PresenterPaneContainer::SharedPaneDescriptor& rpPane,
928 const awt::Rectangle& rCenterBox,
929 const sal_Int32 nLeftBorderWidth)
931 // Place button. When the callout is near the center then the button is
932 // centered over the callout. Otherwise it is centered with respect to
933 // the whole window.
934 sal_Int32 nCloseButtonCenter (rCenterBox.Width/2);
935 if (rpPane.get() != NULL && rpPane->mxPane.is())
937 const sal_Int32 nCalloutCenter (rpPane->mxPane->GetCalloutAnchor().X - nLeftBorderWidth);
938 const sal_Int32 nDistanceFromWindowCenter (abs(nCalloutCenter - rCenterBox.Width/2));
939 const sal_Int32 nButtonWidth (mpCloseButton->GetSize().Width);
940 const static sal_Int32 nMaxDistanceForCalloutCentering (nButtonWidth * 2);
941 if (nDistanceFromWindowCenter < nMaxDistanceForCalloutCentering)
943 if (nCalloutCenter < nButtonWidth/2)
944 nCloseButtonCenter = nButtonWidth/2;
945 else if (nCalloutCenter > rCenterBox.Width-nButtonWidth/2)
946 nCloseButtonCenter = rCenterBox.Width-nButtonWidth/2;
947 else
948 nCloseButtonCenter = nCalloutCenter;
951 mpCloseButton->SetCenter(geometry::RealPoint2D(
952 nCloseButtonCenter,
953 rCenterBox.Height - mpCloseButton->GetSize().Height/ 2));
959 void PresenterSlideSorter::ClearBackground (
960 const Reference<rendering::XCanvas>& rxCanvas,
961 const awt::Rectangle& rUpdateBox)
963 OSL_ASSERT(rxCanvas.is());
965 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
966 mpPresenterController->GetCanvasHelper()->Paint(
967 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
968 rxCanvas,
969 rUpdateBox,
970 awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
971 awt::Rectangle());
977 double PresenterSlideSorter::GetSlideAspectRatio (void) const
979 double nSlideAspectRatio (28.0/21.0);
983 Reference<container::XIndexAccess> xSlides(mxSlideShowController, UNO_QUERY_THROW);
984 if (mxSlideShowController.is() && xSlides->getCount()>0)
986 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
987 sal_Int32 nWidth (28000);
988 sal_Int32 nHeight (21000);
989 if ((xProperties->getPropertyValue(OUString::createFromAscii("Width")) >>= nWidth)
990 && (xProperties->getPropertyValue(OUString::createFromAscii("Height")) >>= nHeight)
991 && nHeight > 0)
993 nSlideAspectRatio = double(nWidth) / double(nHeight);
997 catch (RuntimeException&)
999 OSL_ASSERT(false);
1002 return nSlideAspectRatio;
1008 Reference<rendering::XBitmap> PresenterSlideSorter::GetPreview (const sal_Int32 nSlideIndex)
1010 if (nSlideIndex < 0 || nSlideIndex>=mpLayout->mnSlideCount)
1011 return NULL;
1012 else if (mxPane.is())
1013 return mxPreviewCache->getSlidePreview(nSlideIndex, mxPane->getCanvas());
1014 else
1015 return NULL;
1021 void PresenterSlideSorter::PaintPreview (
1022 const Reference<rendering::XCanvas>& rxCanvas,
1023 const css::awt::Rectangle& rUpdateBox,
1024 const sal_Int32 nSlideIndex)
1026 OSL_ASSERT(rxCanvas.is());
1028 geometry::IntegerSize2D aSize (mpLayout->maPreviewSize);
1030 if (PresenterGeometryHelper::AreRectanglesDisjoint(
1031 rUpdateBox,
1032 mpLayout->GetBoundingBox(nSlideIndex)))
1034 return;
1037 Reference<rendering::XBitmap> xPreview (GetPreview(nSlideIndex));
1039 const geometry::RealPoint2D aTopLeft (
1040 mpLayout->GetWindowPosition(
1041 mpLayout->GetPoint(nSlideIndex, -1, -1)));
1043 // Create clip rectangle as intersection of the current update area and
1044 // the bounding box of all previews.
1045 geometry::RealRectangle2D aBoundingBox (mpLayout->maBoundingBox);
1046 aBoundingBox.Y2 += 1;
1047 const geometry::RealRectangle2D aClipBox (
1048 PresenterGeometryHelper::Intersection(
1049 PresenterGeometryHelper::ConvertRectangle(rUpdateBox),
1050 aBoundingBox));
1051 Reference<rendering::XPolyPolygon2D> xClip (
1052 PresenterGeometryHelper::CreatePolygon(aClipBox, rxCanvas->getDevice()));
1054 const rendering::ViewState aViewState (geometry::AffineMatrix2D(1,0,0, 0,1,0), xClip);
1057 rendering::RenderState aRenderState (
1058 geometry::AffineMatrix2D(
1059 1, 0, aTopLeft.X,
1060 0, 1, aTopLeft.Y),
1061 NULL,
1062 Sequence<double>(4),
1063 rendering::CompositeOperation::SOURCE);
1066 // Emphasize the current slide.
1067 if (nSlideIndex == mnCurrentSlideIndex)
1069 if (mpCurrentSlideFrameRenderer.get() != NULL)
1071 const awt::Rectangle aSlideBoundingBox(
1072 sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.X),
1073 sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.Y),
1074 aSize.Width,
1075 aSize.Height);
1076 maCurrentSlideFrameBoundingBox
1077 = mpCurrentSlideFrameRenderer->GetBoundingBox(aSlideBoundingBox);
1078 mpCurrentSlideFrameRenderer->PaintCurrentSlideFrame (
1079 aSlideBoundingBox,
1080 mxCanvas,
1081 aClipBox);
1085 // Paint the preview.
1086 if (xPreview.is())
1088 aSize = xPreview->getSize();
1089 if (aSize.Width > 0 && aSize.Height > 0)
1091 rxCanvas->drawBitmap(xPreview, aViewState, aRenderState);
1095 // Create a polygon that is used to paint a frame around previews. Its
1096 // coordinates are chosen in the local coordinate system of a preview.
1097 if ( ! mxPreviewFrame.is())
1098 mxPreviewFrame = PresenterGeometryHelper::CreatePolygon(
1099 awt::Rectangle(-1, -1, aSize.Width+2, aSize.Height+2),
1100 rxCanvas->getDevice());
1102 // Paint a border around the preview.
1103 if (mxPreviewFrame.is())
1105 const geometry::RealRectangle2D aBox (0, 0, aSize.Width, aSize.Height);
1106 const util::Color aFrameColor (0x00000000);
1107 PresenterCanvasHelper::SetDeviceColor(aRenderState, aFrameColor);
1108 rxCanvas->drawPolyPolygon(mxPreviewFrame, aViewState, aRenderState);
1111 // Paint mouse over effect.
1112 mpMouseOverManager->Paint(nSlideIndex, mxCanvas, xClip);
1118 void PresenterSlideSorter::Paint (const awt::Rectangle& rUpdateBox)
1120 const bool bCanvasChanged ( ! mxCanvas.is());
1121 if ( ! ProvideCanvas())
1122 return;
1124 if (mpLayout->mnRowCount<=0 || mpLayout->mnColumnCount<=0)
1126 OSL_ASSERT(mpLayout->mnRowCount>0 || mpLayout->mnColumnCount>0);
1127 return;
1130 mbIsPaintPending = false;
1132 ClearBackground(mxCanvas, rUpdateBox);
1134 // Give the canvas to the controls.
1135 if (bCanvasChanged)
1137 if (mpHorizontalScrollBar.is())
1138 mpHorizontalScrollBar->SetCanvas(mxCanvas);
1139 if (mpVerticalScrollBar.is())
1140 mpVerticalScrollBar->SetCanvas(mxCanvas);
1141 if (mpCloseButton.is())
1142 mpCloseButton->SetCanvas(mxCanvas, mxWindow);
1145 // Now that the controls have a canvas we can do the layouting.
1146 if (mbIsLayoutPending)
1147 UpdateLayout();
1149 // Paint the horizontal separator.
1150 rendering::RenderState aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0),
1151 NULL, Sequence<double>(4), rendering::CompositeOperation::SOURCE);
1152 PresenterCanvasHelper::SetDeviceColor(aRenderState, maSeparatorColor);
1153 mxCanvas->drawLine(
1154 geometry::RealPoint2D(0, mnSeparatorY),
1155 geometry::RealPoint2D(mxWindow->getPosSize().Width, mnSeparatorY),
1156 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL),
1157 aRenderState);
1159 // Paint the slides.
1160 if ( ! PresenterGeometryHelper::AreRectanglesDisjoint(
1161 rUpdateBox,
1162 PresenterGeometryHelper::ConvertRectangle(mpLayout->maBoundingBox)))
1164 mpLayout->ForAllVisibleSlides(
1165 ::boost::bind(&PresenterSlideSorter::PaintPreview, this, mxCanvas, rUpdateBox, _1));
1168 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
1169 if (xSpriteCanvas.is())
1170 xSpriteCanvas->updateScreen(sal_False);
1176 void PresenterSlideSorter::SetHorizontalOffset (const double nXOffset)
1178 if (mpLayout->SetHorizontalOffset(nXOffset))
1180 mxPreviewCache->setVisibleRange(
1181 mpLayout->GetFirstVisibleSlideIndex(),
1182 mpLayout->GetLastVisibleSlideIndex());
1184 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
1191 void PresenterSlideSorter::SetVerticalOffset (const double nYOffset)
1193 if (mpLayout->SetVerticalOffset(nYOffset))
1195 mxPreviewCache->setVisibleRange(
1196 mpLayout->GetFirstVisibleSlideIndex(),
1197 mpLayout->GetLastVisibleSlideIndex());
1199 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
1206 void PresenterSlideSorter::GotoSlide (const sal_Int32 nSlideIndex)
1208 mxSlideShowController->gotoSlideIndex(nSlideIndex);
1209 mpPresenterController->HideSlideSorter();
1215 bool PresenterSlideSorter::ProvideCanvas (void)
1217 if ( ! mxCanvas.is())
1219 if (mxPane.is())
1220 mxCanvas = mxPane->getCanvas();
1222 // Register as event listener so that we are informed when the
1223 // canvas is disposed (and we have to fetch another one).
1224 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
1225 if (xComponent.is())
1226 xComponent->addEventListener(static_cast<awt::XWindowListener*>(this));
1228 // Tell the scrollbar about the canvas.
1229 if (mpHorizontalScrollBar.is())
1230 mpHorizontalScrollBar->SetCanvas(mxCanvas);
1232 mpCurrentSlideFrameRenderer.reset(
1233 new CurrentSlideFrameRenderer(mxComponentContext, mxCanvas));
1235 return mxCanvas.is();
1241 void PresenterSlideSorter::ThrowIfDisposed (void)
1242 throw (lang::DisposedException)
1244 if (rBHelper.bDisposed || rBHelper.bInDispose)
1246 throw lang::DisposedException (
1247 OUString(RTL_CONSTASCII_USTRINGPARAM(
1248 "PresenterSlideSorter has been already disposed")),
1249 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1256 //===== PresenterSlideSorter::Layout ==========================================
1258 PresenterSlideSorter::Layout::Layout (
1259 const Orientation eOrientation,
1260 const ::rtl::Reference<PresenterScrollBar>& rpHorizontalScrollBar,
1261 const ::rtl::Reference<PresenterScrollBar>& rpVerticalScrollBar)
1262 : maBoundingBox(),
1263 maPreviewSize(),
1264 mnHorizontalOffset(0),
1265 mnVerticalOffset(0),
1266 mnHorizontalGap(0),
1267 mnVerticalGap(0),
1268 mnHorizontalBorder(0),
1269 mnVerticalBorder(0),
1270 mnRowCount(1),
1271 mnColumnCount(1),
1272 mnSlideCount(0),
1273 mnSlideIndexAtMouse(-1),
1274 mnFirstVisibleColumn(-1),
1275 mnLastVisibleColumn(-1),
1276 mnFirstVisibleRow(-1),
1277 mnLastVisibleRow(-1),
1278 meOrientation(eOrientation),
1279 mpHorizontalScrollBar(rpHorizontalScrollBar),
1280 mpVerticalScrollBar(rpVerticalScrollBar)
1287 void PresenterSlideSorter::Layout::Update (
1288 const geometry::RealRectangle2D& rBoundingBox,
1289 const double nSlideAspectRatio)
1291 maBoundingBox = rBoundingBox;
1293 mnHorizontalBorder = gnHorizontalBorder;
1294 mnVerticalBorder = gnVerticalBorder;
1296 const double nWidth (rBoundingBox.X2 - rBoundingBox.X1 - 2*mnHorizontalBorder);
1297 const double nHeight (rBoundingBox.Y2 - rBoundingBox.Y1 - 2*mnVerticalBorder);
1298 if (nWidth<=0 || nHeight<=0)
1299 return;
1301 double nPreviewWidth;
1303 // Determine column count, preview width, and horizontal gap (borders
1304 // are half the gap). Try to use the preferred values. Try more to
1305 // stay in the valid intervalls. This last constraint may be not
1306 // fullfilled in some cases.
1307 const double nElementWidth = nWidth / gnPreferredColumnCount;
1308 if (nElementWidth < gnMinimalPreviewWidth + gnMinimalHorizontalPreviewGap)
1310 // The preferred column count is too large.
1311 // Can we use the preferred preview width?
1312 if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
1314 // Yes.
1315 nPreviewWidth = gnPreferredPreviewWidth;
1316 mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
1317 / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
1318 mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1320 else
1322 // No. Set the column count to 1 and adapt preview width and
1323 // gap.
1324 mnColumnCount = 1;
1325 mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
1326 if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
1327 nPreviewWidth = nWidth - gnMinimalHorizontalPreviewGap;
1328 else
1329 nPreviewWidth = ::std::max(gnMinimalPreviewWidth, nWidth-mnHorizontalGap);
1332 else if (nElementWidth > gnMaximalPreviewWidth + gnMaximalHorizontalPreviewGap)
1334 // The preferred column count is too small.
1335 nPreviewWidth = gnPreferredPreviewWidth;
1336 mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
1337 / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
1338 mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1340 else
1342 // The preferred column count is possible. Determine gap and
1343 // preview width.
1344 mnColumnCount = gnPreferredColumnCount;
1345 if (nElementWidth - gnPreferredPreviewWidth < gnMinimalHorizontalPreviewGap)
1347 // Use the minimal gap and adapt the preview width.
1348 mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
1349 nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
1351 else if (nElementWidth - gnPreferredPreviewWidth <= gnMaximalHorizontalPreviewGap)
1353 // Use the maximal gap and adapt the preview width.
1354 mnHorizontalGap = round(gnMaximalHorizontalPreviewGap);
1355 nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
1357 else
1359 // Use the preferred preview width and adapt the gap.
1360 nPreviewWidth = gnPreferredPreviewWidth;
1361 mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1365 // Now determine the row count, preview height, and vertical gap.
1366 const double nPreviewHeight = nPreviewWidth / nSlideAspectRatio;
1367 mnRowCount = ::std::max(
1368 sal_Int32(1),
1369 sal_Int32(ceil((nHeight+gnPreferredVerticalPreviewGap)
1370 / (nPreviewHeight + gnPreferredVerticalPreviewGap))));
1371 mnVerticalGap = round(gnPreferredVerticalPreviewGap);
1373 maPreviewSize = geometry::IntegerSize2D(floor(nPreviewWidth), floor(nPreviewHeight));
1375 // Reset the offset.
1376 if (meOrientation == Horizontal)
1378 mnVerticalOffset = round(-(nHeight
1379 - mnRowCount*maPreviewSize.Height - (mnRowCount-1)*mnVerticalGap)
1380 / 2);
1381 mnHorizontalOffset = 0;
1383 else
1385 mnVerticalOffset = 0;
1386 mnHorizontalOffset = round(-(nWidth
1387 - mnColumnCount*maPreviewSize.Width
1388 - (mnColumnCount-1)*mnHorizontalGap)
1389 / 2);
1396 void PresenterSlideSorter::Layout::SetupVisibleArea (void)
1398 geometry::RealPoint2D aPoint (GetLocalPosition(
1399 geometry::RealPoint2D(maBoundingBox.X1, maBoundingBox.Y1)));
1400 if (meOrientation == Horizontal)
1402 mnFirstVisibleColumn = ::std::max(sal_Int32(0), GetColumn(aPoint));
1403 mnFirstVisibleRow = 0;
1405 else
1407 mnFirstVisibleColumn = 0;
1408 mnFirstVisibleRow = ::std::max(sal_Int32(0), GetRow(aPoint));
1411 aPoint = GetLocalPosition(geometry::RealPoint2D( maBoundingBox.X2, maBoundingBox.Y2));
1412 if (meOrientation == Horizontal)
1414 mnLastVisibleColumn = GetColumn(aPoint, true);
1415 mnLastVisibleRow = mnRowCount - 1;
1417 else
1419 mnLastVisibleColumn = mnColumnCount - 1;
1420 mnLastVisibleRow = GetRow(aPoint, true);
1427 bool PresenterSlideSorter::Layout::IsScrollBarNeeded (const sal_Int32 nSlideCount)
1429 geometry::RealPoint2D aBottomRight;
1430 if (GetOrientation() == Layout::Vertical)
1431 aBottomRight = GetPoint(
1432 mnColumnCount * (GetRow(nSlideCount)+1) - 1, +1, +1);
1433 else
1434 aBottomRight = GetPoint(
1435 mnRowCount * (GetColumn(nSlideCount)+1) - 1, +1, +1);
1436 return aBottomRight.X > maBoundingBox.X2-maBoundingBox.X1
1437 || aBottomRight.Y > maBoundingBox.Y2-maBoundingBox.Y1;
1443 geometry::RealPoint2D PresenterSlideSorter::Layout::GetLocalPosition(
1444 const geometry::RealPoint2D& rWindowPoint) const
1446 return css::geometry::RealPoint2D(
1447 rWindowPoint.X - maBoundingBox.X1 + mnHorizontalOffset,
1448 rWindowPoint.Y - maBoundingBox.Y1 + mnVerticalOffset);
1454 geometry::RealPoint2D PresenterSlideSorter::Layout::GetWindowPosition(
1455 const geometry::RealPoint2D& rLocalPoint) const
1457 return css::geometry::RealPoint2D(
1458 rLocalPoint.X - mnHorizontalOffset + maBoundingBox.X1,
1459 rLocalPoint.Y - mnVerticalOffset + maBoundingBox.Y1);
1465 sal_Int32 PresenterSlideSorter::Layout::GetColumn (
1466 const css::geometry::RealPoint2D& rLocalPoint,
1467 const bool bReturnInvalidValue) const
1469 const sal_Int32 nColumn(floor(
1470 (rLocalPoint.X + mnHorizontalGap/2.0) / (maPreviewSize.Width+mnHorizontalGap)));
1471 if (bReturnInvalidValue
1472 || (nColumn>=mnFirstVisibleColumn && nColumn<=mnLastVisibleColumn))
1474 return nColumn;
1476 else
1477 return -1;
1483 sal_Int32 PresenterSlideSorter::Layout::GetRow (
1484 const css::geometry::RealPoint2D& rLocalPoint,
1485 const bool bReturnInvalidValue) const
1487 const sal_Int32 nRow (floor(
1488 (rLocalPoint.Y + mnVerticalGap/2.0) / (maPreviewSize.Height+mnVerticalGap)));
1489 if (bReturnInvalidValue
1490 || (nRow>=mnFirstVisibleRow && nRow<=mnLastVisibleRow))
1492 return nRow;
1494 else
1495 return -1;
1501 sal_Int32 PresenterSlideSorter::Layout::GetSlideIndexForPosition (
1502 const css::geometry::RealPoint2D& rWindowPoint) const
1504 if ( ! PresenterGeometryHelper::IsInside(maBoundingBox, rWindowPoint))
1505 return -1;
1507 const css::geometry::RealPoint2D aLocalPosition (GetLocalPosition(rWindowPoint));
1508 const sal_Int32 nColumn (GetColumn(aLocalPosition));
1509 const sal_Int32 nRow (GetRow(aLocalPosition));
1511 if (nColumn < 0 || nRow < 0)
1512 return -1;
1513 else
1515 sal_Int32 nIndex (GetIndex(nRow, nColumn));
1516 if (nIndex >= mnSlideCount)
1517 return -1;
1518 else
1519 return nIndex;
1526 geometry::RealPoint2D PresenterSlideSorter::Layout::GetPoint (
1527 const sal_Int32 nSlideIndex,
1528 const sal_Int32 nRelativeHorizontalPosition,
1529 const sal_Int32 nRelativeVerticalPosition) const
1531 sal_Int32 nColumn (GetColumn(nSlideIndex));
1532 sal_Int32 nRow (GetRow(nSlideIndex));
1534 geometry::RealPoint2D aPosition (
1535 mnHorizontalBorder + nColumn*(maPreviewSize.Width+mnHorizontalGap),
1536 mnVerticalBorder + nRow*(maPreviewSize.Height+mnVerticalGap));
1538 if (nRelativeHorizontalPosition >= 0)
1540 if (nRelativeHorizontalPosition > 0)
1541 aPosition.X += maPreviewSize.Width;
1542 else
1543 aPosition.X += maPreviewSize.Width / 2.0;
1545 if (nRelativeVerticalPosition >= 0)
1547 if (nRelativeVerticalPosition > 0)
1548 aPosition.Y += maPreviewSize.Height;
1549 else
1550 aPosition.Y += maPreviewSize.Height / 2.0;
1553 return aPosition;
1559 awt::Rectangle PresenterSlideSorter::Layout::GetBoundingBox (const sal_Int32 nSlideIndex) const
1561 const geometry::RealPoint2D aWindowPosition(GetWindowPosition(GetPoint(nSlideIndex, -1, -1)));
1562 return PresenterGeometryHelper::ConvertRectangle(
1563 geometry::RealRectangle2D(
1564 aWindowPosition.X,
1565 aWindowPosition.Y,
1566 aWindowPosition.X + maPreviewSize.Width,
1567 aWindowPosition.Y + maPreviewSize.Height));
1573 void PresenterSlideSorter::Layout::ForAllVisibleSlides (const ::boost::function<void(sal_Int32)>& rAction)
1575 for (sal_Int32 nRow=mnFirstVisibleRow; nRow<=mnLastVisibleRow; ++nRow)
1577 for (sal_Int32 nColumn=mnFirstVisibleColumn; nColumn<=mnLastVisibleColumn; ++nColumn)
1579 const sal_Int32 nSlideIndex (GetIndex(nRow, nColumn));
1580 if (nSlideIndex >= mnSlideCount)
1581 return;
1582 rAction(nSlideIndex);
1590 sal_Int32 PresenterSlideSorter::Layout::GetFirstVisibleSlideIndex (void) const
1592 return GetIndex(mnFirstVisibleRow, mnFirstVisibleColumn);
1598 sal_Int32 PresenterSlideSorter::Layout::GetLastVisibleSlideIndex (void) const
1600 return ::std::min(
1601 GetIndex(mnLastVisibleRow, mnLastVisibleColumn),
1602 mnSlideCount);
1608 bool PresenterSlideSorter::Layout::SetHorizontalOffset (const double nOffset)
1610 if (mnHorizontalOffset != nOffset)
1612 mnHorizontalOffset = round(nOffset);
1613 SetupVisibleArea();
1614 UpdateScrollBars();
1615 return true;
1617 else
1618 return false;
1624 bool PresenterSlideSorter::Layout::SetVerticalOffset (const double nOffset)
1626 if (mnVerticalOffset != nOffset)
1628 mnVerticalOffset = round(nOffset);
1629 SetupVisibleArea();
1630 UpdateScrollBars();
1631 return true;
1633 else
1634 return false;
1640 PresenterSlideSorter::Layout::Orientation
1641 PresenterSlideSorter::Layout::GetOrientation (void) const
1643 return meOrientation;
1649 void PresenterSlideSorter::Layout::UpdateScrollBars (void)
1651 sal_Int32 nTotalColumnCount (0);
1652 sal_Int32 nTotalRowCount (0);
1653 if (meOrientation == Horizontal)
1655 nTotalColumnCount = sal_Int32(ceil(double(mnSlideCount) / double(mnRowCount)));
1656 nTotalRowCount = mnRowCount;
1658 else
1660 nTotalColumnCount = mnColumnCount;
1661 nTotalRowCount = sal_Int32(ceil(double(mnSlideCount) / double(mnColumnCount)));
1664 if (mpHorizontalScrollBar.get() != NULL)
1666 mpHorizontalScrollBar->SetTotalSize(
1667 nTotalColumnCount * maPreviewSize.Width
1668 + (nTotalColumnCount-1) * mnHorizontalGap
1669 + 2*mnHorizontalBorder);
1670 mpHorizontalScrollBar->SetThumbPosition(mnHorizontalOffset, false);
1671 mpHorizontalScrollBar->SetThumbSize(maBoundingBox.X2 - maBoundingBox.X1 + 1);
1672 mpHorizontalScrollBar->SetLineHeight(maPreviewSize.Width);
1674 if (mpVerticalScrollBar.get() != NULL)
1676 mpVerticalScrollBar->SetTotalSize(
1677 nTotalRowCount * maPreviewSize.Height
1678 + (nTotalRowCount-1) * mnVerticalGap
1679 + 2*mnVerticalGap);
1680 mpVerticalScrollBar->SetThumbPosition(mnVerticalOffset, false);
1681 mpVerticalScrollBar->SetThumbSize(maBoundingBox.Y2 - maBoundingBox.Y1 + 1);
1682 mpVerticalScrollBar->SetLineHeight(maPreviewSize.Height);
1687 // No place yet for the vertical scroll bar.
1693 sal_Int32 PresenterSlideSorter::Layout::GetIndex (
1694 const sal_Int32 nRow,
1695 const sal_Int32 nColumn) const
1697 if (meOrientation == Horizontal)
1698 return nColumn * mnRowCount + nRow;
1699 else
1700 return nRow * mnColumnCount + nColumn;
1706 sal_Int32 PresenterSlideSorter::Layout::GetRow (const sal_Int32 nSlideIndex) const
1708 if (meOrientation == Horizontal)
1709 return nSlideIndex % mnRowCount;
1710 else
1711 return nSlideIndex / mnColumnCount;
1717 sal_Int32 PresenterSlideSorter::Layout::GetColumn (const sal_Int32 nSlideIndex) const
1719 if (meOrientation == Horizontal)
1720 return nSlideIndex / mnRowCount;
1721 else
1722 return nSlideIndex % mnColumnCount;
1728 //===== PresenterSlideSorter::MouseOverManager ================================
1730 PresenterSlideSorter::MouseOverManager::MouseOverManager (
1731 const Reference<container::XIndexAccess>& rxSlides,
1732 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
1733 const Reference<awt::XWindow>& rxInvalidateTarget,
1734 const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager)
1735 : mxCanvas(),
1736 mxSlides(rxSlides),
1737 mpLeftLabelBitmap(),
1738 mpCenterLabelBitmap(),
1739 mpRightLabelBitmap(),
1740 mpFont(),
1741 mnSlideIndex(-1),
1742 maSlideBoundingBox(),
1743 mxInvalidateTarget(rxInvalidateTarget),
1744 mpPaintManager(rpPaintManager)
1746 if (rpTheme.get()!=NULL)
1748 ::boost::shared_ptr<PresenterBitmapContainer> pBitmaps (rpTheme->GetBitmapContainer());
1749 if (pBitmaps.get() != NULL)
1751 mpLeftLabelBitmap = pBitmaps->GetBitmap(A2S("LabelLeft"));
1752 mpCenterLabelBitmap = pBitmaps->GetBitmap(A2S("LabelCenter"));
1753 mpRightLabelBitmap = pBitmaps->GetBitmap(A2S("LabelRight"));
1756 mpFont = rpTheme->GetFont(A2S("SlideSorterLabelFont"));
1763 PresenterSlideSorter::MouseOverManager::~MouseOverManager (void)
1770 void PresenterSlideSorter::MouseOverManager::Paint (
1771 const sal_Int32 nSlideIndex,
1772 const Reference<rendering::XCanvas>& rxCanvas,
1773 const Reference<rendering::XPolyPolygon2D>& rxClip)
1775 if (nSlideIndex != mnSlideIndex)
1776 return;
1778 if (mxCanvas != rxCanvas)
1779 SetCanvas(rxCanvas);
1780 if (rxCanvas != NULL)
1782 if ( ! mxBitmap.is())
1783 mxBitmap = CreateBitmap(msText, maSlideBoundingBox.Width);
1784 if (mxBitmap.is())
1786 geometry::IntegerSize2D aSize (mxBitmap->getSize());
1787 const double nXOffset (maSlideBoundingBox.X
1788 + (maSlideBoundingBox.Width - aSize.Width) / 2.0);
1789 const double nYOffset (maSlideBoundingBox.Y
1790 + (maSlideBoundingBox.Height - aSize.Height) / 2.0);
1791 rxCanvas->drawBitmap(
1792 mxBitmap,
1793 rendering::ViewState(
1794 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1795 rxClip),
1796 rendering::RenderState(
1797 geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset),
1798 NULL,
1799 Sequence<double>(4),
1800 rendering::CompositeOperation::SOURCE));
1808 void PresenterSlideSorter::MouseOverManager::SetCanvas (
1809 const Reference<rendering::XCanvas>& rxCanvas)
1811 mxCanvas = rxCanvas;
1812 if (mpFont.get() != NULL)
1813 mpFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY));
1819 void PresenterSlideSorter::MouseOverManager::SetSlide (
1820 const sal_Int32 nSlideIndex,
1821 const awt::Rectangle& rBox)
1823 if (mnSlideIndex == nSlideIndex)
1824 return;
1826 mnSlideIndex = -1;
1827 Invalidate();
1829 maSlideBoundingBox = rBox;
1830 mnSlideIndex = nSlideIndex;
1832 if (nSlideIndex >= 0)
1834 if (mxSlides.get() != NULL)
1836 msText = OUString();
1838 Reference<beans::XPropertySet> xSlideProperties(mxSlides->getByIndex(nSlideIndex), UNO_QUERY);
1839 if (xSlideProperties.is())
1840 xSlideProperties->getPropertyValue(A2S("LinkDisplayName")) >>= msText;
1842 if (msText.getLength() == 0)
1843 msText = A2S("Slide ") + OUString::valueOf(nSlideIndex + 1);
1846 else
1848 msText = OUString();
1850 mxBitmap = NULL;
1852 Invalidate();
1858 Reference<rendering::XBitmap> PresenterSlideSorter::MouseOverManager::CreateBitmap (
1859 const OUString& rsText,
1860 const sal_Int32 nMaximalWidth) const
1862 if ( ! mxCanvas.is())
1863 return NULL;
1865 if (mpFont.get()==NULL || !mpFont->mxFont.is())
1866 return NULL;
1868 // Long text has to be shortened.
1869 const OUString sText (GetFittingText(rsText, nMaximalWidth
1870 - 2*gnHorizontalLabelBorder
1871 - 2*gnHorizontalLabelPadding));
1873 // Determine the size of the label. Its height is defined by the
1874 // bitmaps that are used to paints its background. The width is defined
1875 // by the text.
1876 geometry::IntegerSize2D aLabelSize (CalculateLabelSize(sText));
1878 // Create a new bitmap that will contain the complete label.
1879 Reference<rendering::XBitmap> xBitmap (
1880 mxCanvas->getDevice()->createCompatibleAlphaBitmap(aLabelSize));
1882 if ( ! xBitmap.is())
1883 return NULL;
1885 Reference<rendering::XBitmapCanvas> xBitmapCanvas (xBitmap, UNO_QUERY);
1886 if ( ! xBitmapCanvas.is())
1887 return NULL;
1889 // Paint the background.
1890 PaintButtonBackground(xBitmapCanvas, aLabelSize);
1892 // Paint the text.
1893 if (sText.getLength() > 0)
1896 const rendering::StringContext aContext (sText, 0, sText.getLength());
1897 const Reference<rendering::XTextLayout> xLayout (mpFont->mxFont->createTextLayout(
1898 aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0));
1899 const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds());
1901 const double nXOffset = (aLabelSize.Width - aTextBBox.X2 + aTextBBox.X1) / 2;
1902 const double nYOffset = aLabelSize.Height
1903 - (aLabelSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y2;
1905 const rendering::ViewState aViewState(
1906 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1907 NULL);
1909 rendering::RenderState aRenderState (
1910 geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset),
1911 NULL,
1912 Sequence<double>(4),
1913 rendering::CompositeOperation::SOURCE);
1914 PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
1916 xBitmapCanvas->drawText(
1917 aContext,
1918 mpFont->mxFont,
1919 aViewState,
1920 aRenderState,
1921 rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
1924 return xBitmap;
1930 OUString PresenterSlideSorter::MouseOverManager::GetFittingText (
1931 const OUString& rsText,
1932 const double nMaximalWidth) const
1934 const double nTextWidth (
1935 PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText).Width);
1936 if (nTextWidth > nMaximalWidth)
1938 // Text is too wide. Shorten it by removing characters from the end
1939 // and replacing them by ellipses.
1941 // Guess a start value of the final string length.
1942 double nBestWidth (0);
1943 OUString sBestCandidate;
1944 sal_Int32 nLength (round(rsText.getLength() * nMaximalWidth / nTextWidth));
1945 const OUString sEllipses (A2S("..."));
1946 while (true)
1948 const OUString sCandidate (rsText.copy(0,nLength) + sEllipses);
1949 const double nWidth (
1950 PresenterCanvasHelper::GetTextSize(mpFont->mxFont, sCandidate).Width);
1951 if (nWidth > nMaximalWidth)
1953 // Candidate still too wide, shorten it.
1954 nLength -= 1;
1955 if (nLength <= 0)
1956 break;
1958 else if (nWidth < nMaximalWidth)
1960 // Candidate short enough.
1961 if (nWidth > nBestWidth)
1963 // Best length so far.
1964 sBestCandidate = sCandidate;
1965 nBestWidth = nWidth;
1966 nLength += 1;
1967 if (nLength >= rsText.getLength())
1968 break;
1970 else
1971 break;
1973 else
1975 // Candidate is exactly as long as it may be. Use it
1976 // without looking any further.
1977 sBestCandidate = sCandidate;
1978 break;
1981 return sBestCandidate;
1983 else
1984 return rsText;
1990 geometry::IntegerSize2D PresenterSlideSorter::MouseOverManager::CalculateLabelSize (
1991 const OUString& rsText) const
1993 // Height is specified by the label bitmaps.
1994 sal_Int32 nHeight (32);
1995 if (mpCenterLabelBitmap.get() != NULL)
1997 Reference<rendering::XBitmap> xBitmap (mpCenterLabelBitmap->GetNormalBitmap());
1998 if (xBitmap.is())
1999 nHeight = xBitmap->getSize().Height;
2002 // Width is specified by text width and maximal width.
2003 const geometry::RealSize2D aTextSize (
2004 PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText));
2006 const sal_Int32 nWidth (round(aTextSize.Width + 2*gnHorizontalLabelPadding));
2008 return geometry::IntegerSize2D(nWidth, nHeight);
2014 void PresenterSlideSorter::MouseOverManager::PaintButtonBackground (
2015 const Reference<rendering::XBitmapCanvas>& rxCanvas,
2016 const geometry::IntegerSize2D& rSize) const
2018 // Get the bitmaps for painting the label background.
2019 Reference<rendering::XBitmap> xLeftLabelBitmap;
2020 if (mpLeftLabelBitmap.get() != NULL)
2021 xLeftLabelBitmap = mpLeftLabelBitmap->GetNormalBitmap();
2023 Reference<rendering::XBitmap> xCenterLabelBitmap;
2024 if (mpCenterLabelBitmap.get() != NULL)
2025 xCenterLabelBitmap = mpCenterLabelBitmap->GetNormalBitmap();
2027 Reference<rendering::XBitmap> xRightLabelBitmap;
2028 if (mpRightLabelBitmap.get() != NULL)
2029 xRightLabelBitmap = mpRightLabelBitmap->GetNormalBitmap();
2031 PresenterUIPainter::PaintHorizontalBitmapComposite (
2032 Reference<rendering::XCanvas>(rxCanvas, UNO_QUERY),
2033 awt::Rectangle(0,0, rSize.Width,rSize.Height),
2034 awt::Rectangle(0,0, rSize.Width,rSize.Height),
2035 xLeftLabelBitmap,
2036 xCenterLabelBitmap,
2037 xRightLabelBitmap);
2043 void PresenterSlideSorter::MouseOverManager::Invalidate (void)
2045 if (mpPaintManager.get() != NULL)
2046 mpPaintManager->Invalidate(mxInvalidateTarget, maSlideBoundingBox, true);
2052 //===== PresenterSlideSorter::CurrentSlideFrameRenderer =======================
2054 PresenterSlideSorter::CurrentSlideFrameRenderer::CurrentSlideFrameRenderer (
2055 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
2056 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas)
2057 : mpTopLeft(),
2058 mpTop(),
2059 mpTopRight(),
2060 mpLeft(),
2061 mpRight(),
2062 mpBottomLeft(),
2063 mpBottom(),
2064 mpBottomRight(),
2065 mnTopFrameSize(0),
2066 mnLeftFrameSize(0),
2067 mnRightFrameSize(0),
2068 mnBottomFrameSize(0)
2070 PresenterConfigurationAccess aConfiguration (
2071 rxContext,
2072 OUString::createFromAscii("/org.openoffice.Office.extension.PresenterScreen/"),
2073 PresenterConfigurationAccess::READ_ONLY);
2074 Reference<container::XHierarchicalNameAccess> xBitmaps (
2075 aConfiguration.GetConfigurationNode(
2076 A2S("PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps")),
2077 UNO_QUERY);
2078 if ( ! xBitmaps.is())
2079 return;
2081 PresenterBitmapContainer aContainer (
2082 A2S("PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps"),
2083 ::boost::shared_ptr<PresenterBitmapContainer>(),
2084 rxContext,
2085 rxCanvas,
2086 PresenterComponent::GetBasePath(rxContext));
2088 mpTopLeft = aContainer.GetBitmap(A2S("TopLeft"));
2089 mpTop = aContainer.GetBitmap(A2S("Top"));
2090 mpTopRight = aContainer.GetBitmap(A2S("TopRight"));
2091 mpLeft = aContainer.GetBitmap(A2S("Left"));
2092 mpRight = aContainer.GetBitmap(A2S("Right"));
2093 mpBottomLeft = aContainer.GetBitmap(A2S("BottomLeft"));
2094 mpBottom = aContainer.GetBitmap(A2S("Bottom"));
2095 mpBottomRight = aContainer.GetBitmap(A2S("BottomRight"));
2097 // Determine size of frame.
2098 if (mpTop.get() != NULL)
2099 mnTopFrameSize = mpTop->mnHeight;
2100 if (mpLeft.get() != NULL)
2101 mnLeftFrameSize = mpLeft->mnWidth;
2102 if (mpRight.get() != NULL)
2103 mnRightFrameSize = mpRight->mnWidth;
2104 if (mpBottom.get() != NULL)
2105 mnBottomFrameSize = mpBottom->mnHeight;
2107 if (mpTopLeft.get() != NULL)
2109 mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopLeft->mnHeight);
2110 mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpTopLeft->mnWidth);
2112 if (mpTopRight.get() != NULL)
2114 mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopRight->mnHeight);
2115 mnRightFrameSize = ::std::max(mnRightFrameSize, mpTopRight->mnWidth);
2117 if (mpBottomLeft.get() != NULL)
2119 mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpBottomLeft->mnWidth);
2120 mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomLeft->mnHeight);
2122 if (mpBottomRight.get() != NULL)
2124 mnRightFrameSize = ::std::max(mnRightFrameSize, mpBottomRight->mnWidth);
2125 mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomRight->mnHeight);
2132 PresenterSlideSorter::CurrentSlideFrameRenderer::~CurrentSlideFrameRenderer (void)
2139 void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintCurrentSlideFrame (
2140 const awt::Rectangle& rSlideBoundingBox,
2141 const Reference<rendering::XCanvas>& rxCanvas,
2142 const geometry::RealRectangle2D& rClipBox)
2144 if ( ! rxCanvas.is())
2145 return;
2147 const Reference<rendering::XPolyPolygon2D> xClip (
2148 PresenterGeometryHelper::CreatePolygon(rClipBox, rxCanvas->getDevice()));
2150 if (mpTop.get() != NULL)
2152 PaintBitmapTiled(
2153 mpTop->GetNormalBitmap(),
2154 rxCanvas,
2155 rClipBox,
2156 rSlideBoundingBox.X,
2157 rSlideBoundingBox.Y - mpTop->mnHeight,
2158 rSlideBoundingBox.Width,
2159 mpTop->mnHeight);
2161 if (mpLeft.get() != NULL)
2163 PaintBitmapTiled(
2164 mpLeft->GetNormalBitmap(),
2165 rxCanvas,
2166 rClipBox,
2167 rSlideBoundingBox.X - mpLeft->mnWidth,
2168 rSlideBoundingBox.Y,
2169 mpLeft->mnWidth,
2170 rSlideBoundingBox.Height);
2172 if (mpRight.get() != NULL)
2174 PaintBitmapTiled(
2175 mpRight->GetNormalBitmap(),
2176 rxCanvas,
2177 rClipBox,
2178 rSlideBoundingBox.X + rSlideBoundingBox.Width,
2179 rSlideBoundingBox.Y,
2180 mpRight->mnWidth,
2181 rSlideBoundingBox.Height);
2183 if (mpBottom.get() != NULL)
2185 PaintBitmapTiled(
2186 mpBottom->GetNormalBitmap(),
2187 rxCanvas,
2188 rClipBox,
2189 rSlideBoundingBox.X,
2190 rSlideBoundingBox.Y + rSlideBoundingBox.Height,
2191 rSlideBoundingBox.Width,
2192 mpBottom->mnHeight);
2194 if (mpTopLeft.get() != NULL)
2196 PaintBitmapOnce(
2197 mpTopLeft->GetNormalBitmap(),
2198 rxCanvas,
2199 xClip,
2200 rSlideBoundingBox.X - mpTopLeft->mnWidth,
2201 rSlideBoundingBox.Y - mpTopLeft->mnHeight);
2203 if (mpTopRight.get() != NULL)
2205 PaintBitmapOnce(
2206 mpTopRight->GetNormalBitmap(),
2207 rxCanvas,
2208 xClip,
2209 rSlideBoundingBox.X + rSlideBoundingBox.Width,
2210 rSlideBoundingBox.Y - mpTopLeft->mnHeight);
2212 if (mpBottomLeft.get() != NULL)
2214 PaintBitmapOnce(
2215 mpBottomLeft->GetNormalBitmap(),
2216 rxCanvas,
2217 xClip,
2218 rSlideBoundingBox.X - mpBottomLeft->mnWidth,
2219 rSlideBoundingBox.Y + rSlideBoundingBox.Height);
2221 if (mpBottomRight.get() != NULL)
2223 PaintBitmapOnce(
2224 mpBottomRight->GetNormalBitmap(),
2225 rxCanvas,
2226 xClip,
2227 rSlideBoundingBox.X + rSlideBoundingBox.Width,
2228 rSlideBoundingBox.Y + rSlideBoundingBox.Height);
2235 awt::Rectangle PresenterSlideSorter::CurrentSlideFrameRenderer::GetBoundingBox (
2236 const awt::Rectangle& rSlideBoundingBox)
2238 return awt::Rectangle(
2239 rSlideBoundingBox.X - mnLeftFrameSize,
2240 rSlideBoundingBox.Y - mnTopFrameSize,
2241 rSlideBoundingBox.Width + mnLeftFrameSize + mnRightFrameSize,
2242 rSlideBoundingBox.Height + mnTopFrameSize + mnBottomFrameSize);
2248 void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintBitmapOnce(
2249 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
2250 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
2251 const Reference<rendering::XPolyPolygon2D>& rxClip,
2252 const double nX,
2253 const double nY)
2255 OSL_ASSERT(rxCanvas.is());
2256 if ( ! rxBitmap.is())
2257 return;
2259 const rendering::ViewState aViewState(
2260 geometry::AffineMatrix2D(1,0,0, 0,1,0),
2261 rxClip);
2263 const rendering::RenderState aRenderState (
2264 geometry::AffineMatrix2D(
2265 1, 0, nX,
2266 0, 1, nY),
2267 NULL,
2268 Sequence<double>(4),
2269 rendering::CompositeOperation::SOURCE);
2271 rxCanvas->drawBitmap(
2272 rxBitmap,
2273 aViewState,
2274 aRenderState);
2280 void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintBitmapTiled(
2281 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
2282 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
2283 const geometry::RealRectangle2D& rClipBox,
2284 const double nX0,
2285 const double nY0,
2286 const double nWidth,
2287 const double nHeight)
2289 OSL_ASSERT(rxCanvas.is());
2290 if ( ! rxBitmap.is())
2291 return;
2293 geometry::IntegerSize2D aSize (rxBitmap->getSize());
2295 const rendering::ViewState aViewState(
2296 geometry::AffineMatrix2D(1,0,0, 0,1,0),
2297 PresenterGeometryHelper::CreatePolygon(
2298 PresenterGeometryHelper::Intersection(
2299 rClipBox,
2300 geometry::RealRectangle2D(nX0,nY0,nX0+nWidth,nY0+nHeight)),
2301 rxCanvas->getDevice()));
2303 rendering::RenderState aRenderState (
2304 geometry::AffineMatrix2D(
2305 1, 0, nX0,
2306 0, 1, nY0),
2307 NULL,
2308 Sequence<double>(4),
2309 rendering::CompositeOperation::SOURCE);
2311 const double nX1 = nX0 + nWidth;
2312 const double nY1 = nY0 + nHeight;
2313 for (double nY=nY0; nY<nY1; nY+=aSize.Height)
2314 for (double nX=nX0; nX<nX1; nX+=aSize.Width)
2316 aRenderState.AffineTransform.m02 = nX;
2317 aRenderState.AffineTransform.m12 = nY;
2318 rxCanvas->drawBitmap(
2319 rxBitmap,
2320 aViewState,
2321 aRenderState);
2325 } } // end of namespace ::sdext::presenter