Files
ARCADIA-Studio/crates/vendor/iced_widget/src/responsive.rs
T
sorokin.oleg.edu 9fd76aef3a Add current-draft diagnostic underlines and passive hover
Preserve raw include diagnostic provenance and derive bands from the existing shaped editor. Retain deferred tooltip paragraphs through rendering. Include source, regression, failure and native-trial evidence; corrected native acceptance remains pending.
2026-09-13 01:43:22 -07:00

208 lines
5.2 KiB
Rust

use crate::core::layout::{self, Layout};
use crate::core::mouse;
use crate::core::overlay;
use crate::core::renderer;
use crate::core::widget;
use crate::core::widget::Tree;
use crate::core::{
self, Clipboard, Element, Event, Length, Rectangle, Shell, Size, Vector,
Widget,
};
use crate::space;
/// A widget that is aware of its dimensions.
///
/// A [`Responsive`] widget will always try to fill all the available space of
/// its parent.
pub struct Responsive<
'a,
Message,
Theme = crate::Theme,
Renderer = crate::Renderer,
> {
view: Box<dyn Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a>,
width: Length,
height: Length,
content: Element<'a, Message, Theme, Renderer>,
}
impl<'a, Message, Theme, Renderer> Responsive<'a, Message, Theme, Renderer>
where
Renderer: core::Renderer,
{
/// Creates a new [`Responsive`] widget with a closure that produces its
/// contents.
///
/// The `view` closure will receive the maximum available space for
/// the [`Responsive`] during layout. You can use this [`Size`] to
/// conditionally build the contents.
pub fn new(
view: impl Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a,
) -> Self {
Self {
view: Box::new(view),
width: Length::Fill,
height: Length::Fill,
content: Element::new(space()),
}
}
/// Sets the width of the [`Responsive`].
pub fn width(mut self, width: impl Into<Length>) -> Self {
self.width = width.into();
self
}
/// Sets the height of the [`Responsive`].
pub fn height(mut self, height: impl Into<Length>) -> Self {
self.height = height.into();
self
}
}
impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
for Responsive<'_, Message, Theme, Renderer>
where
Renderer: core::Renderer,
{
fn diff(&self, _tree: &mut Tree) {
// Diff is deferred to layout
}
fn size(&self) -> Size<Length> {
Size {
width: self.width,
height: self.height,
}
}
fn layout(
&mut self,
tree: &mut Tree,
renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
let limits = limits.width(self.width).height(self.height);
let size = limits.max();
self.content = (self.view)(size);
tree.diff_children(std::slice::from_ref(&self.content));
let node = self.content.as_widget_mut().layout(
&mut tree.children[0],
renderer,
&limits.loose(),
);
let size = limits.resolve(self.width, self.height, node.size());
layout::Node::with_children(size, vec![node])
}
fn update(
&mut self,
tree: &mut Tree,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
viewport: &Rectangle,
) {
self.content.as_widget_mut().update(
&mut tree.children[0],
event,
layout.children().next().unwrap(),
cursor,
renderer,
clipboard,
shell,
viewport,
);
}
fn draw(
&self,
tree: &Tree,
renderer: &mut Renderer,
theme: &Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor: mouse::Cursor,
viewport: &Rectangle,
) {
self.content.as_widget().draw(
&tree.children[0],
renderer,
theme,
style,
layout.children().next().unwrap(),
cursor,
viewport,
);
}
fn mouse_interaction(
&self,
tree: &Tree,
layout: Layout<'_>,
cursor: mouse::Cursor,
viewport: &Rectangle,
renderer: &Renderer,
) -> mouse::Interaction {
self.content.as_widget().mouse_interaction(
&tree.children[0],
layout.children().next().unwrap(),
cursor,
viewport,
renderer,
)
}
fn operate(
&mut self,
tree: &mut Tree,
layout: Layout<'_>,
renderer: &Renderer,
operation: &mut dyn widget::Operation,
) {
self.content.as_widget_mut().operate(
&mut tree.children[0],
layout.children().next().unwrap(),
renderer,
operation,
);
}
fn overlay<'a>(
&'a mut self,
tree: &'a mut Tree,
layout: Layout<'a>,
renderer: &Renderer,
viewport: &Rectangle,
translation: Vector,
) -> Option<overlay::Element<'a, Message, Theme, Renderer>> {
self.content.as_widget_mut().overlay(
&mut tree.children[0],
layout.children().next().unwrap(),
renderer,
viewport,
translation,
)
}
}
impl<'a, Message, Theme, Renderer>
From<Responsive<'a, Message, Theme, Renderer>>
for Element<'a, Message, Theme, Renderer>
where
Message: 'a,
Theme: 'a,
Renderer: core::Renderer + 'a,
{
fn from(responsive: Responsive<'a, Message, Theme, Renderer>) -> Self {
Self::new(responsive)
}
}