Merge remote-tracking branch 'origin/master' into feat/multi-window-support
# Conflicts: # native/src/command/action.rs # native/src/window/action.rs # winit/src/window.rs
This commit is contained in:
commit
63fb608d8b
55 changed files with 1218 additions and 224 deletions
|
|
@ -1,4 +1,6 @@
|
|||
use crate::widget::operation::{self, Focusable, Operation, Scrollable};
|
||||
use crate::widget::operation::{
|
||||
self, Focusable, Operation, Scrollable, TextInput,
|
||||
};
|
||||
use crate::widget::Id;
|
||||
|
||||
use iced_futures::MaybeSend;
|
||||
|
|
@ -86,6 +88,14 @@ where
|
|||
self.operation.focusable(state, id);
|
||||
}
|
||||
|
||||
fn text_input(
|
||||
&mut self,
|
||||
state: &mut dyn TextInput,
|
||||
id: Option<&Id>,
|
||||
) {
|
||||
self.operation.text_input(state, id);
|
||||
}
|
||||
|
||||
fn custom(&mut self, state: &mut dyn Any, id: Option<&Id>) {
|
||||
self.operation.custom(state, id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,45 @@ where
|
|||
layout::Node::new(final_size)
|
||||
}
|
||||
|
||||
/// Draws an [`Image`]
|
||||
pub fn draw<Renderer, Handle>(
|
||||
renderer: &mut Renderer,
|
||||
layout: Layout<'_>,
|
||||
handle: &Handle,
|
||||
content_fit: ContentFit,
|
||||
) where
|
||||
Renderer: image::Renderer<Handle = Handle>,
|
||||
Handle: Clone + Hash,
|
||||
{
|
||||
let Size { width, height } = renderer.dimensions(handle);
|
||||
let image_size = Size::new(width as f32, height as f32);
|
||||
|
||||
let bounds = layout.bounds();
|
||||
let adjusted_fit = content_fit.fit(image_size, bounds.size());
|
||||
|
||||
let render = |renderer: &mut Renderer| {
|
||||
let offset = Vector::new(
|
||||
(bounds.width - adjusted_fit.width).max(0.0) / 2.0,
|
||||
(bounds.height - adjusted_fit.height).max(0.0) / 2.0,
|
||||
);
|
||||
|
||||
let drawing_bounds = Rectangle {
|
||||
width: adjusted_fit.width,
|
||||
height: adjusted_fit.height,
|
||||
..bounds
|
||||
};
|
||||
|
||||
renderer.draw(handle.clone(), drawing_bounds + offset)
|
||||
};
|
||||
|
||||
if adjusted_fit.width > bounds.width || adjusted_fit.height > bounds.height
|
||||
{
|
||||
renderer.with_layer(bounds, render);
|
||||
} else {
|
||||
render(renderer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Message, Renderer, Handle> Widget<Message, Renderer> for Image<Handle>
|
||||
where
|
||||
Renderer: image::Renderer<Handle = Handle>,
|
||||
|
|
@ -149,34 +188,7 @@ where
|
|||
_cursor_position: Point,
|
||||
_viewport: &Rectangle,
|
||||
) {
|
||||
let Size { width, height } = renderer.dimensions(&self.handle);
|
||||
let image_size = Size::new(width as f32, height as f32);
|
||||
|
||||
let bounds = layout.bounds();
|
||||
let adjusted_fit = self.content_fit.fit(image_size, bounds.size());
|
||||
|
||||
let render = |renderer: &mut Renderer| {
|
||||
let offset = Vector::new(
|
||||
(bounds.width - adjusted_fit.width).max(0.0) / 2.0,
|
||||
(bounds.height - adjusted_fit.height).max(0.0) / 2.0,
|
||||
);
|
||||
|
||||
let drawing_bounds = Rectangle {
|
||||
width: adjusted_fit.width,
|
||||
height: adjusted_fit.height,
|
||||
..bounds
|
||||
};
|
||||
|
||||
renderer.draw(self.handle.clone(), drawing_bounds + offset)
|
||||
};
|
||||
|
||||
if adjusted_fit.width > bounds.width
|
||||
|| adjusted_fit.height > bounds.height
|
||||
{
|
||||
renderer.with_layer(bounds, render);
|
||||
} else {
|
||||
render(renderer)
|
||||
}
|
||||
draw(renderer, layout, &self.handle, self.content_fit)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ where
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::None => write!(f, "Outcome::None"),
|
||||
Self::Some(output) => write!(f, "Outcome::Some({:?})", output),
|
||||
Self::Some(output) => write!(f, "Outcome::Some({output:?})"),
|
||||
Self::Chain(_) => write!(f, "Outcome::Chain(...)"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ pub use iced_style::pane_grid::{Line, StyleSheet};
|
|||
use crate::event::{self, Event};
|
||||
use crate::layout;
|
||||
use crate::mouse;
|
||||
use crate::overlay;
|
||||
use crate::overlay::{self, Group};
|
||||
use crate::renderer;
|
||||
use crate::touch;
|
||||
use crate::widget;
|
||||
|
|
@ -450,14 +450,17 @@ where
|
|||
layout: Layout<'_>,
|
||||
renderer: &Renderer,
|
||||
) -> Option<overlay::Element<'_, Message, Renderer>> {
|
||||
self.contents
|
||||
let children = self
|
||||
.contents
|
||||
.iter_mut()
|
||||
.zip(&mut tree.children)
|
||||
.zip(layout.children())
|
||||
.filter_map(|(((_, pane), tree), layout)| {
|
||||
pane.overlay(tree, layout, renderer)
|
||||
.filter_map(|(((_, content), state), layout)| {
|
||||
content.overlay(state, layout, renderer)
|
||||
})
|
||||
.next()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(!children.is_empty()).then(|| Group::with_children(children).overlay())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,60 +20,6 @@ use std::borrow::Cow;
|
|||
|
||||
pub use iced_style::pick_list::{Appearance, StyleSheet};
|
||||
|
||||
/// The handle to the right side of the [`PickList`].
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Handle<Renderer>
|
||||
where
|
||||
Renderer: text::Renderer,
|
||||
{
|
||||
/// Displays an arrow icon (▼).
|
||||
///
|
||||
/// This is the default.
|
||||
Arrow {
|
||||
/// Font size of the content.
|
||||
size: Option<u16>,
|
||||
},
|
||||
/// A custom handle.
|
||||
Custom {
|
||||
/// Font that will be used to display the `text`,
|
||||
font: Renderer::Font,
|
||||
/// Text that will be shown.
|
||||
text: String,
|
||||
/// Font size of the content.
|
||||
size: Option<u16>,
|
||||
},
|
||||
/// No handle will be shown.
|
||||
None,
|
||||
}
|
||||
|
||||
impl<Renderer> Default for Handle<Renderer>
|
||||
where
|
||||
Renderer: text::Renderer,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::Arrow { size: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Renderer> Handle<Renderer>
|
||||
where
|
||||
Renderer: text::Renderer,
|
||||
{
|
||||
fn content(&self) -> Option<(Renderer::Font, String, Option<u16>)> {
|
||||
match self {
|
||||
Self::Arrow { size } => Some((
|
||||
Renderer::ICON_FONT,
|
||||
Renderer::ARROW_DOWN_ICON.to_string(),
|
||||
*size,
|
||||
)),
|
||||
Self::Custom { font, text, size } => {
|
||||
Some((font.clone(), text.clone(), *size))
|
||||
}
|
||||
Self::None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A widget for selecting a single value from a list of options.
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct PickList<'a, T, Message, Renderer>
|
||||
|
|
@ -90,7 +36,7 @@ where
|
|||
padding: Padding,
|
||||
text_size: Option<u16>,
|
||||
font: Renderer::Font,
|
||||
handle: Handle<Renderer>,
|
||||
handle: Handle<Renderer::Font>,
|
||||
style: <Renderer::Theme as StyleSheet>::Style,
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +107,7 @@ where
|
|||
}
|
||||
|
||||
/// Sets the [`Handle`] of the [`PickList`].
|
||||
pub fn handle(mut self, handle: Handle<Renderer>) -> Self {
|
||||
pub fn handle(mut self, handle: Handle<Renderer::Font>) -> Self {
|
||||
self.handle = handle;
|
||||
self
|
||||
}
|
||||
|
|
@ -258,7 +204,7 @@ where
|
|||
|
||||
fn draw(
|
||||
&self,
|
||||
_tree: &Tree,
|
||||
tree: &Tree,
|
||||
renderer: &mut Renderer,
|
||||
theme: &Renderer::Theme,
|
||||
_style: &renderer::Style,
|
||||
|
|
@ -278,6 +224,7 @@ where
|
|||
self.selected.as_ref(),
|
||||
&self.handle,
|
||||
&self.style,
|
||||
|| tree.state.downcast_ref::<State<T>>(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -349,6 +296,46 @@ impl<T> Default for State<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The handle to the right side of the [`PickList`].
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Handle<Font> {
|
||||
/// Displays an arrow icon (▼).
|
||||
///
|
||||
/// This is the default.
|
||||
Arrow {
|
||||
/// Font size of the content.
|
||||
size: Option<u16>,
|
||||
},
|
||||
/// A custom static handle.
|
||||
Static(Icon<Font>),
|
||||
/// A custom dynamic handle.
|
||||
Dynamic {
|
||||
/// The [`Icon`] used when [`PickList`] is closed.
|
||||
closed: Icon<Font>,
|
||||
/// The [`Icon`] used when [`PickList`] is open.
|
||||
open: Icon<Font>,
|
||||
},
|
||||
/// No handle will be shown.
|
||||
None,
|
||||
}
|
||||
|
||||
impl<Font> Default for Handle<Font> {
|
||||
fn default() -> Self {
|
||||
Self::Arrow { size: None }
|
||||
}
|
||||
}
|
||||
|
||||
/// The icon of a [`Handle`].
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Icon<Font> {
|
||||
/// Font that will be used to display the `code_point`,
|
||||
pub font: Font,
|
||||
/// The unicode code point that will be used as the icon.
|
||||
pub code_point: char,
|
||||
/// Font size of the content.
|
||||
pub size: Option<u16>,
|
||||
}
|
||||
|
||||
/// Computes the layout of a [`PickList`].
|
||||
pub fn layout<Renderer, T>(
|
||||
renderer: &Renderer,
|
||||
|
|
@ -568,7 +555,7 @@ where
|
|||
}
|
||||
|
||||
/// Draws a [`PickList`].
|
||||
pub fn draw<T, Renderer>(
|
||||
pub fn draw<'a, T, Renderer>(
|
||||
renderer: &mut Renderer,
|
||||
theme: &Renderer::Theme,
|
||||
layout: Layout<'_>,
|
||||
|
|
@ -578,12 +565,13 @@ pub fn draw<T, Renderer>(
|
|||
font: &Renderer::Font,
|
||||
placeholder: Option<&str>,
|
||||
selected: Option<&T>,
|
||||
handle: &Handle<Renderer>,
|
||||
handle: &Handle<Renderer::Font>,
|
||||
style: &<Renderer::Theme as StyleSheet>::Style,
|
||||
state: impl FnOnce() -> &'a State<T>,
|
||||
) where
|
||||
Renderer: text::Renderer,
|
||||
Renderer::Theme: StyleSheet,
|
||||
T: ToString,
|
||||
T: ToString + 'a,
|
||||
{
|
||||
let bounds = layout.bounds();
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
|
|
@ -605,11 +593,30 @@ pub fn draw<T, Renderer>(
|
|||
style.background,
|
||||
);
|
||||
|
||||
if let Some((font, text, size)) = handle.content() {
|
||||
let handle = match handle {
|
||||
Handle::Arrow { size } => {
|
||||
Some((Renderer::ICON_FONT, Renderer::ARROW_DOWN_ICON, *size))
|
||||
}
|
||||
Handle::Static(Icon {
|
||||
font,
|
||||
code_point,
|
||||
size,
|
||||
}) => Some((font.clone(), *code_point, *size)),
|
||||
Handle::Dynamic { open, closed } => {
|
||||
if state().is_open {
|
||||
Some((open.font.clone(), open.code_point, open.size))
|
||||
} else {
|
||||
Some((closed.font.clone(), closed.code_point, closed.size))
|
||||
}
|
||||
}
|
||||
Handle::None => None,
|
||||
};
|
||||
|
||||
if let Some((font, code_point, size)) = handle {
|
||||
let size = f32::from(size.unwrap_or_else(|| renderer.default_size()));
|
||||
|
||||
renderer.fill_text(Text {
|
||||
content: &text,
|
||||
content: &code_point.to_string(),
|
||||
size,
|
||||
font,
|
||||
color: style.handle_color,
|
||||
|
|
|
|||
|
|
@ -389,8 +389,8 @@ where
|
|||
let padding = padding.fit(Size::ZERO, limits.max());
|
||||
|
||||
let limits = limits
|
||||
.pad(padding)
|
||||
.width(width)
|
||||
.pad(padding)
|
||||
.height(Length::Units(text_size));
|
||||
|
||||
let mut text = layout::Node::new(limits.resolve(Size::ZERO));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue