summaryrefslogtreecommitdiffstats
path: root/src/interactive/widgets/mark.rs
blob: 67596bda246c5e5acf2fe5fac0dd0b9ee4a95752 (plain)
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crate::interactive::{widgets::COLOR_MARKED_LIGHT, CursorDirection, EntryMark, EntryMarkMap};
use dua::path_of;
use dua::traverse::{Tree, TreeIndex};
use std::borrow::Borrow;
use termion::{event::Key, event::Key::*};
use tui::{
    buffer::Buffer,
    layout::Rect,
    style::{Modifier, Style},
    widgets::Block,
    widgets::Borders,
    widgets::Text,
};
use tui_react::{List, ListProps};

#[derive(Default)]
pub struct MarkPane {
    selected: Option<usize>,
    marked: EntryMarkMap,
    list: List,
}

pub struct MarkPaneProps {
    pub border_style: Style,
}

impl MarkPane {
    pub fn toggle_index(mut self, index: TreeIndex, tree: &Tree) -> Option<Self> {
        if self.marked.get(&index).is_some() {
            self.marked.remove(&index);
        } else {
            if let Some(e) = tree.node_weight(index) {
                self.marked.insert(
                    index,
                    EntryMark {
                        size: e.size,
                        path: path_of(tree, index),
                    },
                );
            }
        }
        if self.marked.is_empty() {
            None
        } else {
            Some(self)
        }
    }
    pub fn marked(&self) -> &EntryMarkMap {
        &self.marked
    }
    pub fn key(&mut self, key: Key) {
        match key {
            Ctrl('u') | PageUp => self.change_selection(CursorDirection::PageUp),
            Char('k') | Up => self.change_selection(CursorDirection::Up),
            Char('j') | Down => self.change_selection(CursorDirection::Down),
            Ctrl('d') | PageDown => self.change_selection(CursorDirection::PageDown),
            _ => {}
        };
    }

    fn change_selection(&mut self, _direction: CursorDirection) {}

    pub fn render(&mut self, props: impl Borrow<MarkPaneProps>, area: Rect, buf: &mut Buffer) {
        let MarkPaneProps { border_style } = props.borrow();

        let marked: &_ = &self.marked;
        let block = Block::default()
            .title("Marked Entries")
            .border_style(*border_style)
            .borders(Borders::ALL);
        let entry_in_view = self
            .selected
            .map(|selected| selected)
            .or(Some(marked.len().saturating_sub(1)));
        let selected = self.selected;
        let entries = marked.values().enumerate().map(|(idx, v)| {
            let modifier = match selected {
                Some(selected) if idx == selected => Modifier::BOLD,
                _ => Modifier::empty(),
            };
            let name = Text::Styled(
                v.path.to_string_lossy(),
                Style {
                    fg: COLOR_MARKED_LIGHT,
                    modifier,
                    ..Style::default()
                },
            );
            vec![name]
        });

        let props = ListProps {
            block: Some(block),
            entry_in_view,
        };
        self.list.render(props, entries, area, buf)
    }
}