Wrap each layer in a CircularFocus

This commit is contained in:
Alexandre Bury 2019-01-24 11:57:30 -08:00
parent 3e1eefd2db
commit ec8f7c93e8
3 changed files with 70 additions and 54 deletions

View File

@ -1,6 +1,6 @@
extern crate cursive; extern crate cursive;
use cursive::views::{Dialog, TextView}; use cursive::views::{CircularFocus, Dialog, TextView};
use cursive::Cursive; use cursive::Cursive;
fn main() { fn main() {
@ -10,9 +10,12 @@ fn main() {
// Creates a dialog with a single "Quit" button // Creates a dialog with a single "Quit" button
siv.add_layer( siv.add_layer(
// Most views can be configured in a chainable way // Most views can be configured in a chainable way
Dialog::around(TextView::new("Hello Dialog!")) CircularFocus::wrap_tab(
.title("Cursive") Dialog::around(TextView::new("Hello Dialog!"))
.button("Quit", |s| s.quit()), .title("Cursive")
.button("Foo", |s| ())
.button("Quit", |s| s.quit()),
),
); );
// Starts the event loop. // Starts the event loop.

View File

@ -53,6 +53,8 @@ impl<T: View> CircularFocus<T> {
pub fn wraps_arrows(&self) -> bool { pub fn wraps_arrows(&self) -> bool {
self.wrap_arrows self.wrap_arrows
} }
inner_getters!(self.view: T);
} }
impl<T: View> ViewWrapper for CircularFocus<T> { impl<T: View> ViewWrapper for CircularFocus<T> {

View File

@ -5,7 +5,7 @@ use std::ops::Deref;
use theme::ColorStyle; use theme::ColorStyle;
use vec::Vec2; use vec::Vec2;
use view::{IntoBoxedView, Offset, Position, Selector, View, ViewWrapper}; use view::{IntoBoxedView, Offset, Position, Selector, View, ViewWrapper};
use views::{Layer, ShadowView, ViewBox}; use views::{CircularFocus, Layer, ShadowView, ViewBox};
use Printer; use Printer;
use With; use With;
@ -55,27 +55,39 @@ impl Placement {
// A child view can be wrapped in multiple ways. // A child view can be wrapped in multiple ways.
enum ChildWrapper<T: View> { enum ChildWrapper<T: View> {
// Some views include a shadow around. // Some views include a shadow around.
Shadow(ShadowView<Layer<T>>), Shadow(ShadowView<Layer<CircularFocus<T>>>),
// Some include only include a background. // Some include only include a background.
Backfilled(Layer<T>), Backfilled(Layer<CircularFocus<T>>),
// Some views don't even have a background (they'll be transparent). // Some views don't even have a background (they'll be transparent).
Plain(T), Plain(CircularFocus<T>),
} }
impl<T: View> ChildWrapper<T> { impl<T: View> ChildWrapper<T> {
fn unwrap(self) -> T { fn unwrap(self) -> T {
match self { match self {
// ShadowView::into_inner and Layer::into_inner can never fail. // All these into_inner() can never fail.
ChildWrapper::Shadow(shadow) => { // (ShadowView, Layer, CircularFocus)
shadow.into_inner().ok().unwrap().into_inner().ok().unwrap() ChildWrapper::Shadow(shadow) => shadow
} .into_inner()
.ok()
.unwrap()
.into_inner()
.ok()
.unwrap()
.into_inner()
.ok()
.unwrap(),
// Layer::into_inner can never fail. // Layer::into_inner can never fail.
ChildWrapper::Backfilled(background) => { ChildWrapper::Backfilled(background) => background
background.into_inner().ok().unwrap() .into_inner()
} .ok()
ChildWrapper::Plain(layer) => layer, .unwrap()
.into_inner()
.ok()
.unwrap(),
ChildWrapper::Plain(layer) => layer.into_inner().ok().unwrap(),
} }
} }
} }
@ -84,9 +96,13 @@ impl<T: View> ChildWrapper<T> {
/// Returns a reference to the inner view /// Returns a reference to the inner view
pub fn get_inner(&self) -> &T { pub fn get_inner(&self) -> &T {
match *self { match *self {
ChildWrapper::Shadow(ref shadow) => shadow.get_inner().get_inner(), ChildWrapper::Shadow(ref shadow) => {
ChildWrapper::Backfilled(ref background) => background.get_inner(), shadow.get_inner().get_inner().get_inner()
ChildWrapper::Plain(ref layer) => layer, }
ChildWrapper::Backfilled(ref background) => {
background.get_inner().get_inner()
}
ChildWrapper::Plain(ref layer) => layer.get_inner(),
} }
} }
@ -94,12 +110,12 @@ impl<T: View> ChildWrapper<T> {
pub fn get_inner_mut(&mut self) -> &mut T { pub fn get_inner_mut(&mut self) -> &mut T {
match *self { match *self {
ChildWrapper::Shadow(ref mut shadow) => { ChildWrapper::Shadow(ref mut shadow) => {
shadow.get_inner_mut().get_inner_mut() shadow.get_inner_mut().get_inner_mut().get_inner_mut()
} }
ChildWrapper::Backfilled(ref mut background) => { ChildWrapper::Backfilled(ref mut background) => {
background.get_inner_mut() background.get_inner_mut().get_inner_mut()
} }
ChildWrapper::Plain(ref mut layer) => layer, ChildWrapper::Plain(ref mut layer) => layer.get_inner_mut(),
} }
} }
} }
@ -202,7 +218,9 @@ impl StackView {
{ {
let boxed = ViewBox::boxed(view); let boxed = ViewBox::boxed(view);
self.layers.push(Child { self.layers.push(Child {
view: ChildWrapper::Backfilled(Layer::new(boxed)), view: ChildWrapper::Backfilled(Layer::new(
CircularFocus::wrap_tab(boxed),
)),
size: Vec2::zero(), size: Vec2::zero(),
placement: Placement::Fullscreen, placement: Placement::Fullscreen,
virgin: true, virgin: true,
@ -307,7 +325,7 @@ impl StackView {
self.layers.push(Child { self.layers.push(Child {
// Skip padding for absolute/parent-placed views // Skip padding for absolute/parent-placed views
view: ChildWrapper::Shadow( view: ChildWrapper::Shadow(
ShadowView::new(Layer::new(boxed)) ShadowView::new(Layer::new(CircularFocus::wrap_tab(boxed)))
.top_padding(position.y == Offset::Center) .top_padding(position.y == Offset::Center)
.left_padding(position.x == Offset::Center), .left_padding(position.x == Offset::Center),
), ),
@ -332,7 +350,7 @@ impl StackView {
{ {
let boxed = ViewBox::boxed(view); let boxed = ViewBox::boxed(view);
self.layers.push(Child { self.layers.push(Child {
view: ChildWrapper::Plain(boxed), view: ChildWrapper::Plain(CircularFocus::wrap_tab(boxed)),
size: Vec2::new(0, 0), size: Vec2::new(0, 0),
placement: Placement::Floating(position), placement: Placement::Floating(position),
virgin: true, virgin: true,
@ -531,7 +549,8 @@ impl View for StackView {
match StackPositionIterator::new( match StackPositionIterator::new(
self.layers.iter_mut(), self.layers.iter_mut(),
self.last_size, self.last_size,
).last() )
.last()
{ {
None => EventResult::Ignored, None => EventResult::Ignored,
Some((v, offset)) => v.view.on_event(event.relativized(offset)), Some((v, offset)) => v.view.on_event(event.relativized(offset)),
@ -674,33 +693,25 @@ mod tests {
.layer(TextView::new("1")) .layer(TextView::new("1"))
.layer(TextView::new("2")); .layer(TextView::new("2"));
assert!( assert!(stack
stack .get(LayerPosition::FromFront(0))
.get(LayerPosition::FromFront(0)) .unwrap()
.unwrap() .as_any()
.as_any() .is::<TextView>());
.is::<TextView>() assert!(stack
); .get(LayerPosition::FromBack(0))
assert!( .unwrap()
stack .as_any()
.get(LayerPosition::FromBack(0)) .is::<TextView>());
.unwrap() assert!(stack
.as_any() .get_mut(LayerPosition::FromFront(0))
.is::<TextView>() .unwrap()
); .as_any_mut()
assert!( .is::<TextView>());
stack assert!(stack
.get_mut(LayerPosition::FromFront(0)) .get_mut(LayerPosition::FromBack(0))
.unwrap() .unwrap()
.as_any_mut() .as_any_mut()
.is::<TextView>() .is::<TextView>());
);
assert!(
stack
.get_mut(LayerPosition::FromBack(0))
.unwrap()
.as_any_mut()
.is::<TextView>()
);
} }
} }