Skip to content

Commit

Permalink
Implement wrapping in text field
Browse files Browse the repository at this point in the history
Closes #101
  • Loading branch information
trevarj authored and osa1 committed Apr 12, 2020
1 parent f8477c3 commit d532efd
Show file tree
Hide file tree
Showing 6 changed files with 399 additions and 73 deletions.
2 changes: 2 additions & 0 deletions libtiny_tui/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub use termbox_simple::*;
pub(crate) struct Config {
#[serde(default)]
pub(crate) colors: Colors,
#[serde(default)]
pub(crate) text_field_wrap: bool,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
39 changes: 25 additions & 14 deletions libtiny_tui/src/messaging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ struct ActivityLine {
}

impl MessagingUI {
pub(crate) fn new(width: i32, height: i32, status: bool) -> MessagingUI {
pub(crate) fn new(width: i32, height: i32, status: bool, text_field_wrap: bool) -> MessagingUI {
MessagingUI {
msg_area: MsgArea::new(width, height - 1),
input_field: TextField::new(width),
input_field: TextField::new(width, height - 1, text_field_wrap),
exit_dialogue: None,
width,
height,
Expand All @@ -106,10 +106,18 @@ impl MessagingUI {
self.current_nick.as_deref()
}

pub(crate) fn draw(&self, tb: &mut Termbox, colors: &Colors, pos_x: i32, pos_y: i32) {
pub(crate) fn draw(&mut self, tb: &mut Termbox, colors: &Colors, pos_x: i32, pos_y: i32) {
let lines = self.input_field.calculate_lines();
// make space for textfield expansion
if self.height - lines >= 5 {
self.msg_area.resize(self.width, self.height - lines);
} else {
let widget_width = self.calculate_input_field_width(self.width);
self.input_field.resize(widget_width, 1);
}
self.msg_area.draw(tb, colors, pos_x, pos_y);

let input_field_y = pos_y + self.height - 1;
let input_field_y = pos_y + self.height - lines;
match &self.exit_dialogue {
Some(exit_dialogue) => {
exit_dialogue.draw(tb, colors, pos_x, input_field_y);
Expand Down Expand Up @@ -209,11 +217,7 @@ impl MessagingUI {
}
}

pub(crate) fn resize(&mut self, width: i32, height: i32) {
self.width = width;
self.height = height;
self.msg_area.resize(width, height - 1);

fn calculate_input_field_width(&mut self, width: i32) -> i32 {
let nick_width = match self.current_nick {
None => 0,
Some(ref rc) =>
Expand All @@ -223,15 +227,22 @@ impl MessagingUI {
}
};

self.show_current_nick = (nick_width as f32) <= (width as f32) * (30f32 / 100f32);

let widget_width = if self.show_current_nick {
self.show_current_nick = nick_width as f32 <= width as f32 * (30f32 / 100f32);
if self.show_current_nick {
width - nick_width
} else {
width
};
}
}

pub(crate) fn resize(&mut self, width: i32, height: i32) {
self.width = width;
self.height = height;
self.msg_area.resize(width, height - 1);

let widget_width = self.calculate_input_field_width(width);

self.input_field.resize(widget_width);
self.input_field.resize(widget_width, height - 1);

// We don't show the nick in exit dialogue, so it has the full width
for exit_dialogue in &mut self.exit_dialogue {
Expand Down
165 changes: 165 additions & 0 deletions libtiny_tui/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::tui::TUI;

use libtiny_ui::*;
use term_input::Key;
use termbox_simple::CellBuf;
use time::Tm;

Expand Down Expand Up @@ -170,3 +171,167 @@ fn small_screen_2() {
|< #chan |";
expect_screen(screen, &tui, 21, 4);
}

///
/// Tests text wrap on
///
#[test]
fn test_text_field_wrap() {
let mut tui = TUI::new_test(60, 8);
tui.set_text_field_wrap_test(true);

let server = "chat.freenode.net";
tui.new_server_tab(server);
tui.set_nick(server, "osa1");

// switch to server tab
tui.next_tab();

// write some stuff
let target = MsgTarget::CurrentTab;
let ts: Tm = unsafe { ::std::mem::zeroed() };
tui.add_msg("test test test", ts, &target);

for _ in 0..65 {
let event = term_input::Event::Key(Key::Char('a'));
tui.handle_input_event(event);
}

tui.draw();

#[rustfmt::skip]
let screen =
"| |
| |
| |
| |
|00:00 test test test |
|osa1: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
| aaaaaaaaaaa |
|mentions chat.freenode.net |";

expect_screen(screen, &tui, 60, 8);
}

///
/// Tests text wrap on
/// Writes some text that will wrap
/// Deletes the text to check if the input field went back to 1 line
///
#[test]
fn test_text_field_wrap_add_delete() {
let mut tui = TUI::new_test(60, 8);
tui.set_text_field_wrap_test(true);

let server = "chat.freenode.net";
tui.new_server_tab(server);
tui.set_nick(server, "osa1");

// switch to server tab
tui.next_tab();

// write some stuff
let target = MsgTarget::CurrentTab;
let ts: Tm = unsafe { ::std::mem::zeroed() };
tui.add_msg("test test test", ts, &target);

for _ in 0..65 {
let event = term_input::Event::Key(Key::Char('a'));
tui.handle_input_event(event);
}

tui.draw();

// Hit ctrl-a to go to the beginning of line
let ctrl_a_event = term_input::Event::Key(Key::Ctrl('a'));
tui.handle_input_event(ctrl_a_event);
// Hit ctrl-k to clear the line
let ctrl_k_event = term_input::Event::Key(Key::Ctrl('k'));
tui.handle_input_event(ctrl_k_event);

tui.draw();

#[rustfmt::skip]
let screen =
"| |
| |
| |
| |
| |
|00:00 test test test |
|osa1: |
|mentions chat.freenode.net |";

expect_screen(screen, &tui, 60, 8);
}

///
/// Tests scroll mode on (text wrap off)
///
#[test]
fn test_text_field_wrap_false() {
let mut tui = TUI::new_test(60, 8);
tui.set_text_field_wrap_test(false);

let server = "chat.freenode.net";
tui.new_server_tab(server);
tui.set_nick(server, "osa1");
// switch to server tab
tui.next_tab();

for _ in 0..65 {
let event = term_input::Event::Key(Key::Char('a'));
tui.handle_input_event(event);
}

tui.draw();

#[rustfmt::skip]
let screen =
"| |
| |
| |
| |
| |
| |
|osa1: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
|mentions chat.freenode.net |";
// cursor space^
expect_screen(screen, &tui, 60, 8);
}

///
/// Tests scroll (text wrap on) small screen
///
#[test]
fn test_scroll_text_field_wrap_true() {
let mut tui = TUI::new_test(30, 10);
tui.set_text_field_wrap_test(true);

let server = "chat.freenode.net";
tui.new_server_tab(server);
tui.set_nick(server, "osa1");
// switch to server tab
tui.next_tab();

for _ in 0..65 {
let event = term_input::Event::Key(Key::Char('a'));
tui.handle_input_event(event);
}

tui.draw();
#[rustfmt::skip]
let screen =
"| |
| |
| |
| |
| |
| |
| |
| |
|osa1: aaaaaaaaaaaaaaaaaaaaaaa |
|mentions chat.freenode.net |";
// cursor space^
expect_screen(screen, &tui, 30, 10);
}
Loading

0 comments on commit d532efd

Please sign in to comment.