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