mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Replace SizeRequest with simple Vec2
We may go back to an enum though, to handle text views in LinearLayouts. But the previous Fixed/AtMost/Unknown distinction was useless.
This commit is contained in:
parent
c958093b74
commit
1b1d7166a1
@ -1,3 +1,5 @@
|
||||
|
||||
/*
|
||||
/// Integer division that rounds up.
|
||||
pub fn div_up_usize(p: usize, q: usize) -> usize {
|
||||
div_up(p as u32, q as u32) as usize
|
||||
@ -11,3 +13,4 @@ pub fn div_up(p: u32, q: u32) -> u32 {
|
||||
1 + p / q
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -2,7 +2,7 @@
|
||||
use vec::Vec2;
|
||||
|
||||
/// Describes a vertical or horizontal orientation for a view.
|
||||
#[derive(Clone,Copy,PartialEq)]
|
||||
#[derive(Clone,Copy,Debug,PartialEq)]
|
||||
pub enum Orientation {
|
||||
/// Horizontal orientation
|
||||
Horizontal,
|
||||
|
@ -295,7 +295,6 @@ impl Color {
|
||||
} else if value.len() == 3 {
|
||||
// RGB values between 0 and 5 maybe?
|
||||
let rgb: Vec<_> = value.chars().map(|c| c as i16 - '0' as i16).collect();
|
||||
println!("{:?}", rgb);
|
||||
if rgb.iter().all(|&i| i >= 0 && i < 6) {
|
||||
Some(Color::RgbLowRes(rgb[0] as u8, rgb[1] as u8, rgb[2] as u8))
|
||||
} else {
|
||||
|
@ -1,5 +1,7 @@
|
||||
use std::cmp;
|
||||
|
||||
use vec::{ToVec2, Vec2};
|
||||
use super::{DimensionRequest, SizeRequest, View, ViewWrapper};
|
||||
use super::{View, ViewWrapper};
|
||||
|
||||
/// `BoxView` is a wrapper around an other view, with a given minimum size.
|
||||
pub struct BoxView<T: View> {
|
||||
@ -28,16 +30,18 @@ impl<T: View> BoxView<T> {
|
||||
impl<T: View> ViewWrapper for BoxView<T> {
|
||||
wrap_impl!(&self.view);
|
||||
|
||||
fn wrap_get_min_size(&self, mut req: SizeRequest) -> Vec2 {
|
||||
fn wrap_get_min_size(&self, mut req: Vec2) -> Vec2 {
|
||||
if self.size.x > 0 {
|
||||
req.w = DimensionRequest::AtMost(self.size.x);
|
||||
req.x = cmp::min(self.size.x, req.x);
|
||||
}
|
||||
if self.size.y > 0 {
|
||||
req.h = DimensionRequest::AtMost(self.size.y);
|
||||
req.y = cmp::min(self.size.y, req.y);
|
||||
}
|
||||
|
||||
let mut 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;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use std::rc::Rc;
|
||||
use theme::ColorStyle;
|
||||
use Cursive;
|
||||
use vec::Vec2;
|
||||
use view::{SizeRequest, View};
|
||||
use view::{View};
|
||||
use event::*;
|
||||
use printer::Printer;
|
||||
|
||||
@ -42,7 +42,7 @@ impl View for Button {
|
||||
});
|
||||
}
|
||||
|
||||
fn get_min_size(&self, _: SizeRequest) -> Vec2 {
|
||||
fn get_min_size(&self, _: Vec2) -> Vec2 {
|
||||
// Meh. Fixed size we are.
|
||||
Vec2::new(2 + self.label.chars().count(), 1)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use Cursive;
|
||||
use align::*;
|
||||
use event::*;
|
||||
use theme::ColorStyle;
|
||||
use view::{DimensionRequest, Selector, SizeRequest, TextView, View};
|
||||
use view::{Selector, TextView, View};
|
||||
use view::{Button, SizedView};
|
||||
use vec::{ToVec4, Vec2, Vec4};
|
||||
use printer::Printer;
|
||||
@ -157,9 +157,9 @@ impl View for Dialog {
|
||||
|
||||
}
|
||||
|
||||
fn get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||
fn get_min_size(&self, req: Vec2) -> Vec2 {
|
||||
// Padding and borders are not available for kids.
|
||||
let content_req = req.reduced(self.padding.combined() + self.borders.combined());
|
||||
let content_req = req - (self.padding.combined() + self.borders.combined());
|
||||
let content_size = self.content.get_min_size(content_req);
|
||||
|
||||
let mut buttons_size = Vec2::new(0, 0);
|
||||
@ -189,16 +189,13 @@ impl View for Dialog {
|
||||
|
||||
fn layout(&mut self, mut size: Vec2) {
|
||||
// Padding and borders are taken, sorry.
|
||||
// TODO: handle border-less themes?
|
||||
size = size - (self.borders.combined() + self.padding.combined());
|
||||
let req = SizeRequest {
|
||||
w: DimensionRequest::AtMost(size.x),
|
||||
h: DimensionRequest::AtMost(size.y),
|
||||
};
|
||||
|
||||
// Buttons are kings, we give them everything they want.
|
||||
let mut buttons_height = 0;
|
||||
for button in self.buttons.iter_mut().rev() {
|
||||
let size = button.get_min_size(req);
|
||||
let size = button.get_min_size(size);
|
||||
buttons_height = max(buttons_height, size.y + 1);
|
||||
button.layout(size);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use std::cmp::min;
|
||||
|
||||
use theme::{ColorStyle, Effect};
|
||||
use vec::Vec2;
|
||||
use view::{IdView, SizeRequest, View};
|
||||
use view::{IdView, View};
|
||||
use event::*;
|
||||
use printer::Printer;
|
||||
|
||||
@ -123,7 +123,7 @@ impl View for EditView {
|
||||
self.last_length = size.x;
|
||||
}
|
||||
|
||||
fn get_min_size(&self, _: SizeRequest) -> Vec2 {
|
||||
fn get_min_size(&self, _: Vec2) -> Vec2 {
|
||||
Vec2::new(self.min_length, 1)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use view::{DimensionRequest, SizeRequest, View, ViewWrapper};
|
||||
use view::{View, ViewWrapper};
|
||||
use vec::Vec2;
|
||||
|
||||
/// Simple wrapper view that asks for all the space it can get.
|
||||
@ -16,18 +16,7 @@ impl<T: View> FullView<T> {
|
||||
impl<T: View> ViewWrapper for FullView<T> {
|
||||
wrap_impl!(&self.view);
|
||||
|
||||
fn wrap_get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||
let w = match req.w {
|
||||
DimensionRequest::Fixed(w) |
|
||||
DimensionRequest::AtMost(w) => w,
|
||||
DimensionRequest::Unknown => self.view.get_min_size(req).x,
|
||||
};
|
||||
let h = match req.h {
|
||||
DimensionRequest::Fixed(h) |
|
||||
DimensionRequest::AtMost(h) => h,
|
||||
DimensionRequest::Unknown => self.view.get_min_size(req).y,
|
||||
};
|
||||
|
||||
Vec2::new(w, h)
|
||||
fn wrap_get_min_size(&self, req: Vec2) -> Vec2 {
|
||||
req
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use view::{DimensionRequest, SizeRequest, View};
|
||||
use view::View;
|
||||
use vec::Vec2;
|
||||
use printer::Printer;
|
||||
use orientation::Orientation;
|
||||
@ -115,6 +115,8 @@ impl View for LinearLayout {
|
||||
for (i, child) in self.children.iter_mut().enumerate() {
|
||||
child.view.draw(&printer.sub_printer(offset, child.size, i == self.focus));
|
||||
|
||||
// On the axis given by the orientation,
|
||||
// add the child size to the offset.
|
||||
*self.orientation.get_ref(&mut offset) += self.orientation
|
||||
.get(&child.size);
|
||||
}
|
||||
@ -122,18 +124,16 @@ impl View for LinearLayout {
|
||||
|
||||
fn layout(&mut self, size: Vec2) {
|
||||
// Compute the very minimal required size
|
||||
let req = SizeRequest {
|
||||
w: DimensionRequest::AtMost(size.x),
|
||||
h: DimensionRequest::AtMost(size.y),
|
||||
};
|
||||
// Look how mean we are: we offer the whole size to every child.
|
||||
// As if they could get it all.
|
||||
let min_sizes: Vec<Vec2> = self.children
|
||||
.iter()
|
||||
.map(|child| child.view.get_min_size(req))
|
||||
.map(|child| Vec2::min(size, child.view.get_min_size(size)))
|
||||
.collect();
|
||||
let min_size = self.orientation.stack(min_sizes.iter());
|
||||
|
||||
// Emulate 'non-strict inequality' on integers
|
||||
// (default comparison on Vec2 is strict)
|
||||
// (default comparison on Vec2 is strict, and (0,1).cmp((1,1)) is undefined)
|
||||
if !(min_size < size + (1, 1)) {
|
||||
// Error! Not enough space! Emergency procedures!
|
||||
return;
|
||||
@ -160,7 +160,7 @@ impl View for LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||
fn get_min_size(&self, req: Vec2) -> Vec2 {
|
||||
// First, make a naive scenario: everything will work fine.
|
||||
let sizes: Vec<Vec2> = self.children
|
||||
.iter()
|
||||
|
@ -5,7 +5,6 @@ mod view_wrapper;
|
||||
|
||||
// Essentials components
|
||||
mod position;
|
||||
mod request;
|
||||
mod view_path;
|
||||
|
||||
// Helper bases
|
||||
@ -36,7 +35,6 @@ use printer::Printer;
|
||||
|
||||
pub use self::position::{Position, Offset};
|
||||
|
||||
pub use self::request::{DimensionRequest, SizeRequest};
|
||||
pub use self::scroll::ScrollBase;
|
||||
|
||||
pub use self::id_view::IdView;
|
||||
@ -65,7 +63,7 @@ pub trait View {
|
||||
}
|
||||
|
||||
/// Returns the minimum size the view requires under the given restrictions.
|
||||
fn get_min_size(&self, SizeRequest) -> Vec2 {
|
||||
fn get_min_size(&self, Vec2) -> Vec2 {
|
||||
Vec2::new(1, 1)
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ use std::rc::Rc;
|
||||
use theme::ColorStyle;
|
||||
use Cursive;
|
||||
use align::*;
|
||||
use view::{DimensionRequest, IdView, SizeRequest, View};
|
||||
use view::{IdView, View};
|
||||
use event::{Event, EventResult, Key};
|
||||
use vec::Vec2;
|
||||
use printer::Printer;
|
||||
@ -150,7 +150,10 @@ impl<T: 'static> View for SelectView<T> {
|
||||
});
|
||||
}
|
||||
|
||||
fn get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||
fn get_min_size(&self, req: Vec2) -> Vec2 {
|
||||
// Items here are not compressible.
|
||||
// So no matter what the horizontal requirements are,
|
||||
// we'll still return our longest item.
|
||||
let w = self.items
|
||||
.iter()
|
||||
.map(|item| item.label.len())
|
||||
@ -158,13 +161,7 @@ impl<T: 'static> View for SelectView<T> {
|
||||
.unwrap_or(1);
|
||||
let h = self.items.len();
|
||||
|
||||
let scrolling = if let DimensionRequest::Fixed(r_h) = req.h {
|
||||
r_h < h
|
||||
} else if let DimensionRequest::AtMost(r_h) = req.h {
|
||||
r_h < h
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let scrolling = req.y < h;
|
||||
|
||||
// Add 2 spaces for the scrollbar if we need
|
||||
let w = if scrolling {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use view::{SizeRequest, View, ViewWrapper};
|
||||
use view::{View, ViewWrapper};
|
||||
use printer::Printer;
|
||||
use vec::Vec2;
|
||||
use theme::ColorStyle;
|
||||
@ -20,8 +20,8 @@ impl<T: View> ShadowView<T> {
|
||||
impl<T: View> ViewWrapper for ShadowView<T> {
|
||||
wrap_impl!(&self.view);
|
||||
|
||||
fn wrap_get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||
self.view.get_min_size(req.reduced((2, 2))) + (2, 2)
|
||||
fn wrap_get_min_size(&self, req: Vec2) -> Vec2 {
|
||||
self.view.get_min_size(req - (2, 2)) + (2, 2)
|
||||
}
|
||||
|
||||
fn wrap_layout(&mut self, size: Vec2) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::any::Any;
|
||||
|
||||
use vec::Vec2;
|
||||
use view::{DimensionRequest, Selector, ShadowView, SizeRequest, View, Position};
|
||||
use view::{Selector, ShadowView, View, Position};
|
||||
use event::{Event, EventResult};
|
||||
use printer::Printer;
|
||||
use theme::ColorStyle;
|
||||
@ -78,14 +78,10 @@ impl View for StackView {
|
||||
fn layout(&mut self, size: Vec2) {
|
||||
// The call has been made, we can't ask for more space anymore.
|
||||
// Let's make do with what we have.
|
||||
let req = SizeRequest {
|
||||
w: DimensionRequest::AtMost(size.x),
|
||||
h: DimensionRequest::AtMost(size.y),
|
||||
};
|
||||
|
||||
for layer in &mut self.layers {
|
||||
// Give each guy what he asks for, within the budget constraints.
|
||||
layer.size = Vec2::min(size, layer.view.get_min_size(req));
|
||||
layer.size = Vec2::min(size, layer.view.get_min_size(size));
|
||||
layer.view.layout(layer.size);
|
||||
|
||||
// We do it here instead of when adding a new layer because...?
|
||||
@ -97,16 +93,13 @@ impl View for StackView {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_min_size(&self, size: SizeRequest) -> Vec2 {
|
||||
fn get_min_size(&self, size: Vec2) -> Vec2 {
|
||||
// The min size is the max of all children's
|
||||
let mut s = Vec2::new(1, 1);
|
||||
|
||||
for layer in &self.layers {
|
||||
let vs = layer.view.get_min_size(size);
|
||||
s = Vec2::max(s, vs);
|
||||
}
|
||||
|
||||
s
|
||||
self.layers
|
||||
.iter()
|
||||
.map(|layer| layer.view.get_min_size(size))
|
||||
.fold(Vec2::new(1, 1), Vec2::max)
|
||||
}
|
||||
|
||||
fn take_focus(&mut self) -> bool {
|
||||
|
@ -1,8 +1,7 @@
|
||||
use std::cmp::max;
|
||||
|
||||
use vec::Vec2;
|
||||
use view::{DimensionRequest, SizeRequest, View};
|
||||
use div::*;
|
||||
use view::View;
|
||||
use printer::Printer;
|
||||
use align::*;
|
||||
use event::*;
|
||||
@ -105,15 +104,6 @@ impl TextView {
|
||||
.fold(0, |sum, x| sum + x)
|
||||
}
|
||||
|
||||
// Given the specified height,
|
||||
// how many columns do we need to properly display?
|
||||
fn get_num_cols(&self, max_height: usize) -> usize {
|
||||
let len = self.content.chars().count();
|
||||
(div_up_usize(len, max_height)..len)
|
||||
.find(|w| self.get_num_lines(*w) <= max_height)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
// In the absence of any constraint, what size would we like?
|
||||
fn get_ideal_size(&self) -> Vec2 {
|
||||
let mut max_width = 0;
|
||||
@ -244,34 +234,19 @@ impl View for TextView {
|
||||
EventResult::Consumed(None)
|
||||
}
|
||||
|
||||
fn get_min_size(&self, size: SizeRequest) -> Vec2 {
|
||||
match (size.w, size.h) {
|
||||
// If we have no directive, ask for a single big line.
|
||||
// TODO: what if the text has newlines??
|
||||
(DimensionRequest::Unknown, DimensionRequest::Unknown) => self.get_ideal_size(),
|
||||
(DimensionRequest::Fixed(w), _) => {
|
||||
// In a BoxView or something.
|
||||
let h = self.get_num_lines(w);
|
||||
Vec2::new(w, h)
|
||||
}
|
||||
(_, DimensionRequest::Fixed(h)) => {
|
||||
let w = self.get_num_cols(h);
|
||||
Vec2::new(w, h)
|
||||
}
|
||||
(DimensionRequest::AtMost(w), _) => {
|
||||
// Don't _force_ the max width, but take it if we have to.
|
||||
let ideal = self.get_ideal_size();
|
||||
fn get_min_size(&self, size: Vec2) -> Vec2 {
|
||||
// If we have no directive, ask for a single big line.
|
||||
// TODO: what if the text has newlines??
|
||||
// Don't _force_ the max width, but take it if we have to.
|
||||
let ideal = self.get_ideal_size();
|
||||
|
||||
if w >= ideal.x {
|
||||
// This is the cheap path
|
||||
ideal
|
||||
} else {
|
||||
// This is the expensive one :(
|
||||
let h = self.get_num_lines(w);
|
||||
Vec2::new(w, h)
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
if size.x >= ideal.x {
|
||||
ideal
|
||||
} else {
|
||||
// Ok, se we have less width than we'd like.
|
||||
// Take everything we can, and plan our height accordingly.
|
||||
let h = self.get_num_lines(size.x);
|
||||
Vec2::new(size.x, h)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::any::Any;
|
||||
|
||||
use vec::Vec2;
|
||||
use view::{Selector, SizeRequest, View};
|
||||
use view::{Selector, View};
|
||||
use printer::Printer;
|
||||
use event::{Event, EventResult};
|
||||
|
||||
@ -21,7 +21,7 @@ pub trait ViewWrapper {
|
||||
}
|
||||
|
||||
/// Wraps the get_min_size method.
|
||||
fn wrap_get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||
fn wrap_get_min_size(&self, req: Vec2) -> Vec2 {
|
||||
self.get_view().get_min_size(req)
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ impl<T: ViewWrapper> View for T {
|
||||
self.wrap_draw(printer);
|
||||
}
|
||||
|
||||
fn get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||
fn get_min_size(&self, req: Vec2) -> Vec2 {
|
||||
self.wrap_get_min_size(req)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user