Add mouse event relativization to StackView and ShadowView

So that key_codes example works fine.
This commit is contained in:
Alexandre Bury 2017-10-11 11:35:18 -07:00
parent 2d703811c5
commit 4e07d8891f
2 changed files with 107 additions and 41 deletions

View File

@ -1,4 +1,5 @@
use Printer; use Printer;
use event::{Event, EventResult};
use theme::ColorStyle; use theme::ColorStyle;
use vec::Vec2; use vec::Vec2;
use view::{View, ViewWrapper}; use view::{View, ViewWrapper};
@ -23,8 +24,10 @@ impl<T: View> ShadowView<T> {
} }
fn padding(&self) -> Vec2 { fn padding(&self) -> Vec2 {
Vec2::new(1 + self.left_padding as usize, Vec2::new(
1 + self.top_padding as usize) 1 + self.left_padding as usize,
1 + self.top_padding as usize,
)
} }
/// If set, adds an empty column to the left of the view. /// If set, adds an empty column to the left of the view.
@ -58,17 +61,21 @@ impl<T: View> ViewWrapper for ShadowView<T> {
self.view.layout(size.saturating_sub(offset)); self.view.layout(size.saturating_sub(offset));
} }
fn wrap_draw(&self, printer: &Printer) { fn wrap_on_event(&mut self, event: Event) -> EventResult {
self.view.on_event(event.relativized((1, 1)))
}
if printer.size.y <= self.top_padding as usize || fn wrap_draw(&self, printer: &Printer) {
printer.size.x <= self.left_padding as usize { if printer.size.y <= self.top_padding as usize
|| printer.size.x <= self.left_padding as usize
{
// Nothing to do if there's no place to draw. // Nothing to do if there's no place to draw.
return; return;
} }
// Skip the first row/column // Skip the first row/column
let offset = Vec2::new(self.left_padding as usize, let offset =
self.top_padding as usize); Vec2::new(self.left_padding as usize, self.top_padding as usize);
let printer = &printer.offset(offset, true); let printer = &printer.offset(offset, true);
if printer.theme.shadow { if printer.theme.shadow {
let h = printer.size.y; let h = printer.size.y;
@ -85,9 +92,11 @@ impl<T: View> ViewWrapper for ShadowView<T> {
} }
// Draw the view background // Draw the view background
let printer = printer.sub_printer(Vec2::zero(), let printer = printer.sub_printer(
printer.size.saturating_sub((1, 1)), Vec2::zero(),
true); printer.size.saturating_sub((1, 1)),
true,
);
self.view.draw(&printer); self.view.draw(&printer);
} }
} }

View File

