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 event::{Event, EventResult};
use theme::ColorStyle;
use vec::Vec2;
use view::{View, ViewWrapper};
@ -23,8 +24,10 @@ impl<T: View> ShadowView<T> {
}
fn padding(&self) -> Vec2 {
Vec2::new(1 + self.left_padding as usize,
1 + self.top_padding as usize)
Vec2::new(
1 + self.left_padding as usize,
1 + self.top_padding as usize,
)
}
/// 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));
}
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 ||
printer.size.x <= self.left_padding as usize {
fn wrap_draw(&self, printer: &Printer) {
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.
return;
}
// Skip the first row/column
let offset = Vec2::new(self.left_padding as usize,
self.top_padding as usize);
let offset =
Vec2::new(self.left_padding as usize, self.top_padding as usize);
let printer = &printer.offset(offset, true);
if printer.theme.shadow {
let h = printer.size.y;
@ -85,9 +92,11 @@ impl<T: View> ViewWrapper for ShadowView<T> {
}
// Draw the view background
let printer = printer.sub_printer(Vec2::zero(),
let printer = printer.sub_printer(
Vec2::zero(),
printer.size.saturating_sub((1, 1)),
true);
true,
);
self.view.draw(&printer);
}
}

View File

@ -1,9 +1,9 @@
use Printer;
use ::With;
use With;
use direction::Direction;
use event::{Event, EventResult};
use std::any::Any;
use std::ops::Deref;
use theme::ColorStyle;
use vec::Vec2;
use view::{Offset, Position, Selector, View};
@ -22,11 +22,13 @@ enum Placement {
}
impl Placement {
pub fn compute_offset<S, A, P>(&self, size: S, available: A, parent: P)
-> Vec2
where S: Into<Vec2>,
pub fn compute_offset<S, A, P>(
&self, size: S, available: A, parent: P
) -> Vec2
where
S: Into<Vec2>,
A: Into<Vec2>,
P: Into<Vec2>
P: Into<Vec2>,
{
match *self {
Placement::Floating(ref position) => {
@ -63,7 +65,8 @@ impl StackView {
///
/// Fullscreen layers have no shadow.
pub fn add_fullscreen_layer<T>(&mut self, view: T)
where T: 'static + View
where
T: 'static + View,
{
self.layers.push(Child {
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.
pub fn add_layer<T>(&mut self, view: T)
where T: 'static + View
where
T: 'static + View,
{
self.add_layer_at(Position::center(), view);
}
@ -84,7 +88,8 @@ impl StackView {
///
/// Chainable variant.
pub fn layer<T>(self, view: T) -> Self
where T: 'static + View
where
T: 'static + View,
{
self.with(|s| s.add_layer(view))
}
@ -93,20 +98,24 @@ impl StackView {
///
/// Chainable variant.
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))
}
/// Adds a view on top of the stack.
pub fn add_layer_at<T>(&mut self, position: Position, view: T)
where T: 'static + View
where
T: 'static + View,
{
self.layers.push(Child {
// Skip padding for absolute/parent-placed views
view: Box::new(ShadowView::new(Layer::new(view))
view: Box::new(
ShadowView::new(Layer::new(view))
.top_padding(position.y == Offset::Center)
.left_padding(position.x == Offset::Center)),
.left_padding(position.x == Offset::Center),
),
size: Vec2::new(0, 0),
placement: Placement::Floating(position),
virgin: true,
@ -117,7 +126,8 @@ impl StackView {
///
/// Chainable variant.
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))
}
@ -131,8 +141,11 @@ impl StackView {
pub fn offset(&self) -> Vec2 {
let mut previous = Vec2::zero();
for layer in &self.layers {
let offset = layer.placement
.compute_offset(layer.size, self.last_size, previous);
let offset = layer.placement.compute_offset(
layer.size,
self.last_size,
previous,
);
previous = offset;
}
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 {
fn draw(&self, printer: &Printer) {
let last = self.layers.len();
let mut previous = Vec2::zero();
printer.with_color(ColorStyle::Primary, |printer| {
for (i, v) in self.layers.iter().enumerate() {
// Place the view
// Center the view
let offset = v.placement
.compute_offset(v.size, printer.size, previous);
previous = offset;
for (i, (v, offset)) in
StackPositionIterator::new(self.layers.iter(), printer.size)
.enumerate()
{
v.view
.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 {
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,
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,
mut callback: Box<FnMut(&mut Any) + 'a>) {
fn call_on_any<'a>(
&mut self, selector: &Selector,
mut callback: Box<FnMut(&mut Any) + 'a>,
) {
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)));
}
}