Skip to main content

journey/widgets/
layout.rs

1//! Pure geometry for journey's two screens.
2//!
3//! The generic [`Shell`](crate::widgets::Shell) places each child by calling
4//! one of these functions with the container bounds, so the browse (gitk) and
5//! commit (git-gui) layouts are simply two sets of rectangles.
6
7use saudade::Rect;
8
9// ---- browse (gitk) layout -------------------------------------------------
10
11/// Height of the menu bar (shared by both screens).
12pub const MENU_H: i32 = 20;
13/// Height of the search toolbar below the menu.
14pub const TOOLBAR_H: i32 = 26;
15/// Width of the changed-files pane on the lower left.
16pub const FILES_W: i32 = 300;
17/// Fraction of the content height given to the history pane.
18pub const HISTORY_FRAC: f32 = 0.46;
19/// Slight breathing room around — and between — the three browse panes
20/// (history, files, diff), so they don't run into each other or the window
21/// edge.
22pub const BROWSE_PAD: i32 = 4;
23
24pub fn browse_menu(b: Rect) -> Rect {
25    Rect::new(b.x, b.y, b.w, MENU_H)
26}
27
28pub fn browse_toolbar(b: Rect) -> Rect {
29    Rect::new(b.x, b.y + MENU_H, b.w, TOOLBAR_H)
30}
31
32/// Top of the padded three-pane content area, below the menu and toolbar.
33fn content_y(b: Rect) -> i32 {
34    b.y + MENU_H + TOOLBAR_H + BROWSE_PAD
35}
36
37/// Height available to the three panes, after top and bottom padding.
38fn content_h(b: Rect) -> i32 {
39    (b.h - MENU_H - TOOLBAR_H - 2 * BROWSE_PAD).max(0)
40}
41
42/// Height of the history pane: a fraction of the content area, leaving a gap
43/// above the lower (files + diff) band.
44fn history_h(b: Rect) -> i32 {
45    let avail = (content_h(b) - BROWSE_PAD).max(0);
46    (avail as f32 * HISTORY_FRAC).round() as i32
47}
48
49pub fn browse_history(b: Rect) -> Rect {
50    Rect::new(
51        b.x + BROWSE_PAD,
52        content_y(b),
53        (b.w - 2 * BROWSE_PAD).max(0),
54        history_h(b),
55    )
56}
57
58pub fn browse_files(b: Rect) -> Rect {
59    let (lower_y, lower_h) = lower_band(b);
60    Rect::new(b.x + BROWSE_PAD, lower_y, clamp_files_w(b), lower_h)
61}
62
63pub fn browse_diff(b: Rect) -> Rect {
64    let (lower_y, lower_h) = lower_band(b);
65    let files_w = clamp_files_w(b);
66    let diff_x = b.x + 2 * BROWSE_PAD + files_w;
67    let diff_w = (b.w - files_w - 3 * BROWSE_PAD).max(0);
68    Rect::new(diff_x, lower_y, diff_w, lower_h)
69}
70
71/// The (top, height) of the lower band holding the files and diff panes, below
72/// the history pane and the gap under it.
73fn lower_band(b: Rect) -> (i32, i32) {
74    let lower_y = content_y(b) + history_h(b) + BROWSE_PAD;
75    let lower_h = (content_h(b) - history_h(b) - BROWSE_PAD).max(0);
76    (lower_y, lower_h)
77}
78
79/// Width of the files pane, clamped so the diff pane keeps a usable minimum
80/// once the inter-pane gap is accounted for.
81fn clamp_files_w(b: Rect) -> i32 {
82    FILES_W.min((b.w - 3 * BROWSE_PAD - 80).max(0))
83}
84
85// ---- commit (git-gui) layout ----------------------------------------------
86
87const LEFT_W: i32 = 320;
88const PAD: i32 = 6;
89const HEADING_H: i32 = 18;
90const LEFT_BTN_H: i32 = 28;
91const RIGHT_BTN_H: i32 = 34;
92const DIFF_FRAC: f32 = 0.5;
93const BTN_W: i32 = 96;
94const BTN_GAP: i32 = 4;
95
96pub fn commit_menu(b: Rect) -> Rect {
97    Rect::new(b.x, b.y, b.w, MENU_H)
98}
99
100fn content_top(b: Rect) -> i32 {
101    b.y + MENU_H
102}
103fn content_height(b: Rect) -> i32 {
104    (b.h - MENU_H).max(0)
105}
106fn left_x(b: Rect) -> i32 {
107    b.x + PAD
108}
109fn left_w() -> i32 {
110    (LEFT_W - 2 * PAD).max(0)
111}
112fn left_area_h(b: Rect) -> i32 {
113    (content_height(b) - LEFT_BTN_H).max(0)
114}
115fn section_h(b: Rect) -> i32 {
116    left_area_h(b) / 2
117}
118
119pub fn commit_unstaged_label(b: Rect) -> Rect {
120    Rect::new(left_x(b), content_top(b) + 2, left_w(), HEADING_H)
121}
122
123pub fn commit_unstaged_list(b: Rect) -> Rect {
124    let y = content_top(b) + 2 + HEADING_H;
125    Rect::new(
126        left_x(b),
127        y,
128        left_w(),
129        (section_h(b) - HEADING_H - 4).max(0),
130    )
131}
132
133pub fn commit_staged_label(b: Rect) -> Rect {
134    let y = content_top(b) + section_h(b) + 2;
135    Rect::new(left_x(b), y, left_w(), HEADING_H)
136}
137
138pub fn commit_staged_list(b: Rect) -> Rect {
139    let y = content_top(b) + section_h(b) + 2 + HEADING_H;
140    let h = (left_area_h(b) - section_h(b) - HEADING_H - 4).max(0);
141    Rect::new(left_x(b), y, left_w(), h)
142}
143
144fn left_btn_y(b: Rect) -> i32 {
145    content_top(b) + left_area_h(b) + 2
146}
147
148pub fn commit_stage_btn(b: Rect) -> Rect {
149    Rect::new(left_x(b), left_btn_y(b), BTN_W, 24)
150}
151
152pub fn commit_unstage_btn(b: Rect) -> Rect {
153    Rect::new(left_x(b) + BTN_W + BTN_GAP, left_btn_y(b), BTN_W, 24)
154}
155
156pub fn commit_rescan_btn(b: Rect) -> Rect {
157    Rect::new(left_x(b) + 2 * (BTN_W + BTN_GAP), left_btn_y(b), BTN_W, 24)
158}
159
160fn right_x(b: Rect) -> i32 {
161    b.x + LEFT_W
162}
163fn right_w(b: Rect) -> i32 {
164    (b.w - LEFT_W).max(0)
165}
166fn right_inner_x(b: Rect) -> i32 {
167    right_x(b) + PAD
168}
169fn right_inner_w(b: Rect) -> i32 {
170    (right_w(b) - 2 * PAD).max(0)
171}
172fn diff_h(b: Rect) -> i32 {
173    (content_height(b) as f32 * DIFF_FRAC) as i32
174}
175fn right_btn_y(b: Rect) -> i32 {
176    content_top(b) + content_height(b) - RIGHT_BTN_H + 4
177}
178
179pub fn commit_diff(b: Rect) -> Rect {
180    Rect::new(
181        right_inner_x(b),
182        content_top(b) + 2,
183        right_inner_w(b),
184        (diff_h(b) - 4).max(0),
185    )
186}
187
188pub fn commit_msg_label(b: Rect) -> Rect {
189    Rect::new(
190        right_inner_x(b),
191        content_top(b) + diff_h(b),
192        right_inner_w(b),
193        HEADING_H,
194    )
195}
196
197pub fn commit_editor(b: Rect) -> Rect {
198    let top = content_top(b) + diff_h(b) + HEADING_H;
199    let h = (right_btn_y(b) - top - 4).max(0);
200    Rect::new(right_inner_x(b), top, right_inner_w(b), h)
201}
202
203pub fn commit_amend(b: Rect) -> Rect {
204    Rect::new(right_inner_x(b), right_btn_y(b), 180, 24)
205}
206
207pub fn commit_commit_btn(b: Rect) -> Rect {
208    let w = 110;
209    Rect::new(right_x(b) + right_w(b) - PAD - w, right_btn_y(b), w, 26)
210}