1 #include <hikari/layout.h>
2
3 #include <assert.h>
4
5 #include <hikari/split.h>
6 #include <hikari/tile.h>
7 #include <hikari/view.h>
8
9 void
hikari_layout_init(struct hikari_layout * layout,struct hikari_split * split,struct hikari_sheet * sheet)10 hikari_layout_init(struct hikari_layout *layout,
11 struct hikari_split *split,
12 struct hikari_sheet *sheet)
13 {
14 layout->split = hikari_split_copy(split);
15 layout->sheet = sheet;
16 wl_list_init(&layout->tiles);
17 }
18
19 void
hikari_layout_fini(struct hikari_layout * layout)20 hikari_layout_fini(struct hikari_layout *layout)
21 {
22 hikari_split_free(layout->split);
23 }
24
25 #define CYCLE_LAYOUT(name, link) \
26 struct hikari_view *hikari_layout_##name##_view( \
27 struct hikari_layout *layout) \
28 { \
29 struct wl_list *link = layout->tiles.link; \
30 struct hikari_tile *link##_tile; \
31 \
32 do { \
33 if (link == &layout->tiles) { \
34 return NULL; \
35 } else { \
36 link##_tile = wl_container_of(link, link##_tile, layout_tiles); \
37 } \
38 link = link->link; \
39 } while (hikari_view_is_hidden(link##_tile->view)); \
40 \
41 assert(link##_tile != NULL); \
42 assert(link##_tile->view != NULL); \
43 assert(!hikari_view_is_hidden(link##_tile->view)); \
44 \
45 return link##_tile->view; \
46 }
47
CYCLE_LAYOUT(first,next)48 CYCLE_LAYOUT(first, next)
49 CYCLE_LAYOUT(last, prev)
50 #undef CYCLE_LAYOUT
51
52 void
53 hikari_layout_reset(struct hikari_layout *layout)
54 {
55 assert(layout != NULL);
56
57 struct hikari_sheet *sheet = layout->sheet;
58
59 struct hikari_view *view;
60 wl_list_for_each (view, &sheet->views, sheet_views) {
61 if (hikari_view_is_tiled(view)) {
62 hikari_view_reset_geometry(view);
63 }
64 }
65 }
66
67 static void
restack(struct hikari_layout * layout)68 restack(struct hikari_layout *layout)
69 {
70 assert(layout != NULL);
71
72 struct hikari_tile *tile;
73 wl_list_for_each_reverse (tile, &layout->tiles, layout_tiles) {
74 struct hikari_view *view = tile->view;
75
76 if (hikari_view_is_hidden(view)) {
77 hikari_view_show(view);
78 } else {
79 hikari_view_raise(view);
80 }
81 }
82 }
83
84 void
hikari_layout_restack_append(struct hikari_layout * layout)85 hikari_layout_restack_append(struct hikari_layout *layout)
86 {
87 assert(layout != NULL);
88
89 restack(layout);
90
91 hikari_sheet_apply_split(layout->sheet, layout->split);
92 }
93
94 static bool
view_is_prependable(struct hikari_view * view)95 view_is_prependable(struct hikari_view *view)
96 {
97 return !hikari_view_is_tiled(view) && hikari_view_is_tileable(view);
98 }
99
100 static void
raise_prependable(struct hikari_sheet * sheet)101 raise_prependable(struct hikari_sheet *sheet)
102 {
103 struct hikari_view *view, *view_temp, *first = NULL;
104 wl_list_for_each_reverse_safe (view, view_temp, &sheet->views, sheet_views) {
105 if (view_is_prependable(view)) {
106 if (view == first) {
107 break;
108 } else if (first == NULL) {
109 first = view;
110 }
111
112 hikari_view_raise(view);
113 }
114 }
115 }
116
117 void
hikari_layout_restack_prepend(struct hikari_layout * layout)118 hikari_layout_restack_prepend(struct hikari_layout *layout)
119 {
120 assert(layout != NULL);
121
122 restack(layout);
123 raise_prependable(layout->sheet);
124
125 hikari_sheet_apply_split(layout->sheet, layout->split);
126 }
127