@ -1,9 +1,9 @@
use Printer; use Printer;
use With;
use ::With;
use direction::Direction; use direction::Direction;
use event::{Event, EventResult}; use event::{Event, EventResult};
use std::any::Any; use std::any::Any;
use std::ops::Deref;
use theme::ColorStyle; use theme::ColorStyle;
use vec::Vec2; use vec::Vec2;
use view::{Offset, Position, Selector, View}; use view::{Offset, Position, Selector, View};
@ -22,11 +22,13 @@ enum Placement {
} }
impl Placement { impl Placement {
pub fn compute_offset<S, A, P>(&self, size: S, available: A, parent: P) pub fn compute_offset<S, A, P>(
-> Vec2 &self, size: S, available: A, parent: P
where S: Into<Vec2>, ) -> Vec2
A: Into<Vec2>, where
P: Into<Vec2> S: Into<Vec2>,
A: Into<Vec2>,
P: Into<Vec2>,
{ {
match *self { match *self {
Placement::Floating(ref position) => { Placement::Floating(ref position) => {
@ -63,7 +65,8 @@ impl StackView {
/// ///
/// Fullscreen layers have no shadow. /// Fullscreen layers have no shadow.
pub fn add_fullscreen_layer<T>(&mut self, view: T) pub fn add_fullscreen_layer<T>(&mut self, view: T)
where T: 'static + View where
T: 'static + View,
{ {
self.layers.push(Child { self.layers.push(Child {
view: Box::new(Layer::new(view)), view: Box::new(Layer::new(view)),
@ -75,7 +78,8 @@ impl StackView {
/// Adds new view on top of the stack in the center of the screen. /// Adds new view on top of the stack in the center of the screen.
pub fn add_layer<T>(&mut self, view: T) pub fn add_layer<T>(&mut self, view: T)
where T: 'static + View where
T: 'static + View,
{ {
self.add_layer_at(Position::center(), view); self.add_layer_at(Position::center(), view);
} }
@ -84,7 +88,8 @@ impl StackView {
/// ///
/// Chainable variant. /// Chainable variant.
pub fn layer<T>(self, view: T) -> Self pub fn layer<T>(self, view: T) -> Self
where T: 'static + View where
T: 'static + View,
{ {
self.with(|s| s.add_layer(view)) self.with(|s| s.add_layer(view))
} }
@ -93,20 +98,24 @@ impl StackView {
/// ///
/// Chainable variant. /// Chainable variant.
pub fn fullscreen_layer<T>(self, view: T) -> Self pub fn fullscreen_layer<T>(self, view: T) -> Self
where T: 'static + View where
T: 'static + View,
{ {
self.with(|s| s.add_fullscreen_layer(view)) self.with(|s| s.add_fullscreen_layer(view))
} }
/// Adds a view on top of the stack. /// Adds a view on top of the stack.
pub fn add_layer_at<T>(&mut self, position: Position, view: T) pub fn add_layer_at<T>(&mut self, position: Position, view: T)
where T: 'static + View where
T: 'static + View,
{ {
self.layers.push(Child { self.layers.push(Child {
// Skip padding for absolute/parent-placed views // Skip padding for absolute/parent-placed views
view: Box::new(ShadowView::new(Layer::new(view)) view: Box::new(
.top_padding(position.y == Offset::Center) ShadowView::new(Layer::new(view))
.left_padding(position.x == Offset::Center)), .top_padding(position.y == Offset::Center)
.left_padding(position.x == Offset::Center),
),
size: Vec2::new(0, 0), size: Vec2::new(0, 0),
placement: Placement::Floating(position), placement: Placement::Floating(position),
virgin: true, virgin: true,
@ -117,7 +126,8 @@ impl StackView {
/// ///
/// Chainable variant. /// Chainable variant.
pub fn layer_at<T>(self, position: Position, view: T) -> Self pub fn layer_at<T>(self, position: Position, view: T) -> Self
where T: 'static + View where
T: 'static + View,
{ {
self.with(|s| s.add_layer_at(position, view)) self.with(|s| s.add_layer_at(position, view))
} }
@ -131,8 +141,11 @@ impl StackView {
pub fn offset(&self) -> Vec2 { pub fn offset(&self) -> Vec2 {
let mut previous = Vec2::zero(); let mut previous = Vec2::zero();
for layer in &self.layers { for layer in &self.layers {
let offset = layer.placement let offset = layer.placement.compute_offset(
.compute_offset(layer.size, self.last_size, previous); layer.size,
self.last_size,
previous,
);
previous = offset; previous = offset;
} }
previous previous
@ -144,18 +157,52 @@ impl StackView {
} }
} }
struct StackPositionIterator<R: Deref<Target = Child>, I: Iterator<Item = R>> {
inner: I,
previous: Vec2,
total_size: Vec2,
}
impl<R: Deref<Target = Child>, I: Iterator<Item = R>>
StackPositionIterator<R, I> {
/// Returns a new StackPositionIterator
pub fn new(inner: I, total_size: Vec2) -> Self {
let previous = Vec2::zero();
StackPositionIterator {
inner,
previous,
total_size,
}
}
}
impl<R: Deref<Target = Child>, I: Iterator<Item = R>> Iterator
for StackPositionIterator<R, I> {
type Item = (R, Vec2);
fn next(&mut self) -> Option<(R, Vec2)> {
self.inner.next().map(|v| {
let offset = v.placement.compute_offset(
v.size,
self.total_size,
self.previous,
);
self.previous = offset;
(v, offset)
})
}
}
impl View for StackView { impl View for StackView {
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
let last = self.layers.len(); let last = self.layers.len();
let mut previous = Vec2::zero();
printer.with_color(ColorStyle::Primary, |printer| { printer.with_color(ColorStyle::Primary, |printer| {
for (i, v) in self.layers.iter().enumerate() { for (i, (v, offset)) in
// Place the view StackPositionIterator::new(self.layers.iter(), printer.size)
// Center the view .enumerate()
let offset = v.placement {
.compute_offset(v.size, printer.size, previous);
previous = offset;
v.view v.view
.draw(&printer.sub_printer(offset, v.size, i + 1 == last)); .draw(&printer.sub_printer(offset, v.size, i + 1 == last));
} }
@ -163,9 +210,15 @@ impl View for StackView {
} }
fn on_event(&mut self, event: Event) -> EventResult { fn on_event(&mut self, event: Event) -> EventResult {
match self.layers.last_mut() { // Use the stack position iterator to get the offset of the top layer.
// TODO: save it instead when drawing?
match StackPositionIterator::new(
self.layers.iter_mut(),
self.last_size,
).last()
{
None => EventResult::Ignored, None => EventResult::Ignored,
Some(v) => v.view.on_event(event), Some((v, offset)) => v.view.on_event(event.relativized(offset)),
} }
} }
@ -208,10 +261,14 @@ impl View for StackView {
} }
} }
fn call_on_any<'a>(&mut self, selector: &Selector, fn call_on_any<'a>(
mut callback: Box<FnMut(&mut Any) + 'a>) { &mut self, selector: &Selector,
mut callback: Box<FnMut(&mut Any) + 'a>,
) {
for layer in &mut self.layers { for layer in &mut self.layers {
layer.view.call_on_any(selector, Box::new(|any| callback(any))); layer
.view
.call_on_any(selector, Box::new(|any| callback(any)));
} }
} }