TermOx
scrollbar.hpp
1 #ifndef TERMOX_WIDGET_WIDGETS_SCROLLBAR_HPP
2 #define TERMOX_WIDGET_WIDGETS_SCROLLBAR_HPP
3 #include <cstddef>
4 #include <memory>
5 
6 #include <signals_light/signal.hpp>
7 
8 #include <termox/painter/color.hpp>
9 #include <termox/painter/glyph.hpp>
10 #include <termox/painter/glyph_string.hpp>
11 #include <termox/widget/layouts/detail/linear_layout.hpp>
12 #include <termox/widget/layouts/horizontal.hpp>
13 #include <termox/widget/layouts/vertical.hpp>
14 #include <termox/widget/point.hpp>
15 #include <termox/widget/widget.hpp>
16 #include <termox/widget/widgets/button.hpp>
17 #include <termox/widget/widgets/textbox.hpp>
18 
19 namespace ox {
20 
22 
26 template <template <typename> typename Layout_t>
27 class Scrollbar : public Layout_t<Widget> {
28  public:
29  struct Parameters {
30  std::size_t size = 0;
31  std::size_t position = invalid_position;
32  };
33 
34  private:
35  class Middle : public Widget {
36  public:
38 
39  public:
40  static auto constexpr invalid_position = -1uL;
41 
42  public:
43  explicit Middle(std::size_t size = 0, std::size_t position = 0);
44 
45  explicit Middle(Parameters p);
46 
47  public:
48  void set_position(std::size_t p);
49 
50  void set_size(std::size_t s);
51 
52  void set_bar_fg(Color c);
53 
54  void set_bar_bg(Color c);
55 
57  [[nodiscard]] auto find_position_from_point(Point p) -> std::size_t;
58 
59  protected:
60  auto paint_event(Painter& p) -> bool override;
61 
62  auto resize_event(Area new_size, Area old_size) -> bool override;
63 
64  private:
65  static auto constexpr is_vertical =
66  layout::is_vertical_v<Layout_t<Widget>>;
67 
68  private:
69  std::size_t size_;
70  std::size_t position_;
71 
72  Glyph bar_ = is_vertical ? U'█' : U'▬';
73 
74  int slider_position_;
75  std::size_t slider_length_;
76 
77  private:
78  void update_length_and_position();
79 
80  [[nodiscard]] auto max_length() const -> std::size_t;
81  };
82 
83  public:
84  static auto constexpr invalid_position = -1uL;
85 
86  public:
87  Button& decrement_btn =
88  this->template make_child<Button>(Glyph_string{top_symbol_});
89 
90  Middle& middle = this->template make_child<Middle>({0, invalid_position});
91 
92  Button& increment_btn =
93  this->template make_child<Button>(Glyph_string{bottom_symbol_});
94 
95  public:
96  sl::Signal<void(std::size_t)> new_position;
97  sl::Signal<void()> decremented;
98  sl::Signal<void()> incremented;
99 
100  public:
101  explicit Scrollbar(std::size_t size = 0,
102  std::size_t position = invalid_position);
103 
104  explicit Scrollbar(Parameters p);
105 
106  public:
107  [[nodiscard]] auto get_size() const -> std::size_t;
108 
109  void set_size(std::size_t s);
110 
111  void increment_size();
112 
113  void decrement_size();
114 
115  [[nodiscard]] auto get_position() const -> std::size_t;
116 
117  void set_position(std::size_t p);
118 
119  void decrement_position();
120 
121  void increment_position();
122 
124  auto handle_wheel(Mouse::Button button) -> bool;
125 
126  protected:
127  auto mouse_wheel_event_filter(Widget&, Mouse const& m) -> bool override;
128 
129  auto mouse_press_event_filter(Widget& w, Mouse const& m) -> bool override;
130 
131  auto mouse_move_event_filter(Widget& w, Mouse const& m) -> bool override;
132 
133  private:
134  std::size_t size_;
135  std::size_t position_;
136 
137  private:
138  static auto constexpr is_vertical = layout::is_vertical_v<Layout_t<Widget>>;
139  static auto constexpr top_symbol_ = is_vertical ? U'▴' : U'◂';
140  static auto constexpr bottom_symbol_ = is_vertical ? U'▾' : U'▸';
141 };
142 
144 template <template <typename> typename Layout_t>
145 [[nodiscard]] auto scrollbar(
146  std::size_t size = 0,
147  std::size_t position = Scrollbar<Layout_t>::invalid_position)
148  -> std::unique_ptr<Scrollbar<Layout_t>>;
149 
151 template <template <typename> typename Layout_t>
152 [[nodiscard]] auto scrollbar(typename Scrollbar<Layout_t>::Parameters p)
153  -> std::unique_ptr<Scrollbar<Layout_t>>;
154 
155 using HScrollbar = Scrollbar<layout::Horizontal>;
156 
158 [[nodiscard]] auto hscrollbar(
159  std::size_t size = 0,
160  std::size_t position = HScrollbar::invalid_position)
161  -> std::unique_ptr<HScrollbar>;
162 
164 [[nodiscard]] auto hscrollbar(HScrollbar::Parameters p)
165  -> std::unique_ptr<HScrollbar>;
166 
167 using VScrollbar = Scrollbar<layout::Vertical>;
168 
170 [[nodiscard]] auto vscrollbar(
171  std::size_t size = 0,
172  std::size_t position = VScrollbar::invalid_position)
173  -> std::unique_ptr<VScrollbar>;
174 
176 [[nodiscard]] auto vscrollbar(VScrollbar::Parameters p)
177  -> std::unique_ptr<VScrollbar>;
178 
180 template <template <typename> typename Layout_t,
181  typename Child,
182  typename Parameters>
183 void link(Scrollbar<Layout_t>& scrollbar,
184  layout::detail::Linear_layout<Child, Parameters>& layout,
185  bool hijack_scroll = true)
186 {
187  scrollbar.set_size(layout.child_count());
188 
189  scrollbar.new_position.connect([&](std::size_t p) {
190  if (p < layout.child_count())
191  layout.set_child_offset(p);
192  });
193 
194  layout.child_added.connect([&](auto&) { scrollbar.increment_size(); });
195  layout.child_removed.connect([&](auto&) { scrollbar.decrement_size(); });
196  if (hijack_scroll) {
197  layout.child_added.connect([&](auto& child) {
198  child.install_event_filter(scrollbar);
199  for (Widget* descendant : child.get_descendants())
200  descendant->install_event_filter(scrollbar);
201  });
202  scrollbar.mouse_wheel_scrolled_filter.connect(
203  [&](auto&, auto const& mouse) {
204  return scrollbar.handle_wheel(mouse.button);
205  });
206  layout.mouse_wheel_scrolled.connect(
207  [&](auto const& mouse) { scrollbar.handle_wheel(mouse.button); });
208  }
209 }
210 
212 template <template <typename> typename Layout_t>
213 void link(Scrollbar<Layout_t>& scrollbar, Textbox& textbox);
214 
215 } // namespace ox
216 #endif // TERMOX_WIDGET_WIDGETS_SCROLLBAR_HPP
Button widget that emits Signal on a left mouse button press.
Definition: button.hpp:18
Color numbers [0 - 180] are valid.
Definition: color.hpp:16
Holds a collection of Glyphs with a similar interface to std::string.
Definition: glyph_string.hpp:19
Contains functions to paint Glyphs to a Widget's screen area.
Definition: painter.hpp:21
Scrollbar to display progress through some structure, and control progress.
Definition: scrollbar.hpp:27
auto handle_wheel(Mouse::Button button) -> bool
Returns true if button was a scoll wheel button.
Definition: scrollbar.cpp:279
Definition: widget.hpp:31
Holds a description of a paintable tile on the screen.
Definition: glyph.hpp:11
Definition: scrollbar.hpp:29