frame.rs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. use kahlo::{math::PixelSideOffsets, prelude::*};
  2. use crate::{
  3. component::Component,
  4. layout::{LayoutNode, LayoutNodeAccess, LayoutNodeContainer, SizePolicy},
  5. theme::Theme,
  6. ui::UIHandle,
  7. window::RenderFormat,
  8. };
  9. use super::Widget;
  10. pub struct Frame<C: Component> {
  11. layout: LayoutNode,
  12. child: Option<Box<dyn Widget<C>>>,
  13. _ghost: std::marker::PhantomData<C>,
  14. }
  15. impl<C: Component> Frame<C> {
  16. pub fn new(uih: &UIHandle) -> Self {
  17. let mut nnode = uih.new_layout_node();
  18. nnode
  19. .set_height_policy(SizePolicy::expanding(1))
  20. .set_width_policy(SizePolicy::expanding(1));
  21. Self {
  22. layout: nnode,
  23. child: None,
  24. _ghost: Default::default(),
  25. }
  26. }
  27. pub fn set_child(&mut self, child: Box<dyn Widget<C>>) {
  28. self.child = Some(child);
  29. self.layout.relayout();
  30. }
  31. }
  32. impl<C: Component> LayoutNodeContainer for Frame<C> {
  33. fn layout_node(&self) -> &LayoutNode {
  34. &self.layout
  35. }
  36. fn layout_child(&self, ndx: usize) -> Option<LayoutNodeAccess> {
  37. if ndx == 0 {
  38. Some(self.child.as_ref()?.layout_node())
  39. } else {
  40. None
  41. }
  42. }
  43. fn layout_child_count(&self) -> usize {
  44. if self.child.is_some() {
  45. 1
  46. } else {
  47. 0
  48. }
  49. }
  50. }
  51. impl<C: Component> Widget<C> for Frame<C> {
  52. fn poll(
  53. &mut self,
  54. _uih: &mut UIHandle,
  55. _input_state: Option<&crate::input::InputState>,
  56. ) -> Vec<C::Msg> {
  57. vec![]
  58. }
  59. fn layout_node(&self) -> LayoutNodeAccess {
  60. LayoutNodeAccess::new(self)
  61. }
  62. fn layout_node_mut(&mut self) -> &mut LayoutNode {
  63. &mut self.layout
  64. }
  65. fn render(&self, theme: &Theme, target: &mut kahlo::BitmapMut<RenderFormat>) {
  66. let area = self.layout.render_area().unwrap();
  67. target.fill_region(area, theme.border);
  68. target.fill_region(
  69. area.inner_box(PixelSideOffsets::new_all_same(theme.border_width as i32)),
  70. theme.panel,
  71. );
  72. }
  73. }