Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c5fd940

Browse files
author
Sebastian Thiel
committed
FINALLY! It works, and is on the way to using tui-react
1 parent 180ebb7 commit c5fd940

5 files changed

Lines changed: 118 additions & 219 deletions

File tree

src/interactive/react/list.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{BlockProps, Component};
1+
use super::BlockProps;
22
use std::borrow::Borrow;
33
use std::iter::repeat;
44
use tui::{
@@ -20,36 +20,40 @@ pub fn fill_background_to_right(mut s: String, entire_width: u16) -> String {
2020
#[derive(Default)] // TODO: remove Clone derive
2121
pub struct ReactList {
2222
/// The index at which the list last started. Used for scrolling
23-
start_index: usize,
23+
offset: usize,
2424
}
2525

2626
impl ReactList {
27-
fn update_start_index(&mut self, selected: Option<usize>, height: usize) -> &mut Self {
28-
self.start_index = match selected {
27+
fn list_offset_for(&self, entry_in_view: Option<usize>, height: usize) -> usize {
28+
match entry_in_view {
2929
Some(pos) => match height as usize {
30-
h if self.start_index + h - 1 < pos => pos - h + 1,
31-
_ if self.start_index > pos => pos,
32-
_ => self.start_index,
30+
h if self.offset + h - 1 < pos => pos - h + 1,
31+
_ if self.offset > pos => pos,
32+
_ => self.offset,
3333
},
3434
None => 0,
35-
};
36-
self
35+
}
3736
}
3837
}
3938

40-
pub struct ReactListProps<'b, 't> {
39+
#[derive(Default)]
40+
pub struct ReactListProps<'b> {
4141
pub block: Option<BlockProps<'b>>,
42-
pub items: Vec<Vec<Text<'t>>>,
42+
pub entry_in_view: Option<usize>,
4343
}
4444

4545
impl ReactList {
46-
pub fn render<'a, 'b>(
46+
pub fn render<'a, 't>(
4747
&mut self,
48-
props: impl Borrow<ReactListProps<'a, 'b>>,
48+
props: impl Borrow<ReactListProps<'a>>,
49+
items: impl IntoIterator<Item = Vec<Text<'t>>>,
4950
area: Rect,
5051
buf: &mut Buffer,
5152
) {
52-
let ReactListProps { block, items } = props.borrow();
53+
let ReactListProps {
54+
block,
55+
entry_in_view,
56+
} = props.borrow();
5357

5458
let list_area = match block {
5559
Some(b) => {
@@ -58,12 +62,18 @@ impl ReactList {
5862
}
5963
None => area,
6064
};
65+
self.offset = self.list_offset_for(*entry_in_view, list_area.height as usize);
6166

6267
if list_area.width < 1 || list_area.height < 1 {
6368
return;
6469
}
6570

66-
for (i, text_iterator) in items.iter().enumerate().take(list_area.height as usize) {
71+
for (i, text_iterator) in items
72+
.into_iter()
73+
.skip(self.offset)
74+
.enumerate()
75+
.take(list_area.height as usize)
76+
{
6777
let (x, y) = (list_area.left(), list_area.top() + i as u16);
6878
Paragraph::new(text_iterator.iter()).draw(
6979
Rect {

src/interactive/widgets/entries.rs

Lines changed: 92 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
use crate::{
2-
interactive::react::Component,
3-
interactive::{
4-
react::{BlockProps, ReactList, ReactListProps},
5-
widgets::{fill_background_to_right, ListState},
6-
DisplayOptions, EntryDataBundle,
7-
},
1+
use crate::interactive::{
2+
react::{fill_background_to_right, BlockProps, ReactList, ReactListProps},
3+
DisplayOptions, EntryDataBundle,
84
};
95
use dua::traverse::{Tree, TreeIndex};
106
use itertools::Itertools;
@@ -16,20 +12,19 @@ use tui::{
1612
widgets::{Borders, Text, Widget},
1713
};
1814

19-
pub struct Entries<'a, 'b> {
15+
pub struct Entries<'a> {
2016
pub tree: &'a Tree,
2117
pub root: TreeIndex,
2218
pub display: DisplayOptions,
2319
pub selected: Option<TreeIndex>,
24-
pub list_state: &'b mut ListState,
2520
pub entries: &'a [EntryDataBundle],
2621
pub border_style: Style,
2722
pub is_focussed: bool,
2823

2924
pub list: ReactList,
3025
}
3126

32-
impl<'a, 'b> Widget for Entries<'a, 'b> {
27+
impl<'a, 'b> Widget for Entries<'a> {
3328
fn draw(&mut self, area: Rect, buf: &mut Buffer) {
3429
let Self {
3530
tree,
@@ -38,7 +33,6 @@ impl<'a, 'b> Widget for Entries<'a, 'b> {
3833
entries,
3934
selected,
4035
border_style,
41-
list_state,
4236
is_focussed,
4337
list,
4438
} = self;
@@ -63,105 +57,97 @@ impl<'a, 'b> Widget for Entries<'a, 'b> {
6357
title: Some(&title),
6458
..Default::default()
6559
};
66-
67-
let offset = list_state
68-
.update(
69-
selected.map(|selected| {
70-
entries
71-
.iter()
72-
.find_position(|b| b.index == selected)
73-
.map(|(idx, _)| idx)
74-
.unwrap_or(0)
75-
}),
76-
block.inner(area).height as usize,
77-
)
78-
.start_index;
60+
let entry_in_view = selected.map(|selected| {
61+
entries
62+
.iter()
63+
.find_position(|b| b.index == selected)
64+
.map(|(idx, _)| idx)
65+
.unwrap_or(0)
66+
});
7967

8068
let props = ReactListProps {
8169
block: Some(block),
82-
items: entries
83-
.iter()
84-
.skip(offset)
85-
.map(
86-
|EntryDataBundle {
87-
index: node_idx,
88-
data: w,
89-
is_dir,
90-
exists,
91-
}| {
92-
let (is_selected, style) = match selected {
93-
Some(idx) if *idx == *node_idx => (
94-
true,
95-
Style {
96-
fg: Color::Black,
97-
bg: if *is_focussed {
98-
Color::White
99-
} else {
100-
Color::DarkGray
101-
},
102-
..Default::default()
103-
},
104-
),
105-
_ => (
106-
false,
107-
Style {
108-
fg: Color::White,
109-
bg: Color::Reset,
110-
..Default::default()
111-
},
112-
),
113-
};
114-
115-
let bytes = Text::Styled(
116-
format!(
117-
"{:>byte_column_width$}",
118-
display.byte_format.display(w.size).to_string(), // we would have to impl alignment/padding ourselves otherwise...
119-
byte_column_width = display.byte_format.width()
120-
)
121-
.into(),
122-
Style {
123-
fg: match (is_selected, *is_focussed) {
124-
(true, true) => Color::DarkGray,
125-
(true, false) => Color::Black,
126-
_ => Color::Green,
127-
},
128-
..style
129-
},
130-
);
131-
let percentage = Text::Styled(
132-
format!(
133-
" |{}| ",
134-
display.byte_vis.display(w.size as f32 / total as f32)
135-
)
136-
.into(),
137-
style,
138-
);
139-
let name = Text::Styled(
140-
fill_background_to_right(
141-
format!(
142-
"{prefix}{}",
143-
w.name.to_string_lossy(),
144-
prefix = if *is_dir && !is_top(*root) { "/" } else { " " }
145-
),
146-
area.width,
147-
)
148-
.into(),
149-
Style {
150-
fg: match (!is_dir, exists) {
151-
(true, true) if !is_selected => Color::DarkGray,
152-
(true, true) => style.fg,
153-
(_, false) => Color::Red,
154-
(false, true) => style.fg,
155-
},
156-
..style
70+
entry_in_view,
71+
};
72+
let lines = entries.iter().map(
73+
|EntryDataBundle {
74+
index: node_idx,
75+
data: w,
76+
is_dir,
77+
exists,
78+
}| {
79+
let (is_selected, style) = match selected {
80+
Some(idx) if *idx == *node_idx => (
81+
true,
82+
Style {
83+
fg: Color::Black,
84+
bg: if *is_focussed {
85+
Color::White
86+
} else {
87+
Color::DarkGray
15788
},
158-
);
159-
let column_segments = vec![bytes, percentage, name];
160-
column_segments
89+
..Default::default()
90+
},
91+
),
92+
_ => (
93+
false,
94+
Style {
95+
fg: Color::White,
96+
bg: Color::Reset,
97+
..Default::default()
98+
},
99+
),
100+
};
101+
102+
let bytes = Text::Styled(
103+
format!(
104+
"{:>byte_column_width$}",
105+
display.byte_format.display(w.size).to_string(), // we would have to impl alignment/padding ourselves otherwise...
106+
byte_column_width = display.byte_format.width()
107+
)
108+
.into(),
109+
Style {
110+
fg: match (is_selected, *is_focussed) {
111+
(true, true) => Color::DarkGray,
112+
(true, false) => Color::Black,
113+
_ => Color::Green,
114+
},
115+
..style
161116
},
162-
)
163-
.collect(),
164-
};
165-
list.render(props, area, buf);
117+
);
118+
let percentage = Text::Styled(
119+
format!(
120+
" |{}| ",
121+
display.byte_vis.display(w.size as f32 / total as f32)
122+
)
123+
.into(),
124+
style,
125+
);
126+
let name = Text::Styled(
127+
fill_background_to_right(
128+
format!(
129+
"{prefix}{}",
130+
w.name.to_string_lossy(),
131+
prefix = if *is_dir && !is_top(*root) { "/" } else { " " }
132+
),
133+
area.width,
134+
)
135+
.into(),
136+
Style {
137+
fg: match (!is_dir, exists) {
138+
(true, true) if !is_selected => Color::DarkGray,
139+
(true, true) => style.fg,
140+
(_, false) => Color::Red,
141+
(false, true) => style.fg,
142+
},
143+
..style
144+
},
145+
);
146+
let column_segments = vec![bytes, percentage, name];
147+
column_segments
148+
},
149+
);
150+
151+
list.render(props, lines, area, buf);
166152
}
167153
}

src/interactive/widgets/list.rs

Lines changed: 0 additions & 81 deletions
This file was deleted.

0 commit comments

Comments
 (0)