2 * Copyright 2012, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
6 * Marc Flerackers (mflerackers@androme.be)
7 * Stefano Ceccherini (stefano.ceccherini@gmail.com)
8 * John Scipione (jscipione@gmail.com)
12 #include "InlineScrollView.h"
14 #include <ControlLook.h>
16 #include <InterfaceDefs.h>
23 const int kDefaultScrollStep
= 19;
24 const int kScrollerDimension
= 12;
27 class ScrollArrow
: public BView
{
29 ScrollArrow(BRect frame
);
30 virtual ~ScrollArrow();
32 bool IsEnabled() const { return fEnabled
; };
33 void SetEnabled(bool enabled
);
40 class UpScrollArrow
: public ScrollArrow
{
42 UpScrollArrow(BRect frame
);
43 virtual ~UpScrollArrow();
45 virtual void Draw(BRect updateRect
);
46 virtual void MouseDown(BPoint where
);
50 class DownScrollArrow
: public ScrollArrow
{
52 DownScrollArrow(BRect frame
);
53 virtual ~DownScrollArrow();
55 virtual void Draw(BRect updateRect
);
56 virtual void MouseDown(BPoint where
);
60 class LeftScrollArrow
: public ScrollArrow
{
62 LeftScrollArrow(BRect frame
);
63 virtual ~LeftScrollArrow();
65 virtual void Draw(BRect updateRect
);
66 virtual void MouseDown(BPoint where
);
70 class RightScrollArrow
: public ScrollArrow
{
72 RightScrollArrow(BRect frame
);
73 virtual ~RightScrollArrow();
75 virtual void Draw(BRect updateRect
);
76 virtual void MouseDown(BPoint where
);
83 ScrollArrow::ScrollArrow(BRect frame
)
85 BView(frame
, "menu scroll arrow", B_FOLLOW_NONE
, B_WILL_DRAW
),
88 SetViewUIColor(B_MENU_BACKGROUND_COLOR
);
92 ScrollArrow::~ScrollArrow()
98 ScrollArrow::SetEnabled(bool enabled
)
108 UpScrollArrow::UpScrollArrow(BRect frame
)
115 UpScrollArrow::~UpScrollArrow()
121 UpScrollArrow::Draw(BRect updateRect
)
123 SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR
),
127 SetHighColor(0, 0, 0);
129 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR
),
133 FillRect(Bounds(), B_SOLID_LOW
);
135 float middle
= Bounds().right
/ 2;
136 FillTriangle(BPoint(middle
, (kScrollerDimension
/ 2) - 3),
137 BPoint(middle
+ 5, (kScrollerDimension
/ 2) + 2),
138 BPoint(middle
- 5, (kScrollerDimension
/ 2) + 2));
143 UpScrollArrow::MouseDown(BPoint where
)
148 TInlineScrollView
* parent
= dynamic_cast<TInlineScrollView
*>(Parent());
154 parent
->GetSteps(&smallStep
, &largeStep
);
156 BMessage
* message
= Window()->CurrentMessage();
158 message
->FindInt32("modifiers", &modifiers
);
159 // pressing the shift key scrolls faster
160 if ((modifiers
& B_SHIFT_KEY
) != 0)
161 parent
->ScrollBy(-largeStep
);
163 parent
->ScrollBy(-smallStep
);
172 DownScrollArrow::DownScrollArrow(BRect frame
)
179 DownScrollArrow::~DownScrollArrow()
185 DownScrollArrow::Draw(BRect updateRect
)
187 SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR
),
191 SetHighColor(0, 0, 0);
193 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR
),
197 BRect frame
= Bounds();
198 FillRect(frame
, B_SOLID_LOW
);
200 float middle
= Bounds().right
/ 2;
201 FillTriangle(BPoint(middle
, frame
.bottom
- (kScrollerDimension
/ 2) + 3),
202 BPoint(middle
+ 5, frame
.bottom
- (kScrollerDimension
/ 2) - 2),
203 BPoint(middle
- 5, frame
.bottom
- (kScrollerDimension
/ 2) - 2));
208 DownScrollArrow::MouseDown(BPoint where
)
213 TInlineScrollView
* grandparent
214 = dynamic_cast<TInlineScrollView
*>(Parent()->Parent());
215 if (grandparent
== NULL
)
220 grandparent
->GetSteps(&smallStep
, &largeStep
);
222 BMessage
* message
= Window()->CurrentMessage();
224 message
->FindInt32("modifiers", &modifiers
);
225 // pressing the shift key scrolls faster
226 if ((modifiers
& B_SHIFT_KEY
) != 0)
227 grandparent
->ScrollBy(largeStep
);
229 grandparent
->ScrollBy(smallStep
);
238 LeftScrollArrow::LeftScrollArrow(BRect frame
)
245 LeftScrollArrow::~LeftScrollArrow()
251 LeftScrollArrow::Draw(BRect updateRect
)
253 SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR
), B_DARKEN_1_TINT
));
256 SetHighColor(0, 0, 0);
258 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR
),
262 FillRect(Bounds(), B_SOLID_LOW
);
264 float middle
= Bounds().bottom
/ 2;
265 FillTriangle(BPoint((kScrollerDimension
/ 2) - 3, middle
),
266 BPoint((kScrollerDimension
/ 2) + 2, middle
+ 5),
267 BPoint((kScrollerDimension
/ 2) + 2, middle
- 5));
272 LeftScrollArrow::MouseDown(BPoint where
)
277 TInlineScrollView
* parent
= dynamic_cast<TInlineScrollView
*>(Parent());
283 parent
->GetSteps(&smallStep
, &largeStep
);
285 BMessage
* message
= Window()->CurrentMessage();
287 message
->FindInt32("modifiers", &modifiers
);
288 // pressing the shift key scrolls faster
289 if ((modifiers
& B_SHIFT_KEY
) != 0)
290 parent
->ScrollBy(-largeStep
);
292 parent
->ScrollBy(-smallStep
);
301 RightScrollArrow::RightScrollArrow(BRect frame
)
308 RightScrollArrow::~RightScrollArrow()
314 RightScrollArrow::Draw(BRect updateRect
)
316 SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR
), B_DARKEN_1_TINT
));
319 SetHighColor(0, 0, 0);
321 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR
),
325 BRect frame
= Bounds();
326 FillRect(frame
, B_SOLID_LOW
);
328 float middle
= Bounds().bottom
/ 2;
329 FillTriangle(BPoint(kScrollerDimension
/ 2 + 3, middle
),
330 BPoint(kScrollerDimension
/ 2 - 2, middle
+ 5),
331 BPoint(kScrollerDimension
/ 2 - 2, middle
- 5));
336 RightScrollArrow::MouseDown(BPoint where
)
341 TInlineScrollView
* grandparent
342 = dynamic_cast<TInlineScrollView
*>(Parent()->Parent());
343 if (grandparent
== NULL
)
348 grandparent
->GetSteps(&smallStep
, &largeStep
);
350 BMessage
* message
= Window()->CurrentMessage();
352 message
->FindInt32("modifiers", &modifiers
);
353 // pressing the shift key scrolls faster
354 if ((modifiers
& B_SHIFT_KEY
) != 0)
355 grandparent
->ScrollBy(largeStep
);
357 grandparent
->ScrollBy(smallStep
);
366 TInlineScrollView::TInlineScrollView(BView
* target
,
367 enum orientation orientation
)
369 BView(BRect(0, 0, 0, 0), "inline scroll view", B_FOLLOW_NONE
, B_WILL_DRAW
),
371 fBeginScrollArrow(NULL
),
372 fEndScrollArrow(NULL
),
373 fScrollStep(kDefaultScrollStep
),
376 fOrientation(orientation
)
381 TInlineScrollView::~TInlineScrollView()
383 if (fBeginScrollArrow
!= NULL
) {
384 fBeginScrollArrow
->RemoveSelf();
385 delete fBeginScrollArrow
;
386 fBeginScrollArrow
= NULL
;
389 if (fEndScrollArrow
!= NULL
) {
390 fEndScrollArrow
->RemoveSelf();
391 delete fEndScrollArrow
;
392 fEndScrollArrow
= NULL
;
398 TInlineScrollView::AttachedToWindow()
400 BView::AttachedToWindow();
406 fTarget
->MoveTo(0, 0);
411 TInlineScrollView::DetachedFromWindow()
413 BView::DetachedFromWindow();
416 fTarget
->RemoveSelf();
418 if (fBeginScrollArrow
!= NULL
)
419 fBeginScrollArrow
->RemoveSelf();
421 if (fEndScrollArrow
!= NULL
)
422 fEndScrollArrow
->RemoveSelf();
427 TInlineScrollView::Draw(BRect updateRect
)
429 BRect frame
= Bounds();
430 be_control_look
->DrawButtonBackground(this, frame
, updateRect
,
431 ui_color(B_MENU_BACKGROUND_COLOR
));
439 TInlineScrollView::AttachScrollers()
444 BRect frame
= Bounds();
446 if (HasScrollers()) {
447 if (fOrientation
== B_VERTICAL
) {
448 fScrollLimit
= fTarget
->Bounds().Height()
449 - (frame
.Height() - 2 * kScrollerDimension
);
451 fScrollLimit
= fTarget
->Bounds().Width()
452 - (frame
.Width() - 2 * kScrollerDimension
);
455 if (fScrollValue
> fScrollLimit
) {
456 // If scroll value is above limit scroll back
457 float delta
= fScrollLimit
- fScrollValue
;
458 if (fOrientation
== B_VERTICAL
)
459 fTarget
->ScrollBy(0, delta
);
461 fTarget
->ScrollBy(delta
, 0);
463 fScrollValue
= fScrollLimit
;
468 fTarget
->MakeFocus(true);
470 if (fOrientation
== B_VERTICAL
) {
471 if (fBeginScrollArrow
== NULL
) {
472 fBeginScrollArrow
= new UpScrollArrow(
473 BRect(frame
.left
, frame
.top
, frame
.right
,
474 kScrollerDimension
- 1));
475 AddChild(fBeginScrollArrow
);
478 if (fEndScrollArrow
== NULL
) {
479 fEndScrollArrow
= new DownScrollArrow(
480 BRect(0, frame
.bottom
- 2 * kScrollerDimension
+ 1, frame
.right
,
481 frame
.bottom
- kScrollerDimension
));
482 fTarget
->AddChild(fEndScrollArrow
);
485 fTarget
->MoveBy(0, kScrollerDimension
);
487 fScrollLimit
= fTarget
->Bounds().Height()
488 - (frame
.Height() - 2 * kScrollerDimension
);
490 if (fBeginScrollArrow
== NULL
) {
491 fBeginScrollArrow
= new LeftScrollArrow(
492 BRect(frame
.left
, frame
.top
,
493 frame
.left
+ kScrollerDimension
- 1, frame
.bottom
));
494 AddChild(fBeginScrollArrow
);
497 if (fEndScrollArrow
== NULL
) {
498 fEndScrollArrow
= new RightScrollArrow(
499 BRect(frame
.right
- 2 * kScrollerDimension
+ 1, frame
.top
,
500 frame
.right
, frame
.bottom
));
501 fTarget
->AddChild(fEndScrollArrow
);
504 fTarget
->MoveBy(kScrollerDimension
, 0);
506 fScrollLimit
= fTarget
->Bounds().Width()
507 - (frame
.Width() - 2 * kScrollerDimension
);
510 fBeginScrollArrow
->SetEnabled(false);
511 fEndScrollArrow
->SetEnabled(true);
518 TInlineScrollView::DetachScrollers()
523 if (fEndScrollArrow
) {
524 fEndScrollArrow
->RemoveSelf();
525 delete fEndScrollArrow
;
526 fEndScrollArrow
= NULL
;
529 if (fBeginScrollArrow
) {
530 fBeginScrollArrow
->RemoveSelf();
531 delete fBeginScrollArrow
;
532 fBeginScrollArrow
= NULL
;
536 // We don't remember the position where the last scrolling
537 // ended, so scroll back to the beginning.
538 if (fOrientation
== B_VERTICAL
)
539 fTarget
->MoveBy(0, -kScrollerDimension
);
541 fTarget
->MoveBy(-kScrollerDimension
, 0);
543 fTarget
->ScrollTo(0, 0);
550 TInlineScrollView::HasScrollers() const
552 return fTarget
!= NULL
&& fBeginScrollArrow
!= NULL
553 && fEndScrollArrow
!= NULL
;
558 TInlineScrollView::SetSmallStep(float step
)
565 TInlineScrollView::GetSteps(float* _smallStep
, float* _largeStep
) const
567 if (_smallStep
!= NULL
)
568 *_smallStep
= fScrollStep
;
569 if (_largeStep
!= NULL
) {
570 *_largeStep
= fScrollStep
* 3;
576 TInlineScrollView::ScrollBy(const float& step
)
582 if (fScrollValue
== 0)
583 fBeginScrollArrow
->SetEnabled(true);
585 if (fScrollValue
+ step
>= fScrollLimit
) {
586 // If we reached the limit, only scroll to the end
587 if (fOrientation
== B_VERTICAL
) {
588 fTarget
->ScrollBy(0, fScrollLimit
- fScrollValue
);
589 fEndScrollArrow
->MoveBy(0, fScrollLimit
- fScrollValue
);
591 fTarget
->ScrollBy(fScrollLimit
- fScrollValue
, 0);
592 fEndScrollArrow
->MoveBy(fScrollLimit
- fScrollValue
, 0);
594 fEndScrollArrow
->SetEnabled(false);
595 fScrollValue
= fScrollLimit
;
597 if (fOrientation
== B_VERTICAL
) {
598 fTarget
->ScrollBy(0, step
);
599 fEndScrollArrow
->MoveBy(0, step
);
601 fTarget
->ScrollBy(step
, 0);
602 fEndScrollArrow
->MoveBy(step
, 0);
604 fScrollValue
+= step
;
606 } else if (step
< 0) {
607 if (fScrollValue
== fScrollLimit
)
608 fEndScrollArrow
->SetEnabled(true);
610 if (fScrollValue
+ step
<= 0) {
611 if (fOrientation
== B_VERTICAL
) {
612 fTarget
->ScrollBy(0, -fScrollValue
);
613 fEndScrollArrow
->MoveBy(0, -fScrollValue
);
615 fTarget
->ScrollBy(-fScrollValue
, 0);
616 fEndScrollArrow
->MoveBy(-fScrollValue
, 0);
618 fBeginScrollArrow
->SetEnabled(false);
621 if (fOrientation
== B_VERTICAL
) {
622 fTarget
->ScrollBy(0, step
);
623 fEndScrollArrow
->MoveBy(0, step
);
625 fTarget
->ScrollBy(step
, 0);
626 fEndScrollArrow
->MoveBy(step
, 0);
628 fScrollValue
+= step
;
632 //fTarget->Invalidate();