From 4e07d8891f0fc71bfc7fdd0647082060dee50af1 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Wed, 11 Oct 2017 11:35:18 -0700 Subject: [PATCH] Add mouse event relativization to StackView and ShadowView So that key_codes example works fine. --- src/views/shadow_view.rs | 29 ++++++---- src/views/stack_view.rs | 119 +++++++++++++++++++++++++++++---------- 2 files changed, 107 insertions(+), 41 deletions(-) diff --git a/src/views/shadow_view.rs b/src/views/shadow_view.rs index f7f9174..9e3f9e0 100644 --- a/src/views/shadow_view.rs +++ b/src/views/shadow_view.rs @@ -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 ShadowView { } 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 ViewWrapper for ShadowView { 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 ViewWrapper for ShadowView { } // Draw the view background - let printer = printer.sub_printer(Vec2::zero(), - printer.size.saturating_sub((1, 1)), - true); + let printer = printer.sub_printer( + Vec2::zero(), + printer.size.saturating_sub((1, 1)), + true, + ); self.view.draw(&printer); } } diff --git a/src/views/stack_view.rs b/src/views/stack_view.rs index e610520..8871c96 100644 --- a/src/views/stack_view.rs +++ b/src/views/stack_view.rs @@ -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(&self, size: S, available: A, parent: P) - -> Vec2 - where S: Into, - A: Into, - P: Into + pub fn compute_offset( + &self, size: S, available: A, parent: P + ) -> Vec2 + where + S: Into, + A: Into, + P: Into, { match *self { Placement::Floating(ref position) => { @@ -63,7 +65,8 @@ impl StackView { /// /// Fullscreen layers have no shadow. pub fn add_fullscreen_layer(&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(&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(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(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(&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)) - .top_padding(position.y == Offset::Center) - .left_padding(position.x == Offset::Center)), + view: Box::new( + ShadowView::new(Layer::new(view)) + .top_padding(position.y == 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(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, I: Iterator> { + inner: I, + previous: Vec2, + total_size: Vec2, +} + +impl, I: Iterator> + StackPositionIterator { + /// Returns a new StackPositionIterator + pub fn new(inner: I, total_size: Vec2) -> Self { + let previous = Vec2::zero(); + StackPositionIterator { + inner, + previous, + total_size, + } + } +} + +impl, I: Iterator> Iterator + for StackPositionIterator { + 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) { + fn call_on_any<'a>( + &mut self, selector: &Selector, + mut callback: Box, + ) { 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))); } }