diff --git a/CHANGELOG.md b/CHANGELOG.md index fad172c..1ed4d93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ - Add `Dialog::into_content`. - Add `Callback::from_fn_once` and `once1!` macro to wrap a `FnOnce` in a `FnMut`. +- Add `FixedLayoutView` with manual placement of child views. +- Add `OnLayoutView` to override `View::Layout` ### Bugfixes diff --git a/cursive-core/src/views/mod.rs b/cursive-core/src/views/mod.rs index 4cdde9b..5ff2366 100644 --- a/cursive-core/src/views/mod.rs +++ b/cursive-core/src/views/mod.rs @@ -79,6 +79,7 @@ mod menu_popup; mod menubar; mod named_view; mod on_event_view; +mod on_layout_view; mod padded_view; mod panel; mod progress_bar; @@ -114,6 +115,7 @@ pub use self::menu_popup::MenuPopup; pub use self::menubar::Menubar; pub use self::named_view::{NamedView, ViewRef}; pub use self::on_event_view::OnEventView; +pub use self::on_layout_view::OnLayoutView; pub use self::padded_view::PaddedView; pub use self::panel::Panel; pub use self::progress_bar::ProgressBar; diff --git a/cursive-core/src/views/on_layout_view.rs b/cursive-core/src/views/on_layout_view.rs new file mode 100644 index 0000000..4a4d2b6 --- /dev/null +++ b/cursive-core/src/views/on_layout_view.rs @@ -0,0 +1,59 @@ +use crate::{view::ViewWrapper, Vec2, View}; + +/// View wrapper overriding the `View::layout` method. +pub struct OnLayoutView { + view: V, + on_layout: Box, +} + +impl OnLayoutView { + /// Wraps a view in an `OnLayoutView`. + /// + /// Will run the given closure for layout _instead_ of the one from `view`. + /// + /// ```rust + /// use cursive_core::{View, views::{TextView, OnLayoutView}}; + /// + /// let view = TextView::new("foo"); + /// + /// // Here we just run the innver view's layout. + /// OnLayoutView::new(view, |v, s| v.layout(s)); + /// ``` + pub fn new(view: V, on_layout: F) -> Self + where + F: FnMut(&mut V, Vec2) + 'static, + { + let on_layout = Box::new(on_layout); + OnLayoutView { view, on_layout } + } + + /// Wraps a view in an `OnLayoutView`. + /// + /// This is a shortcut for `Self::new(view, V::layout)` + /// + /// You can change it later with `set_on_layout`. + pub fn wrap(view: V) -> Self + where + V: View, + { + Self::new(view, V::layout) + } + + /// Replaces the callback to run. + pub fn set_on_layout(&mut self, on_layout: F) + where + F: FnMut(&mut V, Vec2) + 'static, + { + self.on_layout = Box::new(on_layout); + } + + inner_getters!(self.view: V); +} + +impl ViewWrapper for OnLayoutView { + wrap_impl!(self.view: V); + + fn wrap_layout(&mut self, size: Vec2) { + (self.on_layout)(&mut self.view, size); + } +}