summaryrefslogtreecommitdiffstats
path: root/src/view/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/mod.rs')
-rw-r--r--src/view/mod.rs187
1 files changed, 179 insertions, 8 deletions
diff --git a/src/view/mod.rs b/src/view/mod.rs
index a166ad7..3893ec0 100644
--- a/src/view/mod.rs
+++ b/src/view/mod.rs
@@ -1,8 +1,179 @@
-mod line_segment;
-#[allow(clippy::module_inception)]
-mod view;
-mod view_line;
-
-pub use self::line_segment::LineSegment;
-pub use self::view::View;
-pub use self::view_line::ViewLine;
+pub(crate) mod line_segment;
+pub(crate) mod view_line;
+
+use crate::constants::{
+ MINIMUM_COMPACT_WINDOW_WIDTH,
+ MINIMUM_WINDOW_HEIGHT,
+ TITLE,
+ TITLE_HELP_INDICATOR_LENGTH,
+ TITLE_LENGTH,
+ TITLE_SHORT,
+ TITLE_SHORT_LENGTH,
+};
+use crate::display::display_color::DisplayColor;
+use crate::display::Display;
+use crate::scroll::utils::get_scroll_position;
+use crate::view::view_line::ViewLine;
+use crate::Config;
+
+pub(crate) struct View<'v> {
+ config: &'v Config,
+ display: &'v Display<'v>,
+}
+
+impl<'v> View<'v> {
+ pub(crate) fn new(display: &'v Display, config: &'v Config) -> Self {
+ Self { display, config }
+ }
+
+ pub(crate) fn draw_str(&self, s: &str) {
+ self.display.draw_str(s);
+ }
+
+ pub(crate) fn set_color(&self, color: DisplayColor, selected: bool) {
+ self.display.color(color, selected);
+ }
+
+ pub(crate) fn set_style(&self, dim: bool, underline: bool, reverse: bool) {
+ self.display.set_style(dim, underline, reverse);
+ }
+
+ pub(crate) fn check_window_size(&self) -> bool {
+ let (window_width, window_height) = self.get_view_size();
+ !(window_width <= MINIMUM_COMPACT_WINDOW_WIDTH || window_height <= MINIMUM_WINDOW_HEIGHT)
+ }
+
+ pub(crate) fn draw_error(&self, message: &str) {
+ self.draw_title(false);
+ self.display.color(DisplayColor::Normal, false);
+ self.display.set_style(false, false, false);
+ self.display.draw_str(message);
+ self.display.draw_str("\n");
+ self.display.color(DisplayColor::IndicatorColor, false);
+ self.display.draw_str("Press any key to continue");
+ }
+
+ pub(crate) fn clear(&self) {
+ self.display.clear();
+ }
+
+ pub(crate) fn get_view_size(&self) -> (usize, usize) {
+ let (view_width, view_height) = self.display.get_window_size();
+ (view_width as usize, view_height as usize)
+ }
+
+ pub(crate) fn refresh(&self) {
+ self.display.refresh();
+ }
+
+ pub(crate) fn draw_view_lines(&self, lines: &[ViewLine], top: usize, left: usize, height: usize) {
+ let number_of_lines = lines.len();
+
+ let scroll_indicator_index = get_scroll_position(top, number_of_lines, height);
+ let show_scroll_bar = height < number_of_lines;
+
+ let mut index: usize = 0;
+ for line in lines.iter().skip(top).take(height) {
+ self.draw_view_line(line, left, show_scroll_bar);
+ if show_scroll_bar {
+ self.display.color(DisplayColor::Normal, false);
+ self.display.set_style(scroll_indicator_index != index, false, true);
+ self.display.draw_str(" ");
+ }
+ index += 1;
+ }
+
+ if height > lines.len() {
+ self.draw_vertical_spacer((height - index) as i32);
+ }
+ }
+
+ fn draw_view_line(&self, line: &ViewLine, left: usize, scrollbar: bool) {
+ let (window_width, _) = self.display.get_window_size();
+ let window_width = if scrollbar { window_width - 1 } else { window_width } as usize;
+
+ let mut start = 0;
+ let mut left_start = 0;
+ for (i, segment) in line.get_segments().iter().enumerate() {
+ // set left on first non-pinned segment
+ if i == line.get_number_of_pinned_segment() {
+ left_start = left;
+ }
+ let (amount_drawn, segment_size) =
+ segment.draw(left_start, window_width - start, line.get_selected(), &self.display);
+ start += amount_drawn;
+ if start >= window_width {
+ break;
+ }
+ if amount_drawn > 0 {
+ left_start = 0;
+ }
+ else {
+ left_start -= segment_size;
+ }
+ }
+
+ if start < window_width {
+ let padding = " ".repeat(window_width - start);
+ self.display.draw_str(padding.as_str());
+ }
+ }
+
+ pub(crate) fn draw_title(&self, show_help: bool) {
+ self.display.color(DisplayColor::Normal, false);
+ self.display.set_style(false, true, false);
+ let (window_width, _) = self.display.get_window_size();
+
+ if window_width >= TITLE_LENGTH {
+ self.display.draw_str(TITLE);
+ // only draw help if there is room
+ if window_width > TITLE_LENGTH + TITLE_HELP_INDICATOR_LENGTH {
+ if (window_width - TITLE_LENGTH - TITLE_HELP_INDICATOR_LENGTH) > 0 {
+ let padding = " ".repeat((window_width - TITLE_LENGTH - TITLE_HELP_INDICATOR_LENGTH) as usize);
+ self.display.draw_str(padding.as_str());
+ }
+ if show_help {
+ self.display
+ .draw_str(format!("Help: {}", self.config.input_help).as_str());
+ }
+ else {
+ let padding = " ".repeat(TITLE_HELP_INDICATOR_LENGTH as usize);
+ self.display.draw_str(padding.as_str());
+ }
+ }
+ else if (window_width - TITLE_LENGTH) > 0 {
+ let padding = " ".repeat((window_width - TITLE_LENGTH) as usize);
+ self.display.draw_str(padding.as_str());
+ }
+ }
+ else {
+ self.display.draw_str(TITLE_SHORT);
+ if (window_width - TITLE_SHORT_LENGTH) > 0 {
+ let padding = " ".repeat((window_width - TITLE_SHORT_LENGTH) as usize);
+ self.display.draw_str(padding.as_str());
+ }
+ }
+ }
+
+ fn draw_vertical_spacer(&self, repeat: i32) {
+ self.display.color(DisplayColor::Normal, false);
+ self.display.set_style(false, false, false);
+ for _x in 0..repeat {
+ self.display
+ .draw_str(format!("{}\n", self.config.theme.character_vertical_spacing).as_str());
+ }
+ }
+
+ fn draw_prompt(&self, message: &str) {
+ self.draw_title(false);
+ self.display.set_style(false, false, false);
+ self.display.draw_str(&format!("\n{} ", message));
+ }
+
+ pub(crate) fn draw_confirm(&self, message: &str) {
+ self.draw_prompt(&format!(
+ "{} ({}/{})? ",
+ message, self.config.input_confirm_yes, self.config.input_confirm_no
+ ));
+ }
+}