diff --git a/src/context.rs b/src/context.rs index f0d864491..abeed0dc2 100644 --- a/src/context.rs +++ b/src/context.rs @@ -308,6 +308,9 @@ impl<'context, 'window> EventContext<'context, 'window> { None } + /// Advances the focus from this widget to the next widget in `direction`. + /// + /// This widget does not need to be focused. pub fn advance_focus(&mut self, direction: VisualOrder) { self.pending_state.focus = self.next_focus_after(self.current_node.clone(), direction); } @@ -430,6 +433,9 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, ' /// Invokes [`Widget::redraw()`](crate::widget::Widget::redraw) on this /// context's widget. pub fn redraw(&mut self) { + self.current_node + .tree + .note_widget_rendered(self.current_node.id()); self.current_node.clone().lock().as_widget().redraw(self); } } @@ -908,8 +914,13 @@ impl RedrawStatus { } } +/// A type chat can convert to a [`ManagedWidget`] through a [`WidgetContext`]. pub trait ManageWidget { + /// The managed type, which can be `Option` or + /// `ManagedWidget`. type Managed: MapManagedWidget; + + /// Resolve `self` into a [`ManagedWidget`]. fn manage(&self, context: &WidgetContext<'_, '_>) -> Self::Managed; } @@ -940,9 +951,12 @@ impl ManageWidget for ManagedWidget { } } +/// A type that can produce another type when provided a [`ManagedWidget`]. pub trait MapManagedWidget { + /// The result of the mapping operation. type Result; + /// Call `map` with a [`ManagedWidget`]. fn map(self, map: impl FnOnce(ManagedWidget) -> T) -> Self::Result; } diff --git a/src/styles/components.rs b/src/styles/components.rs index fdcca4b2e..e3e309f69 100644 --- a/src/styles/components.rs +++ b/src/styles/components.rs @@ -162,13 +162,17 @@ impl ComponentDefinition for EasingOut { } } +/// A 2d ordering configuration. #[derive(Copy, Clone, Eq, PartialEq)] pub struct VisualOrder { + /// The ordering to apply horizontally. pub horizontal: HorizontalOrder, + /// The ordering to apply vertically. pub vertical: VerticalOrder, } impl VisualOrder { + /// Returns a right-to-left ordering. #[must_use] pub const fn right_to_left() -> Self { Self { @@ -177,6 +181,7 @@ impl VisualOrder { } } + /// Returns a left-to-right ordering. #[must_use] pub const fn left_to_right() -> Self { Self { @@ -185,6 +190,7 @@ impl VisualOrder { } } + /// Returns the reverse ordering of `self`. #[must_use] pub fn rev(self) -> Self { Self { @@ -200,13 +206,17 @@ impl NamedComponent for VisualOrder { } } +/// A horizontal direction. #[derive(Copy, Clone, Eq, PartialEq)] pub enum HorizontalOrder { + /// Describes an order starting at the left and proceeding to the right. LeftToRight, + /// Describes an order starting at the right and proceeding to the left. RightToLeft, } impl HorizontalOrder { + /// Returns the reverse order of `self`. #[must_use] pub fn rev(self) -> Self { match self { @@ -215,7 +225,7 @@ impl HorizontalOrder { } } - pub fn sort_key(self, rect: &Rect) -> Px { + pub(crate) fn sort_key(self, rect: &Rect) -> Px { match self { HorizontalOrder::LeftToRight => rect.origin.x, HorizontalOrder::RightToLeft => -(rect.origin.x + rect.size.width), @@ -223,13 +233,17 @@ impl HorizontalOrder { } } +/// A vertical direction. #[derive(Copy, Clone, Eq, PartialEq)] pub enum VerticalOrder { + /// Describes an order starting at the top and proceeding to the bottom. TopToBottom, + /// Describes an order starting at the bottom and proceeding to the top. BottomToTop, } impl VerticalOrder { + /// Returns the reverse order of `self`. #[must_use] pub fn rev(self) -> Self { match self { @@ -238,14 +252,14 @@ impl VerticalOrder { } } - pub fn max_px(self) -> Px { + pub(crate) fn max_px(self) -> Px { match self { VerticalOrder::TopToBottom => Px::MAX, VerticalOrder::BottomToTop => Px::MIN, } } - pub fn smallest_px(self, a: Px, b: Px) -> Px { + pub(crate) fn smallest_px(self, a: Px, b: Px) -> Px { match self { VerticalOrder::TopToBottom => a.min(b), VerticalOrder::BottomToTop => b.max(a), diff --git a/src/tree.rs b/src/tree.rs index 699f2f529..a77ae9797 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -53,7 +53,6 @@ impl Tree { pub(crate) fn set_layout(&self, widget: WidgetId, rect: Rect) { let mut data = self.data.lock().map_or_else(PoisonError::into_inner, |g| g); - data.render_order.push(widget); let node = data.nodes.get_mut(&widget).expect("missing widget"); node.layout = Some(rect); let mut children_to_offset = node.children.clone(); @@ -79,6 +78,11 @@ impl Tree { data.render_order.clear(); } + pub(crate) fn note_widget_rendered(&self, widget: WidgetId) { + let mut data = self.data.lock().map_or_else(PoisonError::into_inner, |g| g); + data.render_order.push(widget); + } + pub(crate) fn reset_child_layouts(&self, parent: WidgetId) { let mut data = self.data.lock().map_or_else(PoisonError::into_inner, |g| g); let children = data.nodes[&parent].children.clone(); diff --git a/src/widgets/input.rs b/src/widgets/input.rs index 0a6e3c3d3..3d5f9fc85 100644 --- a/src/widgets/input.rs +++ b/src/widgets/input.rs @@ -388,7 +388,7 @@ impl Widget for Input { ); (false, HANDLED) } - (_, Some(text)) if !context.modifiers().state().primary() => { + (_, Some(text)) if !context.modifiers().state().primary() && text != "\t" => { editor.insert_string(&text, None); (true, HANDLED) } diff --git a/src/widgets/resize.rs b/src/widgets/resize.rs index c3bcf622b..0fbb27482 100644 --- a/src/widgets/resize.rs +++ b/src/widgets/resize.rs @@ -1,5 +1,5 @@ use kludgine::figures::units::UPx; -use kludgine::figures::{Fraction, IntoUnsigned, ScreenScale, Size}; +use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, Rect, ScreenScale, Size}; use crate::context::{AsEventContext, GraphicsContext, LayoutContext}; use crate::styles::Dimension; @@ -68,7 +68,8 @@ impl Widget for Resize { available_space: Size, context: &mut LayoutContext<'_, '_, '_, '_, '_>, ) -> Size { - if let (Some(width), Some(height)) = (self.width, self.height) { + let child = self.child.mounted(&mut context.as_event_context()); + let size = if let (Some(width), Some(height)) = (self.width, self.height) { Size::new( width.into_px(context.graphics.scale()).into_unsigned(), height.into_px(context.graphics.scale()).into_unsigned(), @@ -82,10 +83,10 @@ impl Widget for Resize { context.graphics.scale(), ), ); - let child = self.child.mounted(&mut context.as_event_context()); - // TODO set_child_layout context.for_other(&child).layout(available_space) - } + }; + context.set_child_layout(&child, Rect::from(size.into_signed())); + size } }