1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sdext.hxx"
30 
31 #include "PresenterScrollBar.hxx"
32 #include "PresenterBitmapContainer.hxx"
33 #include "PresenterCanvasHelper.hxx"
34 #include "PresenterComponent.hxx"
35 #include "PresenterGeometryHelper.hxx"
36 #include "PresenterPaintManager.hxx"
37 #include "PresenterTimer.hxx"
38 #include "PresenterUIPainter.hxx"
39 #include <com/sun/star/awt/PosSize.hpp>
40 #include <com/sun/star/awt/WindowAttribute.hpp>
41 #include <com/sun/star/awt/XWindowPeer.hpp>
42 #include <com/sun/star/awt/XToolkit.hpp>
43 #include <com/sun/star/rendering/CompositeOperation.hpp>
44 #include <com/sun/star/rendering/TexturingMode.hpp>
45 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
46 #include <boost/bind.hpp>
47 #include <boost/enable_shared_from_this.hpp>
48 #include <boost/weak_ptr.hpp>
49 #include <math.h>
50 
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::uno;
53 using ::rtl::OUString;
54 
55 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
56 
57 const static double gnScrollBarGap (10);
58 
59 namespace sdext { namespace presenter {
60 
61 //===== PresenterScrollBar::MousePressRepeater ================================
62 
63 class PresenterScrollBar::MousePressRepeater
64     : public ::boost::enable_shared_from_this<MousePressRepeater>
65 {
66 public:
67     MousePressRepeater (const ::rtl::Reference<PresenterScrollBar>& rpScrollBar);
68     void Dispose (void);
69     void Start (const PresenterScrollBar::Area& reArea);
70     void Stop (void);
71     void SetMouseArea (const PresenterScrollBar::Area& reArea);
72 
73 private:
74     void Callback (const TimeValue& rCurrentTime);
75     void Execute (void);
76 
77     sal_Int32 mnMousePressRepeaterTaskId;
78     ::rtl::Reference<PresenterScrollBar> mpScrollBar;
79     PresenterScrollBar::Area meMouseArea;
80 };
81 
82 
83 
84 
85 //===== PresenterScrollBar ====================================================
86 
87 boost::weak_ptr<PresenterBitmapContainer> PresenterScrollBar::mpSharedBitmaps;
88 
89 PresenterScrollBar::PresenterScrollBar (
90     const Reference<XComponentContext>& rxComponentContext,
91     const Reference<awt::XWindow>& rxParentWindow,
92     const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager,
93     const ::boost::function<void(double)>& rThumbMotionListener)
94     : PresenterScrollBarInterfaceBase(m_aMutex),
95       mxComponentContext(rxComponentContext),
96       mxParentWindow(rxParentWindow),
97       mxWindow(),
98       mxCanvas(),
99       mxPresenterHelper(),
100       mpPaintManager(rpPaintManager),
101       mnThumbPosition(0),
102       mnTotalSize(0),
103       mnThumbSize(0),
104       mnLineHeight(10),
105       maDragAnchor(-1,-1),
106       maThumbMotionListener(rThumbMotionListener),
107       meButtonDownArea(None),
108       meMouseMoveArea(None),
109       mbIsNotificationActive(false),
110       mpBitmaps(),
111       mpPrevButtonDescriptor(),
112       mpNextButtonDescriptor(),
113       mpPagerStartDescriptor(),
114       mpPagerCenterDescriptor(),
115       mpPagerEndDescriptor(),
116       mpThumbStartDescriptor(),
117       mpThumbCenterDescriptor(),
118       mpThumbEndDescriptor(),
119       mpMousePressRepeater(new MousePressRepeater(this)),
120       mpBackgroundBitmap(),
121       mpCanvasHelper(new PresenterCanvasHelper())
122 {
123     try
124     {
125         Reference<lang::XMultiComponentFactory> xFactory (rxComponentContext->getServiceManager());
126         if ( ! xFactory.is())
127             throw RuntimeException();
128 
129         mxPresenterHelper = Reference<drawing::XPresenterHelper>(
130             xFactory->createInstanceWithContext(
131                 OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"),
132                 rxComponentContext),
133             UNO_QUERY_THROW);
134 
135         if (mxPresenterHelper.is())
136             mxWindow = mxPresenterHelper->createWindow(rxParentWindow,
137                 sal_False,
138                 sal_False,
139                 sal_False,
140                 sal_False);
141 
142         // Make the background transparent.  The slide show paints its own background.
143         Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY_THROW);
144         if (xPeer.is())
145         {
146             xPeer->setBackground(0xff000000);
147         }
148 
149         mxWindow->setVisible(sal_True);
150         mxWindow->addWindowListener(this);
151         mxWindow->addPaintListener(this);
152         mxWindow->addMouseListener(this);
153         mxWindow->addMouseMotionListener(this);
154     }
155     catch (RuntimeException&)
156     {
157     }
158 }
159 
160 
161 
162 
163 PresenterScrollBar::~PresenterScrollBar (void)
164 {
165 }
166 
167 
168 
169 
170 void SAL_CALL PresenterScrollBar::disposing (void)
171 {
172     mpMousePressRepeater->Dispose();
173 
174     if (mxWindow.is())
175     {
176         mxWindow->removeWindowListener(this);
177         mxWindow->removePaintListener(this);
178         mxWindow->removeMouseListener(this);
179         mxWindow->removeMouseMotionListener(this);
180 
181         Reference<lang::XComponent> xComponent (mxWindow, UNO_QUERY);
182         mxWindow = NULL;
183         if (xComponent.is())
184             xComponent->dispose();
185     }
186 
187     mpBitmaps.reset();
188 }
189 
190 
191 
192 
193 void PresenterScrollBar::SetVisible (const bool bIsVisible)
194 {
195     if (mxWindow.is())
196         mxWindow->setVisible(bIsVisible);
197 }
198 
199 
200 
201 
202 void PresenterScrollBar::SetPosSize (const css::geometry::RealRectangle2D& rBox)
203 {
204     if (mxWindow.is())
205     {
206         mxWindow->setPosSize(
207             sal_Int32(floor(rBox.X1)),
208             sal_Int32(ceil(rBox.Y1)),
209             sal_Int32(ceil(rBox.X2-rBox.X1)),
210             sal_Int32(floor(rBox.Y2-rBox.Y1)),
211             awt::PosSize::POSSIZE);
212         UpdateBorders();
213     }
214 }
215 
216 
217 
218 
219 void PresenterScrollBar::SetThumbPosition (
220     double nPosition,
221     const bool bAsynchronousUpdate)
222 {
223     SetThumbPosition(nPosition, bAsynchronousUpdate, true, true);
224 }
225 
226 
227 
228 
229 void PresenterScrollBar::SetThumbPosition (
230     double nPosition,
231     const bool bAsynchronousUpdate,
232     const bool bValidate,
233     const bool bNotify)
234 {
235     if (bValidate)
236         nPosition = ValidateThumbPosition(nPosition);
237 
238     if (nPosition != mnThumbPosition && ! mbIsNotificationActive)
239     {
240         mnThumbPosition = nPosition;
241 
242         UpdateBorders();
243         Repaint(GetRectangle(Total), bAsynchronousUpdate);
244         if (bNotify)
245             NotifyThumbPositionChange();
246     }
247 }
248 
249 
250 
251 
252 double PresenterScrollBar::GetThumbPosition (void) const
253 {
254     return mnThumbPosition;
255 }
256 
257 
258 
259 
260 void PresenterScrollBar::SetTotalSize (const double nTotalSize)
261 {
262     if (mnTotalSize != nTotalSize)
263     {
264         mnTotalSize = nTotalSize + 1;
265         UpdateBorders();
266         Repaint(GetRectangle(Total), false);
267     }
268 }
269 
270 
271 
272 
273 double PresenterScrollBar::GetTotalSize (void) const
274 {
275     return mnTotalSize;
276 }
277 
278 
279 
280 
281 void PresenterScrollBar::SetThumbSize (const double nThumbSize)
282 {
283     OSL_ASSERT(nThumbSize>=0);
284     if (mnThumbSize != nThumbSize)
285     {
286         mnThumbSize = nThumbSize;
287         UpdateBorders();
288         Repaint(GetRectangle(Total), false);
289     }
290 }
291 
292 
293 
294 
295 double PresenterScrollBar::GetThumbSize (void) const
296 {
297     return mnThumbSize;
298 }
299 
300 
301 
302 
303 void PresenterScrollBar::SetLineHeight (const double nLineHeight)
304 {
305     mnLineHeight = nLineHeight;
306 }
307 
308 
309 
310 
311 double PresenterScrollBar::GetLineHeight (void) const
312 {
313     return mnLineHeight;
314 }
315 
316 
317 
318 
319 void PresenterScrollBar::SetCanvas (const Reference<css::rendering::XCanvas>& rxCanvas)
320 {
321     if (mxCanvas != rxCanvas)
322     {
323         mxCanvas = rxCanvas;
324         if (mxCanvas.is())
325         {
326             if (mpBitmaps.get()==NULL)
327             {
328                 if (mpSharedBitmaps.expired())
329                 {
330                     try
331                     {
332                         mpBitmaps.reset(new PresenterBitmapContainer(
333                             OUString::createFromAscii("PresenterScreenSettings/ScrollBar/Bitmaps"),
334                             ::boost::shared_ptr<PresenterBitmapContainer>(),
335                             mxComponentContext,
336                             mxCanvas,
337                             PresenterComponent::GetBasePath(mxComponentContext)));
338                         mpSharedBitmaps = mpBitmaps;
339                     }
340                     catch(Exception&)
341                     {
342                         OSL_ASSERT(false);
343                     }
344                 }
345                 else
346                     mpBitmaps = ::boost::shared_ptr<PresenterBitmapContainer>(mpSharedBitmaps);
347                 UpdateBitmaps();
348                 UpdateBorders();
349             }
350 
351             Repaint(GetRectangle(Total), false);
352         }
353     }
354 }
355 
356 
357 
358 
359 void PresenterScrollBar::SetBackground (const SharedBitmapDescriptor& rpBackgroundBitmap)
360 {
361     mpBackgroundBitmap = rpBackgroundBitmap;
362 }
363 
364 
365 
366 void PresenterScrollBar::CheckValues (void)
367 {
368     mnThumbPosition = ValidateThumbPosition(mnThumbPosition);
369 }
370 
371 
372 
373 
374 double PresenterScrollBar::ValidateThumbPosition (double nPosition)
375 {
376     if (nPosition + mnThumbSize > mnTotalSize)
377         nPosition = mnTotalSize - mnThumbSize;
378     if (nPosition < 0)
379         nPosition = 0;
380     return nPosition;
381 }
382 
383 
384 
385 
386 void PresenterScrollBar::Paint (
387     const awt::Rectangle& rUpdateBox,
388     const bool bNoClip)
389 {
390     if ( ! mxCanvas.is() || ! mxWindow.is())
391     {
392         OSL_ASSERT(mxCanvas.is());
393         OSL_ASSERT(mxWindow.is());
394         return;
395     }
396 
397     if ( ! bNoClip)
398     {
399         if (PresenterGeometryHelper::AreRectanglesDisjoint (rUpdateBox, mxWindow->getPosSize()))
400             return;
401     }
402 
403     PaintBackground(rUpdateBox);
404     PaintComposite(rUpdateBox, PagerUp,
405         mpPagerStartDescriptor, mpPagerCenterDescriptor, SharedBitmapDescriptor());
406     PaintComposite(rUpdateBox, PagerDown,
407         SharedBitmapDescriptor(), mpPagerCenterDescriptor, mpPagerEndDescriptor);
408     PaintComposite(rUpdateBox, Thumb,
409         mpThumbStartDescriptor, mpThumbCenterDescriptor, mpThumbEndDescriptor);
410     PaintBitmap(rUpdateBox, PrevButton, mpPrevButtonDescriptor);
411     PaintBitmap(rUpdateBox, NextButton, mpNextButtonDescriptor);
412 
413     Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
414     if (xSpriteCanvas.is())
415         xSpriteCanvas->updateScreen(sal_False);
416 }
417 
418 
419 
420 
421 
422 
423 //----- XWindowListener -------------------------------------------------------
424 
425 void SAL_CALL PresenterScrollBar::windowResized (const css::awt::WindowEvent& rEvent)
426     throw (css::uno::RuntimeException)
427 {
428     (void)rEvent;
429 }
430 
431 
432 
433 
434 
435 void SAL_CALL PresenterScrollBar::windowMoved (const css::awt::WindowEvent& rEvent)
436     throw (css::uno::RuntimeException)
437 {
438     (void)rEvent;
439 }
440 
441 
442 
443 
444 void SAL_CALL PresenterScrollBar::windowShown (const css::lang::EventObject& rEvent)
445     throw (css::uno::RuntimeException)
446 {
447     (void)rEvent;
448 }
449 
450 
451 
452 
453 void SAL_CALL PresenterScrollBar::windowHidden (const css::lang::EventObject& rEvent)
454     throw (css::uno::RuntimeException)
455 {
456     (void)rEvent;
457 }
458 
459 
460 
461 
462 //----- XPaintListener --------------------------------------------------------
463 
464 void SAL_CALL PresenterScrollBar::windowPaint (const css::awt::PaintEvent& rEvent)
465     throw (css::uno::RuntimeException)
466 {
467     if (mxWindow.is())
468     {
469         awt::Rectangle aRepaintBox (rEvent.UpdateRect);
470         const awt::Rectangle aWindowBox (mxWindow->getPosSize());
471         aRepaintBox.X += aWindowBox.X;
472         aRepaintBox.Y += aWindowBox.Y;
473         Paint(aRepaintBox);
474 
475         Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
476         if (xSpriteCanvas.is())
477             xSpriteCanvas->updateScreen(sal_False);
478     }
479 }
480 
481 
482 
483 
484 //----- XMouseListener --------------------------------------------------------
485 
486 void SAL_CALL PresenterScrollBar::mousePressed (const css::awt::MouseEvent& rEvent)
487     throw(css::uno::RuntimeException)
488 {
489     maDragAnchor.X = rEvent.X;
490     maDragAnchor.Y = rEvent.Y;
491     meButtonDownArea = GetArea(rEvent.X, rEvent.Y);
492 
493     mpMousePressRepeater->Start(meButtonDownArea);
494 }
495 
496 
497 
498 
499 void SAL_CALL PresenterScrollBar::mouseReleased (const css::awt::MouseEvent& rEvent)
500     throw(css::uno::RuntimeException)
501 {
502     (void)rEvent;
503 
504     mpMousePressRepeater->Stop();
505 
506     if (mxPresenterHelper.is())
507         mxPresenterHelper->releaseMouse(mxWindow);
508 }
509 
510 
511 
512 
513 void SAL_CALL PresenterScrollBar::mouseEntered (const css::awt::MouseEvent& rEvent)
514     throw(css::uno::RuntimeException)
515 {
516     (void)rEvent;
517 }
518 
519 
520 
521 
522 void SAL_CALL PresenterScrollBar::mouseExited (const css::awt::MouseEvent& rEvent)
523     throw(css::uno::RuntimeException)
524 {
525     (void)rEvent;
526     if (meMouseMoveArea != None)
527     {
528         const Area eOldMouseMoveArea (meMouseMoveArea);
529         meMouseMoveArea = None;
530         Repaint(GetRectangle(eOldMouseMoveArea), true);
531     }
532     meButtonDownArea = None;
533     meMouseMoveArea = None;
534 
535     mpMousePressRepeater->Stop();
536 }
537 
538 
539 
540 
541 
542 //----- XMouseMotionListener --------------------------------------------------
543 
544 void SAL_CALL PresenterScrollBar::mouseMoved (const css::awt::MouseEvent& rEvent)
545     throw (css::uno::RuntimeException)
546 {
547     const Area eArea (GetArea(rEvent.X, rEvent.Y));
548     if (eArea != meMouseMoveArea)
549     {
550         const Area eOldMouseMoveArea (meMouseMoveArea);
551         meMouseMoveArea = eArea;
552         if (eOldMouseMoveArea != None)
553             Repaint(GetRectangle(eOldMouseMoveArea), meMouseMoveArea==None);
554         if (meMouseMoveArea != None)
555             Repaint(GetRectangle(meMouseMoveArea), true);
556     }
557     mpMousePressRepeater->SetMouseArea(eArea);
558 }
559 
560 
561 
562 
563 void SAL_CALL PresenterScrollBar::mouseDragged (const css::awt::MouseEvent& rEvent)
564     throw (css::uno::RuntimeException)
565 {
566     if (meButtonDownArea != Thumb)
567         return;
568 
569     mpMousePressRepeater->Stop();
570 
571     if (mxPresenterHelper.is())
572         mxPresenterHelper->captureMouse(mxWindow);
573 
574     const double nDragDistance (GetDragDistance(rEvent.X,rEvent.Y));
575     UpdateDragAnchor(nDragDistance);
576     if (nDragDistance != 0)
577     {
578         SetThumbPosition(mnThumbPosition + nDragDistance, false, true, true);
579     }
580 }
581 
582 
583 
584 
585 //----- lang::XEventListener --------------------------------------------------
586 
587 void SAL_CALL PresenterScrollBar::disposing (const css::lang::EventObject& rEvent)
588     throw (css::uno::RuntimeException)
589 {
590     if (rEvent.Source == mxWindow)
591         mxWindow = NULL;
592 }
593 
594 
595 
596 
597 //-----------------------------------------------------------------------------
598 
599 geometry::RealRectangle2D PresenterScrollBar::GetRectangle (const Area eArea) const
600 {
601     OSL_ASSERT(eArea>=0 && eArea<__AreaCount__);
602 
603     return maBox[eArea];
604 }
605 
606 
607 
608 
609 void PresenterScrollBar::Repaint (
610     const geometry::RealRectangle2D aBox,
611     const bool bAsynchronousUpdate)
612 {
613     if (mpPaintManager.get() != NULL)
614         mpPaintManager->Invalidate(
615             mxWindow,
616             PresenterGeometryHelper::ConvertRectangle(aBox),
617             bAsynchronousUpdate);
618 }
619 
620 
621 
622 
623 void PresenterScrollBar::PaintBackground(
624     const css::awt::Rectangle& rUpdateBox)
625 {
626     if (mpBackgroundBitmap.get() == NULL)
627         return;
628 
629     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
630     mpCanvasHelper->Paint(
631         mpBackgroundBitmap,
632         mxCanvas,
633         rUpdateBox,
634         aWindowBox,
635         awt::Rectangle());
636 }
637 
638 
639 
640 
641 void PresenterScrollBar::PaintBitmap(
642     const css::awt::Rectangle& rUpdateBox,
643     const Area eArea,
644     const SharedBitmapDescriptor& rpBitmaps)
645 {
646     const geometry::RealRectangle2D aLocalBox (GetRectangle(eArea));
647     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
648     geometry::RealRectangle2D aBox (aLocalBox);
649     aBox.X1 += aWindowBox.X;
650     aBox.Y1 += aWindowBox.Y;
651     aBox.X2 += aWindowBox.X;
652     aBox.Y2 += aWindowBox.Y;
653 
654     Reference<rendering::XBitmap> xBitmap (GetBitmap(eArea,rpBitmaps));
655 
656     if (xBitmap.is())
657     {
658         Reference<rendering::XPolyPolygon2D> xClipPolygon (
659             PresenterGeometryHelper::CreatePolygon(
660                 PresenterGeometryHelper::Intersection(rUpdateBox,
661                     PresenterGeometryHelper::ConvertRectangle(aBox)),
662                 mxCanvas->getDevice()));
663 
664         const rendering::ViewState aViewState (
665             geometry::AffineMatrix2D(1,0,0, 0,1,0),
666             xClipPolygon);
667 
668         const geometry::IntegerSize2D aBitmapSize (xBitmap->getSize());
669         rendering::RenderState aRenderState (
670             geometry::AffineMatrix2D(
671                 1,0,aBox.X1 + (aBox.X2-aBox.X1 - aBitmapSize.Width)/2,
672                 0,1,aBox.Y1 + (aBox.Y2-aBox.Y1 - aBitmapSize.Height)/2),
673             NULL,
674             Sequence<double>(4),
675             rendering::CompositeOperation::SOURCE);
676 
677         mxCanvas->drawBitmap(
678             xBitmap,
679             aViewState,
680             aRenderState);
681     }
682 }
683 
684 
685 
686 
687 void PresenterScrollBar::NotifyThumbPositionChange (void)
688 {
689     if ( ! mbIsNotificationActive)
690     {
691         mbIsNotificationActive = true;
692 
693         try
694         {
695             maThumbMotionListener(mnThumbPosition);
696         }
697         catch (Exception&)
698         {
699         }
700 
701         mbIsNotificationActive = false;
702     }
703 }
704 
705 
706 
707 
708 PresenterScrollBar::Area PresenterScrollBar::GetArea (const double nX, const double nY) const
709 {
710     const geometry::RealPoint2D aPoint(nX, nY);
711 
712     if (PresenterGeometryHelper::IsInside(GetRectangle(Pager), aPoint))
713     {
714         if (PresenterGeometryHelper::IsInside(GetRectangle(Thumb), aPoint))
715             return Thumb;
716         else if (PresenterGeometryHelper::IsInside(GetRectangle(PagerUp), aPoint))
717             return PagerUp;
718         else if (PresenterGeometryHelper::IsInside(GetRectangle(PagerDown), aPoint))
719             return PagerDown;
720     }
721     else if (PresenterGeometryHelper::IsInside(GetRectangle(PrevButton), aPoint))
722         return PrevButton;
723     else if (PresenterGeometryHelper::IsInside(GetRectangle(NextButton), aPoint))
724         return NextButton;
725 
726     return None;
727 }
728 
729 
730 
731 
732 void PresenterScrollBar::UpdateWidthOrHeight (
733     sal_Int32& rSize,
734     const SharedBitmapDescriptor& rpDescriptor)
735 {
736     if (rpDescriptor.get() != NULL)
737     {
738         Reference<rendering::XBitmap> xBitmap (rpDescriptor->GetNormalBitmap());
739         if (xBitmap.is())
740         {
741             const geometry::IntegerSize2D aBitmapSize (xBitmap->getSize());
742             const sal_Int32 nBitmapSize = (sal_Int32)GetMinor(aBitmapSize.Width, aBitmapSize.Height);
743             if (nBitmapSize > rSize)
744                 rSize = nBitmapSize;
745         }
746     }
747 }
748 
749 
750 
751 
752 css::uno::Reference<css::rendering::XBitmap> PresenterScrollBar::GetBitmap (
753     const Area eArea,
754     const SharedBitmapDescriptor& rpBitmaps) const
755 {
756     if (rpBitmaps.get() == NULL)
757         return NULL;
758     else
759         return rpBitmaps->GetBitmap(GetBitmapMode(eArea));
760 }
761 
762 
763 
764 
765 PresenterBitmapContainer::BitmapDescriptor::Mode PresenterScrollBar::GetBitmapMode (
766     const Area eArea) const
767 {
768     if (IsDisabled(eArea))
769         return PresenterBitmapContainer::BitmapDescriptor::Disabled;
770     else if (eArea == meMouseMoveArea)
771         return PresenterBitmapContainer::BitmapDescriptor::MouseOver;
772     else
773         return PresenterBitmapContainer::BitmapDescriptor::Normal;
774 }
775 
776 
777 
778 
779 bool PresenterScrollBar::IsDisabled (const Area eArea) const
780 {
781     OSL_ASSERT(eArea>=0 && eArea<__AreaCount__);
782 
783     return ! maEnabledState[eArea];
784 }
785 
786 
787 
788 
789 //===== PresenterVerticalScrollBar ============================================
790 
791 PresenterVerticalScrollBar::PresenterVerticalScrollBar (
792     const Reference<XComponentContext>& rxComponentContext,
793     const Reference<awt::XWindow>& rxParentWindow,
794     const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager,
795     const ::boost::function<void(double)>& rThumbMotionListener)
796     : PresenterScrollBar(rxComponentContext, rxParentWindow, rpPaintManager, rThumbMotionListener),
797       mnScrollBarWidth(0)
798 {
799 }
800 
801 
802 
803 
804 PresenterVerticalScrollBar::~PresenterVerticalScrollBar (void)
805 {
806 }
807 
808 
809 
810 
811 double PresenterVerticalScrollBar::GetDragDistance (const sal_Int32 nX, const sal_Int32 nY) const
812 {
813     (void)nX;
814     const double nDistance (nY - maDragAnchor.Y);
815     if (nDistance == 0)
816         return 0;
817     else
818     {
819         const awt::Rectangle aWindowBox (mxWindow->getPosSize());
820         const double nBarWidth (aWindowBox.Width);
821         const double nPagerHeight (aWindowBox.Height - 2*nBarWidth);
822         const double nDragDistance (mnTotalSize / nPagerHeight * nDistance);
823         if (nDragDistance + mnThumbPosition < 0)
824             return -mnThumbPosition;
825         else if (mnThumbPosition + nDragDistance > mnTotalSize-mnThumbSize)
826             return mnTotalSize-mnThumbSize-mnThumbPosition;
827         else
828             return nDragDistance;
829     }
830 }
831 
832 
833 
834 
835 void PresenterVerticalScrollBar::UpdateDragAnchor (const double nDragDistance)
836 {
837     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
838     const double nBarWidth (aWindowBox.Width);
839     const double nPagerHeight (aWindowBox.Height - 2*nBarWidth);
840     maDragAnchor.Y += nDragDistance * nPagerHeight /  mnTotalSize;
841 }
842 
843 
844 
845 
846 sal_Int32 PresenterVerticalScrollBar::GetSize (void) const
847 {
848     return mnScrollBarWidth;
849 }
850 
851 
852 
853 
854 geometry::RealPoint2D PresenterVerticalScrollBar::GetPoint (
855     const double nMajor, const double nMinor) const
856 {
857     return geometry::RealPoint2D(nMinor, nMajor);
858 }
859 
860 
861 
862 
863 double PresenterVerticalScrollBar::GetMajor (const double nX, const double nY) const
864 {
865     (void)nX;
866     return nY;
867 }
868 
869 
870 
871 
872 double PresenterVerticalScrollBar::GetMinor (const double nX, const double nY) const
873 {
874     (void)nY;
875     return nX;
876 }
877 
878 
879 
880 
881 void PresenterVerticalScrollBar::UpdateBorders (void)
882 {
883     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
884     double nBottom = aWindowBox.Height;
885 
886     if (mpNextButtonDescriptor.get() != NULL)
887     {
888         Reference<rendering::XBitmap> xBitmap (mpNextButtonDescriptor->GetNormalBitmap());
889         if (xBitmap.is())
890         {
891             geometry::IntegerSize2D aSize (xBitmap->getSize());
892             maBox[NextButton] = geometry::RealRectangle2D(
893                 0, nBottom - aSize.Height, aWindowBox.Width, nBottom);
894             nBottom -= aSize.Height + gnScrollBarGap;
895         }
896     }
897     if (mpPrevButtonDescriptor.get() != NULL)
898     {
899         Reference<rendering::XBitmap> xBitmap (mpPrevButtonDescriptor->GetNormalBitmap());
900         if (xBitmap.is())
901         {
902             geometry::IntegerSize2D aSize (xBitmap->getSize());
903             maBox[PrevButton] = geometry::RealRectangle2D(
904                 0, nBottom - aSize.Height, aWindowBox.Width, nBottom);
905             nBottom -= aSize.Height + gnScrollBarGap;
906         }
907     }
908     const double nPagerHeight (nBottom);
909     maBox[Pager] = geometry::RealRectangle2D(
910         0,0, aWindowBox.Width, nBottom);
911     if (mnTotalSize < 1)
912     {
913         maBox[Thumb] = maBox[Pager];
914 
915         // Set up the enabled/disabled states.
916         maEnabledState[PrevButton] = false;
917         maEnabledState[PagerUp] = false;
918         maEnabledState[NextButton] = false;
919         maEnabledState[PagerDown] = false;
920         maEnabledState[Thumb] = false;
921     }
922     else
923     {
924         const double nThumbSize = ::std::min(mnThumbSize,mnTotalSize);
925         const double nThumbPosition = ::std::min(::std::max(0.0,mnThumbPosition), mnTotalSize - nThumbSize);
926         maBox[Thumb] = geometry::RealRectangle2D(
927             0, nThumbPosition / mnTotalSize * nPagerHeight,
928             aWindowBox.Width,
929                 (nThumbPosition+nThumbSize) / mnTotalSize * nPagerHeight);
930 
931         // Set up the enabled/disabled states.
932         maEnabledState[PrevButton] = nThumbPosition>0;
933         maEnabledState[PagerUp] = nThumbPosition>0;
934         maEnabledState[NextButton] = nThumbPosition+nThumbSize < mnTotalSize;
935         maEnabledState[PagerDown] = nThumbPosition+nThumbSize < mnTotalSize;
936         maEnabledState[Thumb] = nThumbSize < mnTotalSize;
937     }
938     maBox[PagerUp] = geometry::RealRectangle2D(
939         maBox[Pager].X1, maBox[Pager].Y1, maBox[Pager].X2, maBox[Thumb].Y1-1);
940     maBox[PagerDown] = geometry::RealRectangle2D(
941         maBox[Pager].X1, maBox[Thumb].Y2+1, maBox[Pager].X2, maBox[Pager].Y2);
942     maBox[Total] = PresenterGeometryHelper::Union(
943         PresenterGeometryHelper::Union(maBox[PrevButton], maBox[NextButton]),
944         maBox[Pager]);
945 }
946 
947 
948 
949 
950 void PresenterVerticalScrollBar::UpdateBitmaps (void)
951 {
952     if (mpBitmaps.get() != NULL)
953     {
954         mpPrevButtonDescriptor = mpBitmaps->GetBitmap(A2S("Up"));
955         mpNextButtonDescriptor = mpBitmaps->GetBitmap(A2S("Down"));
956         mpPagerStartDescriptor = mpBitmaps->GetBitmap(A2S("PagerTop"));
957         mpPagerCenterDescriptor = mpBitmaps->GetBitmap(A2S("PagerVertical"));
958         mpPagerEndDescriptor = mpBitmaps->GetBitmap(A2S("PagerBottom"));
959         mpThumbStartDescriptor = mpBitmaps->GetBitmap(A2S("ThumbTop"));
960         mpThumbCenterDescriptor = mpBitmaps->GetBitmap(A2S("ThumbVertical"));
961         mpThumbEndDescriptor = mpBitmaps->GetBitmap(A2S("ThumbBottom"));
962 
963         mnScrollBarWidth = 0;
964         UpdateWidthOrHeight(mnScrollBarWidth, mpPrevButtonDescriptor);
965         UpdateWidthOrHeight(mnScrollBarWidth, mpNextButtonDescriptor);
966         UpdateWidthOrHeight(mnScrollBarWidth, mpPagerStartDescriptor);
967         UpdateWidthOrHeight(mnScrollBarWidth, mpPagerCenterDescriptor);
968         UpdateWidthOrHeight(mnScrollBarWidth, mpPagerEndDescriptor);
969         UpdateWidthOrHeight(mnScrollBarWidth, mpThumbStartDescriptor);
970         UpdateWidthOrHeight(mnScrollBarWidth, mpThumbCenterDescriptor);
971         UpdateWidthOrHeight(mnScrollBarWidth, mpThumbEndDescriptor);
972         if (mnScrollBarWidth == 0)
973             mnScrollBarWidth = 20;
974     }
975 }
976 
977 
978 
979 
980 void PresenterVerticalScrollBar::PaintComposite(
981     const css::awt::Rectangle& rUpdateBox,
982     const Area eArea,
983     const SharedBitmapDescriptor& rpStartBitmaps,
984     const SharedBitmapDescriptor& rpCenterBitmaps,
985     const SharedBitmapDescriptor& rpEndBitmaps)
986 {
987     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
988     geometry::RealRectangle2D aBox (GetRectangle(eArea));
989     aBox.X1 += aWindowBox.X;
990     aBox.Y1 += aWindowBox.Y;
991     aBox.X2 += aWindowBox.X;
992     aBox.Y2 += aWindowBox.Y;
993 
994     // Get bitmaps and sizes.
995 
996     PresenterUIPainter::PaintVerticalBitmapComposite(
997         mxCanvas,
998         rUpdateBox,
999         (eArea == Thumb
1000             ? PresenterGeometryHelper::ConvertRectangleWithConstantSize(aBox)
1001             : PresenterGeometryHelper::ConvertRectangle(aBox)),
1002         GetBitmap(eArea, rpStartBitmaps),
1003         GetBitmap(eArea, rpCenterBitmaps),
1004         GetBitmap(eArea, rpEndBitmaps));
1005 }
1006 
1007 
1008 
1009 
1010 //===== PresenterHorizontalScrollBar ============================================
1011 
1012 PresenterHorizontalScrollBar::PresenterHorizontalScrollBar (
1013     const Reference<XComponentContext>& rxComponentContext,
1014     const Reference<awt::XWindow>& rxParentWindow,
1015     const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager,
1016     const ::boost::function<void(double)>& rThumbMotionListener)
1017     : PresenterScrollBar(rxComponentContext, rxParentWindow, rpPaintManager, rThumbMotionListener),
1018       mnScrollBarHeight(0)
1019 {
1020 }
1021 
1022 
1023 
1024 
1025 PresenterHorizontalScrollBar::~PresenterHorizontalScrollBar (void)
1026 {
1027 }
1028 
1029 
1030 
1031 
1032 double PresenterHorizontalScrollBar::GetDragDistance (const sal_Int32 nX, const sal_Int32 nY) const
1033 {
1034     (void)nY;
1035     const double nDistance (nX - maDragAnchor.X);
1036     if (nDistance == 0)
1037         return 0;
1038     else
1039     {
1040         const awt::Rectangle aWindowBox (mxWindow->getPosSize());
1041         const double nBarHeight (aWindowBox.Height);
1042         const double nPagerWidth (aWindowBox.Width - 2*nBarHeight);
1043         const double nDragDistance (mnTotalSize / nPagerWidth * nDistance);
1044         if (nDragDistance + mnThumbPosition < 0)
1045             return -mnThumbPosition;
1046         else if (mnThumbPosition + nDragDistance > mnTotalSize-mnThumbSize)
1047             return mnTotalSize-mnThumbSize-mnThumbPosition;
1048         else
1049             return nDragDistance;
1050     }
1051 }
1052 
1053 
1054 
1055 
1056 void PresenterHorizontalScrollBar::UpdateDragAnchor (const double nDragDistance)
1057 {
1058     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
1059         const double nBarHeight (aWindowBox.Height);
1060         const double nPagerWidth (aWindowBox.Width - 2*nBarHeight);
1061     maDragAnchor.X += nDragDistance * nPagerWidth /  mnTotalSize;
1062 }
1063 
1064 
1065 
1066 
1067 sal_Int32 PresenterHorizontalScrollBar::GetSize (void) const
1068 {
1069     return mnScrollBarHeight;
1070 }
1071 
1072 
1073 
1074 
1075 
1076 geometry::RealPoint2D PresenterHorizontalScrollBar::GetPoint (
1077     const double nMajor, const double nMinor) const
1078 {
1079     return geometry::RealPoint2D(nMajor, nMinor);
1080 }
1081 
1082 
1083 
1084 
1085 double PresenterHorizontalScrollBar::GetMajor (const double nX, const double nY) const
1086 {
1087     (void)nY;
1088     return nX;
1089 }
1090 
1091 
1092 
1093 
1094 double PresenterHorizontalScrollBar::GetMinor (const double nX, const double nY) const
1095 {
1096     (void)nX;
1097     return nY;
1098 }
1099 
1100 
1101 
1102 
1103 void PresenterHorizontalScrollBar::UpdateBorders (void)
1104 {
1105     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
1106     double nRight = aWindowBox.Width;
1107     const double nGap (2);
1108 
1109     if (mpNextButtonDescriptor.get() != NULL)
1110     {
1111         Reference<rendering::XBitmap> xBitmap (mpNextButtonDescriptor->GetNormalBitmap());
1112         if (xBitmap.is())
1113         {
1114             geometry::IntegerSize2D aSize (xBitmap->getSize());
1115             maBox[NextButton] = geometry::RealRectangle2D(
1116                 nRight - aSize.Width,0, nRight, aWindowBox.Height);
1117             nRight -= aSize.Width + nGap;
1118         }
1119     }
1120     if (mpPrevButtonDescriptor.get() != NULL)
1121     {
1122         Reference<rendering::XBitmap> xBitmap (mpPrevButtonDescriptor->GetNormalBitmap());
1123         if (xBitmap.is())
1124         {
1125             geometry::IntegerSize2D aSize (xBitmap->getSize());
1126             maBox[PrevButton] = geometry::RealRectangle2D(
1127                 nRight - aSize.Width,0, nRight, aWindowBox.Height);
1128             nRight -= aSize.Width + nGap;
1129         }
1130     }
1131 
1132     const double nPagerWidth (nRight);
1133     maBox[Pager] = geometry::RealRectangle2D(
1134         0,0, nRight, aWindowBox.Height);
1135     if (mnTotalSize == 0)
1136     {
1137         maBox[Thumb] = maBox[Pager];
1138 
1139         // Set up the enabled/disabled states.
1140         maEnabledState[PrevButton] = false;
1141         maEnabledState[PagerUp] = false;
1142         maEnabledState[NextButton] = false;
1143         maEnabledState[PagerDown] = false;
1144         maEnabledState[Thumb] = false;
1145     }
1146     else
1147     {
1148         const double nThumbSize = ::std::min(mnThumbSize,mnTotalSize);
1149         const double nThumbPosition = ::std::min(::std::max(0.0,mnThumbPosition), mnTotalSize - nThumbSize);
1150         maBox[Thumb] = geometry::RealRectangle2D(
1151             (nThumbPosition) / mnTotalSize * nPagerWidth, 0,
1152             (nThumbPosition+nThumbSize) / mnTotalSize * nPagerWidth, aWindowBox.Height);
1153 
1154         // Set up the enabled/disabled states.
1155         maEnabledState[PrevButton] = nThumbPosition>0;
1156         maEnabledState[PagerUp] = nThumbPosition>0;
1157         maEnabledState[NextButton] = nThumbPosition+nThumbSize < mnTotalSize;
1158         maEnabledState[PagerDown] = nThumbPosition+nThumbSize < mnTotalSize;
1159         maEnabledState[Thumb] = nThumbSize < mnTotalSize;
1160     }
1161     maBox[PagerUp] = geometry::RealRectangle2D(
1162         maBox[Pager].X1, maBox[Pager].Y1, maBox[Thumb].X1-1, maBox[Pager].Y2);
1163     maBox[PagerDown] = geometry::RealRectangle2D(
1164         maBox[Thumb].X2+1, maBox[Pager].Y1, maBox[Pager].X2, maBox[Pager].Y2);
1165     maBox[Total] = PresenterGeometryHelper::Union(
1166         PresenterGeometryHelper::Union(maBox[PrevButton], maBox[NextButton]),
1167         maBox[Pager]);
1168 }
1169 
1170 
1171 
1172 
1173 void PresenterHorizontalScrollBar::UpdateBitmaps (void)
1174 {
1175     if (mpBitmaps.get() != NULL)
1176     {
1177         mpPrevButtonDescriptor = mpBitmaps->GetBitmap(A2S("Left"));
1178         mpNextButtonDescriptor = mpBitmaps->GetBitmap(A2S("Right"));
1179         mpPagerStartDescriptor = mpBitmaps->GetBitmap(A2S("PagerLeft"));
1180         mpPagerCenterDescriptor = mpBitmaps->GetBitmap(A2S("PagerHorizontal"));
1181         mpPagerEndDescriptor = mpBitmaps->GetBitmap(A2S("PagerRight"));
1182         mpThumbStartDescriptor = mpBitmaps->GetBitmap(A2S("ThumbLeft"));
1183         mpThumbCenterDescriptor = mpBitmaps->GetBitmap(A2S("ThumbHorizontal"));
1184         mpThumbEndDescriptor = mpBitmaps->GetBitmap(A2S("ThumbRight"));
1185 
1186         mnScrollBarHeight = 0;
1187         UpdateWidthOrHeight(mnScrollBarHeight, mpPrevButtonDescriptor);
1188         UpdateWidthOrHeight(mnScrollBarHeight, mpNextButtonDescriptor);
1189         UpdateWidthOrHeight(mnScrollBarHeight, mpPagerStartDescriptor);
1190         UpdateWidthOrHeight(mnScrollBarHeight, mpPagerCenterDescriptor);
1191         UpdateWidthOrHeight(mnScrollBarHeight, mpPagerEndDescriptor);
1192         UpdateWidthOrHeight(mnScrollBarHeight, mpThumbStartDescriptor);
1193         UpdateWidthOrHeight(mnScrollBarHeight, mpThumbCenterDescriptor);
1194         UpdateWidthOrHeight(mnScrollBarHeight, mpThumbEndDescriptor);
1195         if (mnScrollBarHeight == 0)
1196             mnScrollBarHeight = 20;
1197     }
1198 }
1199 
1200 
1201 
1202 void PresenterHorizontalScrollBar::PaintComposite(
1203     const css::awt::Rectangle& rUpdateBox,
1204     const Area eArea,
1205     const SharedBitmapDescriptor& rpStartBitmaps,
1206     const SharedBitmapDescriptor& rpCenterBitmaps,
1207     const SharedBitmapDescriptor& rpEndBitmaps)
1208 {
1209     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
1210     geometry::RealRectangle2D aBox (GetRectangle(eArea));
1211     aBox.X1 += aWindowBox.X;
1212     aBox.Y1 += aWindowBox.Y;
1213     aBox.X2 += aWindowBox.X;
1214     aBox.Y2 += aWindowBox.Y;
1215 
1216     PresenterUIPainter::PaintHorizontalBitmapComposite(
1217         mxCanvas,
1218         rUpdateBox,
1219         PresenterGeometryHelper::ConvertRectangle(aBox),
1220         GetBitmap(eArea, rpStartBitmaps),
1221         GetBitmap(eArea, rpCenterBitmaps),
1222         GetBitmap(eArea, rpEndBitmaps));
1223 }
1224 
1225 
1226 
1227 
1228 //===== PresenterScrollBar::MousePressRepeater ================================
1229 
1230 PresenterScrollBar::MousePressRepeater::MousePressRepeater (
1231     const ::rtl::Reference<PresenterScrollBar>& rpScrollBar)
1232     : mnMousePressRepeaterTaskId(PresenterTimer::NotAValidTaskId),
1233       mpScrollBar(rpScrollBar),
1234       meMouseArea(PresenterScrollBar::None)
1235 {
1236 }
1237 
1238 
1239 
1240 
1241 void PresenterScrollBar::MousePressRepeater::Dispose (void)
1242 {
1243     Stop();
1244     mpScrollBar = NULL;
1245 }
1246 
1247 
1248 
1249 
1250 void PresenterScrollBar::MousePressRepeater::Start (const PresenterScrollBar::Area& reArea)
1251 {
1252     meMouseArea = reArea;
1253 
1254     if (mnMousePressRepeaterTaskId == PresenterTimer::NotAValidTaskId)
1255     {
1256         // Execute key press operation at least this one time.
1257         Execute();
1258 
1259         // Schedule repeated executions.
1260         mnMousePressRepeaterTaskId = PresenterTimer::ScheduleRepeatedTask (
1261             ::boost::bind(&PresenterScrollBar::MousePressRepeater::Callback, shared_from_this(), _1),
1262             500000000,
1263             250000000);
1264     }
1265     else
1266     {
1267         // There is already an active repeating task.
1268     }
1269 }
1270 
1271 
1272 
1273 
1274 void PresenterScrollBar::MousePressRepeater::Stop (void)
1275 {
1276     if (mnMousePressRepeaterTaskId != PresenterTimer::NotAValidTaskId)
1277     {
1278         const sal_Int32 nTaskId (mnMousePressRepeaterTaskId);
1279         mnMousePressRepeaterTaskId = PresenterTimer::NotAValidTaskId;
1280         PresenterTimer::CancelTask(nTaskId);
1281     }
1282 }
1283 
1284 
1285 
1286 
1287 void PresenterScrollBar::MousePressRepeater::SetMouseArea(const PresenterScrollBar::Area& reArea)
1288 {
1289     if (meMouseArea != reArea)
1290     {
1291         if (mnMousePressRepeaterTaskId != PresenterTimer::NotAValidTaskId)
1292         {
1293             Stop();
1294         }
1295     }
1296 }
1297 
1298 
1299 
1300 
1301 void PresenterScrollBar::MousePressRepeater::Callback (const TimeValue& rCurrentTime)
1302 {
1303     (void)rCurrentTime;
1304 
1305     if (mpScrollBar.get() == NULL)
1306     {
1307         Stop();
1308         return;
1309     }
1310 
1311     Execute();
1312 }
1313 
1314 
1315 
1316 
1317 void PresenterScrollBar::MousePressRepeater::Execute (void)
1318 {
1319     const double nThumbPosition (mpScrollBar->GetThumbPosition());
1320     switch (meMouseArea)
1321     {
1322         case PrevButton:
1323             mpScrollBar->SetThumbPosition(nThumbPosition - mpScrollBar->GetLineHeight(), true);
1324             break;
1325 
1326         case NextButton:
1327             mpScrollBar->SetThumbPosition(nThumbPosition + mpScrollBar->GetLineHeight(), true);
1328             break;
1329 
1330         case PagerUp:
1331             mpScrollBar->SetThumbPosition(nThumbPosition - mpScrollBar->GetThumbSize()*0.8, true);
1332             break;
1333 
1334         case PagerDown:
1335             mpScrollBar->SetThumbPosition(nThumbPosition + mpScrollBar->GetThumbSize()*0.8, true);
1336             break;
1337 
1338         default:
1339             break;
1340     }
1341 }
1342 
1343 
1344 
1345 } } // end of namespace ::sdext::presenter
1346