TermOx
banner.hpp
1 #ifndef TERMOX_WIDGET_WIDGETS_BANNER_HPP
2 #define TERMOX_WIDGET_WIDGETS_BANNER_HPP
3 #include <chrono>
4 #include <cstddef>
5 #include <memory>
6 #include <optional>
7 #include <utility>
8 #include <vector>
9 
10 #include <signals_light/signal.hpp>
11 
12 #include <termox/painter/glyph_string.hpp>
13 #include <termox/painter/painter.hpp>
14 #include <termox/widget/pipe.hpp>
15 #include <termox/widget/widget.hpp>
16 
17 namespace ox {
18 
20  std::size_t index;
21  int position;
22 };
23 
24 auto operator++(Index_and_position& x) -> Index_and_position&;
25 
26 class IP_range {
27  public:
28  using Iter_t = std::vector<Index_and_position>::const_iterator;
29 
30  public:
31  IP_range(Iter_t begin, Iter_t end);
32 
33  public:
34  [[nodiscard]] auto begin() const -> Iter_t;
35 
36  [[nodiscard]] auto end() const -> Iter_t;
37 
38  private:
39  Iter_t begin_;
40  Iter_t end_;
41 };
42 
44 template <typename Animator>
45 class Banner : public Widget {
46  public:
47  using Duration_t = std::chrono::milliseconds;
48 
49  struct Parameters {
50  Glyph_string text = U"";
51  Duration_t interval = Duration_t{50};
52  Animator animator = Animator{};
53  };
54 
55  public:
56  explicit Banner(Glyph_string text = U"",
57  Duration_t interval = std::chrono::milliseconds{50},
58  Animator animator = Animator{})
59  : text_{text}, interval_{interval}, animator_{animator}
60  {
61  *this | pipe::fixed_height(1);
62  animator_.start.connect([this] { this->start(); });
63  animator_.stop.connect([this] { this->stop(); });
64  }
65 
66  explicit Banner(Parameters p)
67  : Banner{std::move(p.text), std::move(p.interval),
68  std::move(p.animator)}
69  {}
70 
71  public:
72  void set_text(Glyph_string text)
73  {
74  this->stop();
75  text_ = std::move(text);
76  range_.reset();
77  animator_.set_text_length(text_.size());
78  this->update();
79  }
80 
81  [[nodiscard]] auto text() const noexcept -> Glyph_string const&
82  {
83  return text_;
84  }
85 
86  void set_interval(Duration_t interval)
87  {
88  auto const running = this->Widget::is_animated();
89  this->stop();
90  interval_ = interval;
91  if (running)
92  this->start();
93  }
94 
95  [[nodiscard]] auto interval() const noexcept -> Duration_t
96  {
97  return interval_;
98  }
99 
100  [[nodiscard]] auto animator() const noexcept -> Animator const&
101  {
102  return animator_;
103  }
104 
105  [[nodiscard]] auto animator() noexcept -> Animator& { return animator_; }
106 
107  protected:
108  auto paint_event(Painter& p) -> bool override
109  {
110  if (range_) {
111  for (auto const& x : *range_)
112  p.put(text_[x.index], {x.position, 0});
113  }
114  else
115  p.put(text_, {0, 0});
116  return Widget::paint_event(p);
117  }
118 
119  auto timer_event() -> bool override
120  {
121  range_ = animator_();
122  this->update();
123  return Widget::timer_event();
124  }
125 
126  auto resize_event(Area new_size, Area old_size) -> bool override
127  {
128  animator_.set_max_length(new_size.width);
129  return Widget::resize_event(new_size, old_size);
130  }
131 
132  private:
133  Glyph_string text_;
134  Duration_t interval_;
135  Animator animator_;
136  std::optional<IP_range> range_;
137 
138  private:
139  void start()
140  {
141  if (text_.size() == 0)
142  return;
143  this->enable_animation(interval_);
144  }
145 
146  void stop()
147  {
148  this->disable_animation();
149  range_.reset();
150  }
151 };
152 
154 template <typename Animator>
155 [[nodiscard]] auto banner(Glyph_string text = U"",
156  typename Banner<Animator>::Duration_t interval =
157  std::chrono::milliseconds{50},
158  Animator animator = Animator{})
159  -> std::unique_ptr<Banner<Animator>>
160 {
161  return std::make_unique<Banner<Animator>>(std::move(text), interval,
162  std::move(animator));
163 }
164 
166 template <typename Animator>
167 [[nodiscard]] auto banner(typename Banner<Animator>::Parameters p)
168  -> std::unique_ptr<Banner<Animator>>
169 {
170  return std::make_unique<Banner<Animator>>(std::move(p));
171 }
172 
173 } // namespace ox
174 
175 namespace ox::animator {
176 
178  public:
179  sl::Signal<void()> start;
180  sl::Signal<void()> stop;
181 
182  protected:
183  Animator_base();
184 
185  public:
186  void set_max_length(std::size_t x);
187 
188  void set_text_length(std::size_t x);
189 
190  protected:
191  [[nodiscard]] auto data() const -> std::vector<Index_and_position> const&;
192 
193  [[nodiscard]] auto data() -> std::vector<Index_and_position>&;
194 
196  void initialize_data();
197 
198  [[nodiscard]] auto max_length() const -> std::size_t;
199 
200  [[nodiscard]] auto text_length() const -> std::size_t;
201 
202  [[nodiscard]] auto is_started() const -> bool;
203 
204  [[nodiscard]] auto begin() -> std::vector<Index_and_position>::iterator;
205 
206  [[nodiscard]] auto begin() const
207  -> std::vector<Index_and_position>::const_iterator;
208 
209  [[nodiscard]] auto end() -> std::vector<Index_and_position>::iterator;
210 
211  [[nodiscard]] auto end() const
212  -> std::vector<Index_and_position>::const_iterator;
213 
214  private:
215  std::vector<Index_and_position> data_;
216  std::size_t max_length_;
217  std::size_t text_length_;
218  bool started_ = false;
219 };
220 
221 /* ------------------- Banner Animation Implementations ----------------------*/
222 
224 class Scan : public Animator_base {
225  public:
226  [[nodiscard]] auto operator()() -> IP_range;
227 
228  void set_text_length(std::size_t x);
229 
230  private:
231  std::size_t begin_;
232  std::size_t end_;
233  std::size_t hold_;
234 };
235 
238  public:
239  [[nodiscard]] auto operator()() -> IP_range;
240 
241  void set_text_length(std::size_t x);
242 
243  private:
244  std::size_t end_;
245 };
246 
248 class Random : public Animator_base {
249  public:
250  [[nodiscard]] auto operator()() -> IP_range;
251 
252  void set_text_length(std::size_t x);
253 
254  private:
255  std::size_t end_;
256 };
257 
258 class Scroll_base : public Animator_base {
259  public:
260  [[nodiscard]] auto operator()() -> IP_range;
261 
262  void set_text_length(std::size_t x);
263 
264  void set_max_length(std::size_t x);
265 
266  protected:
267  std::size_t begin_ = 0;
268  std::size_t hold_ = 0;
269 
270  private:
271  void reset_hold_length();
272 
273  private:
274  std::size_t hold_length_;
275 };
276 
278 class Scroll : public Scroll_base {
279  public:
280  void set_text_length(std::size_t x);
281 };
282 
285  public:
286  void set_text_length(std::size_t x);
287 
288  void set_max_length(std::size_t x);
289 
290  private:
291  [[nodiscard]] auto start_condition() const -> bool;
292 
293  [[nodiscard]] auto stop_condition() const -> bool;
294 
295  void stop_and_reset();
296 };
297 
299 class Unscramble : public Animator_base {
300  public:
301  [[nodiscard]] auto operator()() -> IP_range;
302 
303  void set_text_length(std::size_t x);
304 
305  private:
306  int sorted_to_;
307 
308  private:
309  void initialize_data();
310 };
311 
312 } // namespace ox::animator
313 
314 namespace ox {
315 
317 
319 [[nodiscard]] auto scan_banner(
320  Glyph_string text = U"",
321  Scan_banner::Duration_t interval = std::chrono::milliseconds{50},
322  animator::Scan animator = animator::Scan{}) -> std::unique_ptr<Scan_banner>;
323 
325 [[nodiscard]] auto scan_banner(Scan_banner::Parameters p)
326  -> std::unique_ptr<Scan_banner>;
327 
328 using Persistent_scan_banner = Banner<animator::Persistent_scan>;
329 
331 [[nodiscard]] auto persistent_scan_banner(
332  Glyph_string text = U"",
333  Persistent_scan_banner::Duration_t interval = std::chrono::milliseconds{50},
334  animator::Persistent_scan animator = animator::Persistent_scan{})
335  -> std::unique_ptr<Persistent_scan_banner>;
336 
338 [[nodiscard]] auto persistent_scan_banner(Persistent_scan_banner::Parameters p)
339  -> std::unique_ptr<Persistent_scan_banner>;
340 
341 using Random_banner = Banner<animator::Random>;
342 
344 [[nodiscard]] auto random_banner(
345  Glyph_string text = U"",
346  Random_banner::Duration_t interval = std::chrono::milliseconds{50},
347  animator::Random animator = animator::Random{})
348  -> std::unique_ptr<Random_banner>;
349 
351 [[nodiscard]] auto random_banner(Random_banner::Parameters p)
352  -> std::unique_ptr<Random_banner>;
353 
354 using Scroll_banner = Banner<animator::Scroll>;
355 
357 [[nodiscard]] auto scroll_banner(
358  Glyph_string text = U"",
359  Scroll_banner::Duration_t interval = std::chrono::milliseconds{50},
360  animator::Scroll animator = animator::Scroll{})
361  -> std::unique_ptr<Scroll_banner>;
362 
364 [[nodiscard]] auto scroll_banner(Scroll_banner::Parameters p)
365  -> std::unique_ptr<Scroll_banner>;
366 
367 using Conditional_scroll_banner = Banner<animator::Conditional_scroll>;
368 
370 [[nodiscard]] auto conditional_scroll_banner(
371  Glyph_string text = U"",
372  Conditional_scroll_banner::Duration_t interval =
373  std::chrono::milliseconds{50},
374  animator::Conditional_scroll animator = animator::Conditional_scroll{})
375  -> std::unique_ptr<Conditional_scroll_banner>;
376 
378 [[nodiscard]] auto conditional_scroll_banner(
379  Conditional_scroll_banner::Parameters p)
380  -> std::unique_ptr<Conditional_scroll_banner>;
381 
382 using Unscramble_banner = Banner<animator::Unscramble>;
383 
385 [[nodiscard]] auto unscramble_banner(
386  Glyph_string text = U"",
387  Unscramble_banner::Duration_t interval = std::chrono::milliseconds{50},
388  animator::Unscramble animator = animator::Unscramble{})
389  -> std::unique_ptr<Unscramble_banner>;
390 
392 [[nodiscard]] auto unscramble_banner(Unscramble_banner::Parameters p)
393  -> std::unique_ptr<Unscramble_banner>;
394 
395 } // namespace ox
396 #endif // TERMOX_WIDGET_WIDGETS_BANNER_HPP
Animated Text Line/Label.
Definition: banner.hpp:45
auto paint_event(Painter &p) -> bool override
Handles Paint_event objects.
Definition: banner.hpp:108
auto resize_event(Area new_size, Area old_size) -> bool override
Handles Resize_event objects.
Definition: banner.hpp:126
auto timer_event() -> bool override
Handles Timer_event objects.
Definition: banner.hpp:119
Holds a collection of Glyphs with a similar interface to std::string.
Definition: glyph_string.hpp:19
auto size() const -> int
Return the number of Glyphs in *this Glyph_string.
Definition: glyph_string.cpp:36
Definition: banner.hpp:26
Contains functions to paint Glyphs to a Widget's screen area.
Definition: painter.hpp:21
Definition: widget.hpp:31
virtual auto paint_event(Painter &p) -> bool
Handles Paint_event objects.
Definition: widget.cpp:248
virtual auto resize_event(Area new_size, Area old_size) -> bool
Handles Resize_event objects.
Definition: widget.cpp:224
void enable_animation(std::chrono::milliseconds interval)
Enable animation on this Widget.
Definition: widget.cpp:139
auto is_animated() const -> bool
Return true if this Widget has animation enabled.
Definition: widget.cpp:163
virtual auto timer_event() -> bool
Handles Timer_event objects.
Definition: widget.cpp:250
virtual void update()
Post a paint event to this Widget.
Definition: widget.cpp:110
void disable_animation()
Turn off animation, no more Timer_events will be sent to this Widget.
Definition: widget.cpp:155
Definition: banner.hpp:177
void initialize_data()
Incremented values, length of text.
Definition: banner.cpp:73
Same as Scroll if text length is longer that display length, else static.
Definition: banner.hpp:284
Left to right reveal of text, then hold.
Definition: banner.hpp:237
Random indices are chosed and displayed one at a time.
Definition: banner.hpp:248
Left to right reveal of text, hold, left to right clearing of text.
Definition: banner.hpp:224
Definition: banner.hpp:258
Holds, then scrolls from left to right, then restarts.
Definition: banner.hpp:278
Starts with scrambled text and sorts itself one Glyph at a time.
Definition: banner.hpp:299
Definition: banner.hpp:49
Definition: banner.hpp:19