summaryrefslogtreecommitdiffstats
path: root/native/src/widget
diff options
context:
space:
mode:
authorLibravatar Bingus <shankern@protonmail.com>2023-02-15 14:55:02 -0800
committerLibravatar Bingus <shankern@protonmail.com>2023-02-15 14:55:02 -0800
commit63fb608d8bea8a653bf011f5f9cffc88525576e0 (patch)
tree938c15b85fd9d27ee3a82806cf83bc211e7b94dd /native/src/widget
parent64e0e817c27d720dc954ee94de58ded35b3f9f9a (diff)
parent0cb72f69716adc82ad85a0ee7120edb6e653b0c0 (diff)
downloadiced-63fb608d8bea8a653bf011f5f9cffc88525576e0.tar.gz
iced-63fb608d8bea8a653bf011f5f9cffc88525576e0.tar.bz2
iced-63fb608d8bea8a653bf011f5f9cffc88525576e0.zip
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
Diffstat (limited to 'native/src/widget')
-rw-r--r--native/src/widget/action.rs12
-rw-r--r--native/src/widget/image.rs68
-rw-r--r--native/src/widget/operation.rs2
-rw-r--r--native/src/widget/pane_grid.rs13
-rw-r--r--native/src/widget/pick_list.rs131
-rw-r--r--native/src/widget/text_input.rs2
6 files changed, 130 insertions, 98 deletions
diff --git a/native/src/widget/action.rs b/native/src/widget/action.rs
index 1e21ff38..3f1b6b6c 100644
--- a/native/src/widget/action.rs
+++ b/native/src/widget/action.rs
@@ -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);
}
diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs
index 8bd8ca1e..3ff06a76 100644
--- a/native/src/widget/image.rs
+++ b/native/src/widget/image.rs
@@ -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)
}
}
diff --git a/native/src/widget/operation.rs b/native/src/widget/operation.rs
index 73e6a6b0..53688a21 100644
--- a/native/src/widget/operation.rs
+++ b/native/src/widget/operation.rs
@@ -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(...)"),
}
}
diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs
index 8dbd1825..eb04c0ba 100644
--- a/native/src/widget/pane_grid.rs
+++ b/native/src/widget/pane_grid.rs
@@ -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())
}
}
diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs
index c2853314..b1cdfad4 100644
--- a/native/src/widget/pick_list.rs
+++ b/native/src/widget/pick_list.rs
@@ -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,
diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs
index a62d9f35..bf87e817 100644
--- a/native/src/widget/text_input.rs
+++ b/native/src/widget/text_input.rs
@@ -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));