Merge branch 'master' into dev/system-information

This commit is contained in:
Héctor Ramón Jiménez 2022-05-04 17:19:28 +02:00
commit 27fdc70756
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
90 changed files with 1363 additions and 334 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "iced_native"
version = "0.4.0"
version = "0.5.0"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2021"
description = "A renderer-agnostic library for native GUIs"
@ -16,14 +16,14 @@ unicode-segmentation = "1.6"
num-traits = "0.2"
[dependencies.iced_core]
version = "0.4"
version = "0.5"
path = "../core"
[dependencies.iced_futures]
version = "0.3"
version = "0.4"
path = "../futures"
features = ["thread-pool"]
[dependencies.iced_style]
version = "0.3"
version = "0.4"
path = "../style"

View file

@ -11,6 +11,8 @@ use std::fmt;
/// [`Command`]: crate::Command
pub enum Action<T> {
/// Run a [`Future`] to completion.
///
/// [`Future`]: iced_futures::BoxFuture
Future(iced_futures::BoxFuture<T>),
/// Run a clipboard action.
@ -25,6 +27,8 @@ pub enum Action<T> {
impl<T> Action<T> {
/// Applies a transformation to the result of a [`Command`].
///
/// [`Command`]: crate::Command
pub fn map<A>(
self,
f: impl Fn(T) -> A + 'static + MaybeSend + Sync,

View file

@ -5,7 +5,7 @@ use std::hash::{Hash, Hasher as _};
use std::path::PathBuf;
use std::sync::Arc;
/// An [`Image`] handle.
/// A handle of some image data.
#[derive(Debug, Clone)]
pub struct Handle {
id: u64,
@ -79,7 +79,7 @@ impl Hash for Handle {
}
}
/// The data of an [`Image`].
/// The data of a raster image.
#[derive(Clone, Hash)]
pub enum Data {
/// File data

View file

@ -23,8 +23,8 @@
//! - Build a new renderer, see the [renderer] module.
//! - Build a custom widget, start at the [`Widget`] trait.
//!
//! [`iced_core`]: https://github.com/iced-rs/iced/tree/master/core
//! [`iced_winit`]: https://github.com/iced-rs/iced/tree/master/winit
//! [`iced_core`]: https://github.com/iced-rs/iced/tree/0.4/core
//! [`iced_winit`]: https://github.com/iced-rs/iced/tree/0.4/winit
//! [`druid`]: https://github.com/xi-editor/druid
//! [`raw-window-handle`]: https://github.com/rust-windowing/raw-window-handle
//! [renderer]: crate::renderer

View file

@ -63,7 +63,7 @@ where
event::Status::Ignored
}
/// Returns the current [`mouse::Interaction`] of the [`Widget`].
/// Returns the current [`mouse::Interaction`] of the [`Overlay`].
///
/// By default, it returns [`mouse::Interaction::Idle`].
fn mouse_interaction(

View file

@ -1,24 +1,4 @@
//! Write your own renderer.
//!
//! You will need to implement the `Renderer` trait first. It simply contains
//! an `Output` associated type.
//!
//! There is no common trait to draw all the widgets. Instead, every [`Widget`]
//! constrains its generic `Renderer` type as necessary.
//!
//! This approach is flexible and composable. For instance, the
//! [`Text`] widget only needs a [`text::Renderer`] while a [`Checkbox`] widget
//! needs both a [`text::Renderer`] and a [`checkbox::Renderer`], reusing logic.
//!
//! In the end, a __renderer__ satisfying all the constraints is
//! needed to build a [`UserInterface`].
//!
//! [`Widget`]: crate::Widget
//! [`UserInterface`]: crate::UserInterface
//! [`Text`]: crate::widget::Text
//! [`text::Renderer`]: crate::widget::text::Renderer
//! [`Checkbox`]: crate::widget::Checkbox
//! [`checkbox::Renderer`]: crate::widget::checkbox::Renderer
#[cfg(debug_assertions)]
mod null;
#[cfg(debug_assertions)]
@ -27,8 +7,7 @@ pub use null::Null;
use crate::layout;
use crate::{Background, Color, Element, Rectangle, Vector};
/// A component that can take the state of a user interface and produce an
/// output for its users.
/// A component that can be used by widgets to draw themselves on a screen.
pub trait Renderer: Sized {
/// Lays out the elements of a user interface.
///

View file

@ -5,7 +5,7 @@ use std::hash::{Hash, Hasher as _};
use std::path::PathBuf;
use std::sync::Arc;
/// An [`Svg`] handle.
/// A handle of Svg data.
#[derive(Debug, Clone)]
pub struct Handle {
id: u64,
@ -55,7 +55,7 @@ impl Hash for Handle {
}
}
/// The data of an [`Svg`].
/// The data of a vectorial image.
#[derive(Clone, Hash)]
pub enum Data {
/// File data

View file

@ -39,7 +39,7 @@ pub enum Hit {
}
impl Hit {
/// Computes the cursor position corresponding to this [`HitTestResult`] .
/// Computes the cursor position of the [`Hit`] .
pub fn cursor(self) -> usize {
match self {
Self::CharOffset(i) => i,

View file

@ -16,7 +16,7 @@ use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
/// The [`integration` example] uses a [`UserInterface`] to integrate Iced in
/// an existing graphical application.
///
/// [`integration` example]: https://github.com/iced-rs/iced/tree/0.3/examples/integration
/// [`integration` example]: https://github.com/iced-rs/iced/tree/0.4/examples/integration
#[allow(missing_debug_implementations)]
pub struct UserInterface<'a, Message, Renderer> {
root: Element<'a, Message, Renderer>,
@ -264,11 +264,10 @@ where
/// Draws the [`UserInterface`] with the provided [`Renderer`].
///
/// It returns the some [`Renderer::Output`]. You should update the icon of
/// the mouse cursor accordingly in your system.
/// It returns the current [`mouse::Interaction`]. You should update the
/// icon of the mouse cursor accordingly in your system.
///
/// [`Renderer`]: crate::Renderer
/// [`Renderer::Output`]: crate::Renderer::Output
///
/// # Example
/// We can finally draw our [counter](index.html#usage) by

View file

@ -93,12 +93,12 @@ use crate::{Clipboard, Layout, Length, Point, Rectangle, Shell};
/// - [`geometry`], a custom widget showcasing how to draw geometry with the
/// `Mesh2D` primitive in [`iced_wgpu`].
///
/// [examples]: https://github.com/iced-rs/iced/tree/0.3/examples
/// [`bezier_tool`]: https://github.com/iced-rs/iced/tree/0.3/examples/bezier_tool
/// [`custom_widget`]: https://github.com/iced-rs/iced/tree/0.3/examples/custom_widget
/// [`geometry`]: https://github.com/iced-rs/iced/tree/0.3/examples/geometry
/// [examples]: https://github.com/iced-rs/iced/tree/0.4/examples
/// [`bezier_tool`]: https://github.com/iced-rs/iced/tree/0.4/examples/bezier_tool
/// [`custom_widget`]: https://github.com/iced-rs/iced/tree/0.4/examples/custom_widget
/// [`geometry`]: https://github.com/iced-rs/iced/tree/0.4/examples/geometry
/// [`lyon`]: https://github.com/nical/lyon
/// [`iced_wgpu`]: https://github.com/iced-rs/iced/tree/0.3/wgpu
/// [`iced_wgpu`]: https://github.com/iced-rs/iced/tree/0.4/wgpu
pub trait Widget<Message, Renderer>
where
Renderer: crate::Renderer,

View file

@ -102,7 +102,7 @@ impl<'a, Message, Renderer: text::Renderer> Checkbox<'a, Message, Renderer> {
/// Sets the [`Font`] of the text of the [`Checkbox`].
///
/// [`Font`]: crate::widget::text::Renderer::Font
/// [`Font`]: crate::text::Renderer::Font
pub fn font(mut self, font: Renderer::Font) -> Self {
self.font = font;
self

View file

@ -48,7 +48,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
/// Sets the vertical spacing _between_ elements.
///
/// Custom margins per element do not exist in Iced. You should use this
/// Custom margins per element do not exist in iced. You should use this
/// method instead! While less flexible, it helps you keep spacing between
/// elements consistent.
pub fn spacing(mut self, units: u16) -> Self {

View file

@ -6,7 +6,7 @@
//! The [`pane_grid` example] showcases how to use a [`PaneGrid`] with resizing,
//! drag and drop, and hotkey support.
//!
//! [`pane_grid` example]: https://github.com/iced-rs/iced/tree/0.3/examples/pane_grid
//! [`pane_grid` example]: https://github.com/iced-rs/iced/tree/0.4/examples/pane_grid
mod axis;
mod configuration;
mod content;

View file

@ -2,7 +2,7 @@ use crate::widget::pane_grid::Axis;
/// The arrangement of a [`PaneGrid`].
///
/// [`PaneGrid`]: crate::pane_grid::PaneGrid
/// [`PaneGrid`]: crate::widget::PaneGrid
#[derive(Debug, Clone)]
pub enum Configuration<T> {
/// A split of the available space.
@ -21,6 +21,6 @@ pub enum Configuration<T> {
},
/// A [`Pane`].
///
/// [`Pane`]: crate::pane_grid::Pane
/// [`Pane`]: crate::widget::pane_grid::Pane
Pane(T),
}

View file

@ -55,7 +55,7 @@ where
{
/// Draws the [`Content`] with the provided [`Renderer`] and [`Layout`].
///
/// [`Renderer`]: crate::widget::pane_grid::Renderer
/// [`Renderer`]: crate::Renderer
pub fn draw(
&self,
renderer: &mut Renderer,

View file

@ -1,4 +1,6 @@
//! The state of a [`PaneGrid`].
//!
//! [`PaneGrid`]: crate::widget::PaneGrid
use crate::widget::pane_grid::{
Axis, Configuration, Direction, Node, Pane, Split,
};
@ -21,9 +23,13 @@ use std::collections::{BTreeMap, HashMap};
#[derive(Debug, Clone)]
pub struct State<T> {
/// The panes of the [`PaneGrid`].
///
/// [`PaneGrid`]: crate::widget::PaneGrid
pub panes: HashMap<Pane, T>,
/// The internal state of the [`PaneGrid`].
///
/// [`PaneGrid`]: crate::widget::PaneGrid
pub internal: Internal,
pub(super) action: Action,
@ -198,6 +204,8 @@ impl<T> State<T> {
}
/// The internal state of a [`PaneGrid`].
///
/// [`PaneGrid`]: crate::widget::PaneGrid
#[derive(Debug, Clone)]
pub struct Internal {
layout: Node,
@ -207,6 +215,8 @@ pub struct Internal {
impl Internal {
/// Initializes the [`Internal`] state of a [`PaneGrid`] from a
/// [`Configuration`].
///
/// [`PaneGrid`]: crate::widget::PaneGrid
pub fn from_configuration<T>(
panes: &mut HashMap<Pane, T>,
content: Configuration<T>,
@ -248,11 +258,17 @@ impl Internal {
}
/// The current action of a [`PaneGrid`].
///
/// [`PaneGrid`]: crate::widget::PaneGrid
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Action {
/// The [`PaneGrid`] is idle.
///
/// [`PaneGrid`]: crate::widget::PaneGrid
Idle,
/// A [`Pane`] in the [`PaneGrid`] is being dragged.
///
/// [`PaneGrid`]: crate::widget::PaneGrid
Dragging {
/// The [`Pane`] being dragged.
pane: Pane,
@ -260,6 +276,8 @@ pub enum Action {
origin: Point,
},
/// A [`Split`] in the [`PaneGrid`] is being dragged.
///
/// [`PaneGrid`]: crate::widget::PaneGrid
Resizing {
/// The [`Split`] being dragged.
split: Split,
@ -288,6 +306,8 @@ impl Action {
impl Internal {
/// Calculates the current [`Pane`] regions from the [`PaneGrid`] layout.
///
/// [`PaneGrid`]: crate::widget::PaneGrid
pub fn pane_regions(
&self,
spacing: f32,
@ -297,6 +317,8 @@ impl Internal {
}
/// Calculates the current [`Split`] regions from the [`PaneGrid`] layout.
///
/// [`PaneGrid`]: crate::widget::PaneGrid
pub fn split_regions(
&self,
spacing: f32,

View file

@ -82,7 +82,7 @@ where
{
/// Draws the [`TitleBar`] with the provided [`Renderer`] and [`Layout`].
///
/// [`Renderer`]: crate::widget::pane_grid::Renderer
/// [`Renderer`]: crate::Renderer
pub fn draw(
&self,
renderer: &mut Renderer,

View file

@ -402,21 +402,24 @@ pub fn draw<T, Renderer>(
if let Some(label) =
label.as_ref().map(String::as_str).or_else(|| placeholder)
{
let text_size = f32::from(text_size.unwrap_or(renderer.default_size()));
renderer.fill_text(Text {
content: label,
size: f32::from(text_size.unwrap_or(renderer.default_size())),
size: text_size,
font: font.clone(),
color: is_selected
.then(|| style.text_color)
.unwrap_or(style.placeholder_color),
bounds: Rectangle {
x: bounds.x + f32::from(padding.left),
y: bounds.center_y(),
..bounds
y: bounds.center_y() - text_size / 2.0,
width: bounds.width - f32::from(padding.horizontal()),
height: text_size,
},
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
})
vertical_alignment: alignment::Vertical::Top,
});
}
}

View file

@ -48,7 +48,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
/// Sets the horizontal spacing _between_ elements.
///
/// Custom margins per element do not exist in Iced. You should use this
/// Custom margins per element do not exist in iced. You should use this
/// method instead! While less flexible, it helps you keep spacing between
/// elements consistent.
pub fn spacing(mut self, units: u16) -> Self {

View file

@ -59,7 +59,7 @@ impl<Renderer: text::Renderer> Text<Renderer> {
/// Sets the [`Font`] of the [`Text`].
///
/// [`Font`]: Renderer::Font
/// [`Font`]: crate::text::Renderer::Font
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
self.font = font.into();
self
@ -77,7 +77,7 @@ impl<Renderer: text::Renderer> Text<Renderer> {
self
}
/// Sets the [`HorizontalAlignment`] of the [`Text`].
/// Sets the [`alignment::Horizontal`] of the [`Text`].
pub fn horizontal_alignment(
mut self,
alignment: alignment::Horizontal,
@ -86,7 +86,7 @@ impl<Renderer: text::Renderer> Text<Renderer> {
self
}
/// Sets the [`VerticalAlignment`] of the [`Text`].
/// Sets the [`alignment::Vertical`] of the [`Text`].
pub fn vertical_alignment(
mut self,
alignment: alignment::Vertical,

View file

@ -108,10 +108,9 @@ where
self
}
/// Sets the [`Font`] of the [`Text`].
/// Sets the [`Font`] of the [`TextInput`].
///
/// [`Font`]: crate::widget::text::Renderer::Font
/// [`Text`]: crate::widget::Text
/// [`Font`]: crate::text::Renderer::Font
pub fn font(mut self, font: Renderer::Font) -> Self {
self.font = font;
self
@ -157,6 +156,8 @@ where
/// Draws the [`TextInput`] with the given [`Renderer`], overriding its
/// [`Value`] if provided.
///
/// [`Renderer`]: text::Renderer
pub fn draw(
&self,
renderer: &mut Renderer,
@ -570,6 +571,8 @@ where
/// Draws the [`TextInput`] with the given [`Renderer`], overriding its
/// [`Value`] if provided.
///
/// [`Renderer`]: text::Renderer
pub fn draw<Renderer>(
renderer: &mut Renderer,
layout: Layout<'_>,

View file

@ -107,6 +107,8 @@ impl<'a, Message, Renderer: text::Renderer> Toggler<'a, Message, Renderer> {
}
/// Sets the [`Font`] of the text of the [`Toggler`]
///
/// [`Font`]: crate::text::Renderer::Font
pub fn font(mut self, font: Renderer::Font) -> Self {
self.font = font;
self

View file

@ -29,7 +29,7 @@ where
/// The default padding of a [`Tooltip`] drawn by this renderer.
const DEFAULT_PADDING: u16 = 5;
/// Creates an empty [`Tooltip`].
/// Creates a new [`Tooltip`].
///
/// [`Tooltip`]: struct.Tooltip.html
pub fn new(
@ -98,6 +98,117 @@ pub enum Position {
Right,
}
/// Draws a [`Tooltip`].
pub fn draw<Renderer: crate::Renderer>(
renderer: &mut Renderer,
inherited_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
viewport: &Rectangle,
position: Position,
gap: u16,
padding: u16,
style_sheet: &dyn container::StyleSheet,
layout_text: impl FnOnce(&Renderer, &layout::Limits) -> layout::Node,
draw_text: impl FnOnce(
&mut Renderer,
&renderer::Style,
Layout<'_>,
Point,
&Rectangle,
),
) {
let bounds = layout.bounds();
if bounds.contains(cursor_position) {
let gap = f32::from(gap);
let style = style_sheet.style();
let defaults = renderer::Style {
text_color: style.text_color.unwrap_or(inherited_style.text_color),
};
let text_layout = layout_text(
renderer,
&layout::Limits::new(Size::ZERO, viewport.size())
.pad(Padding::new(padding)),
);
let padding = f32::from(padding);
let text_bounds = text_layout.bounds();
let x_center = bounds.x + (bounds.width - text_bounds.width) / 2.0;
let y_center = bounds.y + (bounds.height - text_bounds.height) / 2.0;
let mut tooltip_bounds = {
let offset = match position {
Position::Top => Vector::new(
x_center,
bounds.y - text_bounds.height - gap - padding,
),
Position::Bottom => Vector::new(
x_center,
bounds.y + bounds.height + gap + padding,
),
Position::Left => Vector::new(
bounds.x - text_bounds.width - gap - padding,
y_center,
),
Position::Right => Vector::new(
bounds.x + bounds.width + gap + padding,
y_center,
),
Position::FollowCursor => Vector::new(
cursor_position.x,
cursor_position.y - text_bounds.height,
),
};
Rectangle {
x: offset.x - padding,
y: offset.y - padding,
width: text_bounds.width + padding * 2.0,
height: text_bounds.height + padding * 2.0,
}
};
if tooltip_bounds.x < viewport.x {
tooltip_bounds.x = viewport.x;
} else if viewport.x + viewport.width
< tooltip_bounds.x + tooltip_bounds.width
{
tooltip_bounds.x =
viewport.x + viewport.width - tooltip_bounds.width;
}
if tooltip_bounds.y < viewport.y {
tooltip_bounds.y = viewport.y;
} else if viewport.y + viewport.height
< tooltip_bounds.y + tooltip_bounds.height
{
tooltip_bounds.y =
viewport.y + viewport.height - tooltip_bounds.height;
}
renderer.with_layer(*viewport, |renderer| {
container::draw_background(renderer, &style, tooltip_bounds);
draw_text(
renderer,
&defaults,
Layout::with_offset(
Vector::new(
tooltip_bounds.x + padding,
tooltip_bounds.y + padding,
),
&text_layout,
),
cursor_position,
viewport,
)
});
}
}
impl<'a, Message, Renderer> Widget<Message, Renderer>
for Tooltip<'a, Message, Renderer>
where
@ -169,100 +280,32 @@ where
viewport,
);
let bounds = layout.bounds();
if bounds.contains(cursor_position) {
let gap = f32::from(self.gap);
let style = self.style_sheet.style();
let defaults = renderer::Style {
text_color: style
.text_color
.unwrap_or(inherited_style.text_color),
};
let text_layout = Widget::<(), Renderer>::layout(
&self.tooltip,
renderer,
&layout::Limits::new(Size::ZERO, viewport.size())
.pad(Padding::new(self.padding)),
);
let padding = f32::from(self.padding);
let text_bounds = text_layout.bounds();
let x_center = bounds.x + (bounds.width - text_bounds.width) / 2.0;
let y_center =
bounds.y + (bounds.height - text_bounds.height) / 2.0;
let mut tooltip_bounds = {
let offset = match self.position {
Position::Top => Vector::new(
x_center,
bounds.y - text_bounds.height - gap - padding,
),
Position::Bottom => Vector::new(
x_center,
bounds.y + bounds.height + gap + padding,
),
Position::Left => Vector::new(
bounds.x - text_bounds.width - gap - padding,
y_center,
),
Position::Right => Vector::new(
bounds.x + bounds.width + gap + padding,
y_center,
),
Position::FollowCursor => Vector::new(
cursor_position.x,
cursor_position.y - text_bounds.height,
),
};
Rectangle {
x: offset.x - padding,
y: offset.y - padding,
width: text_bounds.width + padding * 2.0,
height: text_bounds.height + padding * 2.0,
}
};
if tooltip_bounds.x < viewport.x {
tooltip_bounds.x = viewport.x;
} else if viewport.x + viewport.width
< tooltip_bounds.x + tooltip_bounds.width
{
tooltip_bounds.x =
viewport.x + viewport.width - tooltip_bounds.width;
}
if tooltip_bounds.y < viewport.y {
tooltip_bounds.y = viewport.y;
} else if viewport.y + viewport.height
< tooltip_bounds.y + tooltip_bounds.height
{
tooltip_bounds.y =
viewport.y + viewport.height - tooltip_bounds.height;
}
renderer.with_layer(*viewport, |renderer| {
container::draw_background(renderer, &style, tooltip_bounds);
let tooltip = &self.tooltip;
draw(
renderer,
inherited_style,
layout,
cursor_position,
viewport,
self.position,
self.gap,
self.padding,
self.style_sheet.as_ref(),
|renderer, limits| {
Widget::<(), Renderer>::layout(tooltip, renderer, limits)
},
|renderer, defaults, layout, cursor_position, viewport| {
Widget::<(), Renderer>::draw(
&self.tooltip,
tooltip,
renderer,
&defaults,
Layout::with_offset(
Vector::new(
tooltip_bounds.x + padding,
tooltip_bounds.y + padding,
),
&text_layout,
),
defaults,
layout,
cursor_position,
viewport,
);
});
}
},
)
}
}
@ -273,8 +316,8 @@ where
Message: 'a,
{
fn from(
column: Tooltip<'a, Message, Renderer>,
tooltip: Tooltip<'a, Message, Renderer>,
) -> Element<'a, Message, Renderer> {
Element::new(column)
Element::new(tooltip)
}
}