aboutsummaryrefslogtreecommitdiff
path: root/src/ui/controls/scroll_control.hpp
blob: 84ebca30d14161b46f4de1598a5eff7bd6f2c3d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#pragma once

// ReSharper disable once CppUnusedIncludeDirective
#include "pre.hpp"

#include <optional>
#include <initializer_list>

#include "ui/control.hpp"

namespace cru::ui::controls
{
    // Done: OnMeasureContent
    // Done: OnLayoutContent
    // Done: HitTest(no need)
    // Done: Draw(no need)
    // Done: API
    // Done: ScrollBar
    // Done: MouseEvent
    class ScrollControl : public ContentControl
    {
    private:
        struct ScrollBarInfo
        {
            Rect border = Rect();
            Rect bar = Rect();
        };

        enum class Orientation
        {
            Horizontal,
            Vertical
        };

    public:
        enum class ScrollBarVisibility
        {
            None,
            Auto,
            Always
        };

        static ScrollControl* Create(Control* child = nullptr)
        {
            const auto control = new ScrollControl(true);
            control->SetChild(child);
            return control;
        }

        static constexpr auto control_type = L"ScrollControl";

    protected:
        explicit ScrollControl(bool container);
    public:
        ScrollControl(const ScrollControl& other) = delete;
        ScrollControl(ScrollControl&& other) = delete;
        ScrollControl& operator=(const ScrollControl& other) = delete;
        ScrollControl& operator=(ScrollControl&& other) = delete;
        ~ScrollControl() override;

        StringView GetControlType() const override final;

        bool IsHorizontalScrollEnabled() const
        {
            return horizontal_scroll_enabled_;
        }

        void SetHorizontalScrollEnabled(bool enable);

        bool IsVerticalScrollEnabled() const
        {
            return vertical_scroll_enabled_;
        }

        void SetVerticalScrollEnabled(bool enable);


        ScrollBarVisibility GetHorizontalScrollBarVisibility() const
        {
            return horizontal_scroll_bar_visibility_;
        }

        void SetHorizontalScrollBarVisibility(ScrollBarVisibility visibility);

        ScrollBarVisibility GetVerticalScrollBarVisibility() const
        {
            return vertical_scroll_bar_visibility_;
        }

        void SetVerticalScrollBarVisibility(ScrollBarVisibility visibility);

        float GetViewWidth() const
        {
            return view_width_;
        }

        float GetViewHeight() const
        {
            return view_height_;
        }

        float GetScrollOffsetX() const
        {
            return offset_x_;
        }

        float GetScrollOffsetY() const
        {
            return offset_y_;
        }

        // nullopt for not set. value is auto-coerced.
        void SetScrollOffset(std::optional<float> x, std::optional<float> y);

    protected:
        void SetViewWidth(float length);
        void SetViewHeight(float length);

        Size OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo& additional_info) override final;
        void OnLayoutContent(const Rect& rect, const AdditionalLayoutInfo& additional_info) override final;

        void OnRectChange(const Rect& old_rect, const Rect& new_rect) override;

    private:
        void CoerceAndSetOffsets(float offset_x, float offset_y, bool update_children = true);
        void UpdateScrollBarVisibility();
        void UpdateScrollBarBorderInfo();
        void UpdateScrollBarBarInfo();

    private:
        bool horizontal_scroll_enabled_ = true;
        bool vertical_scroll_enabled_ = true;

        ScrollBarVisibility horizontal_scroll_bar_visibility_ = ScrollBarVisibility::Auto;
        ScrollBarVisibility vertical_scroll_bar_visibility_ = ScrollBarVisibility::Auto;

        bool is_horizontal_scroll_bar_visible_ = false;
        bool is_vertical_scroll_bar_visible_ = false;

        float offset_x_ = 0.0f;
        float offset_y_ = 0.0f;

        float view_width_ = 0.0f;
        float view_height_ = 0.0f;

        ScrollBarInfo horizontal_bar_info_;
        ScrollBarInfo vertical_bar_info_;

        std::optional<Orientation> is_pressing_scroll_bar_ = std::nullopt;
        float pressing_delta_ = 0.0f;
    };
}