1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include "PresenterScrollBar.hxx"
21 #include "PresenterBitmapContainer.hxx"
22 #include "PresenterCanvasHelper.hxx"
23 #include "PresenterGeometryHelper.hxx"
24 #include "PresenterPaintManager.hxx"
25 #include "PresenterTimer.hxx"
26 #include "PresenterUIPainter.hxx"
27 #include <com/sun/star/awt/PosSize.hpp>
28 #include <com/sun/star/awt/XWindowPeer.hpp>
29 #include <com/sun/star/rendering/CompositeOperation.hpp>
30 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
31
32 #include <algorithm>
33 #include <memory>
34 #include <math.h>
35
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::uno;
38
39 const double gnScrollBarGap (10);
40
41 namespace sdext::presenter {
42
43 //===== PresenterScrollBar::MousePressRepeater ================================
44
45 class PresenterScrollBar::MousePressRepeater
46 : public std::enable_shared_from_this<MousePressRepeater>
47 {
48 public:
49 explicit MousePressRepeater (const ::rtl::Reference<PresenterScrollBar>& rpScrollBar);
50 void Dispose();
51 void Start (const PresenterScrollBar::Area& reArea);
52 void Stop();
53 void SetMouseArea (const PresenterScrollBar::Area& reArea);
54
55 private:
56 void Callback ();
57 void Execute();
58
59 sal_Int32 mnMousePressRepeaterTaskId;
60 ::rtl::Reference<PresenterScrollBar> mpScrollBar;
61 PresenterScrollBar::Area meMouseArea;
62 };
63
64 //===== PresenterScrollBar ====================================================
65
66 std::weak_ptr<PresenterBitmapContainer> PresenterScrollBar::mpSharedBitmaps;
67
PresenterScrollBar(const Reference<XComponentContext> & rxComponentContext,const Reference<awt::XWindow> & rxParentWindow,const std::shared_ptr<PresenterPaintManager> & rpPaintManager,const::std::function<void (double)> & rThumbMotionListener)68 PresenterScrollBar::PresenterScrollBar (
69 const Reference<XComponentContext>& rxComponentContext,
70 const Reference<awt::XWindow>& rxParentWindow,
71 const std::shared_ptr<PresenterPaintManager>& rpPaintManager,
72 const ::std::function<void (double)>& rThumbMotionListener)
73 : PresenterScrollBarInterfaceBase(m_aMutex),
74 mxComponentContext(rxComponentContext),
75 mxWindow(),
76 mxCanvas(),
77 mxPresenterHelper(),
78 mpPaintManager(rpPaintManager),
79 mnThumbPosition(0),
80 mnTotalSize(0),
81 mnThumbSize(0),
82 mnLineHeight(10),
83 maDragAnchor(-1,-1),
84 maThumbMotionListener(rThumbMotionListener),
85 meButtonDownArea(None),
86 meMouseMoveArea(None),
87 mbIsNotificationActive(false),
88 mpBitmaps(),
89 mpPrevButtonDescriptor(),
90 mpNextButtonDescriptor(),
91 mpPagerStartDescriptor(),
92 mpPagerCenterDescriptor(),
93 mpPagerEndDescriptor(),
94 mpThumbStartDescriptor(),
95 mpThumbCenterDescriptor(),
96 mpThumbEndDescriptor(),
97 mpMousePressRepeater(std::make_shared<MousePressRepeater>(this)),
98 mpBackgroundBitmap(),
99 mpCanvasHelper(new PresenterCanvasHelper())
100 {
101 try
102 {
103 Reference<lang::XMultiComponentFactory> xFactory (rxComponentContext->getServiceManager());
104 if ( ! xFactory.is())
105 throw RuntimeException();
106
107 mxPresenterHelper.set(
108 xFactory->createInstanceWithContext(
109 "com.sun.star.comp.Draw.PresenterHelper",
110 rxComponentContext),
111 UNO_QUERY_THROW);
112
113 if (mxPresenterHelper.is())
114 mxWindow = mxPresenterHelper->createWindow(rxParentWindow,
115 false,
116 false,
117 false,
118 false);
119
120 // Make the background transparent. The slide show paints its own background.
121 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY_THROW);
122 xPeer->setBackground(0xff000000);
123
124 mxWindow->setVisible(true);
125 mxWindow->addWindowListener(this);
126 mxWindow->addPaintListener(this);
127 mxWindow->addMouseListener(this);
128 mxWindow->addMouseMotionListener(this);
129 }
130 catch (RuntimeException&)
131 {
132 }
133 }
134
~PresenterScrollBar()135 PresenterScrollBar::~PresenterScrollBar()
136 {
137 }
138
disposing()139 void SAL_CALL PresenterScrollBar::disposing()
140 {
141 mpMousePressRepeater->Dispose();
142
143 if (mxWindow.is())
144 {
145 mxWindow->removeWindowListener(this);
146 mxWindow->removePaintListener(this);
147 mxWindow->removeMouseListener(this);
148 mxWindow->removeMouseMotionListener(this);
149
150 Reference<lang::XComponent> xComponent = mxWindow;
151 mxWindow = nullptr;
152 if (xComponent.is())
153 xComponent->dispose();
154 }
155
156 mpBitmaps.reset();
157 }
158
SetVisible(const bool bIsVisible)159 void PresenterScrollBar::SetVisible (const bool bIsVisible)
160 {
161 if (mxWindow.is())
162 mxWindow->setVisible(bIsVisible);
163 }
164
SetPosSize(const css::geometry::RealRectangle2D & rBox)165 void PresenterScrollBar::SetPosSize (const css::geometry::RealRectangle2D& rBox)
166 {
167 if (mxWindow.is())
168 {
169 mxWindow->setPosSize(
170 sal_Int32(floor(rBox.X1)),
171 sal_Int32(ceil(rBox.Y1)),
172 sal_Int32(ceil(rBox.X2-rBox.X1)),
173 sal_Int32(floor(rBox.Y2-rBox.Y1)),
174 awt::PosSize::POSSIZE);
175 UpdateBorders();
176 }
177 }
178
SetThumbPosition(double nPosition,const bool bAsynchronousUpdate)179 void PresenterScrollBar::SetThumbPosition (
180 double nPosition,
181 const bool bAsynchronousUpdate)
182 {
183 nPosition = ValidateThumbPosition(nPosition);
184
185 if (nPosition == mnThumbPosition || mbIsNotificationActive)
186 return;
187
188 mnThumbPosition = nPosition;
189
190 UpdateBorders();
191 Repaint(GetRectangle(Total), bAsynchronousUpdate);
192
193 mbIsNotificationActive = true;
194 try
195 {
196 maThumbMotionListener(mnThumbPosition);
197 }
198 catch (Exception&)
199 {
200 }
201 mbIsNotificationActive = false;
202 }
203
204
SetTotalSize(const double nTotalSize)205 void PresenterScrollBar::SetTotalSize (const double nTotalSize)
206 {
207 if (mnTotalSize != nTotalSize)
208 {
209 mnTotalSize = nTotalSize + 1;
210 UpdateBorders();
211 Repaint(GetRectangle(Total), false);
212 }
213 }
214
SetThumbSize(const double nThumbSize)215 void PresenterScrollBar::SetThumbSize (const double nThumbSize)
216 {
217 OSL_ASSERT(nThumbSize>=0);
218 if (mnThumbSize != nThumbSize)
219 {
220 mnThumbSize = nThumbSize;
221 UpdateBorders();
222 Repaint(GetRectangle(Total), false);
223 }
224 }
225
226
SetLineHeight(const double nLineHeight)227 void PresenterScrollBar::SetLineHeight (const double nLineHeight)
228 {
229 mnLineHeight = nLineHeight;
230 }
231
232
SetCanvas(const Reference<css::rendering::XCanvas> & rxCanvas)233 void PresenterScrollBar::SetCanvas (const Reference<css::rendering::XCanvas>& rxCanvas)
234 {
235 if (mxCanvas == rxCanvas)
236 return;
237
238 mxCanvas = rxCanvas;
239 if (!mxCanvas.is())
240 return;
241
242 if (mpBitmaps == nullptr)
243 {
244 mpBitmaps = mpSharedBitmaps.lock();
245 if (!mpBitmaps)
246 {
247 try
248 {
249 mpBitmaps = std::make_shared<PresenterBitmapContainer>(
250 "PresenterScreenSettings/ScrollBar/Bitmaps",
251 std::shared_ptr<PresenterBitmapContainer>(),
252 mxComponentContext,
253 mxCanvas);
254 mpSharedBitmaps = mpBitmaps;
255 }
256 catch(Exception&)
257 {
258 OSL_ASSERT(false);
259 }
260 }
261 UpdateBitmaps();
262 UpdateBorders();
263 }
264
265 Repaint(GetRectangle(Total), false);
266 }
267
SetBackground(const SharedBitmapDescriptor & rpBackgroundBitmap)268 void PresenterScrollBar::SetBackground (const SharedBitmapDescriptor& rpBackgroundBitmap)
269 {
270 mpBackgroundBitmap = rpBackgroundBitmap;
271 }
272
CheckValues()273 void PresenterScrollBar::CheckValues()
274 {
275 mnThumbPosition = ValidateThumbPosition(mnThumbPosition);
276 }
277
ValidateThumbPosition(double nPosition)278 double PresenterScrollBar::ValidateThumbPosition (double nPosition)
279 {
280 if (nPosition + mnThumbSize > mnTotalSize)
281 nPosition = mnTotalSize - mnThumbSize;
282 if (nPosition < 0)
283 nPosition = 0;
284 return nPosition;
285 }
286
Paint(const awt::Rectangle & rUpdateBox)287 void PresenterScrollBar::Paint (
288 const awt::Rectangle& rUpdateBox)
289 {
290 if ( ! mxCanvas.is() || ! mxWindow.is())
291 {
292 OSL_ASSERT(mxCanvas.is());
293 OSL_ASSERT(mxWindow.is());
294 return;
295 }
296
297 if (PresenterGeometryHelper::AreRectanglesDisjoint (rUpdateBox, mxWindow->getPosSize()))
298 return;
299
300 PaintBackground(rUpdateBox);
301 PaintComposite(rUpdateBox, PagerUp,
302 mpPagerStartDescriptor, mpPagerCenterDescriptor, SharedBitmapDescriptor());
303 PaintComposite(rUpdateBox, PagerDown,
304 SharedBitmapDescriptor(), mpPagerCenterDescriptor, mpPagerEndDescriptor);
305 PaintComposite(rUpdateBox, Thumb,
306 mpThumbStartDescriptor, mpThumbCenterDescriptor, mpThumbEndDescriptor);
307 PaintBitmap(rUpdateBox, PrevButton, mpPrevButtonDescriptor);
308 PaintBitmap(rUpdateBox, NextButton, mpNextButtonDescriptor);
309
310 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
311 if (xSpriteCanvas.is())
312 xSpriteCanvas->updateScreen(false);
313 }
314
315 //----- XWindowListener -------------------------------------------------------
316
windowResized(const css::awt::WindowEvent &)317 void SAL_CALL PresenterScrollBar::windowResized (const css::awt::WindowEvent&) {}
318
windowMoved(const css::awt::WindowEvent &)319 void SAL_CALL PresenterScrollBar::windowMoved (const css::awt::WindowEvent&) {}
320
windowShown(const css::lang::EventObject &)321 void SAL_CALL PresenterScrollBar::windowShown (const css::lang::EventObject&) {}
322
windowHidden(const css::lang::EventObject &)323 void SAL_CALL PresenterScrollBar::windowHidden (const css::lang::EventObject&) {}
324
325 //----- XPaintListener --------------------------------------------------------
326
windowPaint(const css::awt::PaintEvent & rEvent)327 void SAL_CALL PresenterScrollBar::windowPaint (const css::awt::PaintEvent& rEvent)
328 {
329 if (mxWindow.is())
330 {
331 awt::Rectangle aRepaintBox (rEvent.UpdateRect);
332 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
333 aRepaintBox.X += aWindowBox.X;
334 aRepaintBox.Y += aWindowBox.Y;
335 Paint(aRepaintBox);
336
337 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
338 if (xSpriteCanvas.is())
339 xSpriteCanvas->updateScreen(false);
340 }
341 }
342
343 //----- XMouseListener --------------------------------------------------------
344
mousePressed(const css::awt::MouseEvent & rEvent)345 void SAL_CALL PresenterScrollBar::mousePressed (const css::awt::MouseEvent& rEvent)
346 {
347 maDragAnchor.X = rEvent.X;
348 maDragAnchor.Y = rEvent.Y;
349 meButtonDownArea = GetArea(rEvent.X, rEvent.Y);
350
351 mpMousePressRepeater->Start(meButtonDownArea);
352 }
353
mouseReleased(const css::awt::MouseEvent &)354 void SAL_CALL PresenterScrollBar::mouseReleased (const css::awt::MouseEvent&)
355 {
356 mpMousePressRepeater->Stop();
357
358 if (mxPresenterHelper.is())
359 mxPresenterHelper->releaseMouse(mxWindow);
360 }
361
mouseEntered(const css::awt::MouseEvent &)362 void SAL_CALL PresenterScrollBar::mouseEntered (const css::awt::MouseEvent&) {}
363
mouseExited(const css::awt::MouseEvent &)364 void SAL_CALL PresenterScrollBar::mouseExited (const css::awt::MouseEvent&)
365 {
366 if (meMouseMoveArea != None)
367 {
368 const Area eOldMouseMoveArea (meMouseMoveArea);
369 meMouseMoveArea = None;
370 Repaint(GetRectangle(eOldMouseMoveArea), true);
371 }
372 meButtonDownArea = None;
373 meMouseMoveArea = None;
374
375 mpMousePressRepeater->Stop();
376 }
377
378 //----- XMouseMotionListener --------------------------------------------------
379
mouseMoved(const css::awt::MouseEvent & rEvent)380 void SAL_CALL PresenterScrollBar::mouseMoved (const css::awt::MouseEvent& rEvent)
381 {
382 const Area eArea (GetArea(rEvent.X, rEvent.Y));
383 if (eArea != meMouseMoveArea)
384 {
385 const Area eOldMouseMoveArea (meMouseMoveArea);
386 meMouseMoveArea = eArea;
387 if (eOldMouseMoveArea != None)
388 Repaint(GetRectangle(eOldMouseMoveArea), meMouseMoveArea==None);
389 if (meMouseMoveArea != None)
390 Repaint(GetRectangle(meMouseMoveArea), true);
391 }
392 mpMousePressRepeater->SetMouseArea(eArea);
393 }
394
mouseDragged(const css::awt::MouseEvent & rEvent)395 void SAL_CALL PresenterScrollBar::mouseDragged (const css::awt::MouseEvent& rEvent)
396 {
397 if (meButtonDownArea != Thumb)
398 return;
399
400 mpMousePressRepeater->Stop();
401
402 if (mxPresenterHelper.is())
403 mxPresenterHelper->captureMouse(mxWindow);
404
405 const double nDragDistance (GetDragDistance(rEvent.X,rEvent.Y));
406 UpdateDragAnchor(nDragDistance);
407 if (nDragDistance != 0)
408 {
409 SetThumbPosition(mnThumbPosition + nDragDistance, false);
410 }
411 }
412
413 //----- lang::XEventListener --------------------------------------------------
414
disposing(const css::lang::EventObject & rEvent)415 void SAL_CALL PresenterScrollBar::disposing (const css::lang::EventObject& rEvent)
416 {
417 if (rEvent.Source == mxWindow)
418 mxWindow = nullptr;
419 }
420
421
GetRectangle(const Area eArea) const422 geometry::RealRectangle2D const & PresenterScrollBar::GetRectangle (const Area eArea) const
423 {
424 OSL_ASSERT(eArea>=0 && eArea<AreaCount);
425
426 return maBox[eArea];
427 }
428
Repaint(const geometry::RealRectangle2D & rBox,const bool bAsynchronousUpdate)429 void PresenterScrollBar::Repaint (
430 const geometry::RealRectangle2D& rBox,
431 const bool bAsynchronousUpdate)
432 {
433 if (mpPaintManager != nullptr)
434 mpPaintManager->Invalidate(
435 mxWindow,
436 PresenterGeometryHelper::ConvertRectangle(rBox),
437 bAsynchronousUpdate);
438 }
439
PaintBackground(const css::awt::Rectangle & rUpdateBox)440 void PresenterScrollBar::PaintBackground(
441 const css::awt::Rectangle& rUpdateBox)
442 {
443 if (!mpBackgroundBitmap)
444 return;
445
446 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
447 mpCanvasHelper->Paint(
448 mpBackgroundBitmap,
449 mxCanvas,
450 rUpdateBox,
451 aWindowBox,
452 awt::Rectangle());
453 }
454
PaintBitmap(const css::awt::Rectangle & rUpdateBox,const Area eArea,const SharedBitmapDescriptor & rpBitmaps)455 void PresenterScrollBar::PaintBitmap(
456 const css::awt::Rectangle& rUpdateBox,
457 const Area eArea,
458 const SharedBitmapDescriptor& rpBitmaps)
459 {
460 const geometry::RealRectangle2D aLocalBox (GetRectangle(eArea));
461 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
462 geometry::RealRectangle2D aBox (aLocalBox);
463 aBox.X1 += aWindowBox.X;
464 aBox.Y1 += aWindowBox.Y;
465 aBox.X2 += aWindowBox.X;
466 aBox.Y2 += aWindowBox.Y;
467
468 Reference<rendering::XBitmap> xBitmap (GetBitmap(eArea,rpBitmaps));
469
470 if (!xBitmap.is())
471 return;
472
473 Reference<rendering::XPolyPolygon2D> xClipPolygon (
474 PresenterGeometryHelper::CreatePolygon(
475 PresenterGeometryHelper::Intersection(rUpdateBox,
476 PresenterGeometryHelper::ConvertRectangle(aBox)),
477 mxCanvas->getDevice()));
478
479 const rendering::ViewState aViewState (
480 geometry::AffineMatrix2D(1,0,0, 0,1,0),
481 xClipPolygon);
482
483 const geometry::IntegerSize2D aBitmapSize (xBitmap->getSize());
484 rendering::RenderState aRenderState (
485 geometry::AffineMatrix2D(
486 1,0,aBox.X1 + (aBox.X2-aBox.X1 - aBitmapSize.Width)/2,
487 0,1,aBox.Y1 + (aBox.Y2-aBox.Y1 - aBitmapSize.Height)/2),
488 nullptr,
489 Sequence<double>(4),
490 rendering::CompositeOperation::SOURCE);
491
492 mxCanvas->drawBitmap(
493 xBitmap,
494 aViewState,
495 aRenderState);
496 }
497
GetArea(const double nX,const double nY) const498 PresenterScrollBar::Area PresenterScrollBar::GetArea (const double nX, const double nY) const
499 {
500 const geometry::RealPoint2D aPoint(nX, nY);
501
502 if (PresenterGeometryHelper::IsInside(GetRectangle(Pager), aPoint))
503 {
504 if (PresenterGeometryHelper::IsInside(GetRectangle(Thumb), aPoint))
505 return Thumb;
506 else if (PresenterGeometryHelper::IsInside(GetRectangle(PagerUp), aPoint))
507 return PagerUp;
508 else if (PresenterGeometryHelper::IsInside(GetRectangle(PagerDown), aPoint))
509 return PagerDown;
510 }
511 else if (PresenterGeometryHelper::IsInside(GetRectangle(PrevButton), aPoint))
512 return PrevButton;
513 else if (PresenterGeometryHelper::IsInside(GetRectangle(NextButton), aPoint))
514 return NextButton;
515
516 return None;
517 }
518
UpdateWidthOrHeight(sal_Int32 & rSize,const SharedBitmapDescriptor & rpDescriptor)519 void PresenterScrollBar::UpdateWidthOrHeight (
520 sal_Int32& rSize,
521 const SharedBitmapDescriptor& rpDescriptor)
522 {
523 if (rpDescriptor)
524 {
525 Reference<rendering::XBitmap> xBitmap (rpDescriptor->GetNormalBitmap());
526 if (xBitmap.is())
527 {
528 const geometry::IntegerSize2D aBitmapSize (xBitmap->getSize());
529 const sal_Int32 nBitmapSize = static_cast<sal_Int32>(GetMinor(aBitmapSize.Width, aBitmapSize.Height));
530 if (nBitmapSize > rSize)
531 rSize = nBitmapSize;
532 }
533 }
534 }
535
GetBitmap(const Area eArea,const SharedBitmapDescriptor & rpBitmaps) const536 css::uno::Reference<css::rendering::XBitmap> PresenterScrollBar::GetBitmap (
537 const Area eArea,
538 const SharedBitmapDescriptor& rpBitmaps) const
539 {
540 if (!rpBitmaps)
541 return nullptr;
542 else
543 return rpBitmaps->GetBitmap(GetBitmapMode(eArea));
544 }
545
GetBitmapMode(const Area eArea) const546 PresenterBitmapContainer::BitmapDescriptor::Mode PresenterScrollBar::GetBitmapMode (
547 const Area eArea) const
548 {
549 if (IsDisabled(eArea))
550 return PresenterBitmapContainer::BitmapDescriptor::Disabled;
551 else if (eArea == meMouseMoveArea)
552 return PresenterBitmapContainer::BitmapDescriptor::MouseOver;
553 else
554 return PresenterBitmapContainer::BitmapDescriptor::Normal;
555 }
556
IsDisabled(const Area eArea) const557 bool PresenterScrollBar::IsDisabled (const Area eArea) const
558 {
559 OSL_ASSERT(eArea>=0 && eArea<AreaCount);
560
561 return ! maEnabledState[eArea];
562 }
563
564 //===== PresenterVerticalScrollBar ============================================
565
PresenterVerticalScrollBar(const Reference<XComponentContext> & rxComponentContext,const Reference<awt::XWindow> & rxParentWindow,const std::shared_ptr<PresenterPaintManager> & rpPaintManager,const::std::function<void (double)> & rThumbMotionListener)566 PresenterVerticalScrollBar::PresenterVerticalScrollBar (
567 const Reference<XComponentContext>& rxComponentContext,
568 const Reference<awt::XWindow>& rxParentWindow,
569 const std::shared_ptr<PresenterPaintManager>& rpPaintManager,
570 const ::std::function<void (double)>& rThumbMotionListener)
571 : PresenterScrollBar(rxComponentContext, rxParentWindow, rpPaintManager, rThumbMotionListener),
572 mnScrollBarWidth(0)
573 {
574 }
575
~PresenterVerticalScrollBar()576 PresenterVerticalScrollBar::~PresenterVerticalScrollBar()
577 {
578 }
579
GetDragDistance(const sal_Int32,const sal_Int32 nY) const580 double PresenterVerticalScrollBar::GetDragDistance (const sal_Int32, const sal_Int32 nY) const
581 {
582 const double nDistance (nY - maDragAnchor.Y);
583 if (nDistance == 0)
584 return 0;
585 else
586 {
587 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
588 const double nBarWidth (aWindowBox.Width);
589 const double nPagerHeight (aWindowBox.Height - 2*nBarWidth);
590 const double nDragDistance (mnTotalSize / nPagerHeight * nDistance);
591 if (nDragDistance + mnThumbPosition < 0)
592 return -mnThumbPosition;
593 else if (mnThumbPosition + nDragDistance > mnTotalSize-mnThumbSize)
594 return mnTotalSize-mnThumbSize-mnThumbPosition;
595 else
596 return nDragDistance;
597 }
598 }
599
UpdateDragAnchor(const double nDragDistance)600 void PresenterVerticalScrollBar::UpdateDragAnchor (const double nDragDistance)
601 {
602 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
603 const double nBarWidth (aWindowBox.Width);
604 const double nPagerHeight (aWindowBox.Height - 2*nBarWidth);
605 maDragAnchor.Y += nDragDistance * nPagerHeight / mnTotalSize;
606 }
607
GetSize() const608 sal_Int32 PresenterVerticalScrollBar::GetSize() const
609 {
610 return mnScrollBarWidth;
611 }
612
GetMinor(const double nX,const double) const613 double PresenterVerticalScrollBar::GetMinor (const double nX, const double) const
614 {
615 return nX;
616 }
617
UpdateBorders()618 void PresenterVerticalScrollBar::UpdateBorders()
619 {
620 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
621 double nBottom = aWindowBox.Height;
622
623 if (mpNextButtonDescriptor)
624 {
625 Reference<rendering::XBitmap> xBitmap (mpNextButtonDescriptor->GetNormalBitmap());
626 if (xBitmap.is())
627 {
628 geometry::IntegerSize2D aSize (xBitmap->getSize());
629 maBox[NextButton] = geometry::RealRectangle2D(
630 0, nBottom - aSize.Height, aWindowBox.Width, nBottom);
631 nBottom -= aSize.Height + gnScrollBarGap;
632 }
633 }
634 if (mpPrevButtonDescriptor)
635 {
636 Reference<rendering::XBitmap> xBitmap (mpPrevButtonDescriptor->GetNormalBitmap());
637 if (xBitmap.is())
638 {
639 geometry::IntegerSize2D aSize (xBitmap->getSize());
640 maBox[PrevButton] = geometry::RealRectangle2D(
641 0, nBottom - aSize.Height, aWindowBox.Width, nBottom);
642 nBottom -= aSize.Height + gnScrollBarGap;
643 }
644 }
645 const double nPagerHeight (nBottom);
646 maBox[Pager] = geometry::RealRectangle2D(
647 0,0, aWindowBox.Width, nBottom);
648 if (mnTotalSize < 1)
649 {
650 maBox[Thumb] = maBox[Pager];
651
652 // Set up the enabled/disabled states.
653 maEnabledState[PrevButton] = false;
654 maEnabledState[PagerUp] = false;
655 maEnabledState[NextButton] = false;
656 maEnabledState[PagerDown] = false;
657 maEnabledState[Thumb] = false;
658 }
659 else
660 {
661 const double nThumbSize = ::std::min(mnThumbSize,mnTotalSize);
662 const double nThumbPosition = ::std::clamp(mnThumbPosition, 0.0, mnTotalSize - nThumbSize);
663 maBox[Thumb] = geometry::RealRectangle2D(
664 0, nThumbPosition / mnTotalSize * nPagerHeight,
665 aWindowBox.Width,
666 (nThumbPosition+nThumbSize) / mnTotalSize * nPagerHeight);
667
668 // Set up the enabled/disabled states.
669 maEnabledState[PrevButton] = nThumbPosition>0;
670 maEnabledState[PagerUp] = nThumbPosition>0;
671 maEnabledState[NextButton] = nThumbPosition+nThumbSize < mnTotalSize;
672 maEnabledState[PagerDown] = nThumbPosition+nThumbSize < mnTotalSize;
673 maEnabledState[Thumb] = nThumbSize < mnTotalSize;
674 }
675 maBox[PagerUp] = geometry::RealRectangle2D(
676 maBox[Pager].X1, maBox[Pager].Y1, maBox[Pager].X2, maBox[Thumb].Y1-1);
677 maBox[PagerDown] = geometry::RealRectangle2D(
678 maBox[Pager].X1, maBox[Thumb].Y2+1, maBox[Pager].X2, maBox[Pager].Y2);
679 maBox[Total] = PresenterGeometryHelper::Union(
680 PresenterGeometryHelper::Union(maBox[PrevButton], maBox[NextButton]),
681 maBox[Pager]);
682 }
683
UpdateBitmaps()684 void PresenterVerticalScrollBar::UpdateBitmaps()
685 {
686 if (mpBitmaps == nullptr)
687 return;
688
689 mpPrevButtonDescriptor = mpBitmaps->GetBitmap("Up");
690 mpNextButtonDescriptor = mpBitmaps->GetBitmap("Down");
691 mpPagerStartDescriptor = mpBitmaps->GetBitmap("PagerTop");
692 mpPagerCenterDescriptor = mpBitmaps->GetBitmap("PagerVertical");
693 mpPagerEndDescriptor = mpBitmaps->GetBitmap("PagerBottom");
694 mpThumbStartDescriptor = mpBitmaps->GetBitmap("ThumbTop");
695 mpThumbCenterDescriptor = mpBitmaps->GetBitmap("ThumbVertical");
696 mpThumbEndDescriptor = mpBitmaps->GetBitmap("ThumbBottom");
697
698 mnScrollBarWidth = 0;
699 UpdateWidthOrHeight(mnScrollBarWidth, mpPrevButtonDescriptor);
700 UpdateWidthOrHeight(mnScrollBarWidth, mpNextButtonDescriptor);
701 UpdateWidthOrHeight(mnScrollBarWidth, mpPagerStartDescriptor);
702 UpdateWidthOrHeight(mnScrollBarWidth, mpPagerCenterDescriptor);
703 UpdateWidthOrHeight(mnScrollBarWidth, mpPagerEndDescriptor);
704 UpdateWidthOrHeight(mnScrollBarWidth, mpThumbStartDescriptor);
705 UpdateWidthOrHeight(mnScrollBarWidth, mpThumbCenterDescriptor);
706 UpdateWidthOrHeight(mnScrollBarWidth, mpThumbEndDescriptor);
707 if (mnScrollBarWidth == 0)
708 mnScrollBarWidth = 20;
709 }
710
PaintComposite(const css::awt::Rectangle & rUpdateBox,const Area eArea,const SharedBitmapDescriptor & rpStartBitmaps,const SharedBitmapDescriptor & rpCenterBitmaps,const SharedBitmapDescriptor & rpEndBitmaps)711 void PresenterVerticalScrollBar::PaintComposite(
712 const css::awt::Rectangle& rUpdateBox,
713 const Area eArea,
714 const SharedBitmapDescriptor& rpStartBitmaps,
715 const SharedBitmapDescriptor& rpCenterBitmaps,
716 const SharedBitmapDescriptor& rpEndBitmaps)
717 {
718 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
719 geometry::RealRectangle2D aBox (GetRectangle(eArea));
720 aBox.X1 += aWindowBox.X;
721 aBox.Y1 += aWindowBox.Y;
722 aBox.X2 += aWindowBox.X;
723 aBox.Y2 += aWindowBox.Y;
724
725 // Get bitmaps and sizes.
726
727 PresenterUIPainter::PaintVerticalBitmapComposite(
728 mxCanvas,
729 rUpdateBox,
730 (eArea == Thumb
731 ? PresenterGeometryHelper::ConvertRectangleWithConstantSize(aBox)
732 : PresenterGeometryHelper::ConvertRectangle(aBox)),
733 GetBitmap(eArea, rpStartBitmaps),
734 GetBitmap(eArea, rpCenterBitmaps),
735 GetBitmap(eArea, rpEndBitmaps));
736 }
737
738 //===== PresenterScrollBar::MousePressRepeater ================================
739
MousePressRepeater(const::rtl::Reference<PresenterScrollBar> & rpScrollBar)740 PresenterScrollBar::MousePressRepeater::MousePressRepeater (
741 const ::rtl::Reference<PresenterScrollBar>& rpScrollBar)
742 : mnMousePressRepeaterTaskId(PresenterTimer::NotAValidTaskId),
743 mpScrollBar(rpScrollBar),
744 meMouseArea(PresenterScrollBar::None)
745 {
746 }
747
Dispose()748 void PresenterScrollBar::MousePressRepeater::Dispose()
749 {
750 Stop();
751 mpScrollBar = nullptr;
752 }
753
Start(const PresenterScrollBar::Area & reArea)754 void PresenterScrollBar::MousePressRepeater::Start (const PresenterScrollBar::Area& reArea)
755 {
756 meMouseArea = reArea;
757
758 if (mnMousePressRepeaterTaskId == PresenterTimer::NotAValidTaskId)
759 {
760 // Execute key press operation at least this one time.
761 Execute();
762
763 // Schedule repeated executions.
764 auto pThis(shared_from_this());
765 mnMousePressRepeaterTaskId = PresenterTimer::ScheduleRepeatedTask (
766 mpScrollBar->GetComponentContext(),
767 [pThis] (TimeValue const&) { return pThis->Callback(); },
768 500000000,
769 250000000);
770 }
771 else
772 {
773 // There is already an active repeating task.
774 }
775 }
776
Stop()777 void PresenterScrollBar::MousePressRepeater::Stop()
778 {
779 if (mnMousePressRepeaterTaskId != PresenterTimer::NotAValidTaskId)
780 {
781 const sal_Int32 nTaskId (mnMousePressRepeaterTaskId);
782 mnMousePressRepeaterTaskId = PresenterTimer::NotAValidTaskId;
783 PresenterTimer::CancelTask(nTaskId);
784 }
785 }
786
SetMouseArea(const PresenterScrollBar::Area & reArea)787 void PresenterScrollBar::MousePressRepeater::SetMouseArea(const PresenterScrollBar::Area& reArea)
788 {
789 if (meMouseArea != reArea)
790 {
791 if (mnMousePressRepeaterTaskId != PresenterTimer::NotAValidTaskId)
792 {
793 Stop();
794 }
795 }
796 }
797
Callback()798 void PresenterScrollBar::MousePressRepeater::Callback ()
799 {
800 if (!mpScrollBar)
801 {
802 Stop();
803 return;
804 }
805
806 Execute();
807 }
808
Execute()809 void PresenterScrollBar::MousePressRepeater::Execute()
810 {
811 const double nThumbPosition (mpScrollBar->GetThumbPosition());
812 switch (meMouseArea)
813 {
814 case PrevButton:
815 mpScrollBar->SetThumbPosition(nThumbPosition - mpScrollBar->GetLineHeight(), true);
816 break;
817
818 case NextButton:
819 mpScrollBar->SetThumbPosition(nThumbPosition + mpScrollBar->GetLineHeight(), true);
820 break;
821
822 case PagerUp:
823 mpScrollBar->SetThumbPosition(nThumbPosition - mpScrollBar->GetThumbSize()*0.8, true);
824 break;
825
826 case PagerDown:
827 mpScrollBar->SetThumbPosition(nThumbPosition + mpScrollBar->GetThumbSize()*0.8, true);
828 break;
829
830 default:
831 break;
832 }
833 }
834
835 } // end of namespace ::sdext::presenter
836
837 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
838