Moving screen drawing handling to a submodule.
This commit is contained in:
parent
c11aee9bf6
commit
c7adf195f7
|
@ -1,15 +1,12 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
use termion;
|
use termion;
|
||||||
use termion::event::{Event, Key};
|
use termion::event::{Event, Key};
|
||||||
use termion::input::TermRead;
|
use termion::input::TermRead;
|
||||||
use termion::color;
|
use termion::color;
|
||||||
use termion::raw::{IntoRawMode, RawTerminal};
|
|
||||||
|
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use formatter::{block_index_and_offset, LineFormatter, LINE_BLOCK_LENGTH};
|
use formatter::{block_index_and_offset, LineFormatter, LINE_BLOCK_LENGTH};
|
||||||
|
@ -18,6 +15,9 @@ use string_utils::{is_line_ending, line_ending_to_str, LineEnding};
|
||||||
use utils::digit_count;
|
use utils::digit_count;
|
||||||
|
|
||||||
pub mod formatter;
|
pub mod formatter;
|
||||||
|
mod screen;
|
||||||
|
|
||||||
|
use self::screen::Screen;
|
||||||
|
|
||||||
/// Generalized ui loop.
|
/// Generalized ui loop.
|
||||||
macro_rules! ui_loop {
|
macro_rules! ui_loop {
|
||||||
|
@ -27,7 +27,7 @@ macro_rules! ui_loop {
|
||||||
loop {
|
loop {
|
||||||
// Draw the editor to screen
|
// Draw the editor to screen
|
||||||
{$draw};
|
{$draw};
|
||||||
$term_ui.present();
|
$term_ui.screen.present();
|
||||||
|
|
||||||
// Handle input
|
// Handle input
|
||||||
match $term_ui.inp.next() {
|
match $term_ui.inp.next() {
|
||||||
|
@ -63,7 +63,7 @@ macro_rules! ui_loop {
|
||||||
|
|
||||||
pub struct TermUI<'a> {
|
pub struct TermUI<'a> {
|
||||||
inp: termion::input::Events<io::StdinLock<'a>>,
|
inp: termion::input::Events<io::StdinLock<'a>>,
|
||||||
out: RefCell<RawTerminal<io::Stdout>>,
|
screen: Screen,
|
||||||
editor: Editor<ConsoleLineFormatter>,
|
editor: Editor<ConsoleLineFormatter>,
|
||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
|
@ -76,18 +76,6 @@ enum LoopStatus {
|
||||||
Continue,
|
Continue,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drop for TermUI<'a> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.clear();
|
|
||||||
write!(
|
|
||||||
self.out.borrow_mut(),
|
|
||||||
"{}{}",
|
|
||||||
termion::cursor::Show,
|
|
||||||
termion::cursor::Goto(0, 0),
|
|
||||||
).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> TermUI<'a> {
|
impl<'a> TermUI<'a> {
|
||||||
pub fn new<'b>(stdin: &'b mut io::Stdin) -> TermUI<'b> {
|
pub fn new<'b>(stdin: &'b mut io::Stdin) -> TermUI<'b> {
|
||||||
TermUI::new_from_editor(stdin, Editor::new(ConsoleLineFormatter::new(4)))
|
TermUI::new_from_editor(stdin, Editor::new(ConsoleLineFormatter::new(4)))
|
||||||
|
@ -97,14 +85,13 @@ impl<'a> TermUI<'a> {
|
||||||
stdin: &'b mut io::Stdin,
|
stdin: &'b mut io::Stdin,
|
||||||
ed: Editor<ConsoleLineFormatter>,
|
ed: Editor<ConsoleLineFormatter>,
|
||||||
) -> TermUI<'b> {
|
) -> TermUI<'b> {
|
||||||
let out = io::stdout().into_raw_mode().unwrap();
|
|
||||||
let (w, h) = termion::terminal_size().unwrap();
|
let (w, h) = termion::terminal_size().unwrap();
|
||||||
let mut editor = ed;
|
let mut editor = ed;
|
||||||
editor.update_dim(h as usize - 1, w as usize);
|
editor.update_dim(h as usize - 1, w as usize);
|
||||||
|
|
||||||
TermUI {
|
TermUI {
|
||||||
inp: stdin.lock().events(),
|
inp: stdin.lock().events(),
|
||||||
out: RefCell::new(out),
|
screen: Screen::new(),
|
||||||
editor: editor,
|
editor: editor,
|
||||||
width: w as usize,
|
width: w as usize,
|
||||||
height: h as usize,
|
height: h as usize,
|
||||||
|
@ -114,7 +101,7 @@ impl<'a> TermUI<'a> {
|
||||||
|
|
||||||
pub fn main_ui_loop(&mut self) {
|
pub fn main_ui_loop(&mut self) {
|
||||||
// Hide cursor
|
// Hide cursor
|
||||||
write!(self.out.borrow_mut(), "{}", termion::cursor::Hide).unwrap();
|
self.screen.hide_cursor();
|
||||||
|
|
||||||
self.editor.update_dim(self.height - 1, self.width);
|
self.editor.update_dim(self.height - 1, self.width);
|
||||||
self.editor.formatter.set_wrap_width(self.width as usize);
|
self.editor.formatter.set_wrap_width(self.width as usize);
|
||||||
|
@ -126,7 +113,7 @@ impl<'a> TermUI<'a> {
|
||||||
draw {
|
draw {
|
||||||
self.editor.update_view_dim();
|
self.editor.update_view_dim();
|
||||||
self.editor.formatter.set_wrap_width(self.editor.view_dim.1);
|
self.editor.formatter.set_wrap_width(self.editor.view_dim.1);
|
||||||
self.clear();
|
self.screen.clear();
|
||||||
self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1));
|
self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -229,13 +216,13 @@ impl<'a> TermUI<'a> {
|
||||||
draw {
|
draw {
|
||||||
self.editor.update_view_dim();
|
self.editor.update_view_dim();
|
||||||
self.editor.formatter.set_wrap_width(self.editor.view_dim.1);
|
self.editor.formatter.set_wrap_width(self.editor.view_dim.1);
|
||||||
self.clear();
|
self.screen.clear();
|
||||||
self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1));
|
self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1));
|
||||||
for i in 0..self.width {
|
for i in 0..self.width {
|
||||||
self.draw(i, 0, " ", foreground, background);
|
self.screen.draw(i, 0, " ", foreground, background);
|
||||||
}
|
}
|
||||||
self.draw(1, 0, prefix, foreground, background);
|
self.screen.draw(1, 0, prefix, foreground, background);
|
||||||
self.draw(
|
self.screen.draw(
|
||||||
prefix.len() + 1,
|
prefix.len() + 1,
|
||||||
0,
|
0,
|
||||||
&line[..],
|
&line[..],
|
||||||
|
@ -298,14 +285,14 @@ impl<'a> TermUI<'a> {
|
||||||
|
|
||||||
// Fill in top row with info line color
|
// Fill in top row with info line color
|
||||||
for i in c1.1..(c2.1 + 1) {
|
for i in c1.1..(c2.1 + 1) {
|
||||||
self.draw(i, c1.0, " ", fg, bg);
|
self.screen.draw(i, c1.0, " ", fg, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filename and dirty marker
|
// Filename and dirty marker
|
||||||
let filename = editor.file_path.display();
|
let filename = editor.file_path.display();
|
||||||
let dirty_char = if editor.dirty { "*" } else { "" };
|
let dirty_char = if editor.dirty { "*" } else { "" };
|
||||||
let name = format!("{}{}", filename, dirty_char);
|
let name = format!("{}{}", filename, dirty_char);
|
||||||
self.draw(c1.1 + 1, c1.0, &name[..], fg, bg);
|
self.screen.draw(c1.1 + 1, c1.0, &name[..], fg, bg);
|
||||||
|
|
||||||
// Percentage position in document
|
// Percentage position in document
|
||||||
// TODO: use view instead of cursor for calculation if there is more
|
// TODO: use view instead of cursor for calculation if there is more
|
||||||
|
@ -317,7 +304,8 @@ impl<'a> TermUI<'a> {
|
||||||
100
|
100
|
||||||
};
|
};
|
||||||
let pstring = format!("{}%", percentage);
|
let pstring = format!("{}%", percentage);
|
||||||
self.draw(c2.1 - pstring.len(), c1.0, &pstring[..], fg, bg);
|
self.screen
|
||||||
|
.draw(c2.1 - pstring.len(), c1.0, &pstring[..], fg, bg);
|
||||||
|
|
||||||
// Text encoding info and tab style
|
// Text encoding info and tab style
|
||||||
let nl = match editor.line_ending_type {
|
let nl = match editor.line_ending_type {
|
||||||
|
@ -336,7 +324,7 @@ impl<'a> TermUI<'a> {
|
||||||
"UTF8:{} {}:{}",
|
"UTF8:{} {}:{}",
|
||||||
nl, soft_tabs_str, editor.soft_tab_width as usize
|
nl, soft_tabs_str, editor.soft_tab_width as usize
|
||||||
);
|
);
|
||||||
self.draw(c2.1 - 30, c1.0, &info_line[..], fg, bg);
|
self.screen.draw(c2.1 - 30, c1.0, &info_line[..], fg, bg);
|
||||||
|
|
||||||
// Draw main text editing area
|
// Draw main text editing area
|
||||||
self.draw_editor_text(editor, (c1.0 + 1, c1.1), c2);
|
self.draw_editor_text(editor, (c1.0 + 1, c1.1), c2);
|
||||||
|
@ -375,7 +363,7 @@ impl<'a> TermUI<'a> {
|
||||||
// Fill in the gutter with the appropriate background
|
// Fill in the gutter with the appropriate background
|
||||||
for y in c1.0..(c2.0 + 1) {
|
for y in c1.0..(c2.0 + 1) {
|
||||||
for x in c1.1..(c1.1 + gutter_width - 1) {
|
for x in c1.1..(c1.1 + gutter_width - 1) {
|
||||||
self.draw(x, y, " ", color::White, color::Blue);
|
self.screen.draw(x, y, " ", color::White, color::Blue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +374,7 @@ impl<'a> TermUI<'a> {
|
||||||
let lnx = c1.1 + (gutter_width - 1 - digit_count(line_num as u32, 10) as usize);
|
let lnx = c1.1 + (gutter_width - 1 - digit_count(line_num as u32, 10) as usize);
|
||||||
let lny = screen_line as usize;
|
let lny = screen_line as usize;
|
||||||
if lny >= c1.0 && lny <= c2.0 {
|
if lny >= c1.0 && lny <= c2.0 {
|
||||||
self.draw(
|
self.screen.draw(
|
||||||
lnx,
|
lnx,
|
||||||
lny,
|
lny,
|
||||||
&format!("{}", line_num)[..],
|
&format!("{}", line_num)[..],
|
||||||
|
@ -437,7 +425,7 @@ impl<'a> TermUI<'a> {
|
||||||
// Actually print the character
|
// Actually print the character
|
||||||
if is_line_ending(g) {
|
if is_line_ending(g) {
|
||||||
if at_cursor {
|
if at_cursor {
|
||||||
self.draw(
|
self.screen.draw(
|
||||||
px as usize,
|
px as usize,
|
||||||
py as usize,
|
py as usize,
|
||||||
" ",
|
" ",
|
||||||
|
@ -449,7 +437,7 @@ impl<'a> TermUI<'a> {
|
||||||
for i in 0..width {
|
for i in 0..width {
|
||||||
let tpx = px as usize + i;
|
let tpx = px as usize + i;
|
||||||
if tpx <= c2.1 {
|
if tpx <= c2.1 {
|
||||||
self.draw(
|
self.screen.draw(
|
||||||
tpx as usize,
|
tpx as usize,
|
||||||
py as usize,
|
py as usize,
|
||||||
" ",
|
" ",
|
||||||
|
@ -460,7 +448,7 @@ impl<'a> TermUI<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if at_cursor {
|
if at_cursor {
|
||||||
self.draw(
|
self.screen.draw(
|
||||||
px as usize,
|
px as usize,
|
||||||
py as usize,
|
py as usize,
|
||||||
" ",
|
" ",
|
||||||
|
@ -470,9 +458,21 @@ impl<'a> TermUI<'a> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if at_cursor {
|
if at_cursor {
|
||||||
self.draw(px as usize, py as usize, g, color::Black, color::White);
|
self.screen.draw(
|
||||||
|
px as usize,
|
||||||
|
py as usize,
|
||||||
|
g,
|
||||||
|
color::Black,
|
||||||
|
color::White,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
self.draw(px as usize, py as usize, g, color::White, color::Black);
|
self.screen.draw(
|
||||||
|
px as usize,
|
||||||
|
py as usize,
|
||||||
|
g,
|
||||||
|
color::White,
|
||||||
|
color::Black,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,40 +523,9 @@ impl<'a> TermUI<'a> {
|
||||||
if (px >= c1.1 as isize) && (py >= c1.0 as isize) && (px <= c2.1 as isize)
|
if (px >= c1.1 as isize) && (py >= c1.0 as isize) && (px <= c2.1 as isize)
|
||||||
&& (py <= c2.0 as isize)
|
&& (py <= c2.0 as isize)
|
||||||
{
|
{
|
||||||
self.draw(px as usize, py as usize, " ", color::Black, color::White);
|
self.screen
|
||||||
|
.draw(px as usize, py as usize, " ", color::Black, color::White);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(&self) {
|
|
||||||
write!(
|
|
||||||
self.out.borrow_mut(),
|
|
||||||
"{}{}",
|
|
||||||
color::Bg(color::Black),
|
|
||||||
termion::clear::All
|
|
||||||
).unwrap();
|
|
||||||
self.out.borrow_mut().flush().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn present(&self) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw<C1: color::Color, C2: color::Color>(
|
|
||||||
&self,
|
|
||||||
x: usize,
|
|
||||||
y: usize,
|
|
||||||
text: &str,
|
|
||||||
fg: C1,
|
|
||||||
bg: C2,
|
|
||||||
) {
|
|
||||||
write!(
|
|
||||||
self.out.borrow_mut(),
|
|
||||||
"{}{}{}{}",
|
|
||||||
termion::cursor::Goto((x + 1) as u16, (y + 1) as u16),
|
|
||||||
color::Fg(fg),
|
|
||||||
color::Bg(bg),
|
|
||||||
text
|
|
||||||
).unwrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
72
src/term_ui/screen.rs
Normal file
72
src/term_ui/screen.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use termion;
|
||||||
|
use termion::screen::AlternateScreen;
|
||||||
|
use termion::color;
|
||||||
|
use termion::raw::{IntoRawMode, RawTerminal};
|
||||||
|
|
||||||
|
pub(crate) struct Screen {
|
||||||
|
out: RefCell<AlternateScreen<RawTerminal<io::Stdout>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Screen {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
Screen {
|
||||||
|
out: RefCell::new(AlternateScreen::from(io::stdout().into_raw_mode().unwrap())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn clear(&self) {
|
||||||
|
write!(
|
||||||
|
self.out.borrow_mut(),
|
||||||
|
"{}{}",
|
||||||
|
color::Bg(color::Black),
|
||||||
|
termion::clear::All
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn present(&self) {
|
||||||
|
self.out.borrow_mut().flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn draw<C1: color::Color, C2: color::Color>(
|
||||||
|
&self,
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
text: &str,
|
||||||
|
fg: C1,
|
||||||
|
bg: C2,
|
||||||
|
) {
|
||||||
|
write!(
|
||||||
|
self.out.borrow_mut(),
|
||||||
|
"{}{}{}{}",
|
||||||
|
termion::cursor::Goto((x + 1) as u16, (y + 1) as u16),
|
||||||
|
color::Fg(fg),
|
||||||
|
color::Bg(bg),
|
||||||
|
text
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn hide_cursor(&self) {
|
||||||
|
write!(self.out.borrow_mut(), "{}", termion::cursor::Hide).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn show_cursor(&self) {
|
||||||
|
write!(self.out.borrow_mut(), "{}", termion::cursor::Show).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Screen {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
write!(
|
||||||
|
self.out.borrow_mut(),
|
||||||
|
"{}{}",
|
||||||
|
color::Fg(color::Reset),
|
||||||
|
color::Bg(color::Reset)
|
||||||
|
).unwrap();
|
||||||
|
self.clear();
|
||||||
|
self.show_cursor();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user