Skip to content

Commit

Permalink
Add default for View trait methods (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc authored Nov 5, 2023
1 parent c4cd0d1 commit 41e8ce2
Show file tree
Hide file tree
Showing 19 changed files with 188 additions and 800 deletions.
99 changes: 87 additions & 12 deletions src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ bitflags! {
pub trait View {
fn id(&self) -> Id;

/// This method walk over children and must be implemented if the view has any children.
/// It should return children back to front and should stop if `_for_each` returns `true`.
fn for_each_child<'a>(&'a self, _for_each: &mut dyn FnMut(&'a dyn View) -> bool) {}

/// This method walk over children and must be implemented if the view has any children.
/// It should return children back to front and should stop if `_for_each` returns `true`.
fn for_each_child_mut<'a>(&'a mut self, _for_each: &mut dyn FnMut(&'a mut dyn View) -> bool) {}

fn view_style(&self) -> Option<Style> {
None
}
Expand All @@ -119,14 +127,50 @@ pub trait View {
None
}

fn child(&self, id: Id) -> Option<&dyn View>;
fn child(&self, id: Id) -> Option<&dyn View> {
let mut result = None;
self.for_each_child(&mut |view| {
if view.id() == id {
result = Some(view);
true
} else {
false
}
});
result
}

fn child_mut(&mut self, id: Id) -> Option<&mut dyn View>;
fn child_mut(&mut self, id: Id) -> Option<&mut dyn View> {
let mut result = None;
self.for_each_child_mut(&mut |view| {
if view.id() == id {
result = Some(view);
true
} else {
false
}
});
result
}

fn children(&self) -> Vec<&dyn View>;
fn children(&self) -> Vec<&dyn View> {
let mut result = Vec::new();
self.for_each_child(&mut |view| {
result.push(view);
false
});
result
}

/// At the moment, this is used only to build the debug tree.
fn children_mut(&mut self) -> Vec<&mut dyn View>;
fn children_mut(&mut self) -> Vec<&mut dyn View> {
let mut result = Vec::new();
self.for_each_child_mut(&mut |view| {
result.push(view);
false
});
result
}

fn debug_name(&self) -> std::borrow::Cow<'static, str> {
core::any::type_name::<Self>().into()
Expand All @@ -141,7 +185,9 @@ pub trait View {
///
/// You are in charge of downcasting the state to the expected type and you're required to return
/// indicating if you'd like a layout or paint pass to be scheduled.
fn update(&mut self, cx: &mut UpdateCx, state: Box<dyn Any>) -> ChangeFlags;
fn update(&mut self, _cx: &mut UpdateCx, _state: Box<dyn Any>) -> ChangeFlags {
ChangeFlags::empty()
}

/// Use this method to style the view's children.
fn style(&mut self, cx: &mut StyleCx<'_>) {
Expand All @@ -152,23 +198,52 @@ pub trait View {

/// Use this method to layout the view's children.
/// Usually you'll do this by calling `LayoutCx::layout_node`
fn layout(&mut self, cx: &mut LayoutCx) -> Node;
fn layout(&mut self, cx: &mut LayoutCx) -> Node {
cx.layout_node(self.id(), true, |cx| {
let mut nodes = Vec::new();
self.for_each_child_mut(&mut |child| {
nodes.push(cx.layout_view(child));
false
});
nodes
})
}

/// You must implement this if your view has children.
///
/// Responsible for computing the layout of the view's children.
fn compute_layout(&mut self, _cx: &mut LayoutCx) -> Option<Rect> {
None
fn compute_layout(&mut self, cx: &mut LayoutCx) -> Option<Rect> {
let mut layout_rect: Option<Rect> = None;
self.for_each_child_mut(&mut |child| {
let child_layout = cx.compute_view_layout(child);
if let Some(rect) = layout_rect {
layout_rect = Some(rect.union(child_layout));
} else {
layout_rect = Some(child_layout);
}
false
});
layout_rect
}

/// Implement this to handle events and to pass them down to children
///
/// Return true to stop the event from propagating to other views
fn event(&mut self, cx: &mut EventCx, id_path: Option<&[Id]>, event: Event) -> bool;
fn event(&mut self, cx: &mut EventCx, id_path: Option<&[Id]>, event: Event) -> bool {
let mut handled = false;
self.for_each_child_mut(&mut |child| {
handled |= cx.view_event(child, id_path, event.clone());
handled
});
handled
}

/// `View`-specific implementation. Will be called in the [`View::paint_main`] entry point method.
/// Usually you'll call the child `View::paint_main` method. But you might also draw text, adjust the offset, clip or draw text.
fn paint(&mut self, cx: &mut PaintCx);
fn paint(&mut self, cx: &mut PaintCx) {
self.for_each_child_mut(&mut |child| {
cx.paint_view(child);
false
});
}
}

pub(crate) fn paint_bg(
Expand Down
46 changes: 5 additions & 41 deletions src/views/clip.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use kurbo::{Rect, Size};

use crate::{
id::Id,
view::{ChangeFlags, View},
};
use crate::{id::Id, view::View};

pub struct Clip {
id: Id,
Expand All @@ -22,42 +19,18 @@ impl View for Clip {
self.id
}

fn child(&self, id: Id) -> Option<&dyn View> {
if self.child.id() == id {
Some(&self.child)
} else {
None
}
}

fn child_mut(&mut self, id: Id) -> Option<&mut dyn View> {
if self.child.id() == id {
Some(&mut self.child)
} else {
None
}
fn for_each_child<'a>(&'a self, for_each: &mut dyn FnMut(&'a dyn View) -> bool) {
for_each(&self.child);
}

fn children(&self) -> Vec<&dyn View> {
vec![&self.child]
}

fn children_mut(&mut self) -> Vec<&mut dyn View> {
vec![&mut self.child]
fn for_each_child_mut<'a>(&'a mut self, for_each: &mut dyn FnMut(&'a mut dyn View) -> bool) {
for_each(&mut self.child);
}

fn debug_name(&self) -> std::borrow::Cow<'static, str> {
"Clip".into()
}

fn update(
&mut self,
_cx: &mut crate::context::UpdateCx,
_state: Box<dyn std::any::Any>,
) -> crate::view::ChangeFlags {
ChangeFlags::empty()
}

fn layout(&mut self, cx: &mut crate::context::LayoutCx) -> taffy::prelude::Node {
cx.layout_node(self.id, true, |cx| vec![cx.layout_view(&mut self.child)])
}
Expand All @@ -66,15 +39,6 @@ impl View for Clip {
Some(cx.compute_view_layout(&mut self.child))
}

fn event(
&mut self,
cx: &mut crate::context::EventCx,
id_path: Option<&[Id]>,
event: crate::event::Event,
) -> bool {
cx.view_event(&mut self.child, id_path, event)
}

fn paint(&mut self, cx: &mut crate::context::PaintCx) {
cx.save();
let style = cx.get_builtin_style(self.id);
Expand Down
60 changes: 5 additions & 55 deletions src/views/container.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
use kurbo::Rect;

use crate::{
id::Id,
view::{ChangeFlags, View},
};
use crate::{id::Id, view::View};

/// A simple wrapper around another View. See [`container`]
pub struct Container {
Expand All @@ -27,60 +22,15 @@ impl View for Container {
self.id
}

fn child(&self, id: Id) -> Option<&dyn View> {
if self.child.id() == id {
Some(&self.child)
} else {
None
}
}

fn child_mut(&mut self, id: Id) -> Option<&mut dyn View> {
if self.child.id() == id {
Some(&mut self.child)
} else {
None
}
}

fn children(&self) -> Vec<&dyn View> {
vec![&self.child]
fn for_each_child<'a>(&'a self, for_each: &mut dyn FnMut(&'a dyn View) -> bool) {
for_each(&self.child);
}

fn children_mut(&mut self) -> Vec<&mut dyn View> {
vec![&mut self.child]
fn for_each_child_mut<'a>(&'a mut self, for_each: &mut dyn FnMut(&'a mut dyn View) -> bool) {
for_each(&mut self.child);
}

fn debug_name(&self) -> std::borrow::Cow<'static, str> {
"Container".into()
}

fn update(
&mut self,
_cx: &mut crate::context::UpdateCx,
_state: Box<dyn std::any::Any>,
) -> crate::view::ChangeFlags {
ChangeFlags::empty()
}

fn layout(&mut self, cx: &mut crate::context::LayoutCx) -> taffy::prelude::Node {
cx.layout_node(self.id, true, |cx| vec![cx.layout_view(&mut self.child)])
}

fn compute_layout(&mut self, cx: &mut crate::context::LayoutCx) -> Option<Rect> {
Some(cx.compute_view_layout(&mut self.child))
}

fn event(
&mut self,
cx: &mut crate::context::EventCx,
id_path: Option<&[Id]>,
event: crate::event::Event,
) -> bool {
cx.view_event(&mut self.child, id_path, event)
}

fn paint(&mut self, cx: &mut crate::context::PaintCx) {
cx.paint_view(&mut self.child);
}
}
24 changes: 4 additions & 20 deletions src/views/container_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,28 +57,12 @@ impl View for ContainerBox {
self.id
}

fn child(&self, id: Id) -> Option<&dyn View> {
if self.child.id() == id {
Some(&*self.child)
} else {
None
}
fn for_each_child<'a>(&'a self, for_each: &mut dyn FnMut(&'a dyn View) -> bool) {
for_each(&self.child);
}

fn child_mut(&mut self, id: Id) -> Option<&mut dyn View> {
if self.child.id() == id {
Some(&mut *self.child)
} else {
None
}
}

fn children(&self) -> Vec<&dyn View> {
vec![&*self.child]
}

fn children_mut(&mut self) -> Vec<&mut dyn View> {
vec![&mut *self.child]
fn for_each_child_mut<'a>(&'a mut self, for_each: &mut dyn FnMut(&'a mut dyn View) -> bool) {
for_each(&mut self.child);
}

fn debug_name(&self) -> std::borrow::Cow<'static, str> {
Expand Down
60 changes: 5 additions & 55 deletions src/views/drag_resize_window_area.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
use kurbo::Rect;
use winit::window::ResizeDirection;

use crate::{
action::drag_resize_window,
event::{Event, EventListener},
id::Id,
style::CursorStyle,
view::View,
action::drag_resize_window, event::EventListener, id::Id, style::CursorStyle, view::View,
};

use super::Decorators;
Expand Down Expand Up @@ -49,56 +44,11 @@ impl View for DragResizeWindowArea {
self.id
}

fn child(&self, id: Id) -> Option<&dyn View> {
if self.child.id() == id {
Some(&self.child)
} else {
None
}
fn for_each_child<'a>(&'a self, for_each: &mut dyn FnMut(&'a dyn View) -> bool) {
for_each(&self.child);
}

fn child_mut(&mut self, id: Id) -> Option<&mut dyn View> {
if self.child.id() == id {
Some(&mut self.child)
} else {
None
}
}

fn children(&self) -> Vec<&dyn View> {
vec![&self.child]
}

fn children_mut(&mut self) -> Vec<&mut dyn View> {
vec![&mut self.child]
}

fn update(
&mut self,
_cx: &mut crate::context::UpdateCx,
_state: Box<dyn std::any::Any>,
) -> crate::view::ChangeFlags {
crate::view::ChangeFlags::empty()
}

fn layout(&mut self, cx: &mut crate::context::LayoutCx) -> taffy::prelude::Node {
cx.layout_node(self.id, true, |cx| vec![cx.layout_view(&mut self.child)])
}

fn compute_layout(&mut self, cx: &mut crate::context::LayoutCx) -> Option<Rect> {
Some(cx.compute_view_layout(&mut self.child))
}

fn event(
&mut self,
cx: &mut crate::context::EventCx,
id_path: Option<&[Id]>,
event: Event,
) -> bool {
cx.view_event(&mut self.child, id_path, event)
}

fn paint(&mut self, cx: &mut crate::context::PaintCx) {
cx.paint_view(&mut self.child);
fn for_each_child_mut<'a>(&'a mut self, for_each: &mut dyn FnMut(&'a mut dyn View) -> bool) {
for_each(&mut self.child);
}
}
Loading

0 comments on commit 41e8ce2

Please sign in to comment.