ttx 0.1.0
Loading...
Searching...
No Matches
layout.h
Go to the documentation of this file.
1#pragma once
2
3#include "di/container/tree/tree_set.h"
4#include "di/reflect/prelude.h"
5#include "di/vocab/pointer/box.h"
6#include "direction.h"
7#include "ttx/layout_json.h"
8#include "ttx/pane.h"
9#include "ttx/size.h"
10
11namespace ttx {
12struct LayoutNode;
13struct LayoutPane;
14class LayoutGroup;
15
16// Represents the layout result for a single pane. The row and col
17// coordinates are absolute.
19 u32 row { 0 };
20 u32 col { 0 };
22 LayoutNode* parent { nullptr };
23 LayoutPane const* ref { nullptr };
24 Pane* pane { nullptr };
25
26 auto operator==(LayoutEntry const&) const -> bool = default;
27
28 constexpr friend auto tag_invoke(di::Tag<di::reflect>, di::InPlaceType<LayoutEntry>) {
29 return di::make_fields<"LayoutEntry">(
30 di::field<"row", &LayoutEntry::row>, di::field<"col", &LayoutEntry::col>,
31 di::field<"size", &LayoutEntry::size>, di::field<"parent", &LayoutEntry::parent>,
32 di::field<"ref", &LayoutEntry::ref>, di::field<"pane", &LayoutEntry::pane>);
33 }
34};
35
36// Represents a full layout tree. This is created by calling
37// LayoutGroup::layout().
38struct LayoutNode {
39 u32 row { 0 };
40 u32 col { 0 };
42 di::Vector<di::Variant<di::Box<LayoutNode>, LayoutEntry>> children;
43 LayoutNode* parent { nullptr };
44 LayoutGroup* group { nullptr };
46
47 auto find_pane(Pane* pane) -> di::Optional<LayoutEntry&>;
48 auto find_pane_by_id(u64 id) -> di::Optional<LayoutEntry&>;
49 auto hit_test(u32 row, u32 col) -> di::Optional<LayoutEntry&>;
50
51 auto hit_test_horizontal_line(u32 row, u32 col_start, u32 col_end) -> di::TreeSet<LayoutEntry*>;
52 auto hit_test_vertical_line(u32 col, u32 row_start, u32 row_end) -> di::TreeSet<LayoutEntry*>;
53
54 constexpr friend auto tag_invoke(di::Tag<di::reflect>, di::InPlaceType<LayoutNode>) {
55 return di::make_fields<"LayoutNode">(
56 di::field<"row", &LayoutNode::row>, di::field<"col", &LayoutNode::col>,
57 di::field<"size", &LayoutNode::size>, di::field<"children", &LayoutNode::children>,
58 di::field<"parent", &LayoutNode::parent>, di::field<"group", &LayoutNode::group>,
59 di::field<"direction", &LayoutNode::direction>);
60 }
61};
62
63// Pane sizes are computed in units of this number of precision, using fixed point arithemetic.
64constexpr inline auto max_layout_precision = i64(100'000);
65
66// Represents a pane in a layout group. This includes extra metadata
67// necessary for layout.
68struct LayoutPane {
69 di::Box<Pane> pane {};
70 u64 pane_id { 0 };
71 di::Optional<di::Path> cwd {}; // Used when restoring a pane.
73};
74
81
82constexpr auto tag_invoke(di::Tag<di::reflect>, di::InPlaceType<ResizeDirection>) {
83 using enum ResizeDirection;
84 return di::make_enumerators<"ResizeDirection">(di::enumerator<"Left", Left>, di::enumerator<"Right", Right>,
85 di::enumerator<"Top", Top>, di::enumerator<"Bottom", Bottom>);
86}
87
88// Represents a group of panes in a hierarchy. Instead of using a strict binary tree,
89// we allow multiple children on a single level so that by default, splits made in
90// the same direction share space evenly.
92public:
93 constexpr auto direction() const -> Direction { return m_direction; }
94 constexpr auto empty() const -> bool { return m_children.empty(); }
95 constexpr auto single() const -> bool { return m_children.size() == 1; }
96 constexpr auto relative_size() -> i64& { return m_relative_size; }
97 constexpr auto relative_size() const -> i64 { return m_relative_size; }
98
99 static auto
101 di::FunctionRef<di::Result<di::Box<Pane>>(u64, di::Optional<di::Path>, Size const&)> make_pane)
102 -> di::Result<LayoutGroup>;
103
104 // NOTE: this method returns the correct size for the new pane, and a lvalue reference where
105 // the caller should store its newly created Pane. We need this akward API so that we can
106 // create a Pane with a sane initial size.
107 auto split(Size const& size, u32 row_offset, u32 col_offset, Pane* reference, Direction direction)
108 -> di::Tuple<di::Box<LayoutNode>, di::Optional<LayoutEntry&>, di::Optional<di::Box<Pane>&>>;
109
110 // NOTE: after removing a pane, calling layout() is necessary as any previous LayoutNode's may become invalid.
111 auto remove_pane(Pane* pane) -> di::Box<Pane>;
112
113 // NOTE: after resizing a pane, caling layout() is necessary for the change to take effect. This functions
114 // returns true if any change occurred.
115 auto resize(LayoutNode& root, Pane* pane, ResizeDirection direction, i32 amount_in_cells) -> bool;
116
117 // NOTE: in addition to computing the layout tree, Pane::resize() is called to inform each Pane of its (potentially)
118 // new size.
119 auto layout(Size const& size, u32 row_offset, u32 col_offset) -> di::Box<LayoutNode>;
120
121 auto as_json_v1() const -> json::v1::PaneLayoutNode;
122
123private:
125 friend struct ToJsonV1;
126 friend struct FromJsonV1;
127 friend struct MakePane;
128
129 void redistribute_space(di::Variant<di::Box<LayoutGroup>, di::Box<LayoutPane>>* new_child,
130 i64 original_size_available, i64 new_size_available);
131 void validate_layout();
132
133 di::Vector<di::Variant<di::Box<LayoutGroup>, di::Box<LayoutPane>>> m_children;
134 i64 m_relative_size { max_layout_precision };
135 Direction m_direction { Direction::None };
136};
137}
Definition layout.h:91
constexpr auto empty() const -> bool
Definition layout.h:94
auto resize(LayoutNode &root, Pane *pane, ResizeDirection direction, i32 amount_in_cells) -> bool
Definition layout.cpp:405
auto split(Size const &size, u32 row_offset, u32 col_offset, Pane *reference, Direction direction) -> di::Tuple< di::Box< LayoutNode >, di::Optional< LayoutEntry & >, di::Optional< di::Box< Pane > & > >
Definition layout.cpp:230
friend struct FromJsonV1
Definition layout.h:126
constexpr auto relative_size() -> i64 &
Definition layout.h:96
constexpr auto relative_size() const -> i64
Definition layout.h:97
constexpr auto direction() const -> Direction
Definition layout.h:93
static auto from_json_v1(json::v1::PaneLayoutNode const &json, Size const &size, di::FunctionRef< di::Result< di::Box< Pane > >(u64, di::Optional< di::Path >, Size const &)> make_pane) -> di::Result< LayoutGroup >
Definition layout.cpp:665
friend struct FindPaneInLayoutGroup
Definition layout.h:124
friend struct MakePane
Definition layout.h:127
auto as_json_v1() const -> json::v1::PaneLayoutNode
Definition layout.cpp:604
auto layout(Size const &size, u32 row_offset, u32 col_offset) -> di::Box< LayoutNode >
Definition layout.cpp:486
friend struct ToJsonV1
Definition layout.h:125
auto remove_pane(Pane *pane) -> di::Box< Pane >
Definition layout.cpp:299
constexpr auto single() const -> bool
Definition layout.h:95
Definition pane.h:83
Definition layout_json.h:10
Definition clipboard.h:10
Direction
Definition direction.h:7
@ None
Definition direction.h:8
constexpr auto tag_invoke(di::Tag< di::reflect >, di::InPlaceType< ClipboardMode >)
Definition clipboard.h:21
@ Right
Definition key.h:70
@ Left
Definition key.h:69
constexpr auto max_layout_precision
Definition layout.h:64
ResizeDirection
Definition layout.h:75
@ Bottom
Definition layout.h:79
@ Top
Definition layout.h:78
Definition layout.h:18
LayoutNode * parent
Definition layout.h:22
LayoutPane const * ref
Definition layout.h:23
Size size
Definition layout.h:21
u32 row
Definition layout.h:19
auto operator==(LayoutEntry const &) const -> bool=default
Pane * pane
Definition layout.h:24
u32 col
Definition layout.h:20
constexpr friend auto tag_invoke(di::Tag< di::reflect >, di::InPlaceType< LayoutEntry >)
Definition layout.h:28
Definition layout.h:38
Direction direction
Definition layout.h:45
auto hit_test_horizontal_line(u32 row, u32 col_start, u32 col_end) -> di::TreeSet< LayoutEntry * >
Definition layout.cpp:143
LayoutGroup * group
Definition layout.h:44
u32 row
Definition layout.h:39
auto find_pane_by_id(u64 id) -> di::Optional< LayoutEntry & >
Definition layout.cpp:75
di::Vector< di::Variant< di::Box< LayoutNode >, LayoutEntry > > children
Definition layout.h:42
auto hit_test_vertical_line(u32 col, u32 row_start, u32 row_end) -> di::TreeSet< LayoutEntry * >
Definition layout.cpp:122
auto hit_test(u32 row, u32 col) -> di::Optional< LayoutEntry & >
Definition layout.cpp:98
LayoutNode * parent
Definition layout.h:43
constexpr friend auto tag_invoke(di::Tag< di::reflect >, di::InPlaceType< LayoutNode >)
Definition layout.h:54
u32 col
Definition layout.h:40
auto find_pane(Pane *pane) -> di::Optional< LayoutEntry & >
Definition layout.cpp:55
Size size
Definition layout.h:41
Definition layout.h:68
u64 pane_id
Definition layout.h:70
i64 relative_size
Definition layout.h:72
di::Optional< di::Path > cwd
Definition layout.h:71
di::Box< Pane > pane
Definition layout.h:69
Definition size.h:7
Definition layout_json.h:36