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