mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-27 11:16:03 +00:00
Split Printer::sub_printer into sub-methods
This commit is contained in:
parent
4042a45b8d
commit
8641098781
@ -537,7 +537,7 @@ impl Cursive {
|
||||
1
|
||||
};
|
||||
let id = self.active_screen;
|
||||
let sv_printer = printer.offset((0, offset), !selected);
|
||||
let sv_printer = printer.offset((0, offset)).focused(!selected);
|
||||
|
||||
self.screens[id].draw_bg(&sv_printer);
|
||||
|
||||
@ -545,11 +545,7 @@ impl Cursive {
|
||||
// If the menubar is active, nothing else can be.
|
||||
// Draw the menubar?
|
||||
if self.menubar.visible() {
|
||||
let printer = printer.sub_printer(
|
||||
Vec2::zero(),
|
||||
printer.size,
|
||||
self.menubar.receive_events(),
|
||||
);
|
||||
let printer = printer.focused(self.menubar.receive_events());
|
||||
self.menubar.draw(&printer);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ use theme::{BorderStyle, ColorStyle, Effect, PaletteColor, Style, Theme};
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
use utils::lines::simple::prefix;
|
||||
use vec::Vec2;
|
||||
use with::With;
|
||||
|
||||
/// Convenient interface to draw on a subset of the screen.
|
||||
pub struct Printer<'a> {
|
||||
@ -36,6 +37,20 @@ pub struct Printer<'a> {
|
||||
backend: &'a backend::Concrete,
|
||||
}
|
||||
|
||||
impl<'a> Clone for Printer<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
Printer {
|
||||
offset: self.offset,
|
||||
content_offset: self.content_offset,
|
||||
size: self.size,
|
||||
focused: self.focused,
|
||||
theme: self.theme,
|
||||
backend: self.backend,
|
||||
new: Rc::clone(&self.new),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Printer<'a> {
|
||||
/// Creates a new printer on the given window.
|
||||
///
|
||||
@ -308,37 +323,73 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
|
||||
/// Prints a horizontal delimiter with side border `├` and `┤`.
|
||||
pub fn print_hdelim<T: Into<Vec2>>(&self, start: T, len: usize) {
|
||||
pub fn print_hdelim<T>(&self, start: T, len: usize)
|
||||
where
|
||||
T: Into<Vec2>,
|
||||
{
|
||||
let start = start.into();
|
||||
self.print(start, "├");
|
||||
self.print_hline(start + (1, 0), len.saturating_sub(2), "─");
|
||||
self.print(start + (len.saturating_sub(1), 0), "┤");
|
||||
}
|
||||
|
||||
/// Returns a printer on a subset of this one's area.
|
||||
pub fn sub_printer<S: Into<Vec2>, T: Into<Vec2>>(
|
||||
&'a self, offset: S, size: T, focused: bool
|
||||
) -> Printer<'a> {
|
||||
let size = size.into();
|
||||
let offset = offset.into().or_min(self.size);
|
||||
let available = if !offset.fits_in(self.size) {
|
||||
Vec2::zero()
|
||||
} else {
|
||||
Vec2::min(self.size - offset, size)
|
||||
};
|
||||
Printer {
|
||||
offset: self.offset + offset,
|
||||
// We can't be larger than what remains
|
||||
size: available,
|
||||
focused: self.focused && focused,
|
||||
theme: self.theme,
|
||||
backend: self.backend,
|
||||
new: Rc::clone(&self.new),
|
||||
}
|
||||
/// Returns a sub-printer with the given offset.
|
||||
pub fn offset<S>(&self, offset: S) -> Printer
|
||||
where
|
||||
S: Into<Vec2>,
|
||||
{
|
||||
let offset = offset.into();
|
||||
self.clone().with(|s| {
|
||||
let consumed = Vec2::min(s.content_offset, offset);
|
||||
|
||||
s.content_offset = s.content_offset - consumed;
|
||||
s.offset = s.offset + offset - consumed;
|
||||
s.size = s.size.saturating_sub(offset);
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a sub-printer with the given offset.
|
||||
pub fn offset<S: Into<Vec2>>(&self, offset: S, focused: bool) -> Printer {
|
||||
self.sub_printer(offset, self.size, focused)
|
||||
/// Returns a new sub-printer inheriting the given focus.
|
||||
///
|
||||
/// If `self` is focused and `focused == true`, the child will be focused.
|
||||
///
|
||||
/// Otherwise, he will be unfocused.
|
||||
pub fn focused(&self, focused: bool) -> Self {
|
||||
self.clone().with(|s| {
|
||||
s.focused &= focused;
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a new sub-printer with a cropped area.
|
||||
///
|
||||
/// The new printer size will be the minimum of `size` and its current size.
|
||||
///
|
||||
/// Any size reduction happens at the bottom-right.
|
||||
pub fn cropped<S>(&self, size: S) -> Self
|
||||
where
|
||||
S: Into<Vec2>,
|
||||
{
|
||||
self.clone().with(|s| {
|
||||
s.size = Vec2::min(s.size, size);
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a new sub-printer with a shrinked area.
|
||||
///
|
||||
/// The printer size will be reduced by the given border from the bottom-right.
|
||||
pub fn shrinked<S>(&self, borders: S) -> Self
|
||||
where
|
||||
S: Into<Vec2>,
|
||||
{
|
||||
self.cropped(self.size.saturating_sub(borders))
|
||||
}
|
||||
|
||||
/// Returns a new sub-printer with a content offset.
|
||||
pub fn content_offset<S>(&self, offset: S) -> Self
|
||||
where
|
||||
S: Into<Vec2>,
|
||||
{
|
||||
self.clone().with(|s| {
|
||||
s.content_offset = s.content_offset + offset;
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ impl ScrollBase {
|
||||
// Y is the actual coordinate of the line.
|
||||
// The item ID is then Y + self.start_line
|
||||
line_drawer(
|
||||
&printer.sub_printer(Vec2::new(0, y), Vec2::new(w, 1), true),
|
||||
&printer.offset((0, y)).cropped((w, 1)),
|
||||
y + self.start_line,
|
||||
);
|
||||
}
|
||||
|
@ -371,11 +371,10 @@ impl Dialog {
|
||||
// Add some special effect to the focused button
|
||||
let position = Vec2::new(offset, y);
|
||||
button.offset.set(position);
|
||||
button.button.draw(&printer.sub_printer(
|
||||
position,
|
||||
size,
|
||||
self.focus == DialogFocus::Button(i),
|
||||
));
|
||||
button.button.draw(&printer
|
||||
.offset(position)
|
||||
.cropped(size)
|
||||
.focused(self.focus == DialogFocus::Button(i)));
|
||||
// Keep 1 blank between two buttons
|
||||
offset += size.x + 1;
|
||||
// Also keep 1 blank above the buttons
|
||||
@ -395,11 +394,10 @@ impl Dialog {
|
||||
None => return,
|
||||
};
|
||||
|
||||
self.content.draw(&printer.sub_printer(
|
||||
self.borders.top_left() + self.padding.top_left(),
|
||||
inner_size,
|
||||
self.focus == DialogFocus::Content,
|
||||
));
|
||||
self.content.draw(&printer
|
||||
.offset(self.borders.top_left() + self.padding.top_left())
|
||||
.cropped(inner_size)
|
||||
.focused(self.focus == DialogFocus::Content));
|
||||
}
|
||||
|
||||
fn draw_title(&self, printer: &Printer) {
|
||||
|
@ -327,11 +327,10 @@ impl View for LinearLayout {
|
||||
// eprintln!("Printer size: {:?}", printer.size);
|
||||
// eprintln!("Child size: {:?}", item.child.size);
|
||||
// eprintln!("Offset: {:?}", item.offset);
|
||||
let printer = &printer.sub_printer(
|
||||
self.orientation.make_vec(item.offset, 0),
|
||||
item.child.size,
|
||||
i == self.focus,
|
||||
);
|
||||
let printer = &printer
|
||||
.offset(self.orientation.make_vec(item.offset, 0))
|
||||
.cropped(item.child.size)
|
||||
.focused(i == self.focus);
|
||||
item.child.view.draw(printer);
|
||||
}
|
||||
}
|
||||
|
@ -279,7 +279,9 @@ impl View for ListView {
|
||||
.draw(printer, |printer, i| match self.children[i] {
|
||||
ListChild::Row(ref label, ref view) => {
|
||||
printer.print((0, 0), label);
|
||||
view.draw(&printer.offset((offset, 0), i == self.focus));
|
||||
view.draw(&printer
|
||||
.offset((offset, 0))
|
||||
.focused(i == self.focus));
|
||||
}
|
||||
ListChild::Delimiter => (),
|
||||
});
|
||||
|
@ -211,7 +211,7 @@ impl View for MenuPopup {
|
||||
let h = self.menu.len();
|
||||
// If we're too high, add a vertical offset
|
||||
let offset = self.align.v.get_offset(h, printer.size.y);
|
||||
let printer = &printer.offset((0, offset), true);
|
||||
let printer = &printer.offset((0, offset));
|
||||
|
||||
// Start with a box
|
||||
printer.print_box(Vec2::new(0, 0), printer.size, false);
|
||||
@ -219,8 +219,7 @@ impl View for MenuPopup {
|
||||
// We're giving it a reduced size because of borders.
|
||||
// But we're keeping the full width,
|
||||
// to integrate horizontal delimiters in the frame.
|
||||
let size = printer.size - (0, 2);
|
||||
let printer = printer.sub_printer((0, 1), size, true);
|
||||
let printer = printer.offset((0, 1)).shrinked((0, 1));
|
||||
|
||||
self.scrollbase.draw(&printer, |printer, i| {
|
||||
printer.with_selection(i == self.focus, |printer| {
|
||||
|
@ -35,8 +35,7 @@ impl<V: View> ViewWrapper for Panel<V> {
|
||||
|
||||
fn wrap_draw(&self, printer: &Printer) {
|
||||
printer.print_box((0, 0), printer.size, true);
|
||||
let size = printer.size.saturating_sub((2, 2));
|
||||
let printer = printer.sub_printer((1, 1), size, true);
|
||||
let printer = printer.offset((1, 1)).shrinked((1, 1));
|
||||
self.view.draw(&printer);
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ impl View for ProgressBar {
|
||||
printer.with_effect(Effect::Reverse, |printer| {
|
||||
printer.print((offset, 0), &label);
|
||||
});
|
||||
let printer = &printer.sub_printer((0, 0), (length, 1), true);
|
||||
let printer = &printer.cropped((length, 1));
|
||||
printer.print_hline((0, 0), length, " ");
|
||||
printer.print((offset, 0), &label);
|
||||
});
|
||||
|
@ -6,12 +6,17 @@ use vec::Vec2;
|
||||
pub struct ScrollView<V> {
|
||||
inner: V,
|
||||
offset: Vec2,
|
||||
|
||||
// Togglable horizontal/vertical scrolling?
|
||||
}
|
||||
|
||||
impl <V> View for ScrollView<V> where V: View {
|
||||
|
||||
fn draw(&self, printer: &Printer) {
|
||||
self.printer.offset
|
||||
self.inner.draw(printer);
|
||||
// Draw content
|
||||
let printer = printer.content_offset(self.offset);
|
||||
self.inner.draw(&printer);
|
||||
|
||||
// Draw scrollbar?
|
||||
}
|
||||
}
|
||||
|
@ -703,8 +703,7 @@ impl<T: 'static> View for SelectView<T> {
|
||||
} else {
|
||||
let h = self.items.len();
|
||||
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.offset((0, offset));
|
||||
|
||||
self.scrollbase.draw(printer, |printer, i| {
|
||||
printer.with_selection(i == self.focus(), |printer| {
|
||||
|
@ -86,7 +86,7 @@ impl<T: View> ViewWrapper for ShadowView<T> {
|
||||
self.left_padding as usize,
|
||||
self.top_padding as usize,
|
||||
);
|
||||
let printer = &printer.offset(offset, true);
|
||||
let printer = &printer.offset(offset);
|
||||
if printer.theme.shadow {
|
||||
let h = printer.size.y;
|
||||
let w = printer.size.x;
|
||||
@ -102,11 +102,7 @@ impl<T: View> ViewWrapper for ShadowView<T> {
|
||||
}
|
||||
|
||||
// Draw the view background
|
||||
let printer = printer.sub_printer(
|
||||
Vec2::zero(),
|
||||
printer.size.saturating_sub((1, 1)),
|
||||
true,
|
||||
);
|
||||
let printer = printer.shrinked((1,1));
|
||||
self.view.draw(&printer);
|
||||
}
|
||||
}
|
||||
|
@ -420,11 +420,10 @@ impl StackView {
|
||||
StackPositionIterator::new(self.layers.iter(), printer.size)
|
||||
.enumerate()
|
||||
{
|
||||
v.view.draw(&printer.sub_printer(
|
||||
offset,
|
||||
v.size,
|
||||
i + 1 == last,
|
||||
));
|
||||
v.view.draw(&printer
|
||||
.offset(offset)
|
||||
.cropped(v.size)
|
||||
.focused(i + 1 == last));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -455,7 +455,7 @@ impl View for TextView {
|
||||
let h = self.rows.len();
|
||||
// If the content is smaller than the view, align it somewhere.
|
||||
let offset = self.align.v.get_offset(h, printer.size.y);
|
||||
let printer = &printer.offset((0, offset), true);
|
||||
let printer = &printer.offset((0, offset));
|
||||
|
||||
let content = self.content.lock().unwrap();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user