Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added WidgetProps #69

Merged
merged 19 commits into from
Feb 5, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kayak_core/src/context_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ impl<'a> KayakContextRef<'a> {

/// Adds a widget to the context reference tree that will be committed to the main tree when `commit` is called.
/// This also adds the widget to the `KayakContext` and renders the new widget.
pub fn add_widget<W: crate::Widget + Clone + Default + PartialEq>(
pub fn add_widget<W: crate::Widget>(
&mut self,
widget: W,
widget_index: usize,
Expand Down
11 changes: 4 additions & 7 deletions kayak_core/src/event_dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use crate::cursor::CursorEvent;
use crate::layout_cache::Rect;
use crate::render_command::RenderCommand;
use crate::widget_manager::WidgetManager;
use crate::{
Event, EventType, Index, InputEvent, InputEventCategory, KayakContext, KeyCode, KeyboardEvent,
KeyboardModifiers, PointerEvents, Widget,
};
use crate::{Event, EventType, Index, InputEvent, InputEventCategory, KayakContext, KeyCode, KeyboardEvent, KeyboardModifiers, PointerEvents, BoxedWidget};
use std::collections::{HashMap, HashSet};

type EventMap = HashMap<Index, HashSet<EventType>>;
Expand Down Expand Up @@ -522,7 +519,7 @@ impl EventDispatcher {
fn resolve_pointer_events(index: Index, widget_manager: &WidgetManager) -> PointerEvents {
let mut pointer_events = PointerEvents::default();
if let Some(widget) = widget_manager.current_widgets.get(index).unwrap() {
if let Some(styles) = widget.get_styles() {
if let Some(styles) = widget.get_props().get_styles() {
pointer_events = styles.pointer_events.resolve();
}
}
Expand Down Expand Up @@ -631,8 +628,8 @@ impl EventDispatcher {
///
/// Currently a valid widget is defined as one where:
/// * RenderCommands is neither `Empty` nor `Layout` nor `Clip`
fn can_contain_cursor(widget: &Box<dyn Widget>) -> bool {
if let Some(styles) = widget.get_styles() {
fn can_contain_cursor(widget: &BoxedWidget) -> bool {
if let Some(styles) = widget.get_props().get_styles() {
let cmds = styles.render_command.resolve();
!matches!(
cmds,
Expand Down
59 changes: 40 additions & 19 deletions kayak_core/src/fragment.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,68 @@
use derivative::*;

use crate::{context::KayakContext, context_ref::KayakContextRef, styles::Style, Index, Widget};
use crate::{context_ref::KayakContextRef, styles::Style, Index, Widget, WidgetProps, Children, OnEvent};

#[derive(Derivative)]
#[derivative(Default, Debug, PartialEq, Clone)]
pub struct Fragment {
pub id: Index,
#[derivative(Default(value = "None"))]
pub struct FragmentProps {
pub styles: Option<Style>,
#[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")]
pub children: crate::Children,
#[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")]
pub on_event: Option<crate::OnEvent>,
}

impl Widget for Fragment {
fn get_id(&self) -> Index {
self.id
#[derive(Default, Debug, PartialEq, Clone)]
pub struct Fragment {
pub id: Index,
props: FragmentProps,
}

impl WidgetProps for FragmentProps {
fn get_children(&self) -> Children {
self.children.clone()
}

fn get_styles(&self) -> Option<Style> {
self.styles.clone()
}

fn get_on_event(&self) -> Option<OnEvent> {
None
}

fn focusable(&self) -> Option<bool> {
fn get_focusable(&self) -> Option<bool> {
Some(false)
}
}

fn set_id(&mut self, id: Index) {
self.id = id;
impl Widget for Fragment {
type Props = FragmentProps;

fn constructor(props: Self::Props) -> Self where Self: Sized {
Self {
id: Index::default(),
props,
}
}

fn get_styles(&self) -> Option<Style> {
self.styles.clone()
fn get_id(&self) -> Index {
self.id
}

fn set_id(&mut self, id: Index) {
self.id = id;
}

fn get_name(&self) -> String {
String::from("Fragment")
fn get_props(&self) -> &Self::Props {
&self.props
}

fn on_event(&mut self, _context: &mut KayakContext, _event: &mut crate::Event) {
// Do nothing.
fn get_props_mut(&mut self) -> &mut Self::Props {
&mut self.props
}

fn render(&mut self, context: &mut KayakContextRef) {
let parent_id = self.get_id();
if let Some(children) = self.children.take() {
if let Some(children) = self.props.children.take() {
let mut context = KayakContextRef::new(&mut context.context, Some(parent_id));
children(Some(parent_id), &mut context);
} else {
Expand Down
5 changes: 4 additions & 1 deletion kayak_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@ pub use keys::KeyCode;
pub use resources::Resources;
pub use tree::{Tree, WidgetTree};
pub use vec::VecTracker;
pub use widget::Widget;
pub use widget::{BaseWidget, Widget, WidgetProps};

pub mod derivative {
pub use derivative::*;
}

/// Type alias for dynamic widget objects. We use [BaseWidget] so that we can be object-safe
type BoxedWidget = Box<dyn BaseWidget>;

pub type Children = Option<Arc<dyn Fn(Option<crate::Index>, &mut KayakContextRef) + Send + Sync>>;

#[derive(Clone)]
Expand Down
8 changes: 4 additions & 4 deletions kayak_core/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{

use morphorm::Hierarchy;

use crate::{Arena, Index, Widget};
use crate::{Arena, BoxedWidget, Index};

#[derive(Default, Debug, PartialEq)]
pub struct Tree {
Expand Down Expand Up @@ -567,7 +567,7 @@ impl Tree {
/// * `widgets`: Optionally, provide the current widgets to include metadata about each widget
///
/// returns: ()
pub fn dump(&self, widgets: Option<&Arena<Option<Box<dyn Widget>>>>) {
pub fn dump(&self, widgets: Option<&Arena<Option<BoxedWidget>>>) {
if let Some(root) = self.root_node {
self.dump_at_internal(root, 0, widgets);
}
Expand All @@ -583,15 +583,15 @@ impl Tree {
/// * `widgets`: Optionally, provide the current widgets to include metadata about each widget
///
/// returns: ()
pub fn dump_at(&self, start_index: Index, widgets: Option<&Arena<Option<Box<dyn Widget>>>>) {
pub fn dump_at(&self, start_index: Index, widgets: Option<&Arena<Option<BoxedWidget>>>) {
self.dump_at_internal(start_index, 0, widgets);
}

fn dump_at_internal(
&self,
start_index: Index,
depth: usize,
widgets: Option<&Arena<Option<Box<dyn Widget>>>>,
widgets: Option<&Arena<Option<BoxedWidget>>>,
) {
let mut name = None;
if let Some(widgets) = widgets {
Expand Down
80 changes: 56 additions & 24 deletions kayak_core/src/vec.rs
Original file line number Diff line number Diff line change
@@ -1,71 +1,103 @@
use derivative::*;

use crate::{context::KayakContext, context_ref::KayakContextRef, styles::Style, Index, Widget};
use crate::{context_ref::KayakContextRef, styles::Style, Index, Widget, Children, OnEvent, WidgetProps};

#[derive(Derivative)]
#[derivative(Debug, PartialEq, Clone, Default)]
pub struct VecTracker<T> {
pub id: Index,
#[derivative(Default, Debug, PartialEq, Clone)]
pub struct VecTrackerProps<T> {
MrGVSV marked this conversation as resolved.
Show resolved Hide resolved
pub data: Vec<T>,
#[derivative(Default(value = "None"))]
pub styles: Option<Style>,
#[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")]
pub children: crate::Children,
#[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")]
pub on_event: Option<crate::OnEvent>,
pub data: Vec<T>,
}

#[derive(Derivative)]
#[derivative(Debug, PartialEq, Clone, Default)]
pub struct VecTracker<T> {
pub id: Index,
pub props: VecTrackerProps<T>,
}

impl<T> VecTracker<T> {
pub fn new(data: Vec<T>) -> Self {
Self {
let props = VecTrackerProps {
data,
id: Index::default(),
styles: None,
children: None,
on_event: None,
};

Self {
id: Index::default(),
props,
}
}
}

impl<T, I> From<I> for VecTracker<T>
where
I: Iterator<Item = T>,
where
I: Iterator<Item=T>,
{
fn from(iter: I) -> Self {
Self::new(iter.collect())
}
}

impl<T> WidgetProps for VecTrackerProps<T>
where
T: Widget, {

fn get_children(&self) -> Children {
self.children.clone()
}

fn get_styles(&self) -> Option<Style> {
self.styles.clone()
}

fn get_on_event(&self) -> Option<OnEvent> {
self.on_event.clone()
}

fn get_focusable(&self) -> Option<bool> {
Some(false)
}
}

impl<T> Widget for VecTracker<T>
where
T: Widget + PartialEq + std::fmt::Debug + Clone + Default,
where
T: Widget,
{
fn get_id(&self) -> Index {
self.id
type Props = VecTrackerProps<T>;

fn constructor(props: Self::Props) -> Self where Self: Sized {
Self {
id: Index::default(),
props,
}
}

fn focusable(&self) -> Option<bool> {
Some(false)
fn get_id(&self) -> Index {
self.id
}

fn set_id(&mut self, id: Index) {
self.id = id;
}

fn get_styles(&self) -> Option<Style> {
self.styles.clone()
}

fn get_name(&self) -> String {
String::from("Fragment")
fn get_props(&self) -> &Self::Props {
&self.props
}

fn on_event(&mut self, _context: &mut KayakContext, _event: &mut crate::Event) {
// Do nothing.
fn get_props_mut(&mut self) -> &mut Self::Props {
&mut self.props
}

fn render(&mut self, context: &mut KayakContextRef) {
for (index, item) in self.data.iter().enumerate() {
for (index, item) in self.props.data.iter().enumerate() {
context.add_widget(item.clone(), index);
}

Expand Down
Loading