iced_native/widget/
rule.rs1use crate::layout;
3use crate::renderer;
4use crate::widget::Tree;
5use crate::{
6 Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget,
7};
8
9pub use iced_style::rule::{Appearance, FillMode, StyleSheet};
10
11#[allow(missing_debug_implementations)]
13pub struct Rule<Renderer>
14where
15 Renderer: crate::Renderer,
16 Renderer::Theme: StyleSheet,
17{
18 width: Length,
19 height: Length,
20 is_horizontal: bool,
21 style: <Renderer::Theme as StyleSheet>::Style,
22}
23
24impl<Renderer> Rule<Renderer>
25where
26 Renderer: crate::Renderer,
27 Renderer::Theme: StyleSheet,
28{
29 pub fn horizontal(height: impl Into<Pixels>) -> Self {
31 Rule {
32 width: Length::Fill,
33 height: Length::Fixed(height.into().0),
34 is_horizontal: true,
35 style: Default::default(),
36 }
37 }
38
39 pub fn vertical(width: impl Into<Pixels>) -> Self {
41 Rule {
42 width: Length::Fixed(width.into().0),
43 height: Length::Fill,
44 is_horizontal: false,
45 style: Default::default(),
46 }
47 }
48
49 pub fn style(
51 mut self,
52 style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
53 ) -> Self {
54 self.style = style.into();
55 self
56 }
57}
58
59impl<Message, Renderer> Widget<Message, Renderer> for Rule<Renderer>
60where
61 Renderer: crate::Renderer,
62 Renderer::Theme: StyleSheet,
63{
64 fn width(&self) -> Length {
65 self.width
66 }
67
68 fn height(&self) -> Length {
69 self.height
70 }
71
72 fn layout(
73 &self,
74 _renderer: &Renderer,
75 limits: &layout::Limits,
76 ) -> layout::Node {
77 let limits = limits.width(self.width).height(self.height);
78
79 layout::Node::new(limits.resolve(Size::ZERO))
80 }
81
82 fn draw(
83 &self,
84 _state: &Tree,
85 renderer: &mut Renderer,
86 theme: &Renderer::Theme,
87 _style: &renderer::Style,
88 layout: Layout<'_>,
89 _cursor_position: Point,
90 _viewport: &Rectangle,
91 ) {
92 let bounds = layout.bounds();
93 let style = theme.appearance(&self.style);
94
95 let bounds = if self.is_horizontal {
96 let line_y = (bounds.y + (bounds.height / 2.0)
97 - (style.width as f32 / 2.0))
98 .round();
99
100 let (offset, line_width) = style.fill_mode.fill(bounds.width);
101 let line_x = bounds.x + offset;
102
103 Rectangle {
104 x: line_x,
105 y: line_y,
106 width: line_width,
107 height: style.width as f32,
108 }
109 } else {
110 let line_x = (bounds.x + (bounds.width / 2.0)
111 - (style.width as f32 / 2.0))
112 .round();
113
114 let (offset, line_height) = style.fill_mode.fill(bounds.height);
115 let line_y = bounds.y + offset;
116
117 Rectangle {
118 x: line_x,
119 y: line_y,
120 width: style.width as f32,
121 height: line_height,
122 }
123 };
124
125 renderer.fill_quad(
126 renderer::Quad {
127 bounds,
128 border_radius: style.radius.into(),
129 border_width: 0.0,
130 border_color: Color::TRANSPARENT,
131 },
132 style.color,
133 );
134 }
135}
136
137impl<'a, Message, Renderer> From<Rule<Renderer>>
138 for Element<'a, Message, Renderer>
139where
140 Message: 'a,
141 Renderer: 'a + crate::Renderer,
142 Renderer::Theme: StyleSheet,
143{
144 fn from(rule: Rule<Renderer>) -> Element<'a, Message, Renderer> {
145 Element::new(rule)
146 }
147}