1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
mod help;
mod image;
mod image_list;
mod info;
mod loading;
mod title;

use crate::app::App;
use std::rc::Rc;
use tui::{
    backend::Backend,
    layout::{Constraint, Direction, Layout, Rect},
    widgets::ListState,
    Frame,
};

pub fn draw<B>(rect: &mut Frame<B>, app: &mut App)
where
    B: Backend,
{
    let size = rect.size();

    let main_chunks = main_layout(size);
    let header_chunks = header_layout(main_chunks[0]);
    let body_chunks = body_layout(main_chunks[1]);
    let info_chunks = info_layout(header_chunks[1]);

    let title = title::draw();
    let help = help::draw(app.actions());
    let info = info::draw(app.state());
    let image_list = image_list::draw(app.state());

    rect.render_widget(title, header_chunks[0]);
    rect.render_widget(help, info_chunks[0]);
    rect.render_widget(info, info_chunks[1]);

    let mut state = ListState::default();
    state.select(app.state.get_index());
    rect.render_stateful_widget(image_list, body_chunks[0], &mut state);

    let w = body_chunks[1].width as u32;
    let h = body_chunks[1].height as u32;
    app.state.set_term_size(w, h);

    if app.is_loading() && app.state.get_current_image().is_some() {
        let loading = loading::draw();
        rect.render_widget(loading, body_chunks[1]);
    } else {
        let image = image::draw(app.state());
        rect.render_widget(image, body_chunks[1]);
    }
}

fn main_layout(rect: Rect) -> Rc<[Rect]> {
    Layout::default()
        .direction(Direction::Vertical)
        .constraints([Constraint::Length(8), Constraint::Percentage(90)])
        .margin(1)
        .split(rect)
}

fn header_layout(rect: Rect) -> Rc<[Rect]> {
    Layout::default()
        .direction(Direction::Vertical)
        .constraints([Constraint::Percentage(30), Constraint::Percentage(70)])
        .split(rect)
}

fn info_layout(rect: Rect) -> Rc<[Rect]> {
    Layout::default()
        .direction(Direction::Horizontal)
        .constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
        .split(rect)
}

fn body_layout(rect: Rect) -> Rc<[Rect]> {
    Layout::default()
        .direction(Direction::Horizontal)
        .constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
        .split(rect)
}