Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include <AK/Function.h>
30#include <LibGUI/Widget.h>
31
32namespace GUI {
33
34class ScrollBar final : public Widget {
35 C_OBJECT(ScrollBar)
36public:
37 virtual ~ScrollBar() override;
38
39 Gfx::Orientation orientation() const { return m_orientation; }
40
41 bool is_scrollable() const { return max() != min(); }
42
43 int value() const { return m_value; }
44 int min() const { return m_min; }
45 int max() const { return m_max; }
46 int step() const { return m_step; }
47 int big_step() const { return m_big_step; }
48
49 void set_min(int min) { set_range(min, max()); }
50 void set_max(int max) { set_range(min(), max); }
51 void set_range(int min, int max);
52 void set_value(int value);
53 void set_step(int step) { m_step = step; }
54 void set_big_step(int big_step) { m_big_step = big_step; }
55 bool has_scrubber() const;
56
57 Function<void(int)> on_change;
58
59 enum Component {
60 Invalid,
61 DecrementButton,
62 IncrementButton,
63 Gutter,
64 Scrubber,
65 };
66
67private:
68 explicit ScrollBar(Gfx::Orientation = Gfx::Orientation::Vertical);
69
70 virtual void paint_event(PaintEvent&) override;
71 virtual void mousedown_event(MouseEvent&) override;
72 virtual void mouseup_event(MouseEvent&) override;
73 virtual void mousemove_event(MouseEvent&) override;
74 virtual void mousewheel_event(MouseEvent&) override;
75 virtual void leave_event(Core::Event&) override;
76 virtual void change_event(Event&) override;
77
78 int default_button_size() const { return 16; }
79 int button_size() const { return length(orientation()) <= (default_button_size() * 2) ? length(orientation()) / 2 : default_button_size(); }
80 int button_width() const { return orientation() == Orientation::Vertical ? width() : button_size(); }
81 int button_height() const { return orientation() == Orientation::Horizontal ? height() : button_size(); }
82 Gfx::Rect decrement_button_rect() const;
83 Gfx::Rect increment_button_rect() const;
84 Gfx::Rect decrement_gutter_rect() const;
85 Gfx::Rect increment_gutter_rect() const;
86 Gfx::Rect scrubber_rect() const;
87 int scrubber_size() const;
88 int scrubbable_range_in_pixels() const;
89 void on_automatic_scrolling_timer_fired();
90 void set_automatic_scrolling_active(bool);
91
92 int m_min { 0 };
93 int m_max { 0 };
94 int m_value { 0 };
95 int m_step { 1 };
96 int m_big_step { 5 };
97
98 bool m_scrubbing { false };
99 int m_scrub_start_value { 0 };
100 Gfx::Point m_scrub_origin;
101
102 Gfx::Orientation m_orientation { Gfx::Orientation::Vertical };
103 Component m_hovered_component { Component::Invalid };
104 bool m_scrubber_in_use { false };
105
106 enum class AutomaticScrollingDirection {
107 None = 0,
108 Decrement,
109 Increment,
110 };
111
112 AutomaticScrollingDirection m_automatic_scrolling_direction { AutomaticScrollingDirection::None };
113 RefPtr<Core::Timer> m_automatic_scrolling_timer;
114};
115
116}