Skip to content

Commit 7e00052

Browse files
Merge pull request #15 from josueBarretogit/tui-widget-list-improve-appeareance
improved appearance of application
2 parents 4c45758 + 58b15c0 commit 7e00052

File tree

4 files changed

+88
-48
lines changed

4 files changed

+88
-48
lines changed

Cargo.lock

+17-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "get-blessed"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
edition = "2021"
55
authors = ["Josue <[email protected]>"]
66
readme = "README.md"
@@ -28,3 +28,4 @@ throbber-widgets-tui = "0.5.0"
2828
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] }
2929
crates_io_api = "0.11.0"
3030
type_utilities = { version = "0.1.2", features = ["bool"] }
31+
tui-widget-list = "0.9.0"

src/view/app.rs

+7-27
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub struct Features {
6464
#[derive(Default)]
6565
pub struct CratesList {
6666
widget: CratesListWidget,
67-
state: ListState,
67+
state: tui_widget_list::ListState,
6868
}
6969

7070
///This struct holds the list of crates to be added to user's project
@@ -404,31 +404,11 @@ impl App {
404404
}
405405

406406
pub fn scroll_down(&mut self) {
407-
let next = match self.crates_list.state.selected() {
408-
Some(index) => {
409-
if index == self.crates_list.widget.crates.len().saturating_sub(1) {
410-
0
411-
} else {
412-
index.saturating_add(1)
413-
}
414-
}
415-
None => self.crates_list.state.selected().unwrap_or(0),
416-
};
417-
self.crates_list.state.select(Some(next));
407+
self.crates_list.state.next();
418408
}
419409

420410
pub fn scroll_up(&mut self) {
421-
let next_index = match self.crates_list.state.selected() {
422-
Some(index) => {
423-
if index == 0 {
424-
self.crates_list.widget.crates.len().saturating_sub(1)
425-
} else {
426-
index.saturating_sub(1)
427-
}
428-
}
429-
None => 1,
430-
};
431-
self.crates_list.state.select(Some(next_index));
411+
self.crates_list.state.previous();
432412
}
433413

434414
pub fn scroll_up_features(&mut self) {
@@ -514,14 +494,14 @@ impl App {
514494
}
515495

516496
pub fn get_current_crate_selected(&self) -> Option<(CrateItemList, usize)> {
517-
self.crates_list.state.selected().map(|index| {
497+
self.crates_list.state.selected.map(|index| {
518498
let crate_item = self.crates_list.widget.crates[index].clone();
519499
(crate_item, index)
520500
})
521501
}
522502

523503
pub fn toggle_select_dependencie(&mut self) {
524-
if let Some(index_crate_selected) = self.crates_list.state.selected() {
504+
if let Some(index_crate_selected) = self.crates_list.state.selected {
525505
match self.crate_categories.widget {
526506
CategoriesWidget::Clis => {
527507
toggle_status_one_crate(&mut self.clis_crates[index_crate_selected]);
@@ -570,7 +550,7 @@ impl App {
570550
}
571551

572552
pub fn check_docs(&self) {
573-
if let Some(index_selected) = self.crates_list.state.selected() {
553+
if let Some(index_selected) = self.crates_list.state.selected {
574554
let crate_name = &self.crates_list.widget.crates[index_selected].name;
575555
let url = format!("https://docs.rs/{crate_name}/latest/{crate_name}/");
576556

@@ -579,7 +559,7 @@ impl App {
579559
}
580560

581561
pub fn check_crates_io(&self) {
582-
if let Some(index_selected) = self.crates_list.state.selected() {
562+
if let Some(index_selected) = self.crates_list.state.selected {
583563
let url = format!(
584564
"https://crates.io/crates/{}",
585565
self.crates_list.widget.crates[index_selected].name

src/view/widgets.rs

+62-13
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@ use ratatui::{
33
style::{palette::tailwind, Style},
44
widgets::{
55
block::{Block, Padding, Position, Title},
6-
HighlightSpacing, List, ListDirection, ListItem, ListState, Paragraph, StatefulWidgetRef,
6+
Borders, List, ListDirection, ListItem, ListState, Paragraph,
7+
StatefulWidgetRef, Wrap,
78
},
89
};
910
use strum::{Display, EnumIter, FromRepr, IntoEnumIterator};
1011
use throbber_widgets_tui::{Throbber, ThrobberState};
12+
use tui_widget_list::PreRender;
1113

1214
use crate::dependency_builder::CrateToAdd;
1315

16+
use self::style::Stylize;
17+
1418
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
1519
pub enum ItemListStatus {
1620
Selected,
@@ -117,7 +121,14 @@ impl From<FeatureItemList> for ListItem<'_> {
117121
ItemListStatus::Unselected => ("☐", Color::default()),
118122
};
119123

120-
let line = Line::from(vec![value.name.into(), " ".into(), is_selected.into()]);
124+
let line = match value.status {
125+
ItemListStatus::Selected => {
126+
Line::from(vec![value.name.black(), " ".into(), is_selected.black()])
127+
}
128+
ItemListStatus::Unselected => {
129+
Line::from(vec![value.name.into(), " ".into(), is_selected.into()])
130+
}
131+
};
121132

122133
ListItem::new(line).style(Style::default().bg(bg_color))
123134
}
@@ -169,7 +180,6 @@ impl StatefulWidgetRef for FeaturesWidgetList {
169180
match &self.features {
170181
Some(features) => {
171182
let features_list = List::new(features.clone())
172-
.highlight_style(Style::default().blue())
173183
.highlight_symbol(">> ")
174184
.direction(ListDirection::TopToBottom);
175185

@@ -212,9 +222,52 @@ pub struct CrateItemList {
212222
pub description: String,
213223
pub features: Option<Vec<FeatureItemList>>,
214224
pub status: ItemListStatus,
225+
pub highlight_style: String,
215226
pub is_loading: bool,
216227
}
217228

229+
impl ratatui::widgets::Widget for CrateItemList {
230+
fn render(self, area: Rect, buf: &mut Buffer)
231+
where
232+
Self: Sized,
233+
{
234+
let layout = Layout::default()
235+
.direction(Direction::Horizontal)
236+
.constraints([Constraint::Fill(1), Constraint::Fill(4)]);
237+
238+
let [name_area, description_area] = layout.areas(area);
239+
240+
let (is_selected, bg_color) = match self.status {
241+
ItemListStatus::Selected => ("✓", tailwind::BLUE.c300),
242+
ItemListStatus::Unselected => ("☐", Color::default()),
243+
};
244+
245+
let name = format!("{} {} {}", self.highlight_style, self.name, is_selected);
246+
247+
name.bold().blue().render(name_area, buf);
248+
249+
let description = match self.status {
250+
ItemListStatus::Unselected => self.description.into(),
251+
ItemListStatus::Selected => self.description.black(),
252+
};
253+
254+
Paragraph::new(description)
255+
.block(Block::default().borders(Borders::BOTTOM))
256+
.style(Style::new().bg(bg_color))
257+
.wrap(Wrap { trim: true })
258+
.render(description_area, buf);
259+
}
260+
}
261+
262+
impl PreRender for CrateItemList {
263+
fn pre_render(&mut self, context: &tui_widget_list::PreRenderContext) -> u16 {
264+
if context.is_selected {
265+
self.highlight_style = ">>".to_string();
266+
}
267+
4
268+
}
269+
}
270+
218271
#[derive(Clone, Default)]
219272
pub struct CratesToAddListWidget {
220273
pub crates: Vec<CrateToAdd>,
@@ -263,6 +316,7 @@ impl CrateItemList {
263316
features,
264317
status,
265318
is_loading: true,
319+
highlight_style: String::default(),
266320
}
267321
}
268322
}
@@ -292,16 +346,9 @@ impl From<CrateItemList> for ListItem<'_> {
292346
}
293347

294348
impl StatefulWidgetRef for CratesListWidget {
295-
type State = ListState;
349+
type State = tui_widget_list::ListState;
296350
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
297-
let block = Block::default().padding(Padding::uniform(1));
298-
299-
let list = List::new(self.crates.clone())
300-
.block(block)
301-
.highlight_style(Style::default())
302-
.highlight_symbol(">> ")
303-
.highlight_spacing(HighlightSpacing::Always)
304-
.direction(ListDirection::TopToBottom);
351+
let list = tui_widget_list::List::new(self.crates.clone());
305352

306353
StatefulWidget::render(list, area, buf, state);
307354
}
@@ -333,7 +380,9 @@ impl<'a> Widget for FooterInstructions<'a> {
333380
{
334381
let instructions = Title::from(Line::from(self.instructions));
335382

336-
let info = Title::from(Line::from(vec!["V0.2.0".into()]))
383+
let curret_version = format!("V{}", env!("CARGO_PKG_VERSION"));
384+
385+
let info = Title::from(Line::from(vec![curret_version.into()]))
337386
.position(Position::Top)
338387
.alignment(Alignment::Right);
339388

0 commit comments

Comments
 (0)