Răsfoiți Sursa

Make use of new multi-layout node containers to align text correctly in labels and buttons.

Kestrel 6 luni în urmă
părinte
comite
123ba98f7f
3 a modificat fișierele cu 49 adăugiri și 33 ștergeri
  1. 5 0
      examples/simplest.rs
  2. 24 26
      src/widget/button.rs
  3. 20 7
      src/widget/label.rs

+ 5 - 0
examples/simplest.rs

@@ -1,5 +1,6 @@
 use patina::{prelude::*, ui::UIControlMsg, window::WindowComponent};
 
+/// struct to represent a window and dispatch event processing within it
 struct SimpleWindow {
     widget: <Self as WindowComponent>::RootWidget,
 }
@@ -12,10 +13,12 @@ impl SimpleWindow {
     }
 }
 
+/// messages that can be sent to the window component
 enum SimpleWindowMsg {
     Close,
 }
 
+/// internal message handling
 impl Component for SimpleWindow {
     type ParentMsg = UIControlMsg;
     type Msg = SimpleWindowMsg;
@@ -27,6 +30,7 @@ impl Component for SimpleWindow {
     }
 }
 
+/// window-specific event handling
 impl WindowComponent for SimpleWindow {
     fn map_window_event(&self, we: patina::window::WindowEvent) -> Option<Self::Msg> {
         match we {
@@ -45,5 +49,6 @@ impl WindowComponent for SimpleWindow {
 }
 
 fn main() {
+    // see the docs for make_opinionated_ui
     patina::ui::make_opinionated_ui(SimpleWindow::new).run();
 }

+ 24 - 26
src/widget/button.rs

@@ -21,8 +21,8 @@ enum ButtonState {
 }
 
 pub struct Button<C: Component> {
-    layout_root: LayoutNode,
-    layout_label: LeafLayoutNode,
+    root_layout: LayoutNode,
+    label_layout: LeafLayoutNode,
     text_cache: TextCache,
     label: String,
     state: ButtonState,
@@ -45,8 +45,17 @@ impl<C: Component> Button<C> {
             .set_halign(HorizontalAlignment::Centre);
         *layout.margin_mut() = PixelSideOffsets::new_all_same(uih.theme().border_width as i32);
         Self {
-            layout_root: layout,
-            layout_label: uih.new_layout_node().into(),
+            root_layout: layout,
+            label_layout: {
+                let mut node = uih.new_layout_node();
+                node
+                    .set_width_policy(SizePolicy::fixed(0))
+                    .set_height_policy(SizePolicy::fixed(0))
+                    .set_halign(HorizontalAlignment::Centre)
+                    .set_valign(VerticalAlignment::Centre);
+
+                node.into()
+            },
             text_cache: TextCache::new_with_font_and_size(
                 uih.theme().ui_font.clone(),
                 uih.theme().ui_font_size,
@@ -75,7 +84,7 @@ impl<C: Component> Button<C> {
 
 impl<C: Component> LayoutTreeNode<RootTag> for Button<C> {
     fn current_node(&self) -> &LayoutNode {
-        &self.layout_root
+        &self.root_layout
     }
 
     fn child_count(&self) -> usize {
@@ -84,35 +93,24 @@ impl<C: Component> LayoutTreeNode<RootTag> for Button<C> {
 
     fn child(&self, ndx: usize) -> Option<LayoutNodeAccess<'_>> {
         if ndx == 0 {
-            Some(self.layout_label.access())
+            Some(self.label_layout.access())
         } else {
             None
         }
     }
 }
 
-/*
-impl<C: Component> LayoutNodeContainer for Button<C> {
-    fn layout_node(&self) -> &LayoutNode {
-        &self.layout
-    }
-    fn layout_child(&self, ndx: usize) -> Option<LayoutNodeAccess<'_>> {
-        None
-    }
-    fn layout_child_count(&self) -> usize {
-        0
-    }
-}
-*/
-
 impl<C: Component> Widget<C> for Button<C> {
     fn poll(
         &mut self,
         _uih: &mut UIHandle,
         input_state: Option<&crate::input::InputState>,
     ) -> Vec<<C as Component>::Msg> {
+
+        self.text_cache.update_node_size_hint(&mut *self.label_layout);
+
         let mut result: Vec<<C as Component>::Msg> = vec![];
-        if let Some((istate, area)) = input_state.zip(self.layout_root.render_area()) {
+        if let Some((istate, area)) = input_state.zip(self.root_layout.render_area()) {
             let saved = self.state;
             match istate.mouse_status_in(area, MouseButton::Left) {
                 MouseCheckStatus::Idle | MouseCheckStatus::Leave => {
@@ -130,12 +128,10 @@ impl<C: Component> Widget<C> for Button<C> {
                 }
             }
             if self.state != saved {
-                self.layout_root.render_needed();
+                self.root_layout.render_needed();
             }
         }
 
-        // self.text_cache.update(&mut self.layout, &self.label);
-
         result
     }
 
@@ -143,18 +139,20 @@ impl<C: Component> Widget<C> for Button<C> {
         LayoutNodeAccess::new(self)
     }
     fn layout_node_mut(&mut self) -> &mut LayoutNode {
-        &mut self.layout_root
+        &mut self.root_layout
     }
 
     fn render<'r, 'data: 'r>(&self, target: &mut RenderTarget<'r, 'data>) {
         target
-            .with_node(&self.layout_root)
+            .with_node(&self.root_layout)
             .fill(match self.state {
                 ButtonState::Idle => ColourChoice::Background,
                 ButtonState::Hovered => ColourChoice::Panel,
                 ButtonState::Clicked => ColourChoice::Active,
             })
             .border()
+            .finish();
+        target.with_node(&self.label_layout)
             .simple_text(&self.text_cache, ColourChoice::Foreground)
             .finish();
     }

+ 20 - 7
src/widget/label.rs

@@ -1,7 +1,7 @@
 use std::rc::Rc;
 
 use crate::{
-    layout::{LayoutNode, LayoutNodeAccess, LeafLayoutNode, SizePolicy},
+    layout::{LayoutNode, LayoutNodeAccess, LayoutTreeNode, LeafLayoutNode, SizePolicy},
     render::{RenderTarget, TextCache},
     ui::UIHandle,
     Component,
@@ -10,7 +10,8 @@ use crate::{
 use super::Widget;
 
 pub struct Label<C: Component> {
-    lnode: LeafLayoutNode,
+    root_layout: LayoutNode,
+    text_layout: LeafLayoutNode,
     cache: TextCache,
     _ghost: std::marker::PhantomData<C>,
 }
@@ -27,7 +28,8 @@ impl<C: Component> Label<C> {
         let mut cache = TextCache::new_with_font_and_size(font, pxsize);
         cache.update(text.unwrap_or(""));
         Self {
-            lnode: LeafLayoutNode::new(node),
+            text_layout: LeafLayoutNode::new(node.make_new_node()),
+            root_layout: node,
             cache,
             _ghost: Default::default(),
         }
@@ -65,27 +67,38 @@ impl<C: Component> Label<C> {
     }
 }
 
+impl<C: Component> LayoutTreeNode<()> for Label<C> {
+    fn current_node(&self) -> &LayoutNode {
+        &self.root_layout
+    }
+    fn child_count(&self) -> usize { 1 }
+    fn child(&self, ndx: usize) -> Option<LayoutNodeAccess<'_>> {
+        if ndx == 0 { Some(self.text_layout.access()) }
+        else { None }
+    }
+}
+
 impl<C: Component> Widget<C> for Label<C> {
     fn poll(
         &mut self,
         _uih: &mut UIHandle,
         _input_state: Option<&crate::input::InputState>,
     ) -> Vec<<C as Component>::Msg> {
-        self.cache.update_node_size_hint(&mut *self.lnode);
+        self.cache.update_node_size_hint(&mut *self.text_layout);
 
         vec![]
     }
 
     fn layout_node(&self) -> LayoutNodeAccess {
-        LayoutNodeAccess::new(&self.lnode)
+        LayoutNodeAccess::new(self)
     }
     fn layout_node_mut(&mut self) -> &mut LayoutNode {
-        &mut self.lnode
+        &mut self.root_layout
     }
 
     fn render<'r, 'data: 'r>(&self, target: &mut RenderTarget<'r, 'data>) {
         target
-            .with_node(&self.lnode)
+            .with_node(&self.text_layout)
             .simple_text(&self.cache, crate::render::ColourChoice::Foreground);
 
         /*if !self.lnode.render_check() {