Create iced_core and iced_native
This commit is contained in:
parent
b83a4b42dd
commit
b9e0f74948
81 changed files with 2576 additions and 2709 deletions
111
native/src/widget/button.rs
Normal file
111
native/src/widget/button.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
//! Allow your users to perform actions by pressing a button.
|
||||
//!
|
||||
//! A [`Button`] has some local [`State`] and a [`Class`].
|
||||
//!
|
||||
//! [`Button`]: struct.Button.html
|
||||
//! [`State`]: struct.State.html
|
||||
//! [`Class`]: enum.Class.html
|
||||
|
||||
use crate::input::{mouse, ButtonState};
|
||||
use crate::{
|
||||
Element, Event, Hasher, Layout, MouseCursor, Node, Point, Rectangle, Widget,
|
||||
};
|
||||
use std::hash::Hash;
|
||||
|
||||
pub use iced_core::button::*;
|
||||
|
||||
impl<'a, Message, Renderer> Widget<Message, Renderer> for Button<'a, Message>
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
Message: Copy + std::fmt::Debug,
|
||||
{
|
||||
fn node(&self, renderer: &mut Renderer) -> Node {
|
||||
renderer.node(&self)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
) {
|
||||
match event {
|
||||
Event::Mouse(mouse::Event::Input {
|
||||
button: mouse::Button::Left,
|
||||
state,
|
||||
}) => {
|
||||
if let Some(on_press) = self.on_press {
|
||||
let bounds = layout.bounds();
|
||||
|
||||
match state {
|
||||
ButtonState::Pressed => {
|
||||
self.state.is_pressed =
|
||||
bounds.contains(cursor_position);
|
||||
}
|
||||
ButtonState::Released => {
|
||||
let is_clicked = self.state.is_pressed
|
||||
&& bounds.contains(cursor_position);
|
||||
|
||||
self.state.is_pressed = false;
|
||||
|
||||
if is_clicked {
|
||||
messages.push(on_press);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
}
|
||||
|
||||
fn hash_layout(&self, state: &mut Hasher) {
|
||||
self.width.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// The renderer of a [`Button`].
|
||||
///
|
||||
/// Your [renderer] will need to implement this trait before being
|
||||
/// able to use a [`Button`] in your user interface.
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
/// [renderer]: ../../renderer/index.html
|
||||
pub trait Renderer {
|
||||
/// Creates a [`Node`] for the provided [`Button`].
|
||||
///
|
||||
/// [`Node`]: ../../struct.Node.html
|
||||
/// [`Button`]: struct.Button.html
|
||||
fn node<Message>(&self, button: &Button<'_, Message>) -> Node;
|
||||
|
||||
/// Draws a [`Button`].
|
||||
///
|
||||
/// [`Button`]: struct.Button.html
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
button: &Button<'_, Message>,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor;
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> From<Button<'a, Message>>
|
||||
for Element<'a, Message, Renderer>
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
Message: 'static + Copy + std::fmt::Debug,
|
||||
{
|
||||
fn from(button: Button<'a, Message>) -> Element<'a, Message, Renderer> {
|
||||
Element::new(button)
|
||||
}
|
||||
}
|
||||
95
native/src/widget/checkbox.rs
Normal file
95
native/src/widget/checkbox.rs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
//! Show toggle controls using checkboxes.
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::input::{mouse, ButtonState};
|
||||
use crate::{Element, Event, Hasher, Layout, MouseCursor, Node, Point, Widget};
|
||||
|
||||
pub use iced_core::Checkbox;
|
||||
|
||||
impl<Message, Renderer> Widget<Message, Renderer> for Checkbox<Message>
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn node(&self, renderer: &mut Renderer) -> Node {
|
||||
renderer.node(&self)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
) {
|
||||
match event {
|
||||
Event::Mouse(mouse::Event::Input {
|
||||
button: mouse::Button::Left,
|
||||
state: ButtonState::Pressed,
|
||||
}) => {
|
||||
let mouse_over = layout
|
||||
.children()
|
||||
.any(|child| child.bounds().contains(cursor_position));
|
||||
|
||||
if mouse_over {
|
||||
messages.push((self.on_toggle)(!self.is_checked));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
}
|
||||
|
||||
fn hash_layout(&self, state: &mut Hasher) {
|
||||
self.label.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// The renderer of a [`Checkbox`].
|
||||
///
|
||||
/// Your [renderer] will need to implement this trait before being
|
||||
/// able to use a [`Checkbox`] in your user interface.
|
||||
///
|
||||
/// [`Checkbox`]: struct.Checkbox.html
|
||||
/// [renderer]: ../../renderer/index.html
|
||||
pub trait Renderer {
|
||||
/// Creates a [`Node`] for the provided [`Checkbox`].
|
||||
///
|
||||
/// [`Node`]: ../../struct.Node.html
|
||||
/// [`Checkbox`]: struct.Checkbox.html
|
||||
fn node<Message>(&mut self, checkbox: &Checkbox<Message>) -> Node;
|
||||
|
||||
/// Draws a [`Checkbox`].
|
||||
///
|
||||
/// It receives:
|
||||
/// * the current cursor position
|
||||
/// * the bounds of the [`Checkbox`]
|
||||
/// * the bounds of the label of the [`Checkbox`]
|
||||
/// * whether the [`Checkbox`] is checked or not
|
||||
///
|
||||
/// [`Checkbox`]: struct.Checkbox.html
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
checkbox: &Checkbox<Message>,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor;
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> From<Checkbox<Message>>
|
||||
for Element<'a, Message, Renderer>
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
Message: 'static,
|
||||
{
|
||||
fn from(checkbox: Checkbox<Message>) -> Element<'a, Message, Renderer> {
|
||||
Element::new(checkbox)
|
||||
}
|
||||
}
|
||||
118
native/src/widget/column.rs
Normal file
118
native/src/widget/column.rs
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
use std::hash::Hash;
|
||||
|
||||
use crate::{
|
||||
Element, Event, Hasher, Layout, MouseCursor, Node, Point, Style, Widget,
|
||||
};
|
||||
|
||||
/// A container that distributes its contents vertically.
|
||||
pub type Column<'a, Message, Renderer> =
|
||||
iced_core::Column<Element<'a, Message, Renderer>>;
|
||||
|
||||
impl<'a, Message, Renderer> Widget<Message, Renderer>
|
||||
for Column<'a, Message, Renderer>
|
||||
{
|
||||
fn node(&self, renderer: &mut Renderer) -> Node {
|
||||
let mut children: Vec<Node> = self
|
||||
.children
|
||||
.iter()
|
||||
.map(|child| {
|
||||
let mut node = child.widget.node(renderer);
|
||||
|
||||
let mut style = node.0.style();
|
||||
style.margin.bottom =
|
||||
stretch::style::Dimension::Points(f32::from(self.spacing));
|
||||
|
||||
node.0.set_style(style);
|
||||
node
|
||||
})
|
||||
.collect();
|
||||
|
||||
if let Some(node) = children.last_mut() {
|
||||
let mut style = node.0.style();
|
||||
style.margin.bottom = stretch::style::Dimension::Undefined;
|
||||
|
||||
node.0.set_style(style);
|
||||
}
|
||||
|
||||
let mut style = Style::default()
|
||||
.width(self.width)
|
||||
.height(self.height)
|
||||
.max_width(self.max_width)
|
||||
.max_height(self.max_height)
|
||||
.padding(self.padding)
|
||||
.align_self(self.align_self)
|
||||
.align_items(self.align_items)
|
||||
.justify_content(self.justify_content);
|
||||
|
||||
style.0.flex_direction = stretch::style::FlexDirection::Column;
|
||||
|
||||
Node::with_children(style, children)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
) {
|
||||
self.children.iter_mut().zip(layout.children()).for_each(
|
||||
|(child, layout)| {
|
||||
child
|
||||
.widget
|
||||
.on_event(event, layout, cursor_position, messages)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor {
|
||||
let mut cursor = MouseCursor::OutOfBounds;
|
||||
|
||||
self.children.iter().zip(layout.children()).for_each(
|
||||
|(child, layout)| {
|
||||
let new_cursor =
|
||||
child.widget.draw(renderer, layout, cursor_position);
|
||||
|
||||
if new_cursor != MouseCursor::OutOfBounds {
|
||||
cursor = new_cursor;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
cursor
|
||||
}
|
||||
|
||||
fn hash_layout(&self, state: &mut Hasher) {
|
||||
0.hash(state);
|
||||
self.width.hash(state);
|
||||
self.height.hash(state);
|
||||
self.max_width.hash(state);
|
||||
self.max_height.hash(state);
|
||||
self.align_self.hash(state);
|
||||
self.align_items.hash(state);
|
||||
self.justify_content.hash(state);
|
||||
self.spacing.hash(state);
|
||||
|
||||
for child in &self.children {
|
||||
child.widget.hash_layout(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> From<Column<'a, Message, Renderer>>
|
||||
for Element<'a, Message, Renderer>
|
||||
where
|
||||
Renderer: 'a,
|
||||
Message: 'static,
|
||||
{
|
||||
fn from(
|
||||
column: Column<'a, Message, Renderer>,
|
||||
) -> Element<'a, Message, Renderer> {
|
||||
Element::new(column)
|
||||
}
|
||||
}
|
||||
67
native/src/widget/image.rs
Normal file
67
native/src/widget/image.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
//! Display images in your user interface.
|
||||
|
||||
use crate::{
|
||||
Element, Hasher, Layout, MouseCursor, Node, Point, Rectangle, Widget,
|
||||
};
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
pub use iced_core::Image;
|
||||
|
||||
impl<I, Message, Renderer> Widget<Message, Renderer> for Image<I>
|
||||
where
|
||||
Renderer: self::Renderer<I>,
|
||||
I: Clone,
|
||||
{
|
||||
fn node(&self, renderer: &mut Renderer) -> Node {
|
||||
renderer.node(&self)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: Layout<'_>,
|
||||
_cursor_position: Point,
|
||||
) -> MouseCursor {
|
||||
renderer.draw(&self, layout);
|
||||
|
||||
MouseCursor::OutOfBounds
|
||||
}
|
||||
|
||||
fn hash_layout(&self, state: &mut Hasher) {
|
||||
self.width.hash(state);
|
||||
self.height.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// The renderer of an [`Image`].
|
||||
///
|
||||
/// Your [renderer] will need to implement this trait before being able to use
|
||||
/// an [`Image`] in your user interface.
|
||||
///
|
||||
/// [`Image`]: struct.Image.html
|
||||
/// [renderer]: ../../renderer/index.html
|
||||
pub trait Renderer<I> {
|
||||
/// Creates a [`Node`] for the provided [`Image`].
|
||||
///
|
||||
/// You should probably keep the original aspect ratio, if possible.
|
||||
///
|
||||
/// [`Node`]: ../../struct.Node.html
|
||||
/// [`Image`]: struct.Image.html
|
||||
fn node(&mut self, image: &Image<I>) -> Node;
|
||||
|
||||
/// Draws an [`Image`].
|
||||
///
|
||||
/// [`Image`]: struct.Image.html
|
||||
fn draw(&mut self, image: &Image<I>, layout: Layout<'_>);
|
||||
}
|
||||
|
||||
impl<'a, I, Message, Renderer> From<Image<I>> for Element<'a, Message, Renderer>
|
||||
where
|
||||
Renderer: self::Renderer<I>,
|
||||
I: Clone + 'a,
|
||||
{
|
||||
fn from(image: Image<I>) -> Element<'a, Message, Renderer> {
|
||||
Element::new(image)
|
||||
}
|
||||
}
|
||||
92
native/src/widget/radio.rs
Normal file
92
native/src/widget/radio.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
//! Create choices using radio buttons.
|
||||
use crate::input::{mouse, ButtonState};
|
||||
use crate::{Element, Event, Hasher, Layout, MouseCursor, Node, Point, Widget};
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
pub use iced_core::Radio;
|
||||
|
||||
impl<Message, Renderer> Widget<Message, Renderer> for Radio<Message>
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
Message: Copy + std::fmt::Debug,
|
||||
{
|
||||
fn node(&self, renderer: &mut Renderer) -> Node {
|
||||
renderer.node(&self)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
) {
|
||||
match event {
|
||||
Event::Mouse(mouse::Event::Input {
|
||||
button: mouse::Button::Left,
|
||||
state: ButtonState::Pressed,
|
||||
}) => {
|
||||
if layout.bounds().contains(cursor_position) {
|
||||
messages.push(self.on_click);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
}
|
||||
|
||||
fn hash_layout(&self, state: &mut Hasher) {
|
||||
self.label.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// The renderer of a [`Radio`] button.
|
||||
///
|
||||
/// Your [renderer] will need to implement this trait before being
|
||||
/// able to use a [`Radio`] button in your user interface.
|
||||
///
|
||||
/// [`Radio`]: struct.Radio.html
|
||||
/// [renderer]: ../../renderer/index.html
|
||||
pub trait Renderer {
|
||||
/// Creates a [`Node`] for the provided [`Radio`].
|
||||
///
|
||||
/// [`Node`]: ../../struct.Node.html
|
||||
/// [`Radio`]: struct.Radio.html
|
||||
fn node<Message>(&mut self, radio: &Radio<Message>) -> Node;
|
||||
|
||||
/// Draws a [`Radio`] button.
|
||||
///
|
||||
/// It receives:
|
||||
/// * the current cursor position
|
||||
/// * the bounds of the [`Radio`]
|
||||
/// * the bounds of the label of the [`Radio`]
|
||||
/// * whether the [`Radio`] is selected or not
|
||||
///
|
||||
/// [`Radio`]: struct.Radio.html
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
radio: &Radio<Message>,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor;
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> From<Radio<Message>>
|
||||
for Element<'a, Message, Renderer>
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
Message: 'static + Copy + std::fmt::Debug,
|
||||
{
|
||||
fn from(checkbox: Radio<Message>) -> Element<'a, Message, Renderer> {
|
||||
Element::new(checkbox)
|
||||
}
|
||||
}
|
||||
117
native/src/widget/row.rs
Normal file
117
native/src/widget/row.rs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
use std::hash::Hash;
|
||||
|
||||
use crate::{
|
||||
Element, Event, Hasher, Layout, MouseCursor, Node, Point, Style, Widget,
|
||||
};
|
||||
|
||||
/// A container that distributes its contents horizontally.
|
||||
pub type Row<'a, Message, Renderer> =
|
||||
iced_core::Row<Element<'a, Message, Renderer>>;
|
||||
|
||||
impl<'a, Message, Renderer> Widget<Message, Renderer>
|
||||
for Row<'a, Message, Renderer>
|
||||
{
|
||||
fn node(&self, renderer: &mut Renderer) -> Node {
|
||||
let mut children: Vec<Node> = self
|
||||
.children
|
||||
.iter()
|
||||
.map(|child| {
|
||||
let mut node = child.widget.node(renderer);
|
||||
|
||||
let mut style = node.0.style();
|
||||
style.margin.end =
|
||||
stretch::style::Dimension::Points(f32::from(self.spacing));
|
||||
|
||||
node.0.set_style(style);
|
||||
node
|
||||
})
|
||||
.collect();
|
||||
|
||||
if let Some(node) = children.last_mut() {
|
||||
let mut style = node.0.style();
|
||||
style.margin.end = stretch::style::Dimension::Undefined;
|
||||
|
||||
node.0.set_style(style);
|
||||
}
|
||||
|
||||
let mut style = Style::default()
|
||||
.width(self.width)
|
||||
.height(self.height)
|
||||
.max_width(self.max_width)
|
||||
.max_height(self.max_height)
|
||||
.padding(self.padding)
|
||||
.align_self(self.align_self)
|
||||
.align_items(self.align_items)
|
||||
.justify_content(self.justify_content);
|
||||
|
||||
style.0.flex_direction = stretch::style::FlexDirection::Row;
|
||||
|
||||
Node::with_children(style, children)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
) {
|
||||
self.children.iter_mut().zip(layout.children()).for_each(
|
||||
|(child, layout)| {
|
||||
child
|
||||
.widget
|
||||
.on_event(event, layout, cursor_position, messages)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor {
|
||||
let mut cursor = MouseCursor::OutOfBounds;
|
||||
|
||||
self.children.iter().zip(layout.children()).for_each(
|
||||
|(child, layout)| {
|
||||
let new_cursor =
|
||||
child.widget.draw(renderer, layout, cursor_position);
|
||||
|
||||
if new_cursor != MouseCursor::OutOfBounds {
|
||||
cursor = new_cursor;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
cursor
|
||||
}
|
||||
|
||||
fn hash_layout(&self, state: &mut Hasher) {
|
||||
1.hash(state);
|
||||
self.width.hash(state);
|
||||
self.height.hash(state);
|
||||
self.max_width.hash(state);
|
||||
self.max_height.hash(state);
|
||||
self.align_self.hash(state);
|
||||
self.align_items.hash(state);
|
||||
self.justify_content.hash(state);
|
||||
self.spacing.hash(state);
|
||||
self.spacing.hash(state);
|
||||
|
||||
for child in &self.children {
|
||||
child.widget.hash_layout(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> From<Row<'a, Message, Renderer>>
|
||||
for Element<'a, Message, Renderer>
|
||||
where
|
||||
Renderer: 'a,
|
||||
Message: 'static,
|
||||
{
|
||||
fn from(row: Row<'a, Message, Renderer>) -> Element<'a, Message, Renderer> {
|
||||
Element::new(row)
|
||||
}
|
||||
}
|
||||
126
native/src/widget/slider.rs
Normal file
126
native/src/widget/slider.rs
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
//! Display an interactive selector of a single value from a range of values.
|
||||
//!
|
||||
//! A [`Slider`] has some local [`State`].
|
||||
//!
|
||||
//! [`Slider`]: struct.Slider.html
|
||||
//! [`State`]: struct.State.html
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::input::{mouse, ButtonState};
|
||||
use crate::{Element, Event, Hasher, Layout, MouseCursor, Node, Point, Widget};
|
||||
|
||||
pub use iced_core::slider::*;
|
||||
|
||||
impl<'a, Message, Renderer> Widget<Message, Renderer> for Slider<'a, Message>
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn node(&self, renderer: &mut Renderer) -> Node {
|
||||
renderer.node(&self)
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
messages: &mut Vec<Message>,
|
||||
) {
|
||||
let mut change = || {
|
||||
let bounds = layout.bounds();
|
||||
|
||||
if cursor_position.x <= bounds.x {
|
||||
messages.push((self.on_change)(*self.range.start()));
|
||||
} else if cursor_position.x >= bounds.x + bounds.width {
|
||||
messages.push((self.on_change)(*self.range.end()));
|
||||
} else {
|
||||
let percent = (cursor_position.x - bounds.x) / bounds.width;
|
||||
let value = (self.range.end() - self.range.start()) * percent
|
||||
+ self.range.start();
|
||||
|
||||
messages.push((self.on_change)(value));
|
||||
}
|
||||
};
|
||||
|
||||
match event {
|
||||
Event::Mouse(mouse::Event::Input {
|
||||
button: mouse::Button::Left,
|
||||
state,
|
||||
}) => match state {
|
||||
ButtonState::Pressed => {
|
||||
if layout.bounds().contains(cursor_position) {
|
||||
change();
|
||||
self.state.is_dragging = true;
|
||||
}
|
||||
}
|
||||
ButtonState::Released => {
|
||||
self.state.is_dragging = false;
|
||||
}
|
||||
},
|
||||
Event::Mouse(mouse::Event::CursorMoved { .. }) => {
|
||||
if self.state.is_dragging {
|
||||
change();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor {
|
||||
renderer.draw(&self, layout, cursor_position)
|
||||
}
|
||||
|
||||
fn hash_layout(&self, state: &mut Hasher) {
|
||||
self.width.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// The renderer of a [`Slider`].
|
||||
///
|
||||
/// Your [renderer] will need to implement this trait before being
|
||||
/// able to use a [`Slider`] in your user interface.
|
||||
///
|
||||
/// [`Slider`]: struct.Slider.html
|
||||
/// [renderer]: ../../renderer/index.html
|
||||
pub trait Renderer {
|
||||
/// Creates a [`Node`] for the provided [`Radio`].
|
||||
///
|
||||
/// [`Node`]: ../../struct.Node.html
|
||||
/// [`Radio`]: struct.Radio.html
|
||||
fn node<Message>(&self, slider: &Slider<'_, Message>) -> Node;
|
||||
|
||||
/// Draws a [`Slider`].
|
||||
///
|
||||
/// It receives:
|
||||
/// * the current cursor position
|
||||
/// * the bounds of the [`Slider`]
|
||||
/// * the local state of the [`Slider`]
|
||||
/// * the range of values of the [`Slider`]
|
||||
/// * the current value of the [`Slider`]
|
||||
///
|
||||
/// [`Slider`]: struct.Slider.html
|
||||
/// [`State`]: struct.State.html
|
||||
/// [`Class`]: enum.Class.html
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
slider: &Slider<'_, Message>,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> MouseCursor;
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> From<Slider<'a, Message>>
|
||||
for Element<'a, Message, Renderer>
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
Message: 'static,
|
||||
{
|
||||
fn from(slider: Slider<'a, Message>) -> Element<'a, Message, Renderer> {
|
||||
Element::new(slider)
|
||||
}
|
||||
}
|
||||
77
native/src/widget/text.rs
Normal file
77
native/src/widget/text.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//! Write some text for your users to read.
|
||||
use crate::{Element, Hasher, Layout, MouseCursor, Node, Point, Widget};
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
pub use iced_core::text::*;
|
||||
|
||||
impl<Message, Renderer> Widget<Message, Renderer> for Text
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn node(&self, renderer: &mut Renderer) -> Node {
|
||||
renderer.node(&self)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
layout: Layout<'_>,
|
||||
_cursor_position: Point,
|
||||
) -> MouseCursor {
|
||||
renderer.draw(&self, layout);
|
||||
|
||||
MouseCursor::OutOfBounds
|
||||
}
|
||||
|
||||
fn hash_layout(&self, state: &mut Hasher) {
|
||||
self.content.hash(state);
|
||||
self.size.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// The renderer of a [`Text`] fragment.
|
||||
///
|
||||
/// Your [renderer] will need to implement this trait before being
|
||||
/// able to use [`Text`] in your [`UserInterface`].
|
||||
///
|
||||
/// [`Text`]: struct.Text.html
|
||||
/// [renderer]: ../../renderer/index.html
|
||||
/// [`UserInterface`]: ../../struct.UserInterface.html
|
||||
pub trait Renderer {
|
||||
/// Creates a [`Node`] with the given [`Style`] for the provided [`Text`]
|
||||
/// contents and size.
|
||||
///
|
||||
/// You should probably use [`Node::with_measure`] to allow [`Text`] to
|
||||
/// adapt to the dimensions of its container.
|
||||
///
|
||||
/// [`Node`]: ../../struct.Node.html
|
||||
/// [`Style`]: ../../struct.Style.html
|
||||
/// [`Text`]: struct.Text.html
|
||||
/// [`Node::with_measure`]: ../../struct.Node.html#method.with_measure
|
||||
fn node(&self, text: &Text) -> Node;
|
||||
|
||||
/// Draws a [`Text`] fragment.
|
||||
///
|
||||
/// It receives:
|
||||
/// * the bounds of the [`Text`]
|
||||
/// * the contents of the [`Text`]
|
||||
/// * the size of the [`Text`]
|
||||
/// * the color of the [`Text`]
|
||||
/// * the [`HorizontalAlignment`] of the [`Text`]
|
||||
/// * the [`VerticalAlignment`] of the [`Text`]
|
||||
///
|
||||
/// [`Text`]: struct.Text.html
|
||||
/// [`HorizontalAlignment`]: enum.HorizontalAlignment.html
|
||||
/// [`VerticalAlignment`]: enum.VerticalAlignment.html
|
||||
fn draw(&mut self, text: &Text, layout: Layout<'_>);
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer> From<Text> for Element<'a, Message, Renderer>
|
||||
where
|
||||
Renderer: self::Renderer,
|
||||
{
|
||||
fn from(text: Text) -> Element<'a, Message, Renderer> {
|
||||
Element::new(text)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue