TermOx
pipe.hpp
1 #ifndef TERMOX_WIDGET_PIPE_HPP
2 #define TERMOX_WIDGET_PIPE_HPP
3 #include <chrono>
4 #include <cstddef>
5 #include <memory>
6 #include <string>
7 #include <type_traits>
8 #include <utility>
9 #include <vector>
10 
11 #include <termox/common/filter_iterator.hpp>
12 #include <termox/common/overload.hpp>
13 #include <termox/common/range.hpp>
14 #include <termox/common/transform_iterator.hpp>
15 #include <termox/painter/glyph_string.hpp>
16 #include <termox/system/system.hpp>
17 #include <termox/widget/align.hpp>
18 #include <termox/widget/bordered.hpp>
19 #include <termox/widget/detail/pipe_utility.hpp>
20 #include <termox/widget/focus_policy.hpp>
21 #include <termox/widget/growth.hpp>
22 #include <termox/widget/point.hpp>
23 #include <termox/widget/widget.hpp>
24 #include <termox/widget/wrap.hpp>
25 #include "termox/widget/size_policy.hpp"
26 
27 namespace ox::pipe {
28 
29 // Widget Accessors ------------------------------------------------------------
31 [[nodiscard]] inline auto children()
32 {
33  return [](auto&& w) {
34  auto c = get(w).get_children();
35  return Range{c.begin(), c.end()};
36  };
37 }
38 
40 [[nodiscard]] inline auto descendants()
41 {
42  return [](auto&& w) { return get(w).get_descendants(); };
43 }
44 
45 // Generic Tools ---------------------------------------------------------------
46 template <typename F>
47 [[nodiscard]] auto for_each(F&& f)
48 {
49  return [&](auto&& w) -> decltype(auto) {
50  std::forward<F>(f)(get(w));
51  return std::forward<decltype(w)>(w);
52  };
53 }
54 
56 template <typename F>
57 [[nodiscard]] auto filter(F&& predicate)
58 {
59  return pipe::detail::Filter_predicate{predicate};
60 }
61 
63 [[nodiscard]] inline auto find(std::string const& name)
64 {
65  return pipe::detail::Filter_predicate{
66  [=](auto const& w) { return w.name() == name; }};
67 }
68 
70 template <typename Widget_t>
71 [[nodiscard]] auto filter()
72 {
73  return pipe::detail::Dynamic_filter_predicate<Widget_t>{};
74 }
75 
76 // Widget Modifiers ------------------------------------------------------------
77 [[nodiscard]] inline auto name(std::string const& name)
78 {
79  return [=](auto&& w) -> decltype(auto) {
80  get(w).set_name(std::move(name));
81  return std::forward<decltype(w)>(w);
82  };
83 }
84 
85 [[nodiscard]] inline auto install_filter(Widget& filter)
86 {
87  return [&](auto&& w) -> decltype(auto) {
88  get(w).install_event_filter(filter);
89  return std::forward<decltype(w)>(w);
90  };
91 }
92 
93 [[nodiscard]] inline auto remove_filter(Widget& filter)
94 {
95  return [&](auto&& w) -> decltype(auto) {
96  get(w).remove_event_filter(filter);
97  return std::forward<decltype(w)>(w);
98  };
99 }
100 
101 [[nodiscard]] inline auto animate(std::chrono::milliseconds interval)
102 {
103  return [=](auto&& w) -> decltype(auto) {
104  get(w).enable_animation(interval);
105  return std::forward<decltype(w)>(w);
106  };
107 }
108 
109 [[nodiscard]] inline auto animate(FPS fps)
110 {
111  return [=](auto&& w) -> decltype(auto) {
112  get(w).enable_animation(fps);
113  return std::forward<decltype(w)>(w);
114  };
115 }
116 
117 [[nodiscard]] inline auto disanimate()
118 {
119  return [](auto&& w) -> decltype(auto) {
120  get(w).disable_animation();
121  return std::forward<decltype(w)>(w);
122  };
123 }
124 
125 // Wallpaper Modifiers ---------------------------------------------------------
126 [[nodiscard]] inline auto wallpaper(Glyph g)
127 {
128  return [=](auto&& w) -> decltype(auto) {
129  get(w).set_wallpaper(g);
130  return std::forward<decltype(w)>(w);
131  };
132 }
133 
134 [[nodiscard]] inline auto wallpaper_with_brush()
135 {
136  return [](auto&& w) -> decltype(auto) {
137  get(w).paint_wallpaper_with_brush(true);
138  return std::forward<decltype(w)>(w);
139  };
140 }
141 
142 [[nodiscard]] inline auto wallpaper_without_brush()
143 {
144  return [](auto&& w) -> decltype(auto) {
145  get(w).paint_wallpaper_with_brush(false);
146  return std::forward<decltype(w)>(w);
147  };
148 }
149 
150 } // namespace ox::pipe
151 
152 namespace ox {
153 
154 // Brush Mofifiers -------------------------------------------------------------
155 
157 template <typename Widget_t,
158  typename std::enable_if_t<pipe::detail::is_widget_or_wptr<Widget_t>,
159  int> = 0>
160 auto operator|(Widget_t&& w, Background_color bg) -> decltype(auto)
161 {
162  get(w).brush.background = Color{bg.value};
163  get(w).update();
164  return std::forward<Widget_t>(w);
165 }
166 
168 template <typename Widget_t,
169  typename std::enable_if_t<pipe::detail::is_widget_or_wptr<Widget_t>,
170  int> = 0>
171 auto operator|(Widget_t&& w, Foreground_color fg) -> decltype(auto)
172 {
173  get(w).brush.foreground = Color{fg.value};
174  get(w).update();
175  return std::forward<Widget_t>(w);
176 }
177 
179 template <typename Widget_t,
180  typename std::enable_if_t<pipe::detail::is_widget_or_wptr<Widget_t>,
181  int> = 0>
182 auto operator|(Widget_t&& w, Trait t) -> decltype(auto)
183 {
184  get(w).brush.traits.insert(t);
185  get(w).update();
186  return std::forward<Widget_t>(w);
187 }
188 
189 // Border Mofifiers ------------------------------------------------------------
190 
191 template <
192  typename Widget_t,
193  typename std::enable_if_t<pipe::detail::is_widget_v<Widget_t>, int> = 0>
194 auto operator|(Bordered<Widget_t>& w, ox::Border const& b)
195  -> Bordered<Widget_t>&
196 {
197  w.set_border(b);
198  return w;
199 }
200 
201 template <
202  typename Widget_t,
203  typename std::enable_if_t<pipe::detail::is_widget_v<Widget_t>, int> = 0>
204 auto operator|(std::unique_ptr<Bordered<Widget_t>> w_ptr, ox::Border const& b)
205  -> std::unique_ptr<Bordered<Widget_t>>
206 {
207  w_ptr->set_border(b);
208  return w_ptr;
209 }
210 
211 template <
212  typename Widget_t,
213  typename std::enable_if_t<pipe::detail::is_widget_v<Widget_t>, int> = 0>
214 auto operator|(Bordered<Widget_t>& w, Background_color bg)
215  -> Bordered<Widget_t>&
216 {
217  w.set_border(w.Bordered<Widget_t>::border() | bg);
218  return w;
219 }
220 
221 template <
222  typename Widget_t,
223  typename std::enable_if_t<pipe::detail::is_widget_v<Widget_t>, int> = 0>
224 auto operator|(std::unique_ptr<Bordered<Widget_t>> w_ptr, Background_color bg)
225  -> std::unique_ptr<Bordered<Widget_t>>
226 {
227  w_ptr->set_border(w_ptr->Bordered<Widget_t>::border() | bg);
228  return w_ptr;
229 }
230 
231 template <
232  typename Widget_t,
233  typename std::enable_if_t<pipe::detail::is_widget_v<Widget_t>, int> = 0>
234 auto operator|(Bordered<Widget_t>& w, Foreground_color fg)
235  -> Bordered<Widget_t>&
236 {
237  w.set_border(w.Bordered<Widget_t>::border() | fg);
238  return w;
239 }
240 
241 template <
242  typename Widget_t,
243  typename std::enable_if_t<pipe::detail::is_widget_v<Widget_t>, int> = 0>
244 auto operator|(std::unique_ptr<Bordered<Widget_t>> w_ptr, Foreground_color fg)
245  -> std::unique_ptr<Bordered<Widget_t>>
246 {
247  w_ptr->set_border(w_ptr->Bordered<Widget_t>::border() | fg);
248  return std::move(w_ptr);
249 }
250 
251 } // namespace ox
252 
253 namespace ox::pipe {
254 
255 [[nodiscard]] inline auto drop_north()
256 {
257  return [](auto&& w) -> decltype(auto) {
258  get(w).set_border(ox::drop_north(get(w).border()));
259  return std::forward<decltype(w)>(w);
260  };
261 }
262 
263 [[nodiscard]] inline auto drop_south()
264 {
265  return [](auto&& w) -> decltype(auto) {
266  get(w).set_border(ox::drop_south(get(w).border()));
267  return std::forward<decltype(w)>(w);
268  };
269 }
270 
271 [[nodiscard]] inline auto drop_east()
272 {
273  return [](auto&& w) -> decltype(auto) {
274  get(w).set_border(ox::drop_east(get(w).border()));
275  return std::forward<decltype(w)>(w);
276  };
277 }
278 
279 [[nodiscard]] inline auto drop_west()
280 {
281  return [](auto&& w) -> decltype(auto) {
282  get(w).set_border(ox::drop_west(get(w).border()));
283  return std::forward<decltype(w)>(w);
284  };
285 }
286 
287 [[nodiscard]] inline auto take_north()
288 {
289  return [](auto&& w) -> decltype(auto) {
290  get(w).set_border(ox::take_north(get(w).border()));
291  return std::forward<decltype(w)>(w);
292  };
293 }
294 
295 [[nodiscard]] inline auto take_south()
296 {
297  return [](auto&& w) -> decltype(auto) {
298  get(w).set_border(ox::take_south(get(w).border()));
299  return std::forward<decltype(w)>(w);
300  };
301 }
302 
303 [[nodiscard]] inline auto take_east()
304 {
305  return [](auto&& w) -> decltype(auto) {
306  get(w).set_border(ox::take_east(get(w).border()));
307  return std::forward<decltype(w)>(w);
308  };
309 }
310 
311 [[nodiscard]] inline auto take_west()
312 {
313  return [](auto&& w) -> decltype(auto) {
314  get(w).set_border(ox::take_west(get(w).border()));
315  return std::forward<decltype(w)>(w);
316  };
317 }
318 
320 [[nodiscard]] inline auto discard(Traits ts)
321 {
322  return Overload{[ts](Brush& b) -> Brush& {
323  b.traits.remove(ts);
324  return b;
325  },
326  [ts](Brush const& b) -> Brush {
327  auto copy = b;
328  copy.traits.remove(ts);
329  return copy;
330  },
331  [ts](Brush&& b) -> Brush {
332  b.traits.remove(ts);
333  return std::move(b);
334  },
335  [ts](Glyph& g) -> Glyph& {
336  g.brush.traits.remove(ts);
337  return g;
338  },
339  [ts](Glyph const& g) -> Glyph {
340  auto copy = g;
341  copy.brush.traits.remove(ts);
342  return copy;
343  },
344  [ts](Glyph&& g) -> Glyph {
345  g.brush.traits.remove(ts);
346  return std::move(g);
347  },
348  [ts](Glyph_string& gs) -> Glyph_string& {
349  gs.remove_traits(ts);
350  return gs;
351  },
352  [ts](Glyph_string const& gs) -> Glyph_string {
353  auto copy = gs;
354  copy.remove_traits(ts);
355  return copy;
356  },
357  [ts](Glyph_string&& gs) -> Glyph_string {
358  gs.remove_traits(ts);
359  return std::move(gs);
360  },
361  [ts](auto&& w) -> decltype(auto) {
362  get(w).brush.traits.remove(ts);
363  get(w).update();
364  return std::forward<decltype(w)>(w);
365  }};
366 }
367 
368 [[nodiscard]] inline auto clear_traits()
369 {
370  return Overload{[](Brush& b) -> Brush& {
371  b.traits = Trait::None;
372  return b;
373  },
374  [](Brush b) -> Brush {
375  b.traits = Trait::None;
376  return b;
377  },
378  [](Glyph& g) -> Glyph& {
379  g.brush.traits = Trait::None;
380  return g;
381  },
382  [](Glyph const& g) -> Glyph {
383  auto copy = g;
384  copy.brush.traits = Trait::None;
385  return copy;
386  },
387  [](Glyph&& g) -> Glyph {
388  g.brush.traits = Trait::None;
389  return std::move(g);
390  },
391  [](Glyph_string& gs) -> Glyph_string& {
392  gs.clear_traits();
393  return gs;
394  },
395  [](Glyph_string const& gs) -> Glyph_string {
396  auto copy = gs;
397  copy.clear_traits();
398  return copy;
399  },
400  [](Glyph_string&& gs) -> Glyph_string {
401  gs.clear_traits();
402  return std::move(gs);
403  },
404  [](auto&& w) -> decltype(auto) {
405  get(w).brush.traits = Trait::None;
406  get(w).update();
407  return std::forward<decltype(w)>(w);
408  }};
409 }
410 
411 // Cursor Modifiers ------------------------------------------------------------
412 [[nodiscard]] inline auto show_cursor()
413 {
414  return [](auto&& w) -> decltype(auto) {
415  get(w).cursor.enable();
416  return std::forward<decltype(w)>(w);
417  };
418 }
419 
420 [[nodiscard]] inline auto hide_cursor()
421 {
422  return [](auto&& w) -> decltype(auto) {
423  get(w).cursor.disable();
424  return std::forward<decltype(w)>(w);
425  };
426 }
427 
428 [[nodiscard]] inline auto put_cursor(Point p)
429 {
430  return [=](auto&& w) -> decltype(auto) {
431  get(w).cursor.set_position(p);
432  return std::forward<decltype(w)>(w);
433  };
434 }
435 
436 // Focus_policy ----------------------------------------------------------------
437 [[nodiscard]] inline auto focus(Focus_policy p)
438 {
439  return [=](auto&& w) -> decltype(auto) {
440  get(w).focus_policy = p;
441  return std::forward<decltype(w)>(w);
442  };
443 }
444 
445 [[nodiscard]] inline auto no_focus() { return focus(Focus_policy::None); }
446 
447 [[nodiscard]] inline auto tab_focus() { return focus(Focus_policy::Tab); }
448 
449 [[nodiscard]] inline auto click_focus() { return focus(Focus_policy::Click); }
450 
451 [[nodiscard]] inline auto strong_focus() { return focus(Focus_policy::Strong); }
452 
453 [[nodiscard]] inline auto direct_focus() { return focus(Focus_policy::Direct); }
454 
456 [[nodiscard]] inline auto forward_focus(Widget& receiver)
457 {
458  return [&](auto&& w) -> decltype(auto) {
459  get(w).focused_in.connect([&] { ::ox::System::set_focus(receiver); });
460  return std::forward<decltype(w)>(w);
461  };
462 }
463 
464 // Width Policy Modifiers -----------------------------------------------------
465 
466 [[nodiscard]] inline auto fixed_width(int hint)
467 {
468  return [=](auto&& w) -> decltype(auto) {
469  get(w).width_policy = ox::Size_policy::fixed(hint);
470  return std::forward<decltype(w)>(w);
471  };
472 }
473 
474 [[nodiscard]] inline auto minimum_width(int hint)
475 {
476  return [=](auto&& w) -> decltype(auto) {
477  get(w).width_policy = ox::Size_policy::minimum(hint);
478  return std::forward<decltype(w)>(w);
479  };
480 }
481 
482 [[nodiscard]] inline auto maximum_width(int hint)
483 {
484  return [=](auto&& w) -> decltype(auto) {
485  get(w).width_policy = ox::Size_policy::maximum(hint);
486  return std::forward<decltype(w)>(w);
487  };
488 }
489 
490 [[nodiscard]] inline auto preferred_width(int hint)
491 {
492  return [=](auto&& w) -> decltype(auto) {
493  get(w).width_policy = ox::Size_policy::preferred(hint);
494  return std::forward<decltype(w)>(w);
495  };
496 }
497 
498 [[nodiscard]] inline auto expanding_width(int hint)
499 {
500  return [=](auto&& w) -> decltype(auto) {
501  get(w).width_policy = ox::Size_policy::expanding(hint);
502  return std::forward<decltype(w)>(w);
503  };
504 }
505 
506 [[nodiscard]] inline auto minimum_expanding_width(int hint)
507 {
508  return [=](auto&& w) -> decltype(auto) {
509  get(w).width_policy = ox::Size_policy::minimum_expanding(hint);
510  return std::forward<decltype(w)>(w);
511  };
512 }
513 
514 [[nodiscard]] inline auto ignored_width()
515 {
516  return [](auto&& w) -> decltype(auto) {
517  get(w).width_policy = ox::Size_policy::ignored();
518  return std::forward<decltype(w)>(w);
519  };
520 }
521 
522 [[nodiscard]] inline auto width_hint(int hint)
523 {
524  return [=](auto&& w) -> decltype(auto) {
525  get(w).width_policy.hint(hint);
526  return std::forward<decltype(w)>(w);
527  };
528 }
529 
530 [[nodiscard]] inline auto width_min(int min)
531 {
532  return [=](auto&& w) -> decltype(auto) {
533  get(w).width_policy.min(min);
534  return std::forward<decltype(w)>(w);
535  };
536 }
537 
538 [[nodiscard]] inline auto width_max(int max)
539 {
540  return [=](auto&& w) -> decltype(auto) {
541  get(w).width_policy.max(max);
542  return std::forward<decltype(w)>(w);
543  };
544 }
545 
546 [[nodiscard]] inline auto width_stretch(double stretch)
547 {
548  return [=](auto&& w) -> decltype(auto) {
549  get(w).width_policy.stretch(stretch);
550  return std::forward<decltype(w)>(w);
551  };
552 }
553 
554 [[nodiscard]] inline auto can_ignore_width_min()
555 {
556  return [](auto&& w) -> decltype(auto) {
557  get(w).width_policy.can_ignore_min(true);
558  return std::forward<decltype(w)>(w);
559  };
560 }
561 
562 [[nodiscard]] inline auto cannot_ignore_width_min()
563 {
564  return [](auto&& w) -> decltype(auto) {
565  get(w).width_policy.can_ignore_min(false);
566  return std::forward<decltype(w)>(w);
567  };
568 }
569 
570 // Height Policy Modifiers -----------------------------------------------------
571 
572 [[nodiscard]] inline auto fixed_height(int hint)
573 {
574  return [=](auto&& w) -> decltype(auto) {
575  get(w).height_policy = ox::Size_policy::fixed(hint);
576  return std::forward<decltype(w)>(w);
577  };
578 }
579 
580 [[nodiscard]] inline auto minimum_height(int hint)
581 {
582  return [=](auto&& w) -> decltype(auto) {
583  get(w).height_policy = ox::Size_policy::minimum(hint);
584  return std::forward<decltype(w)>(w);
585  };
586 }
587 
588 [[nodiscard]] inline auto maximum_height(int hint)
589 {
590  return [=](auto&& w) -> decltype(auto) {
591  get(w).height_policy = ox::Size_policy::maximum(hint);
592  return std::forward<decltype(w)>(w);
593  };
594 }
595 
596 [[nodiscard]] inline auto preferred_height(int hint)
597 {
598  return [=](auto&& w) -> decltype(auto) {
599  get(w).height_policy = ox::Size_policy::preferred(hint);
600  return std::forward<decltype(w)>(w);
601  };
602 }
603 
604 [[nodiscard]] inline auto expanding_height(int hint)
605 {
606  return [=](auto&& w) -> decltype(auto) {
607  get(w).height_policy = ox::Size_policy::expanding(hint);
608  return std::forward<decltype(w)>(w);
609  };
610 }
611 
612 [[nodiscard]] inline auto minimum_expanding_height(int hint)
613 {
614  return [=](auto&& w) -> decltype(auto) {
615  get(w).height_policy = ox::Size_policy::minimum_expanding(hint);
616  return std::forward<decltype(w)>(w);
617  };
618 }
619 
620 [[nodiscard]] inline auto ignored_height()
621 {
622  return [](auto&& w) -> decltype(auto) {
623  get(w).height_policy = ox::Size_policy::ignored();
624  return std::forward<decltype(w)>(w);
625  };
626 }
627 
628 [[nodiscard]] inline auto height_hint(int hint)
629 {
630  return [=](auto&& w) -> decltype(auto) {
631  get(w).height_policy.hint(hint);
632  return std::forward<decltype(w)>(w);
633  };
634 }
635 
636 [[nodiscard]] inline auto height_min(int min)
637 {
638  return [=](auto&& w) -> decltype(auto) {
639  get(w).height_policy.min(min);
640  return std::forward<decltype(w)>(w);
641  };
642 }
643 
644 [[nodiscard]] inline auto height_max(int max)
645 {
646  return [=](auto&& w) -> decltype(auto) {
647  get(w).height_policy.max(max);
648  return std::forward<decltype(w)>(w);
649  };
650 }
651 
652 [[nodiscard]] inline auto height_stretch(double stretch)
653 {
654  return [=](auto&& w) -> decltype(auto) {
655  get(w).height_policy.stretch(stretch);
656  return std::forward<decltype(w)>(w);
657  };
658 }
659 
660 [[nodiscard]] inline auto can_ignore_height_min()
661 {
662  return [](auto&& w) -> decltype(auto) {
663  get(w).height_policy.can_ignore_min(true);
664  return std::forward<decltype(w)>(w);
665  };
666 }
667 
668 [[nodiscard]] inline auto cannot_ignore_height_min()
669 {
670  return [](auto&& w) -> decltype(auto) {
671  get(w).height_policy.can_ignore_min(false);
672  return std::forward<decltype(w)>(w);
673  };
674 }
675 
676 // Widget::Signals -------------------------------------------------------------
677 template <typename Handler>
678 [[nodiscard]] inline auto on_enable(Handler&& op)
679 {
680  return [&](auto&& w) -> decltype(auto) {
681  get(w).enabled.connect(std::forward<Handler>(op));
682  return std::forward<decltype(w)>(w);
683  };
684 }
685 
686 template <typename Handler>
687 [[nodiscard]] inline auto on_disable(Handler&& op)
688 {
689  return [&](auto&& w) -> decltype(auto) {
690  get(w).disabled.connect(std::forward<Handler>(op));
691  return std::forward<decltype(w)>(w);
692  };
693 }
694 
695 template <typename Handler>
696 [[nodiscard]] inline auto on_child_added(Handler&& op)
697 {
698  return [&](auto&& w) -> decltype(auto) {
699  get(w).child_added.connect(std::forward<Handler>(op));
700  return std::forward<decltype(w)>(w);
701  };
702 }
703 
704 template <typename Handler>
705 [[nodiscard]] inline auto on_child_removed(Handler&& op)
706 {
707  return [&](auto&& w) -> decltype(auto) {
708  get(w).child_removed.connect(std::forward<Handler>(op));
709  return std::forward<decltype(w)>(w);
710  };
711 }
712 
713 template <typename Handler>
714 [[nodiscard]] inline auto on_child_polished(Handler&& op)
715 {
716  return [&](auto&& w) -> decltype(auto) {
717  get(w).child_polished.connect(std::forward<Handler>(op));
718  return std::forward<decltype(w)>(w);
719  };
720 }
721 
722 template <typename Handler>
723 [[nodiscard]] inline auto on_move(Handler&& op)
724 {
725  return [&](auto&& w) -> decltype(auto) {
726  get(w).moved.connect(std::forward<Handler>(op));
727  return std::forward<decltype(w)>(w);
728  };
729 }
730 
731 template <typename Handler>
732 [[nodiscard]] inline auto on_resize(Handler&& op)
733 {
734  return [&](auto&& w) -> decltype(auto) {
735  get(w).resized.connect(std::forward<Handler>(op));
736  return std::forward<decltype(w)>(w);
737  };
738 }
739 
740 template <typename Handler>
741 [[nodiscard]] inline auto on_mouse_press(Handler&& op)
742 {
743  return [&](auto&& w) -> decltype(auto) {
744  get(w).mouse_pressed.connect(std::forward<Handler>(op));
745  return std::forward<decltype(w)>(w);
746  };
747 }
748 
749 template <typename Handler>
750 [[nodiscard]] inline auto on_left_click(Handler&& op)
751 {
752  return [=](auto&& w) -> decltype(auto) {
753  get(w).mouse_pressed.connect([op](auto const& m) {
754  if (m.button == Mouse::Button::Left)
755  op();
756  });
757  return std::forward<decltype(w)>(w);
758  };
759 }
760 
761 template <typename Handler>
762 [[nodiscard]] inline auto on_middle_click(Handler&& op)
763 {
764  return [=](auto&& w) -> decltype(auto) {
765  get(w).mouse_pressed.connect([op](auto const& m) {
766  if (m.button == Mouse::Button::Middle)
767  op();
768  });
769  return std::forward<decltype(w)>(w);
770  };
771 }
772 
773 template <typename Handler>
774 [[nodiscard]] inline auto on_right_click(Handler&& op)
775 {
776  return [=](auto&& w) -> decltype(auto) {
777  get(w).mouse_pressed.connect([op](auto const& m) {
778  if (m.button == Mouse::Button::Right)
779  op();
780  });
781  return std::forward<decltype(w)>(w);
782  };
783 }
784 
785 template <typename Handler>
786 [[nodiscard]] inline auto on_mouse_release(Handler&& op)
787 {
788  return [&](auto&& w) -> decltype(auto) {
789  get(w).mouse_released.connect(std::forward<Handler>(op));
790  return std::forward<decltype(w)>(w);
791  };
792 }
793 
794 template <typename Handler>
795 [[nodiscard]] inline auto on_mouse_double_click(Handler&& op)
796 {
797  return [&](auto&& w) -> decltype(auto) {
798  get(w).mouse_double_clicked.connect(std::forward<Handler>(op));
799  return std::forward<decltype(w)>(w);
800  };
801 }
802 
803 template <typename Handler>
804 [[nodiscard]] inline auto on_mouse_move(Handler&& op)
805 {
806  return [&](auto&& w) -> decltype(auto) {
807  get(w).mouse_moved.connect(std::forward<Handler>(op));
808  return std::forward<decltype(w)>(w);
809  };
810 }
811 
812 template <typename Handler>
813 [[nodiscard]] inline auto on_key_press(Handler&& op)
814 {
815  return [&](auto&& w) -> decltype(auto) {
816  get(w).key_pressed.connect(std::forward<Handler>(op));
817  return std::forward<decltype(w)>(w);
818  };
819 }
820 
821 template <typename Handler>
822 [[nodiscard]] inline auto bind_key(Key k, Handler&& op)
823 {
824  return [op = std::forward<Handler>(op), k](auto&& w) -> decltype(auto) {
825  get(w).key_pressed.connect([&w, &op, k](auto pressed) {
826  if (pressed == k)
827  op(w);
828  });
829  return std::forward<decltype(w)>(w);
830  };
831 }
832 
833 template <typename Handler>
834 [[nodiscard]] inline auto on_focus_in(Handler&& op)
835 {
836  return [&](auto&& w) -> decltype(auto) {
837  get(w).focused_in.connect(std::forward<Handler>(op));
838  return std::forward<decltype(w)>(w);
839  };
840 }
841 
842 template <typename Handler>
843 [[nodiscard]] inline auto on_focus_out(Handler&& op)
844 {
845  return [&](auto&& w) -> decltype(auto) {
846  get(w).focused_out.connect(std::forward<Handler>(op));
847  return std::forward<decltype(w)>(w);
848  };
849 }
850 
851 template <typename Handler>
852 [[nodiscard]] inline auto on_paint(Handler&& op)
853 {
854  return [&](auto&& w) -> decltype(auto) {
855  get(w).painted.connect(std::forward<Handler>(op));
856  return std::forward<decltype(w)>(w);
857  };
858 }
859 
860 template <typename Handler>
861 [[nodiscard]] inline auto on_timer(Handler&& op)
862 {
863  return [&](auto&& w) -> decltype(auto) {
864  get(w).timer.connect(std::forward<Handler>(op));
865  return std::forward<decltype(w)>(w);
866  };
867 }
868 
869 template <typename Handler>
870 [[nodiscard]] inline auto on_deleted(Handler&& op)
871 {
872  return [&](auto&& w) -> decltype(auto) {
873  get(w).deleted.connect(std::forward<Handler>(op));
874  return std::forward<decltype(w)>(w);
875  };
876 }
877 
878 // Derived Widget::Signals -----------------------------------------------------
879 template <typename Handler>
880 [[nodiscard]] inline auto on_color_selected(Handler&& op)
881 {
882  return [&](auto&& w) -> decltype(auto) {
883  get(w).color_selected.connect(std::forward<Handler>(op));
884  return std::forward<decltype(w)>(w);
885  };
886 }
887 
888 template <typename Handler>
889 [[nodiscard]] inline auto on_press(Handler&& op)
890 {
891  return [&](auto&& w) -> decltype(auto) {
892  get(w).pressed.connect(std::forward<Handler>(op));
893  return std::forward<decltype(w)>(w);
894  };
895 }
896 
897 template <typename Handler>
898 [[nodiscard]] inline auto on_check(Handler&& op)
899 {
900  return [&](auto&& w) -> decltype(auto) {
901  get(w).checked.connect(std::forward<Handler>(op));
902  return std::forward<decltype(w)>(w);
903  };
904 }
905 
906 template <typename Handler>
907 [[nodiscard]] inline auto on_uncheck(Handler&& op)
908 {
909  return [&](auto&& w) -> decltype(auto) {
910  get(w).unchecked.connect(std::forward<Handler>(op));
911  return std::forward<decltype(w)>(w);
912  };
913 }
914 
915 template <typename Handler>
916 [[nodiscard]] inline auto on_toggle(Handler&& op)
917 {
918  return [&](auto&& w) -> decltype(auto) {
919  get(w).toggled.connect(std::forward<Handler>(op));
920  return std::forward<decltype(w)>(w);
921  };
922 }
923 
924 // Derived Widget Modifiers ----------------------------------------------------
925 [[nodiscard]] inline auto active_page(std::size_t p)
926 {
927  return [=](auto&& w) -> decltype(auto) {
928  get(w).set_active_page(p);
929  return std::forward<decltype(w)>(w);
930  };
931 }
932 
933 [[nodiscard]] inline auto label(Glyph_string const& x)
934 {
935  return [=](auto&& w) -> decltype(auto) {
936  get(w).set_label(x);
937  return std::forward<decltype(w)>(w);
938  };
939 }
940 
941 [[nodiscard]] inline auto wrapped()
942 {
943  return [](auto&& w) -> auto& { return get(w).wrapped; };
944 }
945 
946 // Labeled_cycle_box
947 [[nodiscard]] inline auto divider(Glyph x)
948 {
949  return [=](auto&& w) -> decltype(auto) {
950  get(w).set_divider(x);
951  return std::forward<decltype(w)>(w);
952  };
953 }
954 
955 [[nodiscard]] inline auto any_wrap()
956 {
957  return [=](auto&& w) -> decltype(auto) {
958  get(w).set_wrap(Wrap::Any);
959  return std::forward<decltype(w)>(w);
960  };
961 }
962 
963 [[nodiscard]] inline auto word_wrap()
964 {
965  return [=](auto&& w) -> decltype(auto) {
966  get(w).set_wrap(Wrap::Word);
967  return std::forward<decltype(w)>(w);
968  };
969 }
970 
971 [[nodiscard]] inline auto text(Glyph_string x)
972 {
973  return [=](auto&& w) -> decltype(auto) {
974  get(w).set_text(x);
975  return std::forward<decltype(w)>(w);
976  };
977 }
978 
979 template <typename Number_t>
980 [[nodiscard]] inline auto value(Number_t x)
981 {
982  return [=](auto&& w) -> decltype(auto) {
983  get(w).set_value(x);
984  return std::forward<decltype(w)>(w);
985  };
986 }
987 
988 [[nodiscard]] inline auto align_left()
989 {
990  return [=](auto&& w) -> decltype(auto) {
991  get(w).set_alignment(Align::Left);
992  return std::forward<decltype(w)>(w);
993  };
994 }
995 
996 [[nodiscard]] inline auto align_center()
997 {
998  return [=](auto&& w) -> decltype(auto) {
999  get(w).set_alignment(Align::Center);
1000  return std::forward<decltype(w)>(w);
1001  };
1002 }
1003 
1004 [[nodiscard]] inline auto align_right()
1005 {
1006  return [=](auto&& w) -> decltype(auto) {
1007  get(w).set_alignment(Align::Right);
1008  return std::forward<decltype(w)>(w);
1009  };
1010 }
1011 
1012 // Label
1013 [[nodiscard]] inline auto dynamic_growth()
1014 {
1015  return [=](auto&& w) -> decltype(auto) {
1016  get(w).set_growth_strategy(Growth::Dynamic);
1017  return std::forward<decltype(w)>(w);
1018  };
1019 }
1020 
1021 [[nodiscard]] inline auto no_growth()
1022 {
1023  return [=](auto&& w) -> decltype(auto) {
1024  get(w).set_growth_strategy(Growth::Static);
1025  return std::forward<decltype(w)>(w);
1026  };
1027 }
1028 
1029 } // namespace ox::pipe
1030 
1031 namespace ox {
1032 
1034 template <
1035  typename Widget_t,
1036  typename F,
1037  typename = std::enable_if_t<pipe::detail::is_widget_or_wptr<Widget_t>, int>>
1038 auto operator|(Widget_t&& w, F&& op) -> std::invoke_result_t<F, Widget_t&&>
1039 {
1040  return std::forward<F>(op)(std::forward<Widget_t>(w));
1041 }
1042 
1044 template <typename Iter_1, typename Iter_2, typename F>
1045 auto operator|(Range<Iter_1, Iter_2> children, F&& op) -> Range<Iter_1, Iter_2>
1046 {
1047  for (auto& child : children)
1048  child | op;
1049  return children;
1050 }
1051 
1053 template <typename Iter_1, typename Iter_2, typename F>
1054 auto operator|(Range<Iter_1, Iter_2> children,
1055  pipe::detail::Filter_predicate<F>&& p)
1056 {
1057  return Range{Filter_iterator{children.begin(), children.end(),
1058  std::forward<F>(p.predicate)},
1059  children.end()};
1060 }
1061 
1063 template <typename Iter_1, typename Iter_2, typename Widget_t>
1064 auto operator|(Range<Iter_1, Iter_2> children,
1065  pipe::detail::Dynamic_filter_predicate<Widget_t>)
1066 {
1067  // clang format can't handle this one at the moment.
1068  // clang-format off
1069  return Range{
1070  Transform_iterator{
1071  Filter_iterator{ children.begin(), children.end(),
1072  [](auto& w) { return dynamic_cast<Widget_t*>(&w) != nullptr; }},
1073  [](auto& w) -> auto& {return static_cast<Widget_t&>(w); }
1074  }, children.end()};
1075 // clang-format on
1076 }
1077 
1079 template <typename F>
1080 auto operator|(std::vector<Widget*> const& descendants, F&& op)
1081  -> std::vector<Widget*> const&
1082 {
1083  for (auto* d : descendants)
1084  *d | op;
1085  return descendants;
1086 }
1087 
1089 template <typename F>
1090 auto operator|(Glyph_string& gs, F&& op)
1091  -> std::invoke_result_t<F, Glyph_string&>
1092 {
1093  return std::forward<F>(op)(gs);
1094 }
1095 
1097 template <typename F>
1098 auto operator|(Glyph_string const& gs, F&& op)
1099  -> std::invoke_result_t<F, Glyph_string const&>
1100 {
1101  return std::forward<F>(op)(gs);
1102 }
1103 
1105 template <typename F>
1106 auto operator|(Glyph_string&& gs, F&& op)
1107  -> std::invoke_result_t<F, Glyph_string&&>
1108 {
1109  return std::forward<F>(op)(std::move(gs));
1110 }
1111 
1113 template <typename F>
1114 auto operator|(Glyph& g, F&& op) -> std::invoke_result_t<F, Glyph&>
1115 {
1116  return std::forward<F>(op)(g);
1117 }
1118 
1120 template <typename F>
1121 auto operator|(Glyph const& g, F&& op) -> std::invoke_result_t<F, Glyph const&>
1122 {
1123  return std::forward<F>(op)(g);
1124 }
1125 
1127 template <typename F>
1128 auto operator|(Glyph&& g, F&& op) -> std::invoke_result_t<F, Glyph&&>
1129 {
1130  return std::forward<F>(op)(std::move(g));
1131 }
1132 
1134 template <typename F>
1135 auto operator|(Brush& b, F&& op) -> std::invoke_result_t<F, Brush&>
1136 {
1137  return std::forward<F>(op)(b);
1138 }
1139 
1141 template <typename F>
1142 auto operator|(Brush const& b, F&& op) -> std::invoke_result_t<F, Brush const&>
1143 {
1144  return std::forward<F>(op)(b);
1145 }
1146 
1148 template <typename F>
1149 auto operator|(Brush&& b, F&& op) -> std::invoke_result_t<F, Brush&&>
1150 {
1151  return std::forward<F>(op)(std::move(b));
1152 }
1153 
1154 } // namespace ox
1155 #endif // TERMOX_WIDGET_PIPE_HPP
static auto ignored() -> Size_policy
Ignored: Stretch is the only consideration.
Definition: size_policy.cpp:91
static auto fixed(int hint) -> Size_policy
Fixed: hint is the only acceptable size.
Definition: size_policy.cpp:55
static auto minimum(int hint) -> Size_policy
Minimum: hint is the minimum acceptable size, may be larger.
Definition: size_policy.cpp:61
static auto minimum_expanding(int hint) -> Size_policy
Minimum Expanding: hint is minimum, it will expand into unused space.
Definition: size_policy.cpp:85
static auto maximum(int hint) -> Size_policy
Maximum: hint is the maximum acceptable size, may be smaller.
Definition: size_policy.cpp:67
static auto preferred(int hint) -> Size_policy
Preferred: hint is preferred, though it can be any size.
Definition: size_policy.cpp:73
static auto expanding(int hint) -> Size_policy
Expanding: hint is preferred, but it will expand to use extra space.
Definition: size_policy.cpp:79
static void set_focus(Widget &w)
Give program focus to w.
Definition: system.cpp:39
Defines which border walls are enabled and how they are displayed.
Definition: bordered.hpp:21