summaryrefslogtreecommitdiffstats
path: root/pure
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-02-11 23:17:07 +0700
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-02-11 23:17:07 +0700
commitecb3df8e018930c407e469ce2b8f4208a9d15426 (patch)
tree9370945e6c5092e2730ec6835fa6c0556622ca9d /pure
parent01c5004959c9b11f2580840f4553ad7d706f4564 (diff)
downloadiced-ecb3df8e018930c407e469ce2b8f4208a9d15426.tar.gz
iced-ecb3df8e018930c407e469ce2b8f4208a9d15426.tar.bz2
iced-ecb3df8e018930c407e469ce2b8f4208a9d15426.zip
Expose reusable `Button` logic
... and reuse it in `iced_pure`!
Diffstat (limited to '')
-rw-r--r--pure/src/widget/button.rs162
-rw-r--r--pure/src/widget/tree.rs14
2 files changed, 52 insertions, 124 deletions
diff --git a/pure/src/widget/button.rs b/pure/src/widget/button.rs
index 198a3af9..89acb7f5 100644
--- a/pure/src/widget/button.rs
+++ b/pure/src/widget/button.rs
@@ -4,15 +4,16 @@ use iced_native::event::{self, Event};
use iced_native::layout;
use iced_native::mouse;
use iced_native::renderer;
-use iced_native::touch;
+use iced_native::widget::button;
use iced_native::{
- Background, Clipboard, Color, Hasher, Layout, Length, Padding, Point,
- Rectangle, Shell, Vector,
+ Clipboard, Hasher, Layout, Length, Padding, Point, Rectangle, Shell,
};
use iced_style::button::StyleSheet;
use std::any::Any;
+pub use button::State;
+
pub struct Button<'a, Message, Renderer> {
content: Element<'a, Message, Renderer>,
on_press: Option<Message>,
@@ -51,7 +52,7 @@ where
}
fn state(&self) -> Box<dyn Any> {
- Box::new(State { is_pressed: false })
+ Box::new(State::new())
}
fn children(&self) -> &[Element<Message, Renderer>] {
@@ -71,6 +72,8 @@ where
self.tag().hash(state);
self.width.hash(state);
+ self.height.hash(state);
+ self.padding.hash(state);
self.content.as_widget().hash_layout(state);
}
@@ -79,20 +82,16 @@ where
renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits
- .width(self.width)
- .height(self.height)
- .pad(self.padding);
-
- let mut content = self.content.as_widget().layout(renderer, &limits);
- content.move_to(Point::new(
- self.padding.left.into(),
- self.padding.top.into(),
- ));
-
- let size = limits.resolve(content.size()).pad(self.padding);
-
- layout::Node::with_children(size, vec![content])
+ button::layout(
+ renderer,
+ limits,
+ self.width,
+ self.height,
+ self.padding,
+ |renderer, limits| {
+ self.content.as_widget().layout(renderer, &limits)
+ },
+ )
}
fn on_event(
@@ -105,12 +104,6 @@ where
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
) -> event::Status {
- let state = if let Some(state) = tree.state.downcast_mut::<State>() {
- state
- } else {
- return event::Status::Ignored;
- };
-
if let event::Status::Captured = self.content.as_widget_mut().on_event(
&mut tree.children[0],
event.clone(),
@@ -123,42 +116,14 @@ where
return event::Status::Captured;
}
- match event {
- Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
- | Event::Touch(touch::Event::FingerPressed { .. }) => {
- if self.on_press.is_some() {
- let bounds = layout.bounds();
-
- if bounds.contains(cursor_position) {
- state.is_pressed = true;
-
- return event::Status::Captured;
- }
- }
- }
- Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
- | Event::Touch(touch::Event::FingerLifted { .. }) => {
- if let Some(on_press) = self.on_press.clone() {
- let bounds = layout.bounds();
-
- if state.is_pressed {
- state.is_pressed = false;
-
- if bounds.contains(cursor_position) {
- shell.publish(on_press);
- }
-
- return event::Status::Captured;
- }
- }
- }
- Event::Touch(touch::Event::FingerLost { .. }) => {
- state.is_pressed = false;
- }
- _ => {}
- }
-
- event::Status::Ignored
+ button::update(
+ event,
+ layout,
+ cursor_position,
+ shell,
+ &self.on_press,
+ || tree.state_mut::<State>(),
+ )
}
fn draw(
@@ -170,60 +135,17 @@ where
cursor_position: Point,
_viewport: &Rectangle,
) {
- let state = if let Some(state) = tree.state.downcast_ref::<State>() {
- state
- } else {
- return;
- };
-
let bounds = layout.bounds();
let content_layout = layout.children().next().unwrap();
- let is_mouse_over = bounds.contains(cursor_position);
- let is_disabled = self.on_press.is_none();
-
- let styling = if is_disabled {
- self.style_sheet.disabled()
- } else if is_mouse_over {
- if state.is_pressed {
- self.style_sheet.pressed()
- } else {
- self.style_sheet.hovered()
- }
- } else {
- self.style_sheet.active()
- };
-
- if styling.background.is_some() || styling.border_width > 0.0 {
- if styling.shadow_offset != Vector::default() {
- // TODO: Implement proper shadow support
- renderer.fill_quad(
- renderer::Quad {
- bounds: Rectangle {
- x: bounds.x + styling.shadow_offset.x,
- y: bounds.y + styling.shadow_offset.y,
- ..bounds
- },
- border_radius: styling.border_radius,
- border_width: 0.0,
- border_color: Color::TRANSPARENT,
- },
- Background::Color([0.0, 0.0, 0.0, 0.5].into()),
- );
- }
-
- renderer.fill_quad(
- renderer::Quad {
- bounds,
- border_radius: styling.border_radius,
- border_width: styling.border_width,
- border_color: styling.border_color,
- },
- styling
- .background
- .unwrap_or(Background::Color(Color::TRANSPARENT)),
- );
- }
+ let styling = button::draw(
+ renderer,
+ bounds,
+ cursor_position,
+ self.on_press.is_some(),
+ self.style_sheet.as_ref(),
+ || tree.state::<State>(),
+ );
self.content.as_widget().draw(
&tree.children[0],
@@ -245,22 +167,14 @@ where
_viewport: &Rectangle,
_renderer: &Renderer,
) -> mouse::Interaction {
- let is_mouse_over = layout.bounds().contains(cursor_position);
- let is_disabled = self.on_press.is_none();
-
- if is_mouse_over && !is_disabled {
- mouse::Interaction::Pointer
- } else {
- mouse::Interaction::default()
- }
+ button::mouse_interaction(
+ layout,
+ cursor_position,
+ self.on_press.is_some(),
+ )
}
}
-#[derive(Debug, Clone)]
-struct State {
- is_pressed: bool,
-}
-
impl<'a, Message, Renderer> Into<Element<'a, Message, Renderer>>
for Button<'a, Message, Renderer>
where
diff --git a/pure/src/widget/tree.rs b/pure/src/widget/tree.rs
index 2353edc5..1ab6d80b 100644
--- a/pure/src/widget/tree.rs
+++ b/pure/src/widget/tree.rs
@@ -58,4 +58,18 @@ impl Tree {
*self = Self::new(new);
}
}
+
+ pub fn state<T>(&self) -> &T
+ where
+ T: 'static,
+ {
+ self.state.downcast_ref().expect("Downcast widget state")
+ }
+
+ pub fn state_mut<T>(&mut self) -> &mut T
+ where
+ T: 'static,
+ {
+ self.state.downcast_mut().expect("Downcast widget state")
+ }
}