Split width and height in BoxView

They are now both optional
This commit is contained in:
Alexandre Bury 2016-07-11 19:24:00 -07:00
parent c07e8b6aee
commit b7a270f258
8 changed files with 85 additions and 100 deletions

View File

@ -9,7 +9,7 @@ use cursive::event::{EventResult, Event};
fn main() {
let mut siv = Cursive::new();
siv.add_layer(BoxView::new((30, 10), KeyCodeView::new(10)));
siv.add_layer(BoxView::fixed_size((30, 10), KeyCodeView::new(10)));
siv.run();
}

View File

@ -17,7 +17,7 @@ fn main() {
.child(TextView::new("Title").h_align(HAlign::Center))
// Box the textview, so it doesn't get too wide.
// A 0 height value means it will be unconstrained.
.child(BoxView::new((30,0), TextView::new(text))))
.child(BoxView::fixed_width(30, TextView::new(text))))
.button("Quit", |s| s.quit())
.h_align(HAlign::Center));

View File

@ -24,7 +24,7 @@ fn main() {
let mut siv = Cursive::new();
// Let's add a BoxView to keep the list at a reasonable size - it can scroll anyway.
siv.add_layer(Dialog::new(BoxView::new((20, 10), select))
siv.add_layer(Dialog::new(BoxView::fixed_size((20, 10), select))
.title("Where are you from?"));
siv.run();

View File

@ -7,7 +7,7 @@ use backend::Backend;
use B;
use theme::{ColorStyle, Effect, Theme};
use vec::{ToVec2, Vec2};
use vec::Vec2;
/// Convenient interface to draw on a subset of the screen.
#[derive(Clone)]
@ -24,10 +24,10 @@ pub struct Printer {
impl Printer {
/// Creates a new printer on the given window.
pub fn new<T: ToVec2>(size: T, theme: Theme) -> Self {
pub fn new<T: Into<Vec2>>(size: T, theme: Theme) -> Self {
Printer {
offset: Vec2::zero(),
size: size.to_vec2(),
size: size.into(),
focused: true,
theme: theme,
}
@ -36,8 +36,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.
pub fn print<S: ToVec2>(&self, pos: S, text: &str) {
let p = pos.to_vec2();
pub fn print<S: Into<Vec2>>(&self, pos: S, text: &str) {
let p = pos.into();
if p.y >= self.size.y || p.x >= self.size.x {
return;
}
@ -59,8 +59,8 @@ impl Printer {
}
/// Prints a vertical line using the given character.
pub fn print_vline<T: ToVec2>(&self, start: T, len: usize, c: &str) {
let p = start.to_vec2();
pub fn print_vline<T: Into<Vec2>>(&self, start: T, len: usize, c: &str) {
let p = start.into();
if p.y > self.size.y || p.x > self.size.x {
return;
}
@ -73,8 +73,8 @@ impl Printer {
}
/// Prints a horizontal line using the given character.
pub fn print_hline<T: ToVec2>(&self, start: T, len: usize, c: &str) {
let p = start.to_vec2();
pub fn print_hline<T: Into<Vec2>>(&self, start: T, len: usize, c: &str) {
let p = start.into();
if p.y > self.size.y || p.x > self.size.x {
return;
}
@ -125,9 +125,9 @@ impl Printer {
/// # let printer = Printer::new((6,4), theme::load_default());
/// printer.print_box((0,0), (6,4));
/// ```
pub fn print_box<T: ToVec2>(&self, start: T, size: T) {
let start_v = start.to_vec2();
let size_v = size.to_vec2() - (1, 1);
pub fn print_box<T: Into<Vec2>>(&self, start: T, size: T) {
let start_v = start.into();
let size_v = size.into() - (1, 1);
self.print(start_v, "");
self.print(start_v + size_v.keep_x(), "");
@ -157,21 +157,21 @@ impl Printer {
f);
}
pub fn print_hdelim<T: ToVec2>(&self, start: T, len: usize) {
let start = start.to_vec2();
pub fn print_hdelim<T: Into<Vec2>>(&self, start: T, len: usize) {
let start = start.into();
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.
pub fn sub_printer<S: ToVec2>(&self, offset: S, size: S, focused: bool)
pub fn sub_printer<S: Into<Vec2>>(&self, offset: S, size: S, focused: bool)
-> Printer {
let offset_v = offset.to_vec2();
let offset_v = offset.into();
Printer {
offset: self.offset + offset_v,
// We can't be larger than what remains
size: Vec2::min(self.size - offset_v, size.to_vec2()),
size: Vec2::min(self.size - offset_v, size.into()),
focused: self.focused && focused,
theme: self.theme.clone(),
}

View File

@ -68,41 +68,30 @@ impl Vec2 {
}
}
/// A generic trait for converting a value into a 2D vector.
pub trait ToVec2 {
/// Converts self into a Vec2.
fn to_vec2(self) -> Vec2;
}
impl ToVec2 for Vec2 {
fn to_vec2(self) -> Vec2 {
self
impl From<(usize, usize)> for Vec2 {
fn from((x, y): (usize, usize)) -> Self {
Vec2::new(x, y)
}
}
impl ToVec2 for (i32, i32) {
fn to_vec2(self) -> Vec2 {
(self.0 as usize, self.1 as usize).to_vec2()
impl From<(i32, i32)> for Vec2 {
fn from((x, y): (i32, i32)) -> Self {
(x as usize, y as usize).into()
}
}
impl ToVec2 for (usize, usize) {
fn to_vec2(self) -> Vec2 {
Vec2::new(self.0, self.1)
impl From<(u32, u32)> for Vec2 {
fn from((x, y): (u32, u32)) -> Self {
(x as usize, y as usize).into()
}
}
impl ToVec2 for (u32, u32) {
fn to_vec2(self) -> Vec2 {
Vec2::new(self.0 as usize, self.1 as usize)
}
}
impl<T: ToVec2> Add<T> for Vec2 {
impl<T: Into<Vec2>> Add<T> for Vec2 {
type Output = Vec2;
fn add(self, other: T) -> Vec2 {
let ov = other.to_vec2();
let ov = other.into();
Vec2 {
x: self.x + ov.x,
y: self.y + ov.y,
@ -110,11 +99,11 @@ impl<T: ToVec2> Add<T> for Vec2 {
}
}
impl<T: ToVec2> Sub<T> for Vec2 {
impl<T: Into<Vec2>> Sub<T> for Vec2 {
type Output = Vec2;
fn sub(self, other: T) -> Vec2 {
let ov = other.to_vec2();
let ov = other.into();
Vec2 {
x: self.x - ov.x,
y: self.y - ov.y,
@ -194,38 +183,23 @@ impl Vec4 {
}
}
/// Generic trait for converting a value into a Vec4.
pub trait ToVec4 {
/// Converts self to a Vec4.
fn to_vec4(self) -> Vec4;
}
impl ToVec4 for Vec4 {
fn to_vec4(self) -> Vec4 {
self
impl From<(usize, usize, usize, usize)> for Vec4 {
fn from((left, right, top, bottom): (usize, usize, usize, usize)) -> Vec4 {
Vec4::new(left, right, top, bottom)
}
}
impl ToVec4 for (usize, usize, usize, usize) {
fn to_vec4(self) -> Vec4 {
Vec4::new(self.0, self.1, self.2, self.3)
impl From<(i32, i32, i32, i32)> for Vec4 {
fn from((left, right, top, bottom): (i32, i32, i32, i32)) -> Vec4 {
(left as usize, right as usize, top as usize, bottom as usize).into()
}
}
impl ToVec4 for (i32, i32, i32, i32) {
fn to_vec4(self) -> Vec4 {
Vec4::new(self.0 as usize,
self.1 as usize,
self.2 as usize,
self.3 as usize)
}
}
impl<T: ToVec4> Add<T> for Vec4 {
impl<T: Into<Vec4>> Add<T> for Vec4 {
type Output = Vec4;
fn add(self, other: T) -> Vec4 {
let ov = other.to_vec4();
let ov = other.into();
Vec4 {
left: self.left + ov.left,
@ -236,11 +210,11 @@ impl<T: ToVec4> Add<T> for Vec4 {
}
}
impl<T: ToVec4> Sub<T> for Vec4 {
impl<T: Into<Vec4>> Sub<T> for Vec4 {
type Output = Vec4;
fn sub(self, other: T) -> Vec4 {
let ov = other.to_vec4();
let ov = other.into();
Vec4 {
left: self.left - ov.left,

View File

@ -1,11 +1,12 @@
use std::cmp;
use vec::{ToVec2, Vec2};
use vec::Vec2;
use super::{View, ViewWrapper};
/// `BoxView` is a wrapper around an other view, with a given minimum size.
pub struct BoxView<T: View> {
size: Vec2,
width: Option<usize>,
height: Option<usize>,
view: T,
}
@ -17,38 +18,48 @@ impl<T: View> BoxView<T> {
/// ```
/// # use cursive::view::{BoxView,TextView};
/// // Creates a 20x4 BoxView with a TextView content.
/// let view = BoxView::new((20,4), TextView::new("Hello!"));
/// let view = BoxView::fixed_size((20,4), TextView::new("Hello!"));
/// ```
pub fn new<S: ToVec2>(size: S, view: T) -> Self {
pub fn fixed_size<S: Into<Vec2>>(size: S, view: T) -> Self {
let size = size.into();
BoxView::new(Some(size.x), Some(size.y), view)
}
pub fn new(width: Option<usize>, height: Option<usize>, view: T) -> Self {
BoxView {
size: size.to_vec2(),
width: width,
height: height,
view: view,
}
}
pub fn fixed_width(width: usize, view: T) -> Self {
BoxView::new(Some(width), None, view)
}
}
fn min<T: Ord>(a: T, b: Option<T>) -> T {
match b {
Some(b) => cmp::min(a, b),
None => a,
}
}
impl<T: View> ViewWrapper for BoxView<T> {
wrap_impl!(&self.view);
fn wrap_get_min_size(&mut self, mut req: Vec2) -> Vec2 {
if self.size.x > 0 {
req.x = cmp::min(self.size.x, req.x);
}
if self.size.y > 0 {
req.y = cmp::min(self.size.y, req.y);
}
fn wrap_get_min_size(&mut self, req: Vec2) -> Vec2 {
let mut size = self.view.get_min_size(req);
if let (Some(w), Some(h)) = (self.width, self.height) {
Vec2::new(w, h)
} else {
let req = Vec2::new(min(req.x, self.width),
min(req.y, self.height));
let child_size = self.view.get_min_size(req);
// Did he think he got to decide?
// Of course we have the last word here.
if self.size.x > 0 {
size.x = self.size.x;
}
if self.size.y > 0 {
size.y = self.size.y;
}
size
Vec2::new(self.width.unwrap_or(child_size.x),
self.height.unwrap_or(child_size.y))
}
}
}

View File

@ -7,7 +7,7 @@ use event::*;
use theme::ColorStyle;
use view::{Selector, TextView, View};
use view::{Button, SizedView};
use vec::{ToVec4, Vec2, Vec4};
use vec::{Vec2, Vec4};
use printer::Printer;
use unicode_width::UnicodeWidthStr;
@ -99,8 +99,8 @@ impl Dialog {
}
/// Sets the padding in the dialog (around content and buttons).
pub fn padding<T: ToVec4>(mut self, padding: T) -> Self {
self.padding = padding.to_vec4();
pub fn padding<T: Into<Vec4>>(mut self, padding: T) -> Self {
self.padding = padding.into();
self
}

View File

@ -1,5 +1,5 @@
use std::cmp::min;
use vec::{ToVec2, Vec2};
use vec::Vec2;
/// Location of the view on screen
#[derive(PartialEq,Debug,Clone)]
@ -17,13 +17,13 @@ impl Position {
Position::new(Offset::Center, Offset::Center)
}
pub fn absolute<T: ToVec2>(offset: T) -> Self {
let offset = offset.to_vec2();
pub fn absolute<T: Into<Vec2>>(offset: T) -> Self {
let offset = offset.into();
Position::new(Offset::Absolute(offset.x), Offset::Absolute(offset.y))
}
pub fn parent<T: ToVec2>(offset: T) -> Self {
let offset = offset.to_vec2();
pub fn parent<T: Into<Vec2>>(offset: T) -> Self {
let offset = offset.into();
Position::new(Offset::Parent(offset.x), Offset::Parent(offset.y))
}