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