From d231865f885672e8d4f797e5344682890a90f0cc Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Thu, 9 May 2019 12:53:47 +0300 Subject: [PATCH] ui: add scrollbar widget in view/thread.rs --- ui/src/components/mail/view/thread.rs | 34 +++++++++++++++++++++-- ui/src/components/utilities/widgets.rs | 37 +++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/ui/src/components/mail/view/thread.rs b/ui/src/components/mail/view/thread.rs index 917ce64f..b8741491 100644 --- a/ui/src/components/mail/view/thread.rs +++ b/ui/src/components/mail/view/thread.rs @@ -360,7 +360,7 @@ impl ThreadView { /// draw the list fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { - let upper_left = upper_left!(area); + let mut upper_left = pos_inc(upper_left!(area), (1, 0)); let bottom_right = bottom_right!(area); let (width, height) = self.content.size(); if height == 0 { @@ -373,7 +373,9 @@ impl ThreadView { let page_no = (self.new_cursor_pos).wrapping_div(rows); let top_idx = page_no * rows; - + if (rows >= height!(self.content.area())) { + upper_left = pos_dec(upper_left!(area), (1, 0)); + } /* This closure (written for code clarity, should be inlined by the compiler) returns the * **line** of an entry in the ThreadView grid. */ let get_entry_area = |idx: usize, entries: &[ThreadEntry]| { @@ -454,6 +456,18 @@ impl ThreadView { ); self.highlight_line(grid, dest_area, src_area, idx); + if (rows < height!(self.content.area())) { + ScrollBar::draw( + grid, + ( + upper_left!(area), + set_x(bottom_right, get_x(upper_left!(area)) + 1), + ), + self.cursor_pos, + rows, + visibles.len(), + ); + } self.dirty = false; context.dirty_areas.push_back(area); } else { @@ -491,6 +505,22 @@ impl ThreadView { ); self.highlight_line(grid, dest_area, src_area, entry_idx); + if (rows < height!(self.content.area())) { + ScrollBar::draw( + grid, + ( + upper_left!(area), + set_x(bottom_right, get_x(upper_left!(area)) + 1), + ), + self.cursor_pos, + rows, + visibles.len(), + ); + context.dirty_areas.push_back(( + upper_left!(area), + set_x(bottom_right, get_x(upper_left!(area)) + 1), + )); + } let (upper_left, bottom_right) = dest_area; context diff --git a/ui/src/components/utilities/widgets.rs b/ui/src/components/utilities/widgets.rs index 71894171..1da31f30 100644 --- a/ui/src/components/utilities/widgets.rs +++ b/ui/src/components/utilities/widgets.rs @@ -226,7 +226,8 @@ impl FormWidget { buttons: ButtonWidget::new((action, true)), focus: FormFocus::Fields, hide_buttons: false, - id: ComponentId::new_v4(), ..Default::default() + id: ComponentId::new_v4(), + ..Default::default() } } @@ -694,3 +695,37 @@ impl AutoComplete { Some(ret) } } + +pub struct ScrollBar(); + +impl ScrollBar { + pub fn draw(grid: &mut CellBuffer, area: Area, pos: usize, visible_rows: usize, length: usize) { + if length == 0 { + return; + } + let height = height!(area); + if height < 3 { + return; + } + let visible_ratio: f32 = (std::cmp::min(visible_rows, length) as f32) / (length as f32); + let scrollbar_height = std::cmp::max((visible_ratio * (length as f32)) as usize, 1); + let scrollbar_offset = (visible_ratio * (pos as f32)) as usize + 1; + + let (upper_left, bottom_right) = area; + + grid[upper_left].set_ch('▴'); + for y in get_y(upper_left) + 1..(get_y(upper_left) + scrollbar_offset) { + grid[set_y(upper_left, y)].set_ch(' '); + } + for y in (get_y(upper_left) + scrollbar_offset) + ..(get_y(upper_left) + scrollbar_offset + scrollbar_height) + { + grid[set_y(upper_left, y)].set_ch('█'); + } + for y in (get_y(upper_left) + scrollbar_offset + scrollbar_height)..get_y(bottom_right) - 1 + { + grid[set_y(upper_left, y)].set_ch(' '); + } + grid[set_x(bottom_right, get_x(upper_left))].set_ch('▾'); + } +}