Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "vcl/svapp.hxx"
21 : #include "vcl/settings.hxx"
22 :
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>
48 :
49 : using namespace ::com::sun::star;
50 : using namespace ::com::sun::star::uno;
51 : using namespace ::com::sun::star::drawing::framework;
52 :
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);
58 :
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);
67 :
68 : const static sal_Int32 gnHorizontalLabelBorder (3);
69 : const static sal_Int32 gnHorizontalLabelPadding (5);
70 :
71 : const static sal_Int32 gnVerticalButtonPadding (gnVerticalGap);
72 : }
73 :
74 : namespace sdext { namespace presenter {
75 :
76 : namespace {
77 0 : sal_Int32 round (const double nValue) { return sal::static_int_cast<sal_Int32>(0.5 + nValue); }
78 0 : sal_Int32 floor (const double nValue) { return sal::static_int_cast<sal_Int32>(nValue); }
79 : }
80 :
81 : //===== PresenterSlideSorter::Layout ==========================================
82 :
83 0 : class PresenterSlideSorter::Layout
84 : {
85 : public:
86 : Layout (const ::rtl::Reference<PresenterScrollBar>& rpVerticalScrollBar);
87 :
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);
109 :
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;
126 :
127 : private:
128 : ::rtl::Reference<PresenterScrollBar> mpVerticalScrollBar;
129 :
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;
133 : };
134 :
135 : //==== PresenterSlideSorter::MouseOverManager =================================
136 :
137 : class PresenterSlideSorter::MouseOverManager
138 : : ::boost::noncopyable
139 : {
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();
147 :
148 : void Paint (
149 : const sal_Int32 nSlideIndex,
150 : const Reference<rendering::XCanvas>& rxCanvas,
151 : const Reference<rendering::XPolyPolygon2D>& rxClip);
152 :
153 : void SetSlide (
154 : const sal_Int32 nSlideIndex,
155 : const awt::Rectangle& rBox);
156 :
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;
170 :
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.
175 : */
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;
186 : };
187 :
188 : //==== PresenterSlideSorter::CurrentSlideFrameRenderer ========================
189 :
190 : class PresenterSlideSorter::CurrentSlideFrameRenderer
191 : {
192 : public:
193 : CurrentSlideFrameRenderer (
194 : const css::uno::Reference<css::uno::XComponentContext>& rxContext,
195 : const css::uno::Reference<css::rendering::XCanvas>& rxCanvas);
196 : ~CurrentSlideFrameRenderer();
197 :
198 : void PaintCurrentSlideFrame (
199 : const awt::Rectangle& rSlideBoundingBox,
200 : const Reference<rendering::XCanvas>& rxCanvas,
201 : const geometry::RealRectangle2D& rClipBox);
202 :
203 : /** Enlarge the given rectangle to include the current slide indicator.
204 : */
205 : awt::Rectangle GetBoundingBox (
206 : const awt::Rectangle& rSlideBoundingBox);
207 :
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;
221 :
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);
236 : };
237 :
238 : //===== PresenterSlideSorter ==================================================
239 :
240 0 : 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 0 : mxPreviewFrame()
268 : {
269 0 : if ( ! rxContext.is()
270 0 : || ! rxViewId.is()
271 0 : || ! rxController.is()
272 0 : || rpPresenterController.get()==NULL)
273 : {
274 0 : throw lang::IllegalArgumentException();
275 : }
276 :
277 0 : if ( ! mxSlideShowController.is())
278 0 : throw RuntimeException();
279 :
280 : try
281 : {
282 : // Get pane and window.
283 0 : Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
284 : Reference<XConfigurationController> xCC (
285 0 : xCM->getConfigurationController(), UNO_QUERY_THROW);
286 : Reference<lang::XMultiComponentFactory> xFactory (
287 0 : mxComponentContext->getServiceManager(), UNO_QUERY_THROW);
288 :
289 0 : mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
290 0 : mxWindow = mxPane->getWindow();
291 :
292 : // Add window listener.
293 0 : mxWindow->addWindowListener(this);
294 0 : mxWindow->addPaintListener(this);
295 0 : mxWindow->addMouseListener(this);
296 0 : mxWindow->addMouseMotionListener(this);
297 0 : mxWindow->setVisible(sal_True);
298 :
299 : // Remember the current slide.
300 0 : mnCurrentSlideIndex = mxSlideShowController->getCurrentSlideIndex();
301 :
302 : // Create the scroll bar.
303 0 : mpVerticalScrollBar = ::rtl::Reference<PresenterScrollBar>(
304 : new PresenterVerticalScrollBar(
305 : rxContext,
306 : mxWindow,
307 : mpPresenterController->GetPaintManager(),
308 0 : ::boost::bind(&PresenterSlideSorter::SetVerticalOffset,this,_1)));
309 :
310 0 : mpCloseButton = PresenterButton::Create(
311 : rxContext,
312 : mpPresenterController,
313 : mpPresenterController->GetTheme(),
314 : mxWindow,
315 : mxCanvas,
316 0 : "SlideSorterCloser");
317 :
318 0 : if (mpPresenterController->GetTheme().get() != NULL)
319 : {
320 : PresenterTheme::SharedFontDescriptor pFont (
321 0 : mpPresenterController->GetTheme()->GetFont("ButtonFont"));
322 0 : if (pFont.get() != NULL)
323 0 : maSeparatorColor = pFont->mnColor;
324 : }
325 :
326 : // Create the layout.
327 0 : mpLayout.reset(new Layout(mpVerticalScrollBar));
328 :
329 : // Create the preview cache.
330 0 : mxPreviewCache = Reference<drawing::XSlidePreviewCache>(
331 0 : xFactory->createInstanceWithContext(
332 : OUString("com.sun.star.drawing.PresenterPreviewCache"),
333 0 : mxComponentContext),
334 0 : UNO_QUERY_THROW);
335 0 : Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY);
336 0 : mxPreviewCache->setDocumentSlides(xSlides, rxController->getModel());
337 0 : mxPreviewCache->addPreviewCreationNotifyListener(this);
338 0 : if (xSlides.is())
339 : {
340 0 : mpLayout->mnSlideCount = xSlides->getCount();
341 : }
342 :
343 : // Create the mouse over manager.
344 : mpMouseOverManager.reset(new MouseOverManager(
345 : Reference<container::XIndexAccess>(mxSlideShowController, UNO_QUERY),
346 : mpPresenterController->GetTheme(),
347 : mxWindow,
348 0 : mpPresenterController->GetPaintManager()));
349 :
350 : // Listen for changes of the current slide.
351 0 : Reference<beans::XPropertySet> xControllerProperties (rxController, UNO_QUERY_THROW);
352 0 : xControllerProperties->addPropertyChangeListener(
353 : OUString("CurrentPage"),
354 0 : this);
355 :
356 : // Move the current slide in the center of the window.
357 0 : const awt::Rectangle aCurrentSlideBBox (mpLayout->GetBoundingBox(mnCurrentSlideIndex));
358 0 : const awt::Rectangle aWindowBox (mxWindow->getPosSize());
359 0 : SetHorizontalOffset(aCurrentSlideBBox.X - aWindowBox.Width/2.0);
360 : }
361 0 : catch (RuntimeException&)
362 : {
363 0 : disposing();
364 0 : throw;
365 : }
366 0 : }
367 :
368 0 : PresenterSlideSorter::~PresenterSlideSorter()
369 : {
370 0 : }
371 :
372 0 : void SAL_CALL PresenterSlideSorter::disposing()
373 : {
374 0 : mxComponentContext = NULL;
375 0 : mxViewId = NULL;
376 0 : mxPane = NULL;
377 :
378 0 : if (mpVerticalScrollBar.is())
379 : {
380 : Reference<lang::XComponent> xComponent (
381 0 : static_cast<XWeak*>(mpVerticalScrollBar.get()), UNO_QUERY);
382 0 : mpVerticalScrollBar = NULL;
383 0 : if (xComponent.is())
384 0 : xComponent->dispose();
385 : }
386 0 : if (mpCloseButton.is())
387 : {
388 : Reference<lang::XComponent> xComponent (
389 0 : static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY);
390 0 : mpCloseButton = NULL;
391 0 : if (xComponent.is())
392 0 : xComponent->dispose();
393 : }
394 :
395 0 : if (mxCanvas.is())
396 : {
397 0 : Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
398 0 : if (xComponent.is())
399 0 : xComponent->removeEventListener(static_cast<awt::XWindowListener*>(this));
400 0 : mxCanvas = NULL;
401 : }
402 0 : mpPresenterController = NULL;
403 0 : mxSlideShowController = NULL;
404 0 : mpLayout.reset();
405 0 : mpMouseOverManager.reset();
406 :
407 0 : if (mxPreviewCache.is())
408 : {
409 0 : mxPreviewCache->removePreviewCreationNotifyListener(this);
410 :
411 0 : Reference<XComponent> xComponent (mxPreviewCache, UNO_QUERY);
412 0 : mxPreviewCache = NULL;
413 0 : if (xComponent.is())
414 0 : xComponent->dispose();
415 : }
416 :
417 0 : if (mxWindow.is())
418 : {
419 0 : mxWindow->removeWindowListener(this);
420 0 : mxWindow->removePaintListener(this);
421 0 : mxWindow->removeMouseListener(this);
422 0 : mxWindow->removeMouseMotionListener(this);
423 : }
424 0 : }
425 :
426 0 : void PresenterSlideSorter::SetActiveState (const bool bIsActive)
427 : {
428 : (void)bIsActive;
429 0 : }
430 :
431 : //----- lang::XEventListener --------------------------------------------------
432 :
433 0 : void SAL_CALL PresenterSlideSorter::disposing (const lang::EventObject& rEventObject)
434 : throw (RuntimeException, std::exception)
435 : {
436 0 : if (rEventObject.Source == mxWindow)
437 : {
438 0 : mxWindow = NULL;
439 0 : dispose();
440 : }
441 0 : else if (rEventObject.Source == mxPreviewCache)
442 : {
443 0 : mxPreviewCache = NULL;
444 0 : dispose();
445 : }
446 0 : else if (rEventObject.Source == mxCanvas)
447 : {
448 0 : mxCanvas = NULL;
449 0 : mbIsLayoutPending = true;
450 0 : mbIsPaintPending = true;
451 :
452 0 : mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
453 : }
454 0 : }
455 :
456 : //----- XWindowListener -------------------------------------------------------
457 :
458 0 : void SAL_CALL PresenterSlideSorter::windowResized (const awt::WindowEvent& rEvent)
459 : throw (uno::RuntimeException, std::exception)
460 : {
461 : (void)rEvent;
462 0 : ThrowIfDisposed();
463 0 : mbIsLayoutPending = true;
464 0 : mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
465 0 : }
466 :
467 0 : void SAL_CALL PresenterSlideSorter::windowMoved (const awt::WindowEvent& rEvent)
468 : throw (uno::RuntimeException, std::exception)
469 : {
470 : (void)rEvent;
471 0 : ThrowIfDisposed();
472 0 : }
473 :
474 0 : void SAL_CALL PresenterSlideSorter::windowShown (const lang::EventObject& rEvent)
475 : throw (uno::RuntimeException, std::exception)
476 : {
477 : (void)rEvent;
478 0 : ThrowIfDisposed();
479 0 : mbIsLayoutPending = true;
480 0 : mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
481 0 : }
482 :
483 0 : void SAL_CALL PresenterSlideSorter::windowHidden (const lang::EventObject& rEvent)
484 : throw (uno::RuntimeException, std::exception)
485 : {
486 : (void)rEvent;
487 0 : ThrowIfDisposed();
488 0 : }
489 :
490 : //----- XPaintListener --------------------------------------------------------
491 :
492 0 : void SAL_CALL PresenterSlideSorter::windowPaint (const css::awt::PaintEvent& rEvent)
493 : throw (RuntimeException, std::exception)
494 : {
495 : (void)rEvent;
496 :
497 : // Deactivated views must not be painted.
498 0 : if ( ! mbIsPresenterViewActive)
499 0 : return;
500 :
501 0 : Paint(rEvent.UpdateRect);
502 :
503 0 : Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
504 0 : if (xSpriteCanvas.is())
505 0 : xSpriteCanvas->updateScreen(sal_False);
506 : }
507 :
508 : //----- XMouseListener --------------------------------------------------------
509 :
510 0 : void SAL_CALL PresenterSlideSorter::mousePressed (const css::awt::MouseEvent& rEvent)
511 : throw(css::uno::RuntimeException, std::exception)
512 : {
513 0 : css::awt::MouseEvent rTemp =rEvent;
514 : /// check whether RTL interface or not
515 0 : if(AllSettings::GetLayoutRTL()){
516 0 : awt::Rectangle aBox = mxWindow->getPosSize();
517 0 : rTemp.X=aBox.Width-rEvent.X;
518 : }
519 0 : const geometry::RealPoint2D aPosition(rTemp.X, rEvent.Y);
520 0 : mnSlideIndexMousePressed = mpLayout->GetSlideIndexForPosition(aPosition);
521 0 : }
522 :
523 0 : void SAL_CALL PresenterSlideSorter::mouseReleased (const css::awt::MouseEvent& rEvent)
524 : throw(css::uno::RuntimeException, std::exception)
525 : {
526 0 : css::awt::MouseEvent rTemp =rEvent;
527 : /// check whether RTL interface or not
528 0 : if(AllSettings::GetLayoutRTL()){
529 0 : awt::Rectangle aBox = mxWindow->getPosSize();
530 0 : rTemp.X=aBox.Width-rEvent.X;
531 : }
532 0 : const geometry::RealPoint2D aPosition(rTemp.X, rEvent.Y);
533 0 : const sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));
534 :
535 0 : if (nSlideIndex == mnSlideIndexMousePressed && mnSlideIndexMousePressed >= 0)
536 : {
537 0 : switch (rEvent.ClickCount)
538 : {
539 : case 1:
540 : default:
541 0 : GotoSlide(nSlideIndex);
542 0 : break;
543 :
544 : case 2:
545 : OSL_ASSERT(mpPresenterController.get()!=NULL);
546 : OSL_ASSERT(mpPresenterController->GetWindowManager().get()!=NULL);
547 0 : mpPresenterController->GetWindowManager()->SetSlideSorterState(false);
548 0 : GotoSlide(nSlideIndex);
549 0 : break;
550 : }
551 0 : }
552 0 : }
553 :
554 0 : void SAL_CALL PresenterSlideSorter::mouseEntered (const css::awt::MouseEvent& rEvent)
555 : throw(css::uno::RuntimeException, std::exception)
556 : {
557 : (void)rEvent;
558 0 : }
559 :
560 0 : void SAL_CALL PresenterSlideSorter::mouseExited (const css::awt::MouseEvent& rEvent)
561 : throw(css::uno::RuntimeException, std::exception)
562 : {
563 : (void)rEvent;
564 0 : mnSlideIndexMousePressed = -1;
565 0 : if (mpMouseOverManager.get() != NULL)
566 0 : mpMouseOverManager->SetSlide(mnSlideIndexMousePressed, awt::Rectangle(0,0,0,0));
567 0 : }
568 :
569 : //----- XMouseMotionListener --------------------------------------------------
570 :
571 0 : void SAL_CALL PresenterSlideSorter::mouseMoved (const css::awt::MouseEvent& rEvent)
572 : throw (css::uno::RuntimeException, std::exception)
573 : {
574 0 : if (mpMouseOverManager.get() != NULL)
575 : {
576 0 : css::awt::MouseEvent rTemp =rEvent;
577 : /// check whether RTL interface or not
578 0 : if(AllSettings::GetLayoutRTL()){
579 0 : awt::Rectangle aBox = mxWindow->getPosSize();
580 0 : rTemp.X=aBox.Width-rEvent.X;
581 : }
582 0 : const geometry::RealPoint2D aPosition(rTemp.X, rEvent.Y);
583 0 : sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));
584 :
585 0 : if (nSlideIndex < 0)
586 0 : mnSlideIndexMousePressed = -1;
587 :
588 0 : if (nSlideIndex < 0)
589 : {
590 0 : mpMouseOverManager->SetSlide(nSlideIndex, awt::Rectangle(0,0,0,0));
591 : }
592 : else
593 : {
594 : mpMouseOverManager->SetSlide(
595 : nSlideIndex,
596 0 : mpLayout->GetBoundingBox(nSlideIndex));
597 0 : }
598 : }
599 0 : }
600 :
601 0 : void SAL_CALL PresenterSlideSorter::mouseDragged (const css::awt::MouseEvent& rEvent)
602 : throw (css::uno::RuntimeException, std::exception)
603 : {
604 : (void)rEvent;
605 0 : }
606 :
607 : //----- XResourceId -----------------------------------------------------------
608 :
609 0 : Reference<XResourceId> SAL_CALL PresenterSlideSorter::getResourceId()
610 : throw (RuntimeException, std::exception)
611 : {
612 0 : ThrowIfDisposed();
613 0 : return mxViewId;
614 : }
615 :
616 0 : sal_Bool SAL_CALL PresenterSlideSorter::isAnchorOnly()
617 : throw (RuntimeException, std::exception)
618 : {
619 0 : return false;
620 : }
621 :
622 : //----- XPropertyChangeListener -----------------------------------------------
623 :
624 0 : void SAL_CALL PresenterSlideSorter::propertyChange (
625 : const css::beans::PropertyChangeEvent& rEvent)
626 : throw(css::uno::RuntimeException, std::exception)
627 : {
628 : (void)rEvent;
629 0 : }
630 :
631 : //----- XSlidePreviewCacheListener --------------------------------------------
632 :
633 0 : void SAL_CALL PresenterSlideSorter::notifyPreviewCreation (
634 : sal_Int32 nSlideIndex)
635 : throw(css::uno::RuntimeException, std::exception)
636 : {
637 : OSL_ASSERT(mpLayout.get()!=NULL);
638 :
639 0 : awt::Rectangle aBBox (mpLayout->GetBoundingBox(nSlideIndex));
640 0 : mpPresenterController->GetPaintManager()->Invalidate(mxWindow, aBBox, true);
641 0 : }
642 :
643 : //----- XDrawView -------------------------------------------------------------
644 :
645 0 : void SAL_CALL PresenterSlideSorter::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
646 : throw (RuntimeException, std::exception)
647 : {
648 : (void)rxSlide;
649 :
650 0 : ThrowIfDisposed();
651 0 : ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
652 :
653 0 : if (mxSlideShowController.is())
654 : {
655 0 : const sal_Int32 nNewCurrentSlideIndex (mxSlideShowController->getCurrentSlideIndex());
656 0 : if (nNewCurrentSlideIndex != mnCurrentSlideIndex)
657 : {
658 0 : mnCurrentSlideIndex = nNewCurrentSlideIndex;
659 :
660 : // Request a repaint of the previous current slide to hide its
661 : // current slide indicator.
662 : mpPresenterController->GetPaintManager()->Invalidate(
663 : mxWindow,
664 0 : maCurrentSlideFrameBoundingBox);
665 :
666 : // Request a repaint of the new current slide to show its
667 : // current slide indicator.
668 : maCurrentSlideFrameBoundingBox = mpCurrentSlideFrameRenderer->GetBoundingBox(
669 0 : mpLayout->GetBoundingBox(mnCurrentSlideIndex));
670 : mpPresenterController->GetPaintManager()->Invalidate(
671 : mxWindow,
672 0 : maCurrentSlideFrameBoundingBox);
673 : }
674 0 : }
675 0 : }
676 :
677 0 : Reference<drawing::XDrawPage> SAL_CALL PresenterSlideSorter::getCurrentPage()
678 : throw (RuntimeException, std::exception)
679 : {
680 0 : ThrowIfDisposed();
681 0 : return NULL;
682 : }
683 :
684 :
685 :
686 0 : void PresenterSlideSorter::UpdateLayout()
687 : {
688 0 : if ( ! mxWindow.is())
689 0 : return;
690 :
691 0 : mbIsLayoutPending = false;
692 0 : mbIsPaintPending = true;
693 :
694 0 : const awt::Rectangle aWindowBox (mxWindow->getPosSize());
695 0 : awt::Rectangle aCenterBox (aWindowBox);
696 0 : sal_Int32 nLeftBorderWidth (aWindowBox.X);
697 :
698 : // Get border width.
699 : PresenterPaneContainer::SharedPaneDescriptor pPane (
700 : mpPresenterController->GetPaneContainer()->FindViewURL(
701 0 : mxViewId->getResourceURL()));
702 : do
703 : {
704 0 : if (pPane.get() == NULL)
705 0 : break;
706 0 : if ( ! pPane->mxPane.is())
707 0 : break;
708 :
709 : Reference<drawing::framework::XPaneBorderPainter> xBorderPainter (
710 0 : pPane->mxPane->GetPaneBorderPainter());
711 0 : if ( ! xBorderPainter.is())
712 0 : break;
713 0 : aCenterBox = xBorderPainter->addBorder (
714 0 : mxViewId->getAnchor()->getResourceURL(),
715 : awt::Rectangle(0, 0, aWindowBox.Width, aWindowBox.Height),
716 0 : drawing::framework::BorderType_INNER_BORDER);
717 : }
718 : while(false);
719 :
720 : // Place vertical separator.
721 0 : mnSeparatorY = aWindowBox.Height - mpCloseButton->GetSize().Height - gnVerticalButtonPadding;
722 :
723 0 : PlaceCloseButton(pPane, aWindowBox, nLeftBorderWidth);
724 :
725 : geometry::RealRectangle2D aUpperBox(
726 : gnHorizontalBorder,
727 : gnVerticalBorder,
728 0 : aWindowBox.Width - 2*gnHorizontalBorder,
729 0 : mnSeparatorY - gnVerticalGap);
730 :
731 : // Determine whether the scroll bar has to be displayed.
732 0 : aUpperBox = PlaceScrollBars(aUpperBox);
733 :
734 0 : mpLayout->Update(aUpperBox, GetSlideAspectRatio());
735 0 : mpLayout->SetupVisibleArea();
736 0 : mpLayout->UpdateScrollBars();
737 :
738 : // Tell the preview cache about some of the values.
739 0 : mxPreviewCache->setPreviewSize(mpLayout->maPreviewSize);
740 0 : mxPreviewCache->setVisibleRange(
741 : mpLayout->GetFirstVisibleSlideIndex(),
742 0 : mpLayout->GetLastVisibleSlideIndex());
743 :
744 : // Clear the frame polygon so that it is re-created on the next paint.
745 0 : mxPreviewFrame = NULL;
746 : }
747 :
748 0 : geometry::RealRectangle2D PresenterSlideSorter::PlaceScrollBars (
749 : const geometry::RealRectangle2D& rUpperBox)
750 : {
751 0 : mpLayout->Update(rUpperBox, GetSlideAspectRatio());
752 0 : bool bIsScrollBarNeeded (false);
753 0 : Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY_THROW);
754 0 : if (xSlides.is())
755 0 : bIsScrollBarNeeded = mpLayout->IsScrollBarNeeded(xSlides->getCount());
756 0 : if (mpVerticalScrollBar.get() != NULL)
757 : {
758 0 : if (bIsScrollBarNeeded)
759 : {
760 0 : if(AllSettings::GetLayoutRTL())
761 : {
762 : mpVerticalScrollBar->SetPosSize(geometry::RealRectangle2D(
763 : rUpperBox.X1,
764 : rUpperBox.Y1,
765 0 : rUpperBox.X1 + mpVerticalScrollBar->GetSize(),
766 0 : rUpperBox.Y2));
767 0 : mpVerticalScrollBar->SetVisible(true);
768 : // Reduce area covered by the scroll bar from the available
769 : // space.
770 : return geometry::RealRectangle2D(
771 0 : rUpperBox.X1 + gnHorizontalGap + mpVerticalScrollBar->GetSize(),
772 : rUpperBox.Y1,
773 : rUpperBox.X2,
774 0 : rUpperBox.Y2);
775 : }
776 : else
777 : {
778 : // if its not RTL place vertical scroll bar at right border.
779 : mpVerticalScrollBar->SetPosSize(geometry::RealRectangle2D(
780 0 : rUpperBox.X2 - mpVerticalScrollBar->GetSize(),
781 : rUpperBox.Y1,
782 : rUpperBox.X2,
783 0 : rUpperBox.Y2));
784 0 : 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 0 : rUpperBox.X2 - mpVerticalScrollBar->GetSize() - gnHorizontalGap,
791 0 : rUpperBox.Y2);
792 : }
793 : }
794 : else
795 0 : mpVerticalScrollBar->SetVisible(false);
796 : }
797 0 : return rUpperBox;
798 : }
799 :
800 0 : void PresenterSlideSorter::PlaceCloseButton (
801 : const PresenterPaneContainer::SharedPaneDescriptor& rpPane,
802 : const awt::Rectangle& rCenterBox,
803 : const sal_Int32 nLeftBorderWidth)
804 : {
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 0 : sal_Int32 nCloseButtonCenter (rCenterBox.Width/2);
809 0 : if (rpPane.get() != NULL && rpPane->mxPane.is())
810 : {
811 0 : const sal_Int32 nCalloutCenter (rpPane->mxPane->GetCalloutAnchor().X - nLeftBorderWidth);
812 0 : const sal_Int32 nDistanceFromWindowCenter (abs(nCalloutCenter - rCenterBox.Width/2));
813 0 : const sal_Int32 nButtonWidth (mpCloseButton->GetSize().Width);
814 0 : const static sal_Int32 nMaxDistanceForCalloutCentering (nButtonWidth * 2);
815 0 : if (nDistanceFromWindowCenter < nMaxDistanceForCalloutCentering)
816 : {
817 0 : if (nCalloutCenter < nButtonWidth/2)
818 0 : nCloseButtonCenter = nButtonWidth/2;
819 0 : else if (nCalloutCenter > rCenterBox.Width-nButtonWidth/2)
820 0 : nCloseButtonCenter = rCenterBox.Width-nButtonWidth/2;
821 : else
822 0 : nCloseButtonCenter = nCalloutCenter;
823 : }
824 : }
825 : mpCloseButton->SetCenter(geometry::RealPoint2D(
826 : nCloseButtonCenter,
827 0 : rCenterBox.Height - mpCloseButton->GetSize().Height/ 2));
828 0 : }
829 :
830 0 : void PresenterSlideSorter::ClearBackground (
831 : const Reference<rendering::XCanvas>& rxCanvas,
832 : const awt::Rectangle& rUpdateBox)
833 : {
834 : OSL_ASSERT(rxCanvas.is());
835 :
836 0 : const awt::Rectangle aWindowBox (mxWindow->getPosSize());
837 : mpPresenterController->GetCanvasHelper()->Paint(
838 0 : mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
839 : rxCanvas,
840 : rUpdateBox,
841 : awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
842 0 : awt::Rectangle());
843 0 : }
844 :
845 0 : double PresenterSlideSorter::GetSlideAspectRatio() const
846 : {
847 0 : double nSlideAspectRatio (28.0/21.0);
848 :
849 : try
850 : {
851 0 : Reference<container::XIndexAccess> xSlides(mxSlideShowController, UNO_QUERY_THROW);
852 0 : if (mxSlideShowController.is() && xSlides->getCount()>0)
853 : {
854 0 : Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
855 0 : sal_Int32 nWidth (28000);
856 0 : sal_Int32 nHeight (21000);
857 0 : if ((xProperties->getPropertyValue("Width") >>= nWidth)
858 0 : && (xProperties->getPropertyValue("Height") >>= nHeight)
859 0 : && nHeight > 0)
860 : {
861 0 : nSlideAspectRatio = double(nWidth) / double(nHeight);
862 0 : }
863 0 : }
864 : }
865 0 : catch (RuntimeException&)
866 : {
867 : OSL_ASSERT(false);
868 : }
869 :
870 0 : return nSlideAspectRatio;
871 : }
872 :
873 0 : Reference<rendering::XBitmap> PresenterSlideSorter::GetPreview (const sal_Int32 nSlideIndex)
874 : {
875 0 : if (nSlideIndex < 0 || nSlideIndex>=mpLayout->mnSlideCount)
876 0 : return NULL;
877 0 : else if (mxPane.is())
878 0 : return mxPreviewCache->getSlidePreview(nSlideIndex, mxPane->getCanvas());
879 : else
880 0 : return NULL;
881 : }
882 :
883 0 : void PresenterSlideSorter::PaintPreview (
884 : const Reference<rendering::XCanvas>& rxCanvas,
885 : const css::awt::Rectangle& rUpdateBox,
886 : const sal_Int32 nSlideIndex)
887 : {
888 : OSL_ASSERT(rxCanvas.is());
889 :
890 0 : geometry::IntegerSize2D aSize (mpLayout->maPreviewSize);
891 :
892 0 : if (PresenterGeometryHelper::AreRectanglesDisjoint(
893 : rUpdateBox,
894 0 : mpLayout->GetBoundingBox(nSlideIndex)))
895 : {
896 0 : return;
897 : }
898 :
899 0 : Reference<rendering::XBitmap> xPreview (GetPreview(nSlideIndex));
900 0 : bool isRTL = AllSettings::GetLayoutRTL();
901 :
902 : const geometry::RealPoint2D aTopLeft (
903 : mpLayout->GetWindowPosition(
904 0 : mpLayout->GetPoint(nSlideIndex, isRTL?1:-1, -1)));
905 :
906 : PresenterBitmapContainer aContainer (
907 : "PresenterScreenSettings/ScrollBar/Bitmaps",
908 : ::boost::shared_ptr<PresenterBitmapContainer>(),
909 : mxComponentContext,
910 0 : rxCanvas);
911 0 : Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
912 : Reference<drawing::XDrawPage> xPage = Reference<drawing::XDrawPage>(
913 0 : xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY);
914 0 : bool bTransition = PresenterController::HasTransition(xPage);
915 0 : bool bCustomAnimation = PresenterController::HasCustomAnimation(xPage);
916 :
917 : // Create clip rectangle as intersection of the current update area and
918 : // the bounding box of all previews.
919 0 : geometry::RealRectangle2D aBoundingBox (mpLayout->maBoundingBox);
920 0 : aBoundingBox.Y2 += 1;
921 : const geometry::RealRectangle2D aClipBox (
922 : PresenterGeometryHelper::Intersection(
923 : PresenterGeometryHelper::ConvertRectangle(rUpdateBox),
924 0 : aBoundingBox));
925 : Reference<rendering::XPolyPolygon2D> xClip (
926 0 : PresenterGeometryHelper::CreatePolygon(aClipBox, rxCanvas->getDevice()));
927 :
928 0 : const rendering::ViewState aViewState (geometry::AffineMatrix2D(1,0,0, 0,1,0), xClip);
929 :
930 : rendering::RenderState aRenderState (
931 : geometry::AffineMatrix2D(
932 : 1, 0, aTopLeft.X,
933 : 0, 1, aTopLeft.Y),
934 : NULL,
935 : Sequence<double>(4),
936 0 : rendering::CompositeOperation::SOURCE);
937 :
938 : // Emphasize the current slide.
939 0 : if (nSlideIndex == mnCurrentSlideIndex)
940 : {
941 0 : if (mpCurrentSlideFrameRenderer.get() != NULL)
942 : {
943 : const awt::Rectangle aSlideBoundingBox(
944 0 : sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.X),
945 0 : sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.Y),
946 : aSize.Width,
947 0 : aSize.Height);
948 : maCurrentSlideFrameBoundingBox
949 0 : = mpCurrentSlideFrameRenderer->GetBoundingBox(aSlideBoundingBox);
950 : mpCurrentSlideFrameRenderer->PaintCurrentSlideFrame (
951 : aSlideBoundingBox,
952 : mxCanvas,
953 0 : aClipBox);
954 : }
955 : }
956 :
957 : // Paint the preview.
958 0 : if (xPreview.is())
959 : {
960 0 : aSize = xPreview->getSize();
961 0 : if (aSize.Width > 0 && aSize.Height > 0)
962 : {
963 0 : rxCanvas->drawBitmap(xPreview, aViewState, aRenderState);
964 0 : if( bCustomAnimation )
965 : {
966 0 : const awt::Rectangle aAnimationPreviewBox(aTopLeft.X+3, aTopLeft.Y+aSize.Height-40, 0, 0);
967 0 : SharedBitmapDescriptor aAnimationDescriptor = aContainer.GetBitmap("Animation");
968 0 : 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 0 : rendering::CompositeOperation::SOURCE);
976 0 : rxCanvas->drawBitmap(xAnimationIcon, aViewState, aAnimationRenderState);
977 : }
978 0 : if( bTransition )
979 : {
980 0 : const awt::Rectangle aTransitionPreviewBox(aTopLeft.X+3, aTopLeft.Y+aSize.Height-20, 0, 0);
981 0 : SharedBitmapDescriptor aTransitionDescriptor = aContainer.GetBitmap("Transition");
982 0 : 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 0 : rendering::CompositeOperation::SOURCE);
990 0 : rxCanvas->drawBitmap(xTransitionIcon, aViewState, aTransitionRenderState);
991 : }
992 : }
993 : }
994 :
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 0 : if ( ! mxPreviewFrame.is())
998 0 : mxPreviewFrame = PresenterGeometryHelper::CreatePolygon(
999 0 : awt::Rectangle(-1, -1, aSize.Width+2, aSize.Height+2),
1000 0 : rxCanvas->getDevice());
1001 :
1002 : // Paint a border around the preview.
1003 0 : if (mxPreviewFrame.is())
1004 : {
1005 0 : const geometry::RealRectangle2D aBox (0, 0, aSize.Width, aSize.Height);
1006 0 : const util::Color aFrameColor (0x00000000);
1007 0 : PresenterCanvasHelper::SetDeviceColor(aRenderState, aFrameColor);
1008 0 : rxCanvas->drawPolyPolygon(mxPreviewFrame, aViewState, aRenderState);
1009 : }
1010 :
1011 : // Paint mouse over effect.
1012 0 : mpMouseOverManager->Paint(nSlideIndex, mxCanvas, xClip);
1013 : }
1014 :
1015 0 : void PresenterSlideSorter::Paint (const awt::Rectangle& rUpdateBox)
1016 : {
1017 0 : const bool bCanvasChanged ( ! mxCanvas.is());
1018 0 : if ( ! ProvideCanvas())
1019 0 : return;
1020 :
1021 0 : if (mpLayout->mnRowCount<=0 || mpLayout->mnColumnCount<=0)
1022 : {
1023 : OSL_ASSERT(mpLayout->mnRowCount>0 || mpLayout->mnColumnCount>0);
1024 0 : return;
1025 : }
1026 :
1027 0 : mbIsPaintPending = false;
1028 :
1029 0 : ClearBackground(mxCanvas, rUpdateBox);
1030 :
1031 : // Give the canvas to the controls.
1032 0 : if (bCanvasChanged)
1033 : {
1034 0 : if (mpVerticalScrollBar.is())
1035 0 : mpVerticalScrollBar->SetCanvas(mxCanvas);
1036 0 : if (mpCloseButton.is())
1037 0 : mpCloseButton->SetCanvas(mxCanvas, mxWindow);
1038 : }
1039 :
1040 : // Now that the controls have a canvas we can do the layouting.
1041 0 : if (mbIsLayoutPending)
1042 0 : UpdateLayout();
1043 :
1044 : // Paint the horizontal separator.
1045 : rendering::RenderState aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0),
1046 0 : NULL, Sequence<double>(4), rendering::CompositeOperation::SOURCE);
1047 0 : PresenterCanvasHelper::SetDeviceColor(aRenderState, maSeparatorColor);
1048 0 : mxCanvas->drawLine(
1049 : geometry::RealPoint2D(0, mnSeparatorY),
1050 0 : geometry::RealPoint2D(mxWindow->getPosSize().Width, mnSeparatorY),
1051 : rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL),
1052 0 : aRenderState);
1053 :
1054 : // Paint the slides.
1055 0 : if ( ! PresenterGeometryHelper::AreRectanglesDisjoint(
1056 : rUpdateBox,
1057 0 : PresenterGeometryHelper::ConvertRectangle(mpLayout->maBoundingBox)))
1058 : {
1059 : mpLayout->ForAllVisibleSlides(
1060 0 : ::boost::bind(&PresenterSlideSorter::PaintPreview, this, mxCanvas, rUpdateBox, _1));
1061 : }
1062 :
1063 0 : Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
1064 0 : if (xSpriteCanvas.is())
1065 0 : xSpriteCanvas->updateScreen(sal_False);
1066 : }
1067 :
1068 0 : void PresenterSlideSorter::SetHorizontalOffset (const double nXOffset)
1069 : {
1070 0 : if (mpLayout->SetHorizontalOffset(nXOffset))
1071 : {
1072 0 : mxPreviewCache->setVisibleRange(
1073 : mpLayout->GetFirstVisibleSlideIndex(),
1074 0 : mpLayout->GetLastVisibleSlideIndex());
1075 :
1076 0 : mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
1077 : }
1078 0 : }
1079 :
1080 0 : void PresenterSlideSorter::SetVerticalOffset (const double nYOffset)
1081 : {
1082 0 : if (mpLayout->SetVerticalOffset(nYOffset))
1083 : {
1084 0 : mxPreviewCache->setVisibleRange(
1085 : mpLayout->GetFirstVisibleSlideIndex(),
1086 0 : mpLayout->GetLastVisibleSlideIndex());
1087 :
1088 0 : mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
1089 : }
1090 0 : }
1091 :
1092 0 : void PresenterSlideSorter::GotoSlide (const sal_Int32 nSlideIndex)
1093 : {
1094 0 : mxSlideShowController->gotoSlideIndex(nSlideIndex);
1095 0 : }
1096 :
1097 0 : bool PresenterSlideSorter::ProvideCanvas()
1098 : {
1099 0 : if ( ! mxCanvas.is())
1100 : {
1101 0 : if (mxPane.is())
1102 0 : mxCanvas = mxPane->getCanvas();
1103 :
1104 : // Register as event listener so that we are informed when the
1105 : // canvas is disposed (and we have to fetch another one).
1106 0 : Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
1107 0 : if (xComponent.is())
1108 0 : xComponent->addEventListener(static_cast<awt::XWindowListener*>(this));
1109 :
1110 : mpCurrentSlideFrameRenderer.reset(
1111 0 : new CurrentSlideFrameRenderer(mxComponentContext, mxCanvas));
1112 : }
1113 0 : return mxCanvas.is();
1114 : }
1115 :
1116 0 : void PresenterSlideSorter::ThrowIfDisposed()
1117 : throw (lang::DisposedException)
1118 : {
1119 0 : if (rBHelper.bDisposed || rBHelper.bInDispose)
1120 : {
1121 : throw lang::DisposedException (
1122 : OUString(
1123 : "PresenterSlideSorter has been already disposed"),
1124 0 : const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1125 : }
1126 0 : }
1127 :
1128 : //===== PresenterSlideSorter::Layout ==========================================
1129 :
1130 0 : 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 0 : mpVerticalScrollBar(rpVerticalScrollBar)
1149 : {
1150 0 : }
1151 :
1152 0 : void PresenterSlideSorter::Layout::Update (
1153 : const geometry::RealRectangle2D& rBoundingBox,
1154 : const double nSlideAspectRatio)
1155 : {
1156 0 : maBoundingBox = rBoundingBox;
1157 :
1158 0 : mnHorizontalBorder = gnHorizontalBorder;
1159 0 : mnVerticalBorder = gnVerticalBorder;
1160 :
1161 0 : const double nWidth (rBoundingBox.X2 - rBoundingBox.X1 - 2*mnHorizontalBorder);
1162 0 : const double nHeight (rBoundingBox.Y2 - rBoundingBox.Y1 - 2*mnVerticalBorder);
1163 0 : if (nWidth<=0 || nHeight<=0)
1164 0 : return;
1165 :
1166 : double nPreviewWidth;
1167 :
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 0 : const double nElementWidth = nWidth / gnPreferredColumnCount;
1173 0 : if (nElementWidth < gnMinimalPreviewWidth + gnMinimalHorizontalPreviewGap)
1174 : {
1175 : // The preferred column count is too large.
1176 : // Can we use the preferred preview width?
1177 0 : if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
1178 : {
1179 : // Yes.
1180 0 : nPreviewWidth = gnPreferredPreviewWidth;
1181 0 : mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
1182 0 : / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
1183 0 : mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1184 : }
1185 : else
1186 : {
1187 : // No. Set the column count to 1 and adapt preview width and
1188 : // gap.
1189 0 : mnColumnCount = 1;
1190 0 : mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
1191 0 : if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
1192 0 : nPreviewWidth = nWidth - gnMinimalHorizontalPreviewGap;
1193 : else
1194 0 : nPreviewWidth = ::std::max(gnMinimalPreviewWidth, nWidth-mnHorizontalGap);
1195 : }
1196 : }
1197 0 : else if (nElementWidth > gnMaximalPreviewWidth + gnMaximalHorizontalPreviewGap)
1198 : {
1199 : // The preferred column count is too small.
1200 0 : nPreviewWidth = gnPreferredPreviewWidth;
1201 0 : mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
1202 0 : / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
1203 0 : mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1204 : }
1205 : else
1206 : {
1207 : // The preferred column count is possible. Determine gap and
1208 : // preview width.
1209 0 : mnColumnCount = gnPreferredColumnCount;
1210 0 : if (nElementWidth - gnPreferredPreviewWidth < gnMinimalHorizontalPreviewGap)
1211 : {
1212 : // Use the minimal gap and adapt the preview width.
1213 0 : mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
1214 0 : nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
1215 : }
1216 0 : else if (nElementWidth - gnPreferredPreviewWidth <= gnMaximalHorizontalPreviewGap)
1217 : {
1218 : // Use the maximal gap and adapt the preview width.
1219 0 : mnHorizontalGap = round(gnMaximalHorizontalPreviewGap);
1220 0 : nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
1221 : }
1222 : else
1223 : {
1224 : // Use the preferred preview width and adapt the gap.
1225 0 : nPreviewWidth = gnPreferredPreviewWidth;
1226 0 : mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
1227 : }
1228 : }
1229 :
1230 : // Now determine the row count, preview height, and vertical gap.
1231 0 : const double nPreviewHeight = nPreviewWidth / nSlideAspectRatio;
1232 : mnRowCount = ::std::max(
1233 : sal_Int32(1),
1234 0 : sal_Int32(ceil((nHeight+gnPreferredVerticalPreviewGap)
1235 0 : / (nPreviewHeight + gnPreferredVerticalPreviewGap))));
1236 0 : mnVerticalGap = round(gnPreferredVerticalPreviewGap);
1237 :
1238 0 : maPreviewSize = geometry::IntegerSize2D(floor(nPreviewWidth), floor(nPreviewHeight));
1239 :
1240 : // Reset the offset.
1241 0 : mnVerticalOffset = 0;
1242 : mnHorizontalOffset = round(-(nWidth
1243 0 : - mnColumnCount*maPreviewSize.Width
1244 0 : - (mnColumnCount-1)*mnHorizontalGap)
1245 0 : / 2);
1246 : }
1247 :
1248 0 : void PresenterSlideSorter::Layout::SetupVisibleArea()
1249 : {
1250 : geometry::RealPoint2D aPoint (GetLocalPosition(
1251 0 : geometry::RealPoint2D(maBoundingBox.X1, maBoundingBox.Y1)));
1252 0 : mnFirstVisibleColumn = 0;
1253 0 : mnFirstVisibleRow = ::std::max(sal_Int32(0), GetRow(aPoint));
1254 :
1255 0 : aPoint = GetLocalPosition(geometry::RealPoint2D( maBoundingBox.X2, maBoundingBox.Y2));
1256 0 : mnLastVisibleColumn = mnColumnCount - 1;
1257 0 : mnLastVisibleRow = GetRow(aPoint, true);
1258 0 : }
1259 :
1260 0 : bool PresenterSlideSorter::Layout::IsScrollBarNeeded (const sal_Int32 nSlideCount)
1261 : {
1262 0 : geometry::RealPoint2D aBottomRight;
1263 : aBottomRight = GetPoint(
1264 0 : mnColumnCount * (GetRow(nSlideCount)+1) - 1, +1, +1);
1265 0 : return aBottomRight.X > maBoundingBox.X2-maBoundingBox.X1
1266 0 : || aBottomRight.Y > maBoundingBox.Y2-maBoundingBox.Y1;
1267 : }
1268 :
1269 0 : geometry::RealPoint2D PresenterSlideSorter::Layout::GetLocalPosition(
1270 : const geometry::RealPoint2D& rWindowPoint) const
1271 : {
1272 0 : if(AllSettings::GetLayoutRTL())
1273 : {
1274 : return css::geometry::RealPoint2D(
1275 0 : -rWindowPoint.X + maBoundingBox.X2 + mnHorizontalOffset,
1276 0 : rWindowPoint.Y - maBoundingBox.Y1 + mnVerticalOffset);
1277 : }
1278 : else
1279 : {
1280 : return css::geometry::RealPoint2D(
1281 0 : rWindowPoint.X - maBoundingBox.X1 + mnHorizontalOffset,
1282 0 : rWindowPoint.Y - maBoundingBox.Y1 + mnVerticalOffset);
1283 : }
1284 : }
1285 :
1286 0 : geometry::RealPoint2D PresenterSlideSorter::Layout::GetWindowPosition(
1287 : const geometry::RealPoint2D& rLocalPoint) const
1288 : {
1289 0 : if(AllSettings::GetLayoutRTL())
1290 : {
1291 : return css::geometry::RealPoint2D(
1292 0 : -rLocalPoint.X + mnHorizontalOffset + maBoundingBox.X2,
1293 0 : rLocalPoint.Y - mnVerticalOffset + maBoundingBox.Y1);
1294 : }
1295 : else
1296 : {
1297 : return css::geometry::RealPoint2D(
1298 0 : rLocalPoint.X - mnHorizontalOffset + maBoundingBox.X1,
1299 0 : rLocalPoint.Y - mnVerticalOffset + maBoundingBox.Y1);
1300 : }
1301 : }
1302 :
1303 0 : sal_Int32 PresenterSlideSorter::Layout::GetColumn (
1304 : const css::geometry::RealPoint2D& rLocalPoint,
1305 : const bool bReturnInvalidValue) const
1306 : {
1307 : const sal_Int32 nColumn(floor(
1308 0 : (rLocalPoint.X + mnHorizontalGap/2.0) / (maPreviewSize.Width+mnHorizontalGap)));
1309 0 : if (bReturnInvalidValue
1310 0 : || (nColumn>=mnFirstVisibleColumn && nColumn<=mnLastVisibleColumn))
1311 : {
1312 0 : return nColumn;
1313 : }
1314 : else
1315 0 : return -1;
1316 : }
1317 :
1318 0 : sal_Int32 PresenterSlideSorter::Layout::GetRow (
1319 : const css::geometry::RealPoint2D& rLocalPoint,
1320 : const bool bReturnInvalidValue) const
1321 : {
1322 : const sal_Int32 nRow (floor(
1323 0 : (rLocalPoint.Y + mnVerticalGap/2.0) / (maPreviewSize.Height+mnVerticalGap)));
1324 0 : if (bReturnInvalidValue
1325 0 : || (nRow>=mnFirstVisibleRow && nRow<=mnLastVisibleRow))
1326 : {
1327 0 : return nRow;
1328 : }
1329 : else
1330 0 : return -1;
1331 : }
1332 :
1333 0 : sal_Int32 PresenterSlideSorter::Layout::GetSlideIndexForPosition (
1334 : const css::geometry::RealPoint2D& rWindowPoint) const
1335 : {
1336 0 : if ( ! PresenterGeometryHelper::IsInside(maBoundingBox, rWindowPoint))
1337 0 : return -1;
1338 :
1339 0 : const css::geometry::RealPoint2D aLocalPosition (GetLocalPosition(rWindowPoint));
1340 0 : const sal_Int32 nColumn (GetColumn(aLocalPosition));
1341 0 : const sal_Int32 nRow (GetRow(aLocalPosition));
1342 :
1343 0 : if (nColumn < 0 || nRow < 0)
1344 0 : return -1;
1345 : else
1346 : {
1347 0 : sal_Int32 nIndex (GetIndex(nRow, nColumn));
1348 0 : if (nIndex >= mnSlideCount)
1349 0 : return -1;
1350 : else
1351 0 : return nIndex;
1352 : }
1353 : }
1354 :
1355 0 : geometry::RealPoint2D PresenterSlideSorter::Layout::GetPoint (
1356 : const sal_Int32 nSlideIndex,
1357 : const sal_Int32 nRelativeHorizontalPosition,
1358 : const sal_Int32 nRelativeVerticalPosition) const
1359 : {
1360 0 : sal_Int32 nColumn (GetColumn(nSlideIndex));
1361 0 : sal_Int32 nRow (GetRow(nSlideIndex));
1362 :
1363 : geometry::RealPoint2D aPosition (
1364 0 : mnHorizontalBorder + nColumn*(maPreviewSize.Width+mnHorizontalGap),
1365 0 : mnVerticalBorder + nRow*(maPreviewSize.Height+mnVerticalGap));
1366 :
1367 0 : if (nRelativeHorizontalPosition >= 0)
1368 : {
1369 0 : if (nRelativeHorizontalPosition > 0)
1370 0 : aPosition.X += maPreviewSize.Width;
1371 : else
1372 0 : aPosition.X += maPreviewSize.Width / 2.0;
1373 : }
1374 0 : if (nRelativeVerticalPosition >= 0)
1375 : {
1376 0 : if (nRelativeVerticalPosition > 0)
1377 0 : aPosition.Y += maPreviewSize.Height;
1378 : else
1379 0 : aPosition.Y += maPreviewSize.Height / 2.0;
1380 : }
1381 :
1382 0 : return aPosition;
1383 : }
1384 :
1385 0 : awt::Rectangle PresenterSlideSorter::Layout::GetBoundingBox (const sal_Int32 nSlideIndex) const
1386 : {
1387 0 : bool isRTL = AllSettings::GetLayoutRTL();
1388 0 : 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 0 : aWindowPosition.X + maPreviewSize.Width,
1394 0 : aWindowPosition.Y + maPreviewSize.Height));
1395 : }
1396 :
1397 0 : void PresenterSlideSorter::Layout::ForAllVisibleSlides (const ::boost::function<void(sal_Int32)>& rAction)
1398 : {
1399 0 : for (sal_Int32 nRow=mnFirstVisibleRow; nRow<=mnLastVisibleRow; ++nRow)
1400 : {
1401 0 : for (sal_Int32 nColumn=mnFirstVisibleColumn; nColumn<=mnLastVisibleColumn; ++nColumn)
1402 : {
1403 0 : const sal_Int32 nSlideIndex (GetIndex(nRow, nColumn));
1404 0 : if (nSlideIndex >= mnSlideCount)
1405 0 : return;
1406 0 : rAction(nSlideIndex);
1407 : }
1408 : }
1409 : }
1410 :
1411 0 : sal_Int32 PresenterSlideSorter::Layout::GetFirstVisibleSlideIndex() const
1412 : {
1413 0 : return GetIndex(mnFirstVisibleRow, mnFirstVisibleColumn);
1414 : }
1415 :
1416 0 : sal_Int32 PresenterSlideSorter::Layout::GetLastVisibleSlideIndex() const
1417 : {
1418 : return ::std::min(
1419 0 : GetIndex(mnLastVisibleRow, mnLastVisibleColumn),
1420 0 : mnSlideCount);
1421 : }
1422 :
1423 0 : bool PresenterSlideSorter::Layout::SetHorizontalOffset (const double nOffset)
1424 : {
1425 0 : if (mnHorizontalOffset != nOffset)
1426 : {
1427 0 : mnHorizontalOffset = round(nOffset);
1428 0 : SetupVisibleArea();
1429 0 : UpdateScrollBars();
1430 0 : return true;
1431 : }
1432 : else
1433 0 : return false;
1434 : }
1435 :
1436 0 : bool PresenterSlideSorter::Layout::SetVerticalOffset (const double nOffset)
1437 : {
1438 0 : if (mnVerticalOffset != nOffset)
1439 : {
1440 0 : mnVerticalOffset = round(nOffset);
1441 0 : SetupVisibleArea();
1442 0 : UpdateScrollBars();
1443 0 : return true;
1444 : }
1445 : else
1446 0 : return false;
1447 : }
1448 :
1449 0 : void PresenterSlideSorter::Layout::UpdateScrollBars()
1450 : {
1451 0 : sal_Int32 nTotalRowCount (0);
1452 0 : nTotalRowCount = sal_Int32(ceil(double(mnSlideCount) / double(mnColumnCount)));
1453 :
1454 0 : if (mpVerticalScrollBar.get() != NULL)
1455 : {
1456 : mpVerticalScrollBar->SetTotalSize(
1457 0 : nTotalRowCount * maPreviewSize.Height
1458 0 : + (nTotalRowCount-1) * mnVerticalGap
1459 0 : + 2*mnVerticalGap);
1460 0 : mpVerticalScrollBar->SetThumbPosition(mnVerticalOffset, false);
1461 0 : mpVerticalScrollBar->SetThumbSize(maBoundingBox.Y2 - maBoundingBox.Y1 + 1);
1462 0 : mpVerticalScrollBar->SetLineHeight(maPreviewSize.Height);
1463 : }
1464 :
1465 : // No place yet for the vertical scroll bar.
1466 0 : }
1467 :
1468 0 : sal_Int32 PresenterSlideSorter::Layout::GetIndex (
1469 : const sal_Int32 nRow,
1470 : const sal_Int32 nColumn) const
1471 : {
1472 0 : return nRow * mnColumnCount + nColumn;
1473 : }
1474 :
1475 0 : sal_Int32 PresenterSlideSorter::Layout::GetRow (const sal_Int32 nSlideIndex) const
1476 : {
1477 0 : return nSlideIndex / mnColumnCount;
1478 : }
1479 :
1480 0 : sal_Int32 PresenterSlideSorter::Layout::GetColumn (const sal_Int32 nSlideIndex) const
1481 : {
1482 0 : return nSlideIndex % mnColumnCount;
1483 : }
1484 :
1485 : //===== PresenterSlideSorter::MouseOverManager ================================
1486 :
1487 0 : 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 0 : mpPaintManager(rpPaintManager)
1502 : {
1503 0 : if (rpTheme.get()!=NULL)
1504 : {
1505 0 : ::boost::shared_ptr<PresenterBitmapContainer> pBitmaps (rpTheme->GetBitmapContainer());
1506 0 : if (pBitmaps.get() != NULL)
1507 : {
1508 0 : mpLeftLabelBitmap = pBitmaps->GetBitmap("LabelLeft");
1509 0 : mpCenterLabelBitmap = pBitmaps->GetBitmap("LabelCenter");
1510 0 : mpRightLabelBitmap = pBitmaps->GetBitmap("LabelRight");
1511 : }
1512 :
1513 0 : mpFont = rpTheme->GetFont("SlideSorterLabelFont");
1514 : }
1515 0 : }
1516 :
1517 0 : PresenterSlideSorter::MouseOverManager::~MouseOverManager()
1518 : {
1519 0 : }
1520 :
1521 0 : void PresenterSlideSorter::MouseOverManager::Paint (
1522 : const sal_Int32 nSlideIndex,
1523 : const Reference<rendering::XCanvas>& rxCanvas,
1524 : const Reference<rendering::XPolyPolygon2D>& rxClip)
1525 : {
1526 0 : if (nSlideIndex != mnSlideIndex)
1527 0 : return;
1528 :
1529 0 : if (mxCanvas != rxCanvas)
1530 0 : SetCanvas(rxCanvas);
1531 0 : if (rxCanvas != NULL)
1532 : {
1533 0 : if ( ! mxBitmap.is())
1534 0 : mxBitmap = CreateBitmap(msText, maSlideBoundingBox.Width);
1535 0 : if (mxBitmap.is())
1536 : {
1537 0 : geometry::IntegerSize2D aSize (mxBitmap->getSize());
1538 : const double nXOffset (maSlideBoundingBox.X
1539 0 : + (maSlideBoundingBox.Width - aSize.Width) / 2.0);
1540 : const double nYOffset (maSlideBoundingBox.Y
1541 0 : + (maSlideBoundingBox.Height - aSize.Height) / 2.0);
1542 0 : 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 0 : rendering::CompositeOperation::SOURCE));
1552 : }
1553 : }
1554 : }
1555 :
1556 0 : void PresenterSlideSorter::MouseOverManager::SetCanvas (
1557 : const Reference<rendering::XCanvas>& rxCanvas)
1558 : {
1559 0 : mxCanvas = rxCanvas;
1560 0 : if (mpFont.get() != NULL)
1561 0 : mpFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY));
1562 0 : }
1563 :
1564 0 : void PresenterSlideSorter::MouseOverManager::SetSlide (
1565 : const sal_Int32 nSlideIndex,
1566 : const awt::Rectangle& rBox)
1567 : {
1568 0 : if (mnSlideIndex == nSlideIndex)
1569 0 : return;
1570 :
1571 0 : mnSlideIndex = -1;
1572 0 : Invalidate();
1573 :
1574 0 : maSlideBoundingBox = rBox;
1575 0 : mnSlideIndex = nSlideIndex;
1576 :
1577 0 : if (nSlideIndex >= 0)
1578 : {
1579 0 : if (mxSlides.get() != NULL)
1580 : {
1581 0 : msText.clear();
1582 :
1583 0 : Reference<beans::XPropertySet> xSlideProperties(mxSlides->getByIndex(nSlideIndex), UNO_QUERY);
1584 0 : if (xSlideProperties.is())
1585 0 : xSlideProperties->getPropertyValue("LinkDisplayName") >>= msText;
1586 :
1587 0 : if (msText.isEmpty())
1588 0 : msText = "Slide " + OUString::number(nSlideIndex + 1);
1589 : }
1590 : }
1591 : else
1592 : {
1593 0 : msText.clear();
1594 : }
1595 0 : mxBitmap = NULL;
1596 :
1597 0 : Invalidate();
1598 : }
1599 :
1600 0 : Reference<rendering::XBitmap> PresenterSlideSorter::MouseOverManager::CreateBitmap (
1601 : const OUString& rsText,
1602 : const sal_Int32 nMaximalWidth) const
1603 : {
1604 0 : if ( ! mxCanvas.is())
1605 0 : return NULL;
1606 :
1607 0 : if (mpFont.get()==NULL || !mpFont->mxFont.is())
1608 0 : return NULL;
1609 :
1610 : // Long text has to be shortened.
1611 : const OUString sText (GetFittingText(rsText, nMaximalWidth
1612 : - 2*gnHorizontalLabelBorder
1613 0 : - 2*gnHorizontalLabelPadding));
1614 :
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 0 : geometry::IntegerSize2D aLabelSize (CalculateLabelSize(sText));
1619 :
1620 : // Create a new bitmap that will contain the complete label.
1621 : Reference<rendering::XBitmap> xBitmap (
1622 0 : mxCanvas->getDevice()->createCompatibleAlphaBitmap(aLabelSize));
1623 :
1624 0 : if ( ! xBitmap.is())
1625 0 : return NULL;
1626 :
1627 0 : Reference<rendering::XBitmapCanvas> xBitmapCanvas (xBitmap, UNO_QUERY);
1628 0 : if ( ! xBitmapCanvas.is())
1629 0 : return NULL;
1630 :
1631 : // Paint the background.
1632 0 : PaintButtonBackground(xBitmapCanvas, aLabelSize);
1633 :
1634 : // Paint the text.
1635 0 : if (!sText.isEmpty())
1636 : {
1637 :
1638 0 : const rendering::StringContext aContext (sText, 0, sText.getLength());
1639 0 : const Reference<rendering::XTextLayout> xLayout (mpFont->mxFont->createTextLayout(
1640 0 : aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0));
1641 0 : const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds());
1642 :
1643 0 : const double nXOffset = (aLabelSize.Width - aTextBBox.X2 + aTextBBox.X1) / 2;
1644 : const double nYOffset = aLabelSize.Height
1645 0 : - (aLabelSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y2;
1646 :
1647 : const rendering::ViewState aViewState(
1648 : geometry::AffineMatrix2D(1,0,0, 0,1,0),
1649 0 : NULL);
1650 :
1651 : rendering::RenderState aRenderState (
1652 : geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset),
1653 : NULL,
1654 : Sequence<double>(4),
1655 0 : rendering::CompositeOperation::SOURCE);
1656 0 : PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
1657 :
1658 0 : xBitmapCanvas->drawTextLayout (
1659 : xLayout,
1660 : aViewState,
1661 0 : aRenderState);
1662 : }
1663 :
1664 0 : return xBitmap;
1665 : }
1666 :
1667 0 : OUString PresenterSlideSorter::MouseOverManager::GetFittingText (
1668 : const OUString& rsText,
1669 : const double nMaximalWidth) const
1670 : {
1671 : const double nTextWidth (
1672 0 : PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText).Width);
1673 0 : if (nTextWidth > nMaximalWidth)
1674 : {
1675 : // Text is too wide. Shorten it by removing characters from the end
1676 : // and replacing them by ellipses.
1677 :
1678 : // Guess a start value of the final string length.
1679 0 : double nBestWidth (0);
1680 0 : OUString sBestCandidate;
1681 0 : sal_Int32 nLength (round(rsText.getLength() * nMaximalWidth / nTextWidth));
1682 0 : const OUString sEllipses ("...");
1683 : while (true)
1684 : {
1685 0 : const OUString sCandidate (rsText.copy(0,nLength) + sEllipses);
1686 : const double nWidth (
1687 0 : PresenterCanvasHelper::GetTextSize(mpFont->mxFont, sCandidate).Width);
1688 0 : if (nWidth > nMaximalWidth)
1689 : {
1690 : // Candidate still too wide, shorten it.
1691 0 : nLength -= 1;
1692 0 : if (nLength <= 0)
1693 0 : break;
1694 : }
1695 0 : else if (nWidth < nMaximalWidth)
1696 : {
1697 : // Candidate short enough.
1698 0 : if (nWidth > nBestWidth)
1699 : {
1700 : // Best length so far.
1701 0 : sBestCandidate = sCandidate;
1702 0 : nBestWidth = nWidth;
1703 0 : nLength += 1;
1704 0 : if (nLength >= rsText.getLength())
1705 0 : break;
1706 : }
1707 : else
1708 0 : break;
1709 : }
1710 : else
1711 : {
1712 : // Candidate is exactly as long as it may be. Use it
1713 : // without looking any further.
1714 0 : sBestCandidate = sCandidate;
1715 0 : break;
1716 : }
1717 0 : }
1718 0 : return sBestCandidate;
1719 : }
1720 : else
1721 0 : return rsText;
1722 : }
1723 :
1724 0 : geometry::IntegerSize2D PresenterSlideSorter::MouseOverManager::CalculateLabelSize (
1725 : const OUString& rsText) const
1726 : {
1727 : // Height is specified by the label bitmaps.
1728 0 : sal_Int32 nHeight (32);
1729 0 : if (mpCenterLabelBitmap.get() != NULL)
1730 : {
1731 0 : Reference<rendering::XBitmap> xBitmap (mpCenterLabelBitmap->GetNormalBitmap());
1732 0 : if (xBitmap.is())
1733 0 : nHeight = xBitmap->getSize().Height;
1734 : }
1735 :
1736 : // Width is specified by text width and maximal width.
1737 : const geometry::RealSize2D aTextSize (
1738 0 : PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText));
1739 :
1740 0 : const sal_Int32 nWidth (round(aTextSize.Width + 2*gnHorizontalLabelPadding));
1741 :
1742 0 : return geometry::IntegerSize2D(nWidth, nHeight);
1743 : }
1744 :
1745 0 : void PresenterSlideSorter::MouseOverManager::PaintButtonBackground (
1746 : const Reference<rendering::XCanvas>& rxCanvas,
1747 : const geometry::IntegerSize2D& rSize) const
1748 : {
1749 : // Get the bitmaps for painting the label background.
1750 0 : Reference<rendering::XBitmap> xLeftLabelBitmap;
1751 0 : if (mpLeftLabelBitmap.get() != NULL)
1752 0 : xLeftLabelBitmap = mpLeftLabelBitmap->GetNormalBitmap();
1753 :
1754 0 : Reference<rendering::XBitmap> xCenterLabelBitmap;
1755 0 : if (mpCenterLabelBitmap.get() != NULL)
1756 0 : xCenterLabelBitmap = mpCenterLabelBitmap->GetNormalBitmap();
1757 :
1758 0 : Reference<rendering::XBitmap> xRightLabelBitmap;
1759 0 : if (mpRightLabelBitmap.get() != NULL)
1760 0 : xRightLabelBitmap = mpRightLabelBitmap->GetNormalBitmap();
1761 :
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 0 : xRightLabelBitmap);
1769 0 : }
1770 :
1771 0 : void PresenterSlideSorter::MouseOverManager::Invalidate()
1772 : {
1773 0 : if (mpPaintManager.get() != NULL)
1774 0 : mpPaintManager->Invalidate(mxInvalidateTarget, maSlideBoundingBox, true);
1775 0 : }
1776 :
1777 : //===== PresenterSlideSorter::CurrentSlideFrameRenderer =======================
1778 :
1779 0 : 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 0 : mnBottomFrameSize(0)
1794 : {
1795 : PresenterConfigurationAccess aConfiguration (
1796 : rxContext,
1797 : OUString("/org.openoffice.Office.PresenterScreen/"),
1798 0 : PresenterConfigurationAccess::READ_ONLY);
1799 : Reference<container::XHierarchicalNameAccess> xBitmaps (
1800 : aConfiguration.GetConfigurationNode(
1801 : "PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps"),
1802 0 : UNO_QUERY);
1803 0 : if ( ! xBitmaps.is())
1804 0 : return;
1805 :
1806 : PresenterBitmapContainer aContainer (
1807 : "PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps",
1808 : ::boost::shared_ptr<PresenterBitmapContainer>(),
1809 : rxContext,
1810 0 : rxCanvas);
1811 :
1812 0 : mpTopLeft = aContainer.GetBitmap("TopLeft");
1813 0 : mpTop = aContainer.GetBitmap("Top");
1814 0 : mpTopRight = aContainer.GetBitmap("TopRight");
1815 0 : mpLeft = aContainer.GetBitmap("Left");
1816 0 : mpRight = aContainer.GetBitmap("Right");
1817 0 : mpBottomLeft = aContainer.GetBitmap("BottomLeft");
1818 0 : mpBottom = aContainer.GetBitmap("Bottom");
1819 0 : mpBottomRight = aContainer.GetBitmap("BottomRight");
1820 :
1821 : // Determine size of frame.
1822 0 : if (mpTop.get() != NULL)
1823 0 : mnTopFrameSize = mpTop->mnHeight;
1824 0 : if (mpLeft.get() != NULL)
1825 0 : mnLeftFrameSize = mpLeft->mnWidth;
1826 0 : if (mpRight.get() != NULL)
1827 0 : mnRightFrameSize = mpRight->mnWidth;
1828 0 : if (mpBottom.get() != NULL)
1829 0 : mnBottomFrameSize = mpBottom->mnHeight;
1830 :
1831 0 : if (mpTopLeft.get() != NULL)
1832 : {
1833 0 : mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopLeft->mnHeight);
1834 0 : mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpTopLeft->mnWidth);
1835 : }
1836 0 : if (mpTopRight.get() != NULL)
1837 : {
1838 0 : mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopRight->mnHeight);
1839 0 : mnRightFrameSize = ::std::max(mnRightFrameSize, mpTopRight->mnWidth);
1840 : }
1841 0 : if (mpBottomLeft.get() != NULL)
1842 : {
1843 0 : mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpBottomLeft->mnWidth);
1844 0 : mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomLeft->mnHeight);
1845 : }
1846 0 : if (mpBottomRight.get() != NULL)
1847 : {
1848 0 : mnRightFrameSize = ::std::max(mnRightFrameSize, mpBottomRight->mnWidth);
1849 0 : mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomRight->mnHeight);
1850 0 : }
1851 : }
1852 :
1853 0 : PresenterSlideSorter::CurrentSlideFrameRenderer::~CurrentSlideFrameRenderer()
1854 : {
1855 0 : }
1856 :
1857 0 : void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintCurrentSlideFrame (
1858 : const awt::Rectangle& rSlideBoundingBox,
1859 : const Reference<rendering::XCanvas>& rxCanvas,
1860 : const geometry::RealRectangle2D& rClipBox)
1861 : {
1862 0 : if ( ! rxCanvas.is())
1863 0 : return;
1864 :
1865 : const Reference<rendering::XPolyPolygon2D> xClip (
1866 0 : PresenterGeometryHelper::CreatePolygon(rClipBox, rxCanvas->getDevice()));
1867 :
1868 0 : if (mpTop.get() != NULL)
1869 : {
1870 : PaintBitmapTiled(
1871 : mpTop->GetNormalBitmap(),
1872 : rxCanvas,
1873 : rClipBox,
1874 : rSlideBoundingBox.X,
1875 0 : rSlideBoundingBox.Y - mpTop->mnHeight,
1876 : rSlideBoundingBox.Width,
1877 0 : mpTop->mnHeight);
1878 : }
1879 0 : if (mpLeft.get() != NULL)
1880 : {
1881 : PaintBitmapTiled(
1882 : mpLeft->GetNormalBitmap(),
1883 : rxCanvas,
1884 : rClipBox,
1885 0 : rSlideBoundingBox.X - mpLeft->mnWidth,
1886 : rSlideBoundingBox.Y,
1887 0 : mpLeft->mnWidth,
1888 0 : rSlideBoundingBox.Height);
1889 : }
1890 0 : if (mpRight.get() != NULL)
1891 : {
1892 : PaintBitmapTiled(
1893 : mpRight->GetNormalBitmap(),
1894 : rxCanvas,
1895 : rClipBox,
1896 0 : rSlideBoundingBox.X + rSlideBoundingBox.Width,
1897 : rSlideBoundingBox.Y,
1898 0 : mpRight->mnWidth,
1899 0 : rSlideBoundingBox.Height);
1900 : }
1901 0 : if (mpBottom.get() != NULL)
1902 : {
1903 : PaintBitmapTiled(
1904 : mpBottom->GetNormalBitmap(),
1905 : rxCanvas,
1906 : rClipBox,
1907 : rSlideBoundingBox.X,
1908 0 : rSlideBoundingBox.Y + rSlideBoundingBox.Height,
1909 : rSlideBoundingBox.Width,
1910 0 : mpBottom->mnHeight);
1911 : }
1912 0 : if (mpTopLeft.get() != NULL)
1913 : {
1914 : PaintBitmapOnce(
1915 : mpTopLeft->GetNormalBitmap(),
1916 : rxCanvas,
1917 : xClip,
1918 0 : rSlideBoundingBox.X - mpTopLeft->mnWidth,
1919 0 : rSlideBoundingBox.Y - mpTopLeft->mnHeight);
1920 : }
1921 0 : if (mpTopRight.get() != NULL)
1922 : {
1923 : PaintBitmapOnce(
1924 : mpTopRight->GetNormalBitmap(),
1925 : rxCanvas,
1926 : xClip,
1927 0 : rSlideBoundingBox.X + rSlideBoundingBox.Width,
1928 0 : rSlideBoundingBox.Y - mpTopLeft->mnHeight);
1929 : }
1930 0 : if (mpBottomLeft.get() != NULL)
1931 : {
1932 : PaintBitmapOnce(
1933 : mpBottomLeft->GetNormalBitmap(),
1934 : rxCanvas,
1935 : xClip,
1936 0 : rSlideBoundingBox.X - mpBottomLeft->mnWidth,
1937 0 : rSlideBoundingBox.Y + rSlideBoundingBox.Height);
1938 : }
1939 0 : if (mpBottomRight.get() != NULL)
1940 : {
1941 : PaintBitmapOnce(
1942 : mpBottomRight->GetNormalBitmap(),
1943 : rxCanvas,
1944 : xClip,
1945 0 : rSlideBoundingBox.X + rSlideBoundingBox.Width,
1946 0 : rSlideBoundingBox.Y + rSlideBoundingBox.Height);
1947 0 : }
1948 : }
1949 :
1950 0 : awt::Rectangle PresenterSlideSorter::CurrentSlideFrameRenderer::GetBoundingBox (
1951 : const awt::Rectangle& rSlideBoundingBox)
1952 : {
1953 : return awt::Rectangle(
1954 0 : rSlideBoundingBox.X - mnLeftFrameSize,
1955 0 : rSlideBoundingBox.Y - mnTopFrameSize,
1956 0 : rSlideBoundingBox.Width + mnLeftFrameSize + mnRightFrameSize,
1957 0 : rSlideBoundingBox.Height + mnTopFrameSize + mnBottomFrameSize);
1958 : }
1959 :
1960 0 : 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)
1966 : {
1967 : OSL_ASSERT(rxCanvas.is());
1968 0 : if ( ! rxBitmap.is())
1969 0 : return;
1970 :
1971 : const rendering::ViewState aViewState(
1972 : geometry::AffineMatrix2D(1,0,0, 0,1,0),
1973 0 : rxClip);
1974 :
1975 : const rendering::RenderState aRenderState (
1976 : geometry::AffineMatrix2D(
1977 : 1, 0, nX,
1978 : 0, 1, nY),
1979 : NULL,
1980 : Sequence<double>(4),
1981 0 : rendering::CompositeOperation::SOURCE);
1982 :
1983 0 : rxCanvas->drawBitmap(
1984 : rxBitmap,
1985 : aViewState,
1986 0 : aRenderState);
1987 : }
1988 :
1989 0 : 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)
1997 : {
1998 : OSL_ASSERT(rxCanvas.is());
1999 0 : if ( ! rxBitmap.is())
2000 0 : return;
2001 :
2002 0 : geometry::IntegerSize2D aSize (rxBitmap->getSize());
2003 :
2004 : const rendering::ViewState aViewState(
2005 : geometry::AffineMatrix2D(1,0,0, 0,1,0),
2006 : PresenterGeometryHelper::CreatePolygon(
2007 : PresenterGeometryHelper::Intersection(
2008 : rClipBox,
2009 0 : geometry::RealRectangle2D(nX0,nY0,nX0+nWidth,nY0+nHeight)),
2010 0 : rxCanvas->getDevice()));
2011 :
2012 : rendering::RenderState aRenderState (
2013 : geometry::AffineMatrix2D(
2014 : 1, 0, nX0,
2015 : 0, 1, nY0),
2016 : NULL,
2017 : Sequence<double>(4),
2018 0 : rendering::CompositeOperation::SOURCE);
2019 :
2020 0 : const double nX1 = nX0 + nWidth;
2021 0 : const double nY1 = nY0 + nHeight;
2022 0 : for (double nY=nY0; nY<nY1; nY+=aSize.Height)
2023 0 : for (double nX=nX0; nX<nX1; nX+=aSize.Width)
2024 : {
2025 0 : aRenderState.AffineTransform.m02 = nX;
2026 0 : aRenderState.AffineTransform.m12 = nY;
2027 0 : rxCanvas->drawBitmap(
2028 : rxBitmap,
2029 : aViewState,
2030 0 : aRenderState);
2031 0 : }
2032 : }
2033 :
2034 18 : } } // end of namespace ::sdext::presenter
2035 :
2036 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|