mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Apply rustfmt
This commit is contained in:
parent
042e631d9f
commit
80b219f34a
14
src/event.rs
14
src/event.rs
@ -135,7 +135,7 @@ impl Key {
|
|||||||
pub fn from_ncurses(ch: i32) -> Self {
|
pub fn from_ncurses(ch: i32) -> Self {
|
||||||
match ch {
|
match ch {
|
||||||
// Values under 256 are chars and control values
|
// Values under 256 are chars and control values
|
||||||
|
//
|
||||||
// Tab is '\t'
|
// Tab is '\t'
|
||||||
9 => Key::Tab,
|
9 => Key::Tab,
|
||||||
// Treat '\n' and the numpad Enter the same
|
// Treat '\n' and the numpad Enter the same
|
||||||
@ -155,9 +155,8 @@ impl Key {
|
|||||||
521 => Key::CtrlDel,
|
521 => Key::CtrlDel,
|
||||||
522 => Key::CtrlShiftDel,
|
522 => Key::CtrlShiftDel,
|
||||||
// 523: CtrlAltDel?
|
// 523: CtrlAltDel?
|
||||||
|
//
|
||||||
// 524?
|
// 524?
|
||||||
|
|
||||||
525 => Key::AltDown,
|
525 => Key::AltDown,
|
||||||
526 => Key::AltShiftDown,
|
526 => Key::AltShiftDown,
|
||||||
527 => Key::CtrlDown,
|
527 => Key::CtrlDown,
|
||||||
@ -206,7 +205,6 @@ impl Key {
|
|||||||
563 => Key::CtrlShiftRight,
|
563 => Key::CtrlShiftRight,
|
||||||
564 => Key::CtrlAltRight,
|
564 => Key::CtrlAltRight,
|
||||||
// 565?
|
// 565?
|
||||||
|
|
||||||
566 => Key::AltUp,
|
566 => Key::AltUp,
|
||||||
567 => Key::AltShiftUp,
|
567 => Key::AltShiftUp,
|
||||||
568 => Key::CtrlUp,
|
568 => Key::CtrlUp,
|
||||||
@ -235,7 +233,9 @@ impl Key {
|
|||||||
ncurses::KEY_SNEXT => Key::ShiftPageDown,
|
ncurses::KEY_SNEXT => Key::ShiftPageDown,
|
||||||
ncurses::KEY_SPREVIOUS => Key::ShiftPageUp,
|
ncurses::KEY_SPREVIOUS => Key::ShiftPageUp,
|
||||||
// All Fn keys use the same enum with associated number
|
// All Fn keys use the same enum with associated number
|
||||||
f @ ncurses::KEY_F1...ncurses::KEY_F12 => Key::F((f - ncurses::KEY_F0) as u8),
|
f @ ncurses::KEY_F1...ncurses::KEY_F12 => {
|
||||||
|
Key::F((f - ncurses::KEY_F0) as u8)
|
||||||
|
}
|
||||||
f @ 277...288 => Key::ShiftF((f - 277) as u8),
|
f @ 277...288 => Key::ShiftF((f - 277) as u8),
|
||||||
f @ 289...300 => Key::CtrlF((f - 289) as u8),
|
f @ 289...300 => Key::CtrlF((f - 289) as u8),
|
||||||
f @ 301...312 => Key::CtrlShiftF((f - 300) as u8),
|
f @ 301...312 => Key::CtrlShiftF((f - 300) as u8),
|
||||||
@ -244,7 +244,9 @@ impl Key {
|
|||||||
//
|
//
|
||||||
// TODO: shift and ctrl Fn keys
|
// TODO: shift and ctrl Fn keys
|
||||||
// Avoids 8-10 (H,I,J), they are used by other commands.
|
// Avoids 8-10 (H,I,J), they are used by other commands.
|
||||||
c @ 1...7 | c @ 11...25 => Key::CtrlChar(('a' as u8 + (c - 1) as u8) as char),
|
c @ 1...7 | c @ 11...25 => {
|
||||||
|
Key::CtrlChar(('a' as u8 + (c - 1) as u8) as char)
|
||||||
|
}
|
||||||
_ => Key::Unknown(ch),
|
_ => Key::Unknown(ch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ pub enum MenuItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MenuTree {
|
impl MenuTree {
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
@ -38,7 +37,8 @@ impl MenuTree {
|
|||||||
|
|
||||||
pub fn leaf<F: 'static + Fn(&mut Cursive)>(&mut self, title: &str, cb: F)
|
pub fn leaf<F: 'static + Fn(&mut Cursive)>(&mut self, title: &str, cb: F)
|
||||||
-> &mut Self {
|
-> &mut Self {
|
||||||
self.children.push(MenuItem::Leaf(title.to_string(), Rc::new(Box::new(cb))));
|
self.children
|
||||||
|
.push(MenuItem::Leaf(title.to_string(), Rc::new(Box::new(cb))));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +44,12 @@ impl Orientation {
|
|||||||
/// For a vertical view, returns (Max(x),Sum(y)).
|
/// For a vertical view, returns (Max(x),Sum(y)).
|
||||||
pub fn stack<'a, T: Iterator<Item = &'a Vec2>>(&self, iter: T) -> Vec2 {
|
pub fn stack<'a, T: Iterator<Item = &'a Vec2>>(&self, iter: T) -> Vec2 {
|
||||||
match *self {
|
match *self {
|
||||||
Orientation::Horizontal => iter.fold(Vec2::zero(), |a, b| a.stack_horizontal(&b)),
|
Orientation::Horizontal => {
|
||||||
Orientation::Vertical => iter.fold(Vec2::zero(), |a, b| a.stack_vertical(&b)),
|
iter.fold(Vec2::zero(), |a, b| a.stack_horizontal(&b))
|
||||||
|
}
|
||||||
|
Orientation::Vertical => {
|
||||||
|
iter.fold(Vec2::zero(), |a, b| a.stack_vertical(&b))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use std::cmp::min;
|
|||||||
use ncurses;
|
use ncurses;
|
||||||
|
|
||||||
use theme::{ColorPair, Theme};
|
use theme::{ColorPair, Theme};
|
||||||
use vec::{Vec2, ToVec2};
|
use vec::{ToVec2, Vec2};
|
||||||
|
|
||||||
/// Convenient interface to draw on a subset of the screen.
|
/// Convenient interface to draw on a subset of the screen.
|
||||||
pub struct Printer {
|
pub struct Printer {
|
||||||
@ -30,6 +30,8 @@ impl Printer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: use &mut self? We don't *need* it, but it may make sense.
|
||||||
|
// We don't want people to start calling prints in parallel?
|
||||||
/// Prints some text at the given position relative to the window.
|
/// Prints some text at the given position relative to the window.
|
||||||
pub fn print<S: ToVec2>(&self, pos: S, text: &str) {
|
pub fn print<S: ToVec2>(&self, pos: S, text: &str) {
|
||||||
let p = pos.to_vec2();
|
let p = pos.to_vec2();
|
||||||
@ -39,6 +41,7 @@ impl Printer {
|
|||||||
// Do we have enough room for the entire line?
|
// Do we have enough room for the entire line?
|
||||||
let room = self.size.x - p.x;
|
let room = self.size.x - p.x;
|
||||||
// We want the number of CHARACTERS, not bytes.
|
// We want the number of CHARACTERS, not bytes.
|
||||||
|
// (Actually we want the "width" of the string, see unicode-width)
|
||||||
let text = match text.char_indices().nth(room) {
|
let text = match text.char_indices().nth(room) {
|
||||||
Some((i, _)) => &text[..i],
|
Some((i, _)) => &text[..i],
|
||||||
_ => text,
|
_ => text,
|
||||||
@ -46,7 +49,9 @@ impl Printer {
|
|||||||
|
|
||||||
let p = p + self.offset;
|
let p = p + self.offset;
|
||||||
if text.contains("%") {
|
if text.contains("%") {
|
||||||
ncurses::mvprintw(p.y as i32, p.x as i32, &text.replace("%", "%%"));
|
ncurses::mvprintw(p.y as i32,
|
||||||
|
p.x as i32,
|
||||||
|
&text.replace("%", "%%"));
|
||||||
} else {
|
} else {
|
||||||
ncurses::mvprintw(p.y as i32, p.x as i32, text);
|
ncurses::mvprintw(p.y as i32, p.x as i32, text);
|
||||||
}
|
}
|
||||||
@ -133,12 +138,24 @@ impl Printer {
|
|||||||
|
|
||||||
self.print_hline(start_v + (1, 0), size_v.x - 1, "─");
|
self.print_hline(start_v + (1, 0), size_v.x - 1, "─");
|
||||||
self.print_vline(start_v + (0, 1), size_v.y - 1, "│");
|
self.print_vline(start_v + (0, 1), size_v.y - 1, "│");
|
||||||
self.print_hline(start_v + (1, 0) + size_v.keep_y(), size_v.x - 1, "─");
|
self.print_hline(start_v + (1, 0) + size_v.keep_y(),
|
||||||
self.print_vline(start_v + (0, 1) + size_v.keep_x(), size_v.y - 1, "│");
|
size_v.x - 1,
|
||||||
|
"─");
|
||||||
|
self.print_vline(start_v + (0, 1) + size_v.keep_x(),
|
||||||
|
size_v.y - 1,
|
||||||
|
"│");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_hdelim<T: ToVec2>(&self, start: T, len: usize) {
|
||||||
|
let start = start.to_vec2();
|
||||||
|
self.print(start, "├");
|
||||||
|
self.print_hline(start + (1, 0), len - 2, "─");
|
||||||
|
self.print(start + (len - 1, 0), "┤");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a printer on a subset of this one's area.
|
/// Returns a printer on a subset of this one's area.
|
||||||
pub fn sub_printer<S: ToVec2>(&self, offset: S, size: S, focused: bool) -> Printer {
|
pub fn sub_printer<S: ToVec2>(&self, offset: S, size: S, focused: bool)
|
||||||
|
-> Printer {
|
||||||
let offset_v = offset.to_vec2();
|
let offset_v = offset.to_vec2();
|
||||||
Printer {
|
Printer {
|
||||||
offset: self.offset + offset_v,
|
offset: self.offset + offset_v,
|
||||||
|
@ -105,8 +105,12 @@ impl Theme {
|
|||||||
Theme::apply_color(ColorPair::Background,
|
Theme::apply_color(ColorPair::Background,
|
||||||
&self.colors.background,
|
&self.colors.background,
|
||||||
&self.colors.background);
|
&self.colors.background);
|
||||||
Theme::apply_color(ColorPair::Shadow, &self.colors.shadow, &self.colors.shadow);
|
Theme::apply_color(ColorPair::Shadow,
|
||||||
Theme::apply_color(ColorPair::Primary, &self.colors.primary, &self.colors.view);
|
&self.colors.shadow,
|
||||||
|
&self.colors.shadow);
|
||||||
|
Theme::apply_color(ColorPair::Primary,
|
||||||
|
&self.colors.primary,
|
||||||
|
&self.colors.view);
|
||||||
Theme::apply_color(ColorPair::Secondary,
|
Theme::apply_color(ColorPair::Secondary,
|
||||||
&self.colors.secondary,
|
&self.colors.secondary,
|
||||||
&self.colors.view);
|
&self.colors.view);
|
||||||
|
@ -27,7 +27,9 @@ pub fn read_char<F>(first: u8, next: F) -> Result<char, String>
|
|||||||
for _ in 1..n_bytes {
|
for _ in 1..n_bytes {
|
||||||
let byte = next();
|
let byte = next();
|
||||||
if byte & 0xC0 != 0x80 {
|
if byte & 0xC0 != 0x80 {
|
||||||
return Err(format!("Found non-continuation byte after leading: {}", byte));
|
return Err(format!("Found non-continuation byte after leading: \
|
||||||
|
{}",
|
||||||
|
byte));
|
||||||
}
|
}
|
||||||
// We have 6 fresh new bits to read, make room.
|
// We have 6 fresh new bits to read, make room.
|
||||||
res <<= 6;
|
res <<= 6;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Points on the 2D character grid.
|
//! Points on the 2D character grid.
|
||||||
|
|
||||||
use std::ops::{Add, Sub, Mul, Div};
|
use std::ops::{Add, Div, Mul, Sub};
|
||||||
use std::cmp::{min, max, Ordering};
|
use std::cmp::{Ordering, max, min};
|
||||||
|
|
||||||
/// Simple 2D size, in characters.
|
/// Simple 2D size, in characters.
|
||||||
#[derive(Clone,Copy,PartialEq,Debug)]
|
#[derive(Clone,Copy,PartialEq,Debug)]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use vec::{Vec2, ToVec2};
|
use vec::{ToVec2, Vec2};
|
||||||
use super::{View, ViewWrapper, SizeRequest, DimensionRequest};
|
use super::{DimensionRequest, SizeRequest, View, ViewWrapper};
|
||||||
|
|
||||||
/// BoxView is a wrapper around an other view, with a given minimum size.
|
/// BoxView is a wrapper around an other view, with a given minimum size.
|
||||||
pub struct BoxView<T: View> {
|
pub struct BoxView<T: View> {
|
||||||
|
@ -3,7 +3,7 @@ use std::rc::Rc;
|
|||||||
use theme::ColorPair;
|
use theme::ColorPair;
|
||||||
use Cursive;
|
use Cursive;
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{View, SizeRequest};
|
use view::{SizeRequest, View};
|
||||||
use event::*;
|
use event::*;
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
|
|
||||||
@ -50,7 +50,9 @@ impl View for Button {
|
|||||||
fn on_event(&mut self, event: Event) -> EventResult {
|
fn on_event(&mut self, event: Event) -> EventResult {
|
||||||
match event {
|
match event {
|
||||||
// 10 is the ascii code for '\n', that is the return key
|
// 10 is the ascii code for '\n', that is the return key
|
||||||
Event::KeyEvent(Key::Enter) => EventResult::Consumed(Some(self.callback.clone())),
|
Event::KeyEvent(Key::Enter) => {
|
||||||
|
EventResult::Consumed(Some(self.callback.clone()))
|
||||||
|
}
|
||||||
_ => EventResult::Ignored,
|
_ => EventResult::Ignored,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ use Cursive;
|
|||||||
use align::*;
|
use align::*;
|
||||||
use event::*;
|
use event::*;
|
||||||
use theme::ColorPair;
|
use theme::ColorPair;
|
||||||
use view::{View, SizeRequest, DimensionRequest, Selector};
|
use view::{DimensionRequest, Selector, SizeRequest, TextView, View};
|
||||||
use view::{Button, SizedView};
|
use view::{Button, SizedView};
|
||||||
use vec::{Vec2, Vec4, ToVec4};
|
use vec::{ToVec4, Vec2, Vec4};
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
@ -52,6 +52,10 @@ impl Dialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn info(text: &str) -> Self {
|
||||||
|
Self::new(TextView::new(text)).dismiss_button("Ok")
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds a button to the dialog with the given label and callback.
|
/// Adds a button to the dialog with the given label and callback.
|
||||||
///
|
///
|
||||||
/// Consumes and returns self for easy chaining.
|
/// Consumes and returns self for easy chaining.
|
||||||
@ -117,7 +121,9 @@ impl View for Dialog {
|
|||||||
};
|
};
|
||||||
let overhead = self.padding + self.borders;
|
let overhead = self.padding + self.borders;
|
||||||
let mut offset = overhead.left +
|
let mut offset = overhead.left +
|
||||||
self.align.h.get_offset(width, printer.size.x - overhead.horizontal());
|
self.align.h.get_offset(width,
|
||||||
|
printer.size.x -
|
||||||
|
overhead.horizontal());
|
||||||
let y = printer.size.y - self.padding.bottom - self.borders.bottom - 1;
|
let y = printer.size.y - self.padding.bottom - self.borders.bottom - 1;
|
||||||
|
|
||||||
for (i, button) in self.buttons.iter_mut().enumerate() {
|
for (i, button) in self.buttons.iter_mut().enumerate() {
|
||||||
@ -133,10 +139,12 @@ impl View for Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// What do we have left?
|
// What do we have left?
|
||||||
let inner_size = printer.size - Vec2::new(0, height) - self.borders.combined() -
|
let inner_size = printer.size - Vec2::new(0, height) -
|
||||||
|
self.borders.combined() -
|
||||||
self.padding.combined();
|
self.padding.combined();
|
||||||
|
|
||||||
self.content.draw(&printer.sub_printer(self.borders.top_left() + self.padding.top_left(),
|
self.content.draw(&printer.sub_printer(self.borders.top_left() +
|
||||||
|
self.padding.top_left(),
|
||||||
inner_size,
|
inner_size,
|
||||||
self.focus == Focus::Content));
|
self.focus == Focus::Content));
|
||||||
|
|
||||||
@ -148,14 +156,16 @@ impl View for Dialog {
|
|||||||
printer.print((x - 2, 0), "┤ ");
|
printer.print((x - 2, 0), "┤ ");
|
||||||
printer.print((x + len, 0), " ├");
|
printer.print((x + len, 0), " ├");
|
||||||
|
|
||||||
printer.with_color(ColorPair::TitlePrimary, |p| p.print((x, 0), &self.title));
|
printer.with_color(ColorPair::TitlePrimary,
|
||||||
|
|p| p.print((x, 0), &self.title));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_min_size(&self, req: SizeRequest) -> Vec2 {
|
fn get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||||
// Padding and borders are not available for kids.
|
// Padding and borders are not available for kids.
|
||||||
let content_req = req.reduced(self.padding.combined() + self.borders.combined());
|
let content_req = req.reduced(self.padding.combined() +
|
||||||
|
self.borders.combined());
|
||||||
let content_size = self.content.get_min_size(content_req);
|
let content_size = self.content.get_min_size(content_req);
|
||||||
|
|
||||||
let mut buttons_size = Vec2::new(0, 0);
|
let mut buttons_size = Vec2::new(0, 0);
|
||||||
@ -215,7 +225,8 @@ impl View for Dialog {
|
|||||||
self.focus = Focus::Button(0);
|
self.focus = Focus::Button(0);
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::Tab) | Event::KeyEvent(Key::ShiftTab) => {
|
Event::KeyEvent(Key::Tab) |
|
||||||
|
Event::KeyEvent(Key::ShiftTab) => {
|
||||||
self.focus = Focus::Button(0);
|
self.focus = Focus::Button(0);
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
@ -239,7 +250,8 @@ impl View for Dialog {
|
|||||||
EventResult::Ignored
|
EventResult::Ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::Tab) | Event::KeyEvent(Key::ShiftTab) => {
|
Event::KeyEvent(Key::Tab) |
|
||||||
|
Event::KeyEvent(Key::ShiftTab) => {
|
||||||
if self.content.take_focus() {
|
if self.content.take_focus() {
|
||||||
self.focus = Focus::Content;
|
self.focus = Focus::Content;
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
@ -248,7 +260,9 @@ impl View for Dialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Left and Right move to other buttons
|
// Left and Right move to other buttons
|
||||||
Event::KeyEvent(Key::Right) if i + 1 < self.buttons.len() => {
|
Event::KeyEvent(Key::Right) if i + 1 <
|
||||||
|
self.buttons
|
||||||
|
.len() => {
|
||||||
self.focus = Focus::Button(i + 1);
|
self.focus = Focus::Button(i + 1);
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use std::cmp::min;
|
|||||||
|
|
||||||
use theme::ColorPair;
|
use theme::ColorPair;
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{View, IdView, SizeRequest};
|
use view::{IdView, SizeRequest, View};
|
||||||
use event::*;
|
use event::*;
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
|
|
||||||
@ -86,7 +86,8 @@ impl View for EditView {
|
|||||||
printer.print((0, 0), &self.content);
|
printer.print((0, 0), &self.content);
|
||||||
printer.print_hline((len, 0), printer.size.x - len, "_");
|
printer.print_hline((len, 0), printer.size.x - len, "_");
|
||||||
} else {
|
} else {
|
||||||
let visible_end = min(self.content.len(), self.offset + self.last_length);
|
let visible_end = min(self.content.len(),
|
||||||
|
self.offset + self.last_length);
|
||||||
|
|
||||||
let content = &self.content[self.offset..visible_end];
|
let content = &self.content[self.offset..visible_end];
|
||||||
printer.print((0, 0), content);
|
printer.print((0, 0), content);
|
||||||
@ -144,7 +145,10 @@ impl View for EditView {
|
|||||||
Key::Home => self.cursor = 0,
|
Key::Home => self.cursor = 0,
|
||||||
Key::End => self.cursor = self.content.chars().count(),
|
Key::End => self.cursor = self.content.chars().count(),
|
||||||
Key::Left if self.cursor > 0 => self.cursor -= 1,
|
Key::Left if self.cursor > 0 => self.cursor -= 1,
|
||||||
Key::Right if self.cursor < self.content.chars().count() => self.cursor += 1,
|
Key::Right if self.cursor <
|
||||||
|
self.content.chars().count() => {
|
||||||
|
self.cursor += 1
|
||||||
|
}
|
||||||
Key::Backspace if self.cursor > 0 => {
|
Key::Backspace if self.cursor > 0 => {
|
||||||
self.cursor -= 1;
|
self.cursor -= 1;
|
||||||
remove_char(&mut self.content, self.cursor);
|
remove_char(&mut self.content, self.cursor);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use view::{View, ViewWrapper, SizeRequest, DimensionRequest};
|
use view::{DimensionRequest, SizeRequest, View, ViewWrapper};
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
|
|
||||||
/// Simple wrapper view that asks for all the space it can get.
|
/// Simple wrapper view that asks for all the space it can get.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
use view::{View, ViewWrapper, Selector};
|
use view::{Selector, View, ViewWrapper};
|
||||||
|
|
||||||
/// Wrapper view that allows to select its content with a fixed string id.
|
/// Wrapper view that allows to select its content with a fixed string id.
|
||||||
pub struct IdView<T: View> {
|
pub struct IdView<T: View> {
|
||||||
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use Cursive;
|
use Cursive;
|
||||||
use event::{Event, EventResult, ToEvent, Callback};
|
use event::{Callback, Event, EventResult, ToEvent};
|
||||||
use super::{View, ViewWrapper};
|
use super::{View, ViewWrapper};
|
||||||
|
|
||||||
/// A simple wrapper view that catches some ignored event from its child.
|
/// A simple wrapper view that catches some ignored event from its child.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use view::{View, SizeRequest, DimensionRequest};
|
use view::{DimensionRequest, SizeRequest, View};
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
use orientation::Orientation;
|
use orientation::Orientation;
|
||||||
@ -113,9 +113,12 @@ impl View for LinearLayout {
|
|||||||
// Use pre-computed sizes
|
// Use pre-computed sizes
|
||||||
let mut offset = Vec2::zero();
|
let mut offset = Vec2::zero();
|
||||||
for (i, child) in self.children.iter_mut().enumerate() {
|
for (i, child) in self.children.iter_mut().enumerate() {
|
||||||
child.view.draw(&printer.sub_printer(offset, child.size, i == self.focus));
|
child.view.draw(&printer.sub_printer(offset,
|
||||||
|
child.size,
|
||||||
|
i == self.focus));
|
||||||
|
|
||||||
*self.orientation.get_ref(&mut offset) += self.orientation.get(&child.size);
|
*self.orientation.get_ref(&mut offset) += self.orientation
|
||||||
|
.get(&child.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +130,9 @@ impl View for LinearLayout {
|
|||||||
};
|
};
|
||||||
let min_sizes: Vec<Vec2> = self.children
|
let min_sizes: Vec<Vec2> = self.children
|
||||||
.iter()
|
.iter()
|
||||||
.map(|child| child.view.get_min_size(req))
|
.map(|child| {
|
||||||
|
child.view.get_min_size(req)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let min_size = self.orientation.stack(min_sizes.iter());
|
let min_size = self.orientation.stack(min_sizes.iter());
|
||||||
|
|
||||||
@ -148,12 +153,14 @@ impl View for LinearLayout {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
for (child, (child_size, extra)) in self.children
|
for (child, (child_size, extra)) in
|
||||||
.iter_mut()
|
self.children
|
||||||
.zip(min_sizes.iter().zip(extras.iter())) {
|
.iter_mut()
|
||||||
|
.zip(min_sizes.iter().zip(extras.iter())) {
|
||||||
let mut child_size = *child_size;
|
let mut child_size = *child_size;
|
||||||
*self.orientation.get_ref(&mut child_size) += *extra;
|
*self.orientation.get_ref(&mut child_size) += *extra;
|
||||||
*self.orientation.swap().get_ref(&mut child_size) = self.orientation.swap().get(&size);
|
*self.orientation.swap().get_ref(&mut child_size) =
|
||||||
|
self.orientation.swap().get(&size);
|
||||||
child.size = child_size;
|
child.size = child_size;
|
||||||
child.view.layout(child_size);
|
child.view.layout(child_size);
|
||||||
}
|
}
|
||||||
@ -171,9 +178,10 @@ impl View for LinearLayout {
|
|||||||
// Did it work? Champagne!
|
// Did it work? Champagne!
|
||||||
|
|
||||||
|
|
||||||
// Ok, so maybe it didn't.
|
// TODO: Ok, so maybe it didn't.
|
||||||
// Last chance: did someone lie about his needs?
|
// Last chance: did someone lie about his needs?
|
||||||
// Could we squash him a little?
|
// Could we squash him a little?
|
||||||
|
// (Maybe he'll just scroll and it'll be fine?)
|
||||||
|
|
||||||
// Find out who's fluid, if any.
|
// Find out who's fluid, if any.
|
||||||
}
|
}
|
||||||
@ -186,27 +194,34 @@ impl View for LinearLayout {
|
|||||||
self.focus -= 1;
|
self.focus -= 1;
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::ShiftTab) if self.focus + 1 < self.children.len() => {
|
Event::KeyEvent(Key::ShiftTab) if self.focus + 1 <
|
||||||
|
self.children.len() => {
|
||||||
self.focus += 1;
|
self.focus += 1;
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::Left) if self.orientation == Orientation::Horizontal &&
|
Event::KeyEvent(Key::Left) if self.orientation ==
|
||||||
|
Orientation::Horizontal &&
|
||||||
self.focus > 0 => {
|
self.focus > 0 => {
|
||||||
self.focus -= 1;
|
self.focus -= 1;
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::Up) if self.orientation == Orientation::Vertical &&
|
Event::KeyEvent(Key::Up) if self.orientation ==
|
||||||
|
Orientation::Vertical &&
|
||||||
self.focus > 0 => {
|
self.focus > 0 => {
|
||||||
self.focus -= 1;
|
self.focus -= 1;
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::Right) if self.orientation == Orientation::Horizontal &&
|
Event::KeyEvent(Key::Right) if self.orientation ==
|
||||||
self.focus + 1 < self.children.len() => {
|
Orientation::Horizontal &&
|
||||||
|
self.focus + 1 <
|
||||||
|
self.children.len() => {
|
||||||
self.focus += 1;
|
self.focus += 1;
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::Down) if self.orientation == Orientation::Vertical &&
|
Event::KeyEvent(Key::Down) if self.orientation ==
|
||||||
self.focus + 1 < self.children.len() => {
|
Orientation::Vertical &&
|
||||||
|
self.focus + 1 <
|
||||||
|
self.children.len() => {
|
||||||
self.focus += 1;
|
self.focus += 1;
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,9 @@ impl DimensionRequest {
|
|||||||
pub fn reduced(self, offset: usize) -> Self {
|
pub fn reduced(self, offset: usize) -> Self {
|
||||||
match self {
|
match self {
|
||||||
DimensionRequest::Fixed(w) => DimensionRequest::Fixed(w - offset),
|
DimensionRequest::Fixed(w) => DimensionRequest::Fixed(w - offset),
|
||||||
DimensionRequest::AtMost(w) => DimensionRequest::AtMost(w - offset),
|
DimensionRequest::AtMost(w) => {
|
||||||
|
DimensionRequest::AtMost(w - offset)
|
||||||
|
}
|
||||||
DimensionRequest::Unknown => DimensionRequest::Unknown,
|
DimensionRequest::Unknown => DimensionRequest::Unknown,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::cmp::{min, max};
|
use std::cmp::{max, min};
|
||||||
|
|
||||||
use theme::ColorPair;
|
use theme::ColorPair;
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
@ -26,7 +26,8 @@ impl ScrollBase {
|
|||||||
self.content_height = content_height;
|
self.content_height = content_height;
|
||||||
|
|
||||||
if self.scrollable() {
|
if self.scrollable() {
|
||||||
self.start_line = min(self.start_line, self.content_height - self.view_height);
|
self.start_line = min(self.start_line,
|
||||||
|
self.content_height - self.view_height);
|
||||||
} else {
|
} else {
|
||||||
self.start_line = 0;
|
self.start_line = 0;
|
||||||
}
|
}
|
||||||
@ -68,7 +69,8 @@ impl ScrollBase {
|
|||||||
|
|
||||||
/// Scroll down by the given number of line, never going further than the bottom of the view.
|
/// Scroll down by the given number of line, never going further than the bottom of the view.
|
||||||
pub fn scroll_down(&mut self, n: usize) {
|
pub fn scroll_down(&mut self, n: usize) {
|
||||||
self.start_line = min(self.start_line + n, self.content_height - self.view_height);
|
self.start_line = min(self.start_line + n,
|
||||||
|
self.content_height - self.view_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll up by the given number of lines, never going above the top of the view.
|
/// Scroll up by the given number of lines, never going above the top of the view.
|
||||||
@ -101,7 +103,8 @@ impl ScrollBase {
|
|||||||
where F: Fn(&Printer, usize)
|
where F: Fn(&Printer, usize)
|
||||||
{
|
{
|
||||||
// Print the content in a sub_printer
|
// Print the content in a sub_printer
|
||||||
let max_y = min(self.view_height, self.content_height - self.start_line);
|
let max_y = min(self.view_height,
|
||||||
|
self.content_height - self.start_line);
|
||||||
let w = if self.scrollable() {
|
let w = if self.scrollable() {
|
||||||
printer.size.x - 2
|
printer.size.x - 2
|
||||||
} else {
|
} else {
|
||||||
@ -110,7 +113,9 @@ impl ScrollBase {
|
|||||||
for y in 0..max_y {
|
for y in 0..max_y {
|
||||||
// Y is the actual coordinate of the line.
|
// Y is the actual coordinate of the line.
|
||||||
// The item ID is then Y + self.start_line
|
// The item ID is then Y + self.start_line
|
||||||
line_drawer(&printer.sub_printer(Vec2::new(0, y), Vec2::new(w, 1), true),
|
line_drawer(&printer.sub_printer(Vec2::new(0, y),
|
||||||
|
Vec2::new(w, 1),
|
||||||
|
true),
|
||||||
y + self.start_line);
|
y + self.start_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,12 +125,15 @@ impl ScrollBase {
|
|||||||
// We directly compute the size of the scrollbar (this allow use to avoid using floats).
|
// We directly compute the size of the scrollbar (this allow use to avoid using floats).
|
||||||
// (ratio) * max_height
|
// (ratio) * max_height
|
||||||
// Where ratio is ({start or end} / content.height)
|
// Where ratio is ({start or end} / content.height)
|
||||||
let height = max(1, self.view_height * self.view_height / self.content_height);
|
let height = max(1,
|
||||||
|
self.view_height * self.view_height /
|
||||||
|
self.content_height);
|
||||||
// Number of different possible positions
|
// Number of different possible positions
|
||||||
let steps = self.view_height - height + 1;
|
let steps = self.view_height - height + 1;
|
||||||
|
|
||||||
// Now
|
// Now
|
||||||
let start = steps * self.start_line / (1 + self.content_height - self.view_height);
|
let start = steps * self.start_line /
|
||||||
|
(1 + self.content_height - self.view_height);
|
||||||
|
|
||||||
let color = if printer.focused {
|
let color = if printer.focused {
|
||||||
ColorPair::Highlight
|
ColorPair::Highlight
|
||||||
|
@ -4,7 +4,7 @@ use std::rc::Rc;
|
|||||||
use theme::ColorPair;
|
use theme::ColorPair;
|
||||||
use Cursive;
|
use Cursive;
|
||||||
use align::*;
|
use align::*;
|
||||||
use view::{View, IdView, SizeRequest, DimensionRequest};
|
use view::{DimensionRequest, IdView, SizeRequest, View};
|
||||||
use event::{Event, EventResult, Key};
|
use event::{Event, EventResult, Key};
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
@ -53,7 +53,9 @@ impl<T: 'static> SelectView<T> {
|
|||||||
self.select_cb = Some(Rc::new(Box::new(cb)));
|
self.select_cb = Some(Rc::new(Box::new(cb)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a function to be called when an item is selected (when ENTER is pressed).
|
/// Sets a function to be called when an item is selected.
|
||||||
|
///
|
||||||
|
/// (When ENTER is pressed).
|
||||||
pub fn on_select<F>(mut self, cb: F) -> Self
|
pub fn on_select<F>(mut self, cb: F) -> Self
|
||||||
where F: Fn(&mut Cursive, &T) + 'static
|
where F: Fn(&mut Cursive, &T) + 'static
|
||||||
{
|
{
|
||||||
@ -84,7 +86,9 @@ impl<T: 'static> SelectView<T> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value of the currently selected item. Panics if the list is empty.
|
/// Returns the value of the currently selected item.
|
||||||
|
///
|
||||||
|
/// Panics if the list is empty.
|
||||||
pub fn selection(&self) -> Rc<T> {
|
pub fn selection(&self) -> Rc<T> {
|
||||||
self.items[self.focus].value.clone()
|
self.items[self.focus].value.clone()
|
||||||
}
|
}
|
||||||
@ -108,7 +112,7 @@ impl<T: 'static> SelectView<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SelectView<String> {
|
impl SelectView<String> {
|
||||||
/// For String-based SelectView, this is a convenient method to use the label as value.
|
/// Convenient method to use the label as value.
|
||||||
pub fn add_item_str(&mut self, label: &str) {
|
pub fn add_item_str(&mut self, label: &str) {
|
||||||
self.add_item(label, label.to_string());
|
self.add_item(label, label.to_string());
|
||||||
}
|
}
|
||||||
@ -124,7 +128,9 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
|
|
||||||
let h = self.items.len();
|
let h = self.items.len();
|
||||||
let offset = self.align.v.get_offset(h, printer.size.y);
|
let offset = self.align.v.get_offset(h, printer.size.y);
|
||||||
let printer = &printer.sub_printer(Vec2::new(0, offset), printer.size, true);
|
let printer = &printer.sub_printer(Vec2::new(0, offset),
|
||||||
|
printer.size,
|
||||||
|
true);
|
||||||
|
|
||||||
self.scrollbase.draw(printer, |printer, i| {
|
self.scrollbase.draw(printer, |printer, i| {
|
||||||
let style = if i == self.focus {
|
let style = if i == self.focus {
|
||||||
@ -147,7 +153,11 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_min_size(&self, req: SizeRequest) -> Vec2 {
|
fn get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||||
let w = self.items.iter().map(|item| item.label.len()).max().unwrap_or(1);
|
let w = self.items
|
||||||
|
.iter()
|
||||||
|
.map(|item| item.label.len())
|
||||||
|
.max()
|
||||||
|
.unwrap_or(1);
|
||||||
let h = self.items.len();
|
let h = self.items.len();
|
||||||
|
|
||||||
let scrolling = if let DimensionRequest::Fixed(r_h) = req.h {
|
let scrolling = if let DimensionRequest::Fixed(r_h) = req.h {
|
||||||
@ -171,7 +181,8 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
fn on_event(&mut self, event: Event) -> EventResult {
|
fn on_event(&mut self, event: Event) -> EventResult {
|
||||||
match event {
|
match event {
|
||||||
Event::KeyEvent(Key::Up) if self.focus > 0 => self.focus -= 1,
|
Event::KeyEvent(Key::Up) if self.focus > 0 => self.focus -= 1,
|
||||||
Event::KeyEvent(Key::Down) if self.focus + 1 < self.items.len() => self.focus += 1,
|
Event::KeyEvent(Key::Down) if self.focus + 1 <
|
||||||
|
self.items.len() => self.focus += 1,
|
||||||
Event::KeyEvent(Key::PageUp) => self.focus -= min(self.focus, 10),
|
Event::KeyEvent(Key::PageUp) => self.focus -= min(self.focus, 10),
|
||||||
Event::KeyEvent(Key::PageDown) => {
|
Event::KeyEvent(Key::PageDown) => {
|
||||||
self.focus = min(self.focus + 10, self.items.len() - 1)
|
self.focus = min(self.focus + 10, self.items.len() - 1)
|
||||||
@ -179,21 +190,26 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
Event::KeyEvent(Key::Home) => self.focus = 0,
|
Event::KeyEvent(Key::Home) => self.focus = 0,
|
||||||
Event::KeyEvent(Key::End) => self.focus = self.items.len() - 1,
|
Event::KeyEvent(Key::End) => self.focus = self.items.len() - 1,
|
||||||
Event::KeyEvent(Key::Enter) if self.select_cb.is_some() => {
|
Event::KeyEvent(Key::Enter) if self.select_cb.is_some() => {
|
||||||
if let Some(ref cb) = self.select_cb {
|
let cb = self.select_cb.as_ref().unwrap().clone();
|
||||||
let cb = cb.clone();
|
let v = self.selection();
|
||||||
let v = self.selection();
|
// We return a Rc<Box<Callback>>
|
||||||
return EventResult::Consumed(Some(Rc::new(Box::new(move |s| cb(s, &*v)))));
|
// With callback being |s| cb(s, &*v)
|
||||||
}
|
return EventResult::Consumed(Some(Rc::new(Box::new(move |s| cb(s, &*v)))));
|
||||||
}
|
}
|
||||||
Event::CharEvent(c) => {
|
Event::CharEvent(c) => {
|
||||||
// Starting from the current focus, find the first item that match the char.
|
// Starting from the current focus,
|
||||||
// Cycle back to the beginning of the list when we reach the end.
|
// find the first item that match the char.
|
||||||
|
// Cycle back to the beginning of
|
||||||
|
// the list when we reach the end.
|
||||||
// This is achieved by chaining twice the iterator
|
// This is achieved by chaining twice the iterator
|
||||||
let iter = self.items.iter().chain(self.items.iter());
|
let iter = self.items.iter().chain(self.items.iter());
|
||||||
if let Some((i, _)) = iter.enumerate()
|
if let Some((i, _)) = iter.enumerate()
|
||||||
.skip(self.focus + 1)
|
.skip(self.focus + 1)
|
||||||
.find(|&(_, item)| item.label.starts_with(c)) {
|
.find(|&(_, item)| {
|
||||||
// Apply modulo in case we have a hit from the chained iterator
|
item.label.starts_with(c)
|
||||||
|
}) {
|
||||||
|
// Apply modulo in case we have a hit
|
||||||
|
// from the chained iterator
|
||||||
self.focus = i % self.items.len();
|
self.focus = i % self.items.len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use view::{View, ViewWrapper, SizeRequest};
|
use view::{SizeRequest, View, ViewWrapper};
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use theme::ColorPair;
|
use theme::ColorPair;
|
||||||
@ -37,7 +37,9 @@ impl<T: View> ViewWrapper for ShadowView<T> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.view.draw(&printer.sub_printer(Vec2::new(1, 1), printer.size - (2, 2), true));
|
self.view.draw(&printer.sub_printer(Vec2::new(1, 1),
|
||||||
|
printer.size - (2, 2),
|
||||||
|
true));
|
||||||
|
|
||||||
let h = printer.size.y - 1;
|
let h = printer.size.y - 1;
|
||||||
let w = printer.size.x - 1;
|
let w = printer.size.x - 1;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{View, SizeRequest, DimensionRequest, Selector, ShadowView};
|
use view::{DimensionRequest, Selector, ShadowView, SizeRequest, View};
|
||||||
use event::{Event, EventResult};
|
use event::{Event, EventResult};
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
|
|
||||||
@ -66,6 +66,7 @@ impl View for StackView {
|
|||||||
for layer in self.layers.iter_mut() {
|
for layer in self.layers.iter_mut() {
|
||||||
layer.size = Vec2::min(size, layer.view.get_min_size(req));
|
layer.size = Vec2::min(size, layer.view.get_min_size(req));
|
||||||
layer.view.layout(layer.size);
|
layer.view.layout(layer.size);
|
||||||
|
// We do it here instead of when adding a new layer because...?
|
||||||
if layer.virgin {
|
if layer.virgin {
|
||||||
layer.view.take_focus();
|
layer.view.take_focus();
|
||||||
layer.virgin = false;
|
layer.virgin = false;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{View, DimensionRequest, SizeRequest};
|
use view::{DimensionRequest, SizeRequest, View};
|
||||||
use div::*;
|
use div::*;
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
use align::*;
|
use align::*;
|
||||||
@ -15,6 +15,7 @@ pub struct TextView {
|
|||||||
|
|
||||||
align: Align,
|
align: Align,
|
||||||
|
|
||||||
|
// ScrollBase make many scrolling-related things easier
|
||||||
scrollbase: ScrollBase,
|
scrollbase: ScrollBase,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +105,8 @@ impl TextView {
|
|||||||
.fold(0, |sum, x| sum + x)
|
.fold(0, |sum, x| sum + x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given the specified height, how many columns do we need to properly display?
|
// Given the specified height,
|
||||||
|
// how many columns do we need to properly display?
|
||||||
fn get_num_cols(&self, max_height: usize) -> usize {
|
fn get_num_cols(&self, max_height: usize) -> usize {
|
||||||
let len = self.content.chars().count();
|
let len = self.content.chars().count();
|
||||||
(div_up_usize(len, max_height)..len)
|
(div_up_usize(len, max_height)..len)
|
||||||
@ -180,7 +182,8 @@ impl<'a> Iterator for LinesIterator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let i = if content_len == self.width + 1 {
|
let i = if content_len == self.width + 1 {
|
||||||
// We can't look at the index if we're looking at the end of the string
|
// We can't look at the index
|
||||||
|
// if we're looking at the end of the string
|
||||||
content.len()
|
content.len()
|
||||||
} else {
|
} else {
|
||||||
content.char_indices().nth(self.width + 1).unwrap().0
|
content.char_indices().nth(self.width + 1).unwrap().0
|
||||||
@ -210,7 +213,9 @@ impl View for TextView {
|
|||||||
|
|
||||||
let h = self.rows.len();
|
let h = self.rows.len();
|
||||||
let offset = self.align.v.get_offset(h, printer.size.y);
|
let offset = self.align.v.get_offset(h, printer.size.y);
|
||||||
let printer = &printer.sub_printer(Vec2::new(0, offset), printer.size, true);
|
let printer = &printer.sub_printer(Vec2::new(0, offset),
|
||||||
|
printer.size,
|
||||||
|
true);
|
||||||
|
|
||||||
self.scrollbase.draw(printer, |printer, i| {
|
self.scrollbase.draw(printer, |printer, i| {
|
||||||
let row = &self.rows[i];
|
let row = &self.rows[i];
|
||||||
@ -232,7 +237,8 @@ impl View for TextView {
|
|||||||
Event::KeyEvent(Key::Up) if self.scrollbase.can_scroll_up() => {
|
Event::KeyEvent(Key::Up) if self.scrollbase.can_scroll_up() => {
|
||||||
self.scrollbase.scroll_up(1)
|
self.scrollbase.scroll_up(1)
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::Down) if self.scrollbase.can_scroll_down() => {
|
Event::KeyEvent(Key::Down) if self.scrollbase
|
||||||
|
.can_scroll_down() => {
|
||||||
self.scrollbase.scroll_down(1)
|
self.scrollbase.scroll_down(1)
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::PageDown) => self.scrollbase.scroll_down(10),
|
Event::KeyEvent(Key::PageDown) => self.scrollbase.scroll_down(10),
|
||||||
@ -247,8 +253,11 @@ impl View for TextView {
|
|||||||
match (size.w, size.h) {
|
match (size.w, size.h) {
|
||||||
// If we have no directive, ask for a single big line.
|
// If we have no directive, ask for a single big line.
|
||||||
// TODO: what if the text has newlines??
|
// TODO: what if the text has newlines??
|
||||||
(DimensionRequest::Unknown, DimensionRequest::Unknown) => self.get_ideal_size(),
|
(DimensionRequest::Unknown, DimensionRequest::Unknown) => {
|
||||||
|
self.get_ideal_size()
|
||||||
|
}
|
||||||
(DimensionRequest::Fixed(w), _) => {
|
(DimensionRequest::Fixed(w), _) => {
|
||||||
|
// In a BoxView or something.
|
||||||
let h = self.get_num_lines(w);
|
let h = self.get_num_lines(w);
|
||||||
Vec2::new(w, h)
|
Vec2::new(w, h)
|
||||||
}
|
}
|
||||||
@ -261,8 +270,10 @@ impl View for TextView {
|
|||||||
let ideal = self.get_ideal_size();
|
let ideal = self.get_ideal_size();
|
||||||
|
|
||||||
if w >= ideal.x {
|
if w >= ideal.x {
|
||||||
|
// This is the cheap path
|
||||||
ideal
|
ideal
|
||||||
} else {
|
} else {
|
||||||
|
// This is the expensive one :(
|
||||||
let h = self.get_num_lines(w);
|
let h = self.get_num_lines(w);
|
||||||
Vec2::new(w, h)
|
Vec2::new(w, h)
|
||||||
}
|
}
|
||||||
@ -279,7 +290,8 @@ impl View for TextView {
|
|||||||
// Compute the text rows.
|
// Compute the text rows.
|
||||||
self.rows = LinesIterator::new(&self.content, size.x).collect();
|
self.rows = LinesIterator::new(&self.content, size.x).collect();
|
||||||
if self.rows.len() > size.y {
|
if self.rows.len() > size.y {
|
||||||
self.rows = LinesIterator::new(&self.content, size.x - 2).collect();
|
self.rows = LinesIterator::new(&self.content, size.x - 2)
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
self.scrollbase.set_heights(size.y, self.rows.len());
|
self.scrollbase.set_heights(size.y, self.rows.len());
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{View, SizeRequest, Selector};
|
use view::{Selector, SizeRequest, View};
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
use event::{Event, EventResult};
|
use event::{Event, EventResult};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user