ui: expand Listing trait with draw_list and highlight_line
In the course of making the Listing trait a generic way for any kind of listing (eg. NNTP, RSS, et all)embed
parent
c34a55dcac
commit
bb292486f4
|
@ -30,6 +30,12 @@ pub use self::thread::*;
|
|||
mod plain;
|
||||
pub use self::plain::*;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub(in crate::listing) struct DataColumns {
|
||||
columns: [CellBuffer; 12],
|
||||
widths: [usize; 12], // widths of columns calculated in first draw and after size changes
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AccountMenuEntry {
|
||||
name: String,
|
||||
|
@ -40,6 +46,8 @@ struct AccountMenuEntry {
|
|||
trait ListingTrait {
|
||||
fn coordinates(&self) -> (usize, usize, Option<EnvelopeHash>);
|
||||
fn set_coordinates(&mut self, _: (usize, usize, Option<EnvelopeHash>));
|
||||
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context);
|
||||
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -65,6 +73,20 @@ impl ListingTrait for ListingComponent {
|
|||
Threaded(ref mut l) => l.set_coordinates(c),
|
||||
}
|
||||
}
|
||||
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
match self {
|
||||
Compact(ref mut l) => l.draw_list(grid, area, context),
|
||||
Plain(ref mut l) => l.draw_list(grid, area, context),
|
||||
Threaded(ref mut l) => l.draw_list(grid, area, context),
|
||||
}
|
||||
}
|
||||
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context) {
|
||||
match self {
|
||||
Compact(ref mut l) => l.highlight_line(grid, area, idx, context),
|
||||
Plain(ref mut l) => l.highlight_line(grid, area, idx, context),
|
||||
Threaded(ref mut l) => l.highlight_line(grid, area, idx, context),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -123,11 +145,11 @@ impl Component for Listing {
|
|||
grid[(mid, i)].set_bg(Color::Default);
|
||||
}
|
||||
}
|
||||
self.dirty = false;
|
||||
context
|
||||
.dirty_areas
|
||||
.push_back(((mid, get_y(upper_left)), (mid, get_y(bottom_right))));
|
||||
}
|
||||
self.dirty = false;
|
||||
if right_component_width == total_cols {
|
||||
match self.component {
|
||||
Compact(ref mut l) => l.draw(grid, area, context),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -93,6 +93,106 @@ impl ListingTrait for PlainListing {
|
|||
fn set_coordinates(&mut self, coordinates: (usize, usize, Option<EnvelopeHash>)) {
|
||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||
}
|
||||
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let envelope: &Envelope = &account.get_env(&self.local_collection[idx]);
|
||||
|
||||
let fg_color = if !envelope.is_seen() {
|
||||
Color::Byte(0)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
let bg_color = if self.cursor_pos.2 == idx {
|
||||
Color::Byte(246)
|
||||
} else if !envelope.is_seen() {
|
||||
Color::Byte(251)
|
||||
} else if idx % 2 == 0 {
|
||||
Color::Byte(236)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
change_colors(grid, area, fg_color, bg_color);
|
||||
}
|
||||
|
||||
/// Draw the list of `Envelope`s.
|
||||
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if self.cursor_pos.1 != self.new_cursor_pos.1 || self.cursor_pos.0 != self.new_cursor_pos.0
|
||||
{
|
||||
self.refresh_mailbox(context);
|
||||
}
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
if self.length == 0 {
|
||||
clear_area(grid, area);
|
||||
copy_area(grid, &self.content, area, ((0, 0), (MAX_COLS - 1, 0)));
|
||||
context.dirty_areas.push_back(area);
|
||||
return;
|
||||
}
|
||||
let rows = get_y(bottom_right) - get_y(upper_left) + 1;
|
||||
if let Some(mvm) = self.movement.take() {
|
||||
match mvm {
|
||||
PageMovement::PageUp => {
|
||||
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows);
|
||||
}
|
||||
PageMovement::PageDown => {
|
||||
if self.new_cursor_pos.2 + rows + 1 < self.length {
|
||||
self.new_cursor_pos.2 += rows;
|
||||
} else {
|
||||
self.new_cursor_pos.2 = (self.length / rows) * rows;
|
||||
}
|
||||
}
|
||||
PageMovement::Home => {
|
||||
self.new_cursor_pos.2 = 0;
|
||||
}
|
||||
PageMovement::End => {
|
||||
self.new_cursor_pos.2 = (self.length / rows) * rows;
|
||||
}
|
||||
}
|
||||
}
|
||||
let prev_page_no = (self.cursor_pos.2).wrapping_div(rows);
|
||||
let page_no = (self.new_cursor_pos.2).wrapping_div(rows);
|
||||
|
||||
let top_idx = page_no * rows;
|
||||
|
||||
/* If cursor position has changed, remove the highlight from the previous position and
|
||||
* apply it in the new one. */
|
||||
if self.cursor_pos.2 != self.new_cursor_pos.2 && prev_page_no == page_no {
|
||||
let old_cursor_pos = self.cursor_pos;
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
for idx in &[old_cursor_pos.2, self.new_cursor_pos.2] {
|
||||
if *idx >= self.length {
|
||||
continue; //bounds check
|
||||
}
|
||||
let new_area = (
|
||||
set_y(upper_left, get_y(upper_left) + (*idx % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (*idx % rows)),
|
||||
);
|
||||
self.highlight_line(grid, new_area, *idx, context);
|
||||
context.dirty_areas.push_back(new_area);
|
||||
}
|
||||
return;
|
||||
} else if self.cursor_pos != self.new_cursor_pos {
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
}
|
||||
|
||||
/* Page_no has changed, so draw new page */
|
||||
copy_area(
|
||||
grid,
|
||||
&self.content,
|
||||
area,
|
||||
((0, top_idx), (MAX_COLS - 1, self.length)),
|
||||
);
|
||||
self.highlight_line(
|
||||
grid,
|
||||
(
|
||||
set_y(upper_left, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
),
|
||||
self.cursor_pos.2,
|
||||
context,
|
||||
);
|
||||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PlainListing {
|
||||
|
@ -334,106 +434,6 @@ impl PlainListing {
|
|||
);
|
||||
}
|
||||
|
||||
fn highlight_line(&self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let envelope: &Envelope = &account.get_env(&self.local_collection[idx]);
|
||||
|
||||
let fg_color = if !envelope.is_seen() {
|
||||
Color::Byte(0)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
let bg_color = if self.cursor_pos.2 == idx {
|
||||
Color::Byte(246)
|
||||
} else if !envelope.is_seen() {
|
||||
Color::Byte(251)
|
||||
} else if idx % 2 == 0 {
|
||||
Color::Byte(236)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
change_colors(grid, area, fg_color, bg_color);
|
||||
}
|
||||
|
||||
/// Draw the list of `Envelope`s.
|
||||
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if self.cursor_pos.1 != self.new_cursor_pos.1 || self.cursor_pos.0 != self.new_cursor_pos.0
|
||||
{
|
||||
self.refresh_mailbox(context);
|
||||
}
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
if self.length == 0 {
|
||||
clear_area(grid, area);
|
||||
copy_area(grid, &self.content, area, ((0, 0), (MAX_COLS - 1, 0)));
|
||||
context.dirty_areas.push_back(area);
|
||||
return;
|
||||
}
|
||||
let rows = get_y(bottom_right) - get_y(upper_left) + 1;
|
||||
if let Some(mvm) = self.movement.take() {
|
||||
match mvm {
|
||||
PageMovement::PageUp => {
|
||||
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows);
|
||||
}
|
||||
PageMovement::PageDown => {
|
||||
if self.new_cursor_pos.2 + rows + 1 < self.length {
|
||||
self.new_cursor_pos.2 += rows;
|
||||
} else {
|
||||
self.new_cursor_pos.2 = (self.length / rows) * rows;
|
||||
}
|
||||
}
|
||||
PageMovement::Home => {
|
||||
self.new_cursor_pos.2 = 0;
|
||||
}
|
||||
PageMovement::End => {
|
||||
self.new_cursor_pos.2 = (self.length / rows) * rows;
|
||||
}
|
||||
}
|
||||
}
|
||||
let prev_page_no = (self.cursor_pos.2).wrapping_div(rows);
|
||||
let page_no = (self.new_cursor_pos.2).wrapping_div(rows);
|
||||
|
||||
let top_idx = page_no * rows;
|
||||
|
||||
/* If cursor position has changed, remove the highlight from the previous position and
|
||||
* apply it in the new one. */
|
||||
if self.cursor_pos.2 != self.new_cursor_pos.2 && prev_page_no == page_no {
|
||||
let old_cursor_pos = self.cursor_pos;
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
for idx in &[old_cursor_pos.2, self.new_cursor_pos.2] {
|
||||
if *idx >= self.length {
|
||||
continue; //bounds check
|
||||
}
|
||||
let new_area = (
|
||||
set_y(upper_left, get_y(upper_left) + (*idx % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (*idx % rows)),
|
||||
);
|
||||
self.highlight_line(grid, new_area, *idx, context);
|
||||
context.dirty_areas.push_back(new_area);
|
||||
}
|
||||
return;
|
||||
} else if self.cursor_pos != self.new_cursor_pos {
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
}
|
||||
|
||||
/* Page_no has changed, so draw new page */
|
||||
copy_area(
|
||||
grid,
|
||||
&self.content,
|
||||
area,
|
||||
((0, top_idx), (MAX_COLS - 1, self.length)),
|
||||
);
|
||||
self.highlight_line(
|
||||
grid,
|
||||
(
|
||||
set_y(upper_left, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
),
|
||||
self.cursor_pos.2,
|
||||
context,
|
||||
);
|
||||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
fn format_date(envelope: &Envelope) -> String {
|
||||
let d = std::time::UNIX_EPOCH + std::time::Duration::from_secs(envelope.date());
|
||||
let now: std::time::Duration = std::time::SystemTime::now()
|
||||
|
|
|
@ -59,6 +59,112 @@ impl ListingTrait for ThreadListing {
|
|||
fn set_coordinates(&mut self, coordinates: (usize, usize, Option<EnvelopeHash>)) {
|
||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||
}
|
||||
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if self.cursor_pos.1 != self.new_cursor_pos.1 || self.cursor_pos.0 != self.new_cursor_pos.0
|
||||
{
|
||||
self.refresh_mailbox(context);
|
||||
}
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
if self.length == 0 {
|
||||
clear_area(grid, area);
|
||||
copy_area(grid, &self.content, area, ((0, 0), (MAX_COLS - 1, 0)));
|
||||
context.dirty_areas.push_back(area);
|
||||
return;
|
||||
}
|
||||
let rows = get_y(bottom_right) - get_y(upper_left) + 1;
|
||||
let prev_page_no = (self.cursor_pos.2).wrapping_div(rows);
|
||||
let page_no = (self.new_cursor_pos.2).wrapping_div(rows);
|
||||
|
||||
let top_idx = page_no * rows;
|
||||
if !self.initialised {
|
||||
self.initialised = false;
|
||||
copy_area(
|
||||
grid,
|
||||
&self.content,
|
||||
area,
|
||||
((0, top_idx), (MAX_COLS - 1, self.length)),
|
||||
);
|
||||
self.highlight_line(
|
||||
grid,
|
||||
(
|
||||
set_y(upper_left, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
),
|
||||
self.cursor_pos.2,
|
||||
context,
|
||||
);
|
||||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
/* If cursor position has changed, remove the highlight from the previous position and
|
||||
* apply it in the new one. */
|
||||
if self.cursor_pos.2 != self.new_cursor_pos.2 && prev_page_no == page_no {
|
||||
let old_cursor_pos = self.cursor_pos;
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
for idx in &[old_cursor_pos.2, self.new_cursor_pos.2] {
|
||||
if *idx >= self.length {
|
||||
continue; //bounds check
|
||||
}
|
||||
let new_area = (
|
||||
set_y(upper_left, get_y(upper_left) + (*idx % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (*idx % rows)),
|
||||
);
|
||||
self.highlight_line(grid, new_area, *idx, context);
|
||||
context.dirty_areas.push_back(new_area);
|
||||
}
|
||||
return;
|
||||
} else if self.cursor_pos != self.new_cursor_pos {
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
}
|
||||
|
||||
/* Page_no has changed, so draw new page */
|
||||
copy_area(
|
||||
grid,
|
||||
&self.content,
|
||||
area,
|
||||
((0, top_idx), (MAX_COLS - 1, self.length)),
|
||||
);
|
||||
self.highlight_line(
|
||||
grid,
|
||||
(
|
||||
set_y(upper_left, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
),
|
||||
self.cursor_pos.2,
|
||||
context,
|
||||
);
|
||||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
|
||||
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context) {
|
||||
let mailbox = &context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
if mailbox.is_empty() || mailbox.len() <= idx {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.locations[idx] != 0 {
|
||||
let envelope: &Envelope =
|
||||
&context.accounts[self.cursor_pos.0].get_env(&self.locations[idx]);
|
||||
|
||||
let fg_color = if !envelope.is_seen() {
|
||||
Color::Byte(0)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
let bg_color = if self.cursor_pos.2 == idx {
|
||||
Color::Byte(246)
|
||||
} else if !envelope.is_seen() {
|
||||
Color::Byte(251)
|
||||
} else if idx % 2 == 0 {
|
||||
Color::Byte(236)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
change_colors(grid, area, fg_color, bg_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ThreadListing {
|
||||
|
@ -253,114 +359,6 @@ impl ThreadListing {
|
|||
}
|
||||
}
|
||||
|
||||
fn highlight_line(&self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context) {
|
||||
let mailbox = &context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
if mailbox.is_empty() || mailbox.len() <= idx {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.locations[idx] != 0 {
|
||||
let envelope: &Envelope =
|
||||
&context.accounts[self.cursor_pos.0].get_env(&self.locations[idx]);
|
||||
|
||||
let fg_color = if !envelope.is_seen() {
|
||||
Color::Byte(0)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
let bg_color = if self.cursor_pos.2 == idx {
|
||||
Color::Byte(246)
|
||||
} else if !envelope.is_seen() {
|
||||
Color::Byte(251)
|
||||
} else if idx % 2 == 0 {
|
||||
Color::Byte(236)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
change_colors(grid, area, fg_color, bg_color);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw the list of `Envelope`s.
|
||||
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if self.cursor_pos.1 != self.new_cursor_pos.1 || self.cursor_pos.0 != self.new_cursor_pos.0
|
||||
{
|
||||
self.refresh_mailbox(context);
|
||||
}
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
if self.length == 0 {
|
||||
clear_area(grid, area);
|
||||
copy_area(grid, &self.content, area, ((0, 0), (MAX_COLS - 1, 0)));
|
||||
context.dirty_areas.push_back(area);
|
||||
return;
|
||||
}
|
||||
let rows = get_y(bottom_right) - get_y(upper_left) + 1;
|
||||
let prev_page_no = (self.cursor_pos.2).wrapping_div(rows);
|
||||
let page_no = (self.new_cursor_pos.2).wrapping_div(rows);
|
||||
|
||||
let top_idx = page_no * rows;
|
||||
if !self.initialised {
|
||||
self.initialised = false;
|
||||
copy_area(
|
||||
grid,
|
||||
&self.content,
|
||||
area,
|
||||
((0, top_idx), (MAX_COLS - 1, self.length)),
|
||||
);
|
||||
self.highlight_line(
|
||||
grid,
|
||||
(
|
||||
set_y(upper_left, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
),
|
||||
self.cursor_pos.2,
|
||||
context,
|
||||
);
|
||||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
/* If cursor position has changed, remove the highlight from the previous position and
|
||||
* apply it in the new one. */
|
||||
if self.cursor_pos.2 != self.new_cursor_pos.2 && prev_page_no == page_no {
|
||||
let old_cursor_pos = self.cursor_pos;
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
for idx in &[old_cursor_pos.2, self.new_cursor_pos.2] {
|
||||
if *idx >= self.length {
|
||||
continue; //bounds check
|
||||
}
|
||||
let new_area = (
|
||||
set_y(upper_left, get_y(upper_left) + (*idx % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (*idx % rows)),
|
||||
);
|
||||
self.highlight_line(grid, new_area, *idx, context);
|
||||
context.dirty_areas.push_back(new_area);
|
||||
}
|
||||
return;
|
||||
} else if self.cursor_pos != self.new_cursor_pos {
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
}
|
||||
|
||||
/* Page_no has changed, so draw new page */
|
||||
copy_area(
|
||||
grid,
|
||||
&self.content,
|
||||
area,
|
||||
((0, top_idx), (MAX_COLS - 1, self.length)),
|
||||
);
|
||||
self.highlight_line(
|
||||
grid,
|
||||
(
|
||||
set_y(upper_left, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (self.cursor_pos.2 % rows)),
|
||||
),
|
||||
self.cursor_pos.2,
|
||||
context,
|
||||
);
|
||||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
|
||||
fn make_thread_entry(
|
||||
envelope: &Envelope,
|
||||
idx: usize,
|
||||
|
|
Loading…
Reference in New Issue