Use nightly feature `arbitrary_self_types`

This commit is contained in:
Olivier FAURE 2025-01-27 12:23:23 +01:00
parent d77b31b892
commit f0d715802b
20 changed files with 376 additions and 372 deletions

View File

@ -1,6 +1,8 @@
// Copyright 2018 the Xilem Authors and the Druid Authors
// SPDX-License-Identifier: Apache-2.0
use std::ops::Receiver;
use crate::core::{FromDynWidget, MutateCtx, Widget};
use crate::kurbo::Affine;
@ -28,6 +30,10 @@ pub struct WidgetMut<'a, W: Widget + ?Sized> {
pub widget: &'a mut W,
}
impl<W: Widget + ?Sized> Receiver for WidgetMut<'_, W> {
type Target = W;
}
impl<W: Widget + ?Sized> Drop for WidgetMut<'_, W> {
fn drop(&mut self) {
// If this `WidgetMut` is a reborrow, a parent non-reborrow `WidgetMut`

View File

@ -144,6 +144,7 @@
reason = "Potentially controversial code style"
)]
#![expect(clippy::single_match, reason = "General policy not decided")]
#![feature(arbitrary_self_types)]
// TODO - Add logo

View File

@ -75,12 +75,12 @@ impl Button {
// --- MARK: WIDGETMUT ---
impl Button {
/// Set the text.
pub fn set_text(this: &mut WidgetMut<'_, Self>, new_text: impl Into<ArcStr>) {
Label::set_text(&mut Self::label_mut(this), new_text);
pub fn set_text(self: &mut WidgetMut<'_, Self>, new_text: impl Into<ArcStr>) {
Label::set_text(&mut self.label_mut(), new_text);
}
pub fn label_mut<'t>(this: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, Label> {
this.ctx.get_mut(&mut this.widget.label)
pub fn label_mut<'t>(self: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, Label> {
self.ctx.get_mut(&mut self.widget.label)
}
}

View File

@ -46,21 +46,21 @@ impl Checkbox {
// --- MARK: WIDGETMUT ---
impl Checkbox {
pub fn set_checked(this: &mut WidgetMut<'_, Self>, checked: bool) {
this.widget.checked = checked;
pub fn set_checked(self: &mut WidgetMut<'_, Self>, checked: bool) {
self.widget.checked = checked;
// Checked state impacts appearance and accessibility node
this.ctx.request_render();
self.ctx.request_render();
}
/// Set the text.
///
/// We enforce this to be an `ArcStr` to make the allocation explicit.
pub fn set_text(this: &mut WidgetMut<'_, Self>, new_text: ArcStr) {
Label::set_text(&mut Self::label_mut(this), new_text);
pub fn set_text(self: &mut WidgetMut<'_, Self>, new_text: ArcStr) {
Label::set_text(&mut self.label_mut(), new_text);
}
pub fn label_mut<'t>(this: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, Label> {
this.ctx.get_mut(&mut this.widget.label)
pub fn label_mut<'t>(self: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, Label> {
self.ctx.get_mut(&mut self.widget.label)
}
}
@ -288,15 +288,12 @@ mod tests {
harness.edit_root_widget(|mut checkbox| {
let mut checkbox = checkbox.downcast::<Checkbox>();
Checkbox::set_checked(&mut checkbox, true);
Checkbox::set_text(
&mut checkbox,
ArcStr::from("The quick brown fox jumps over the lazy dog"),
);
checkbox.set_checked(true);
checkbox.set_text("The quick brown fox jumps over the lazy dog".into());
let mut label = Checkbox::label_mut(&mut checkbox);
Label::set_brush(&mut label, PRIMARY_LIGHT);
Label::insert_style(&mut label, StyleProperty::FontSize(20.0));
let mut label = checkbox.label_mut();
label.set_brush(PRIMARY_LIGHT);
label.insert_style(StyleProperty::FontSize(20.0));
});
harness.render()

View File

@ -305,28 +305,28 @@ impl Flex {
// --- MARK: WIDGETMUT---
impl Flex {
/// Set the flex direction (see [`Axis`]).
pub fn set_direction(this: &mut WidgetMut<'_, Self>, direction: Axis) {
this.widget.direction = direction;
this.ctx.request_layout();
pub fn set_direction(self: &mut WidgetMut<'_, Self>, direction: Axis) {
self.widget.direction = direction;
self.ctx.request_layout();
}
/// Set the childrens' [`CrossAxisAlignment`].
pub fn set_cross_axis_alignment(this: &mut WidgetMut<'_, Self>, alignment: CrossAxisAlignment) {
this.widget.cross_alignment = alignment;
this.ctx.request_layout();
pub fn set_cross_axis_alignment(self: &mut WidgetMut<'_, Self>, alignment: CrossAxisAlignment) {
self.widget.cross_alignment = alignment;
self.ctx.request_layout();
}
/// Set the childrens' [`MainAxisAlignment`].
pub fn set_main_axis_alignment(this: &mut WidgetMut<'_, Self>, alignment: MainAxisAlignment) {
this.widget.main_alignment = alignment;
this.ctx.request_layout();
pub fn set_main_axis_alignment(self: &mut WidgetMut<'_, Self>, alignment: MainAxisAlignment) {
self.widget.main_alignment = alignment;
self.ctx.request_layout();
}
/// Set whether the container must expand to fill the available space on
/// its main axis.
pub fn set_must_fill_main_axis(this: &mut WidgetMut<'_, Self>, fill: bool) {
this.widget.fill_major_axis = fill;
this.ctx.request_layout();
pub fn set_must_fill_main_axis(self: &mut WidgetMut<'_, Self>, fill: bool) {
self.widget.fill_major_axis = fill;
self.ctx.request_layout();
}
/// Set the spacing along the major axis between any two elements in logical pixels.
@ -341,13 +341,13 @@ impl Flex {
/// If `gap` is not a non-negative finite value.
///
/// See also [`use_default_gap`](Self::use_default_gap).
pub fn set_gap(this: &mut WidgetMut<'_, Self>, gap: f64) {
pub fn set_gap(self: &mut WidgetMut<'_, Self>, gap: f64) {
if gap.is_finite() && gap >= 0.0 {
this.widget.gap = Some(gap);
self.widget.gap = Some(gap);
} else {
panic!("Invalid `gap` {gap}, expected a non-negative finite value.")
}
this.ctx.request_layout();
self.ctx.request_layout();
}
/// Use the default gap value.
@ -359,18 +359,18 @@ impl Flex {
///
/// [`WIDGET_PADDING_VERTICAL`]: crate::theme::WIDGET_PADDING_VERTICAL
/// [`WIDGET_PADDING_HORIZONTAL`]: crate::theme::WIDGET_PADDING_VERTICAL
pub fn use_default_gap(this: &mut WidgetMut<'_, Self>) {
this.widget.gap = None;
this.ctx.request_layout();
pub fn use_default_gap(self: &mut WidgetMut<'_, Self>) {
self.widget.gap = None;
self.ctx.request_layout();
}
/// Equivalent to [`set_gap`](Self::set_gap) if `gap` is `Some`, or
/// [`use_default_gap`](Self::use_default_gap) otherwise.
///
/// Does not perform validation of the provided value.
pub fn set_raw_gap(this: &mut WidgetMut<'_, Self>, gap: Option<f64>) {
this.widget.gap = gap;
this.ctx.request_layout();
pub fn set_raw_gap(self: &mut WidgetMut<'_, Self>, gap: Option<f64>) {
self.widget.gap = gap;
self.ctx.request_layout();
}
/// Add a non-flex child widget.
@ -378,45 +378,45 @@ impl Flex {
/// See also [`with_child`].
///
/// [`with_child`]: Flex::with_child
pub fn add_child(this: &mut WidgetMut<'_, Self>, child: impl Widget) {
pub fn add_child(self: &mut WidgetMut<'_, Self>, child: impl Widget) {
let child = Child::Fixed {
widget: WidgetPod::new(child).erased(),
alignment: None,
};
this.widget.children.push(child);
this.ctx.children_changed();
self.widget.children.push(child);
self.ctx.children_changed();
}
pub fn add_child_id(this: &mut WidgetMut<'_, Self>, child: impl Widget, id: WidgetId) {
pub fn add_child_id(self: &mut WidgetMut<'_, Self>, child: impl Widget, id: WidgetId) {
let child = Child::Fixed {
widget: WidgetPod::new_with_id(child, id).erased(),
alignment: None,
};
this.widget.children.push(child);
this.ctx.children_changed();
self.widget.children.push(child);
self.ctx.children_changed();
}
/// Add a flexible child widget.
pub fn add_flex_child(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
child: impl Widget,
params: impl Into<FlexParams>,
) {
let params = params.into();
let child = new_flex_child(params, WidgetPod::new(child).erased());
this.widget.children.push(child);
this.ctx.children_changed();
self.widget.children.push(child);
self.ctx.children_changed();
}
/// Add a spacer widget with a standard size.
///
/// The actual value of this spacer depends on whether this container is
/// a row or column, as well as theme settings.
pub fn add_default_spacer(this: &mut WidgetMut<'_, Self>) {
let key = axis_default_spacer(this.widget.direction);
Self::add_spacer(this, key);
this.ctx.request_layout();
pub fn add_default_spacer(self: &mut WidgetMut<'_, Self>) {
let key = axis_default_spacer(self.widget.direction);
self.add_spacer(key);
self.ctx.request_layout();
}
/// Add an empty spacer widget with the given size.
@ -425,19 +425,19 @@ impl Flex {
/// generally prefer to use [`add_default_spacer`].
///
/// [`add_default_spacer`]: Flex::add_default_spacer
pub fn add_spacer(this: &mut WidgetMut<'_, Self>, mut len: f64) {
pub fn add_spacer(self: &mut WidgetMut<'_, Self>, mut len: f64) {
if len < 0.0 {
tracing::warn!("add_spacer called with negative length: {}", len);
}
len = len.clamp(0.0, f64::MAX);
let new_child = Child::FixedSpacer(len, 0.0);
this.widget.children.push(new_child);
this.ctx.request_layout();
self.widget.children.push(new_child);
self.ctx.request_layout();
}
/// Add an empty spacer widget with a specific `flex` factor.
pub fn add_flex_spacer(this: &mut WidgetMut<'_, Self>, flex: f64) {
pub fn add_flex_spacer(self: &mut WidgetMut<'_, Self>, flex: f64) {
let flex = if flex >= 0.0 {
flex
} else {
@ -445,8 +445,8 @@ impl Flex {
0.0
};
let new_child = Child::FlexedSpacer(flex, 0.0);
this.widget.children.push(new_child);
this.ctx.request_layout();
self.widget.children.push(new_child);
self.ctx.request_layout();
}
/// Add a non-flex child widget.
@ -454,13 +454,13 @@ impl Flex {
/// See also [`with_child`].
///
/// [`with_child`]: Flex::with_child
pub fn insert_child(this: &mut WidgetMut<'_, Self>, idx: usize, child: impl Widget) {
Self::insert_child_pod(this, idx, WidgetPod::new(child).erased());
pub fn insert_child(self: &mut WidgetMut<'_, Self>, idx: usize, child: impl Widget) {
self.insert_child_pod(idx, WidgetPod::new(child).erased());
}
/// Add a non-flex child widget.
pub fn insert_child_pod(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
idx: usize,
widget: WidgetPod<dyn Widget>,
) {
@ -468,28 +468,28 @@ impl Flex {
widget,
alignment: None,
};
this.widget.children.insert(idx, child);
this.ctx.children_changed();
self.widget.children.insert(idx, child);
self.ctx.children_changed();
}
pub fn insert_flex_child(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
idx: usize,
child: impl Widget,
params: impl Into<FlexParams>,
) {
Self::insert_flex_child_pod(this, idx, WidgetPod::new(child).erased(), params);
self.insert_flex_child_pod(idx, WidgetPod::new(child).erased(), params);
}
pub fn insert_flex_child_pod(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
idx: usize,
child: WidgetPod<dyn Widget>,
params: impl Into<FlexParams>,
) {
let child = new_flex_child(params.into(), child);
this.widget.children.insert(idx, child);
this.ctx.children_changed();
self.widget.children.insert(idx, child);
self.ctx.children_changed();
}
// TODO - remove
@ -497,10 +497,10 @@ impl Flex {
///
/// The actual value of this spacer depends on whether this container is
/// a row or column, as well as theme settings.
pub fn insert_default_spacer(this: &mut WidgetMut<'_, Self>, idx: usize) {
let key = axis_default_spacer(this.widget.direction);
Self::insert_spacer(this, idx, key);
this.ctx.request_layout();
pub fn insert_default_spacer(self: &mut WidgetMut<'_, Self>, idx: usize) {
let key = axis_default_spacer(self.widget.direction);
self.insert_spacer(idx, key);
self.ctx.request_layout();
}
/// Add an empty spacer widget with the given size.
@ -509,19 +509,19 @@ impl Flex {
/// generally prefer to use [`add_default_spacer`].
///
/// [`add_default_spacer`]: Flex::add_default_spacer
pub fn insert_spacer(this: &mut WidgetMut<'_, Self>, idx: usize, mut len: f64) {
pub fn insert_spacer(self: &mut WidgetMut<'_, Self>, idx: usize, mut len: f64) {
if len < 0.0 {
tracing::warn!("add_spacer called with negative length: {}", len);
}
len = len.clamp(0.0, f64::MAX);
let new_child = Child::FixedSpacer(len, 0.0);
this.widget.children.insert(idx, new_child);
this.ctx.request_layout();
self.widget.children.insert(idx, new_child);
self.ctx.request_layout();
}
/// Add an empty spacer widget with a specific `flex` factor.
pub fn insert_flex_spacer(this: &mut WidgetMut<'_, Self>, idx: usize, flex: f64) {
pub fn insert_flex_spacer(self: &mut WidgetMut<'_, Self>, idx: usize, flex: f64) {
let flex = if flex >= 0.0 {
flex
} else {
@ -529,29 +529,29 @@ impl Flex {
0.0
};
let new_child = Child::FlexedSpacer(flex, 0.0);
this.widget.children.insert(idx, new_child);
this.ctx.request_layout();
self.widget.children.insert(idx, new_child);
self.ctx.request_layout();
}
pub fn remove_child(this: &mut WidgetMut<'_, Self>, idx: usize) {
let child = this.widget.children.remove(idx);
pub fn remove_child(self: &mut WidgetMut<'_, Self>, idx: usize) {
let child = self.widget.children.remove(idx);
if let Child::Fixed { widget, .. } | Child::Flex { widget, .. } = child {
this.ctx.remove_child(widget);
self.ctx.remove_child(widget);
}
this.ctx.request_layout();
self.ctx.request_layout();
}
pub fn child_mut<'t>(
this: &'t mut WidgetMut<'_, Self>,
self: &'t mut WidgetMut<'_, Self>,
idx: usize,
) -> Option<WidgetMut<'t, dyn Widget>> {
let child = match &mut this.widget.children[idx] {
let child = match &mut self.widget.children[idx] {
Child::Fixed { widget, .. } | Child::Flex { widget, .. } => widget,
Child::FixedSpacer(..) => return None,
Child::FlexedSpacer(..) => return None,
};
Some(this.ctx.get_mut(child))
Some(self.ctx.get_mut(child))
}
/// Updates the flex parameters for the child at `idx`,
@ -560,11 +560,11 @@ impl Flex {
///
/// Panics if the element at `idx` is not a widget.
pub fn update_child_flex_params(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
idx: usize,
params: impl Into<FlexParams>,
) {
let child = &mut this.widget.children[idx];
let child = &mut self.widget.children[idx];
let child_val = std::mem::replace(child, Child::FixedSpacer(0.0, 0.0));
let widget = match child_val {
Child::Fixed { widget, .. } | Child::Flex { widget, .. } => widget,
@ -574,7 +574,7 @@ impl Flex {
};
let new_child = new_flex_child(params.into(), widget);
*child = new_child;
this.ctx.children_changed();
self.ctx.children_changed();
}
/// Updates the spacer at `idx`, if the spacer was a fixed spacer, it will be overwritten with a flex spacer
@ -582,8 +582,8 @@ impl Flex {
/// # Panics
///
/// Panics if the element at `idx` is not a spacer.
pub fn update_spacer_flex(this: &mut WidgetMut<'_, Self>, idx: usize, flex: f64) {
let child = &mut this.widget.children[idx];
pub fn update_spacer_flex(self: &mut WidgetMut<'_, Self>, idx: usize, flex: f64) {
let child = &mut self.widget.children[idx];
match *child {
Child::FixedSpacer(_, _) | Child::FlexedSpacer(_, _) => {
@ -593,7 +593,7 @@ impl Flex {
panic!("Can't update spacer parameters of a non-spacer element");
}
};
this.ctx.children_changed();
self.ctx.children_changed();
}
/// Updates the spacer at `idx`, if the spacer was a flex spacer, it will be overwritten with a fixed spacer
@ -601,8 +601,8 @@ impl Flex {
/// # Panics
///
/// Panics if the element at `idx` is not a spacer.
pub fn update_spacer_fixed(this: &mut WidgetMut<'_, Self>, idx: usize, len: f64) {
let child = &mut this.widget.children[idx];
pub fn update_spacer_fixed(self: &mut WidgetMut<'_, Self>, idx: usize, len: f64) {
let child = &mut self.widget.children[idx];
match *child {
Child::FixedSpacer(_, _) | Child::FlexedSpacer(_, _) => {
@ -612,16 +612,16 @@ impl Flex {
panic!("Can't update spacer parameters of a non-spacer element");
}
};
this.ctx.children_changed();
self.ctx.children_changed();
}
pub fn clear(this: &mut WidgetMut<'_, Self>) {
if !this.widget.children.is_empty() {
this.ctx.request_layout();
pub fn clear(self: &mut WidgetMut<'_, Self>) {
if !self.widget.children.is_empty() {
self.ctx.request_layout();
for child in this.widget.children.drain(..) {
for child in self.widget.children.drain(..) {
if let Child::Fixed { widget, .. } | Child::Flex { widget, .. } = child {
this.ctx.remove_child(widget);
self.ctx.remove_child(widget);
}
}
}

View File

@ -147,75 +147,75 @@ impl Grid {
/// See also [`with_child`].
///
/// [`with_child`]: Grid::with_child
pub fn add_child(this: &mut WidgetMut<'_, Self>, child: impl Widget, params: GridParams) {
pub fn add_child(self: &mut WidgetMut<'_, Self>, child: impl Widget, params: GridParams) {
let child_pod: WidgetPod<dyn Widget> = WidgetPod::new(child).erased();
Self::insert_child_pod(this, child_pod, params);
self.insert_child_pod(child_pod, params);
}
pub fn add_child_id(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
child: impl Widget,
id: WidgetId,
params: GridParams,
) {
let child_pod: WidgetPod<dyn Widget> = WidgetPod::new_with_id(child, id).erased();
Self::insert_child_pod(this, child_pod, params);
self.insert_child_pod(child_pod, params);
}
/// Add a child widget.
pub fn insert_child_pod(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
widget: WidgetPod<dyn Widget>,
params: GridParams,
) {
let child = new_grid_child(params, widget);
this.widget.children.push(child);
this.ctx.children_changed();
this.ctx.request_layout();
self.widget.children.push(child);
self.ctx.children_changed();
self.ctx.request_layout();
}
pub fn insert_grid_child_at(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
idx: usize,
child: impl Widget,
params: impl Into<GridParams>,
) {
Self::insert_grid_child_pod(this, idx, WidgetPod::new(child).erased(), params);
self.insert_grid_child_pod(idx, WidgetPod::new(child).erased(), params);
}
pub fn insert_grid_child_pod(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
idx: usize,
child: WidgetPod<dyn Widget>,
params: impl Into<GridParams>,
) {
let child = new_grid_child(params.into(), child);
this.widget.children.insert(idx, child);
this.ctx.children_changed();
this.ctx.request_layout();
self.widget.children.insert(idx, child);
self.ctx.children_changed();
self.ctx.request_layout();
}
pub fn set_spacing(this: &mut WidgetMut<'_, Self>, spacing: f64) {
this.widget.grid_spacing = spacing;
this.ctx.request_layout();
pub fn set_spacing(self: &mut WidgetMut<'_, Self>, spacing: f64) {
self.widget.grid_spacing = spacing;
self.ctx.request_layout();
}
pub fn set_width(this: &mut WidgetMut<'_, Self>, width: i32) {
this.widget.grid_width = width;
this.ctx.request_layout();
pub fn set_width(self: &mut WidgetMut<'_, Self>, width: i32) {
self.widget.grid_width = width;
self.ctx.request_layout();
}
pub fn set_height(this: &mut WidgetMut<'_, Self>, height: i32) {
this.widget.grid_height = height;
this.ctx.request_layout();
pub fn set_height(self: &mut WidgetMut<'_, Self>, height: i32) {
self.widget.grid_height = height;
self.ctx.request_layout();
}
pub fn child_mut<'t>(
this: &'t mut WidgetMut<'_, Self>,
self: &'t mut WidgetMut<'_, Self>,
idx: usize,
) -> Option<WidgetMut<'t, dyn Widget>> {
let child = this.widget.children[idx].widget_mut()?;
Some(this.ctx.get_mut(child))
let child = self.widget.children[idx].widget_mut()?;
Some(self.ctx.get_mut(child))
}
/// Updates the grid parameters for the child at `idx`,
@ -224,19 +224,19 @@ impl Grid {
///
/// Panics if the element at `idx` is not a widget.
pub fn update_child_grid_params(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
idx: usize,
params: GridParams,
) {
let child = &mut this.widget.children[idx];
let child = &mut self.widget.children[idx];
child.update_params(params);
this.ctx.request_layout();
self.ctx.request_layout();
}
pub fn remove_child(this: &mut WidgetMut<'_, Self>, idx: usize) {
let child = this.widget.children.remove(idx);
this.ctx.remove_child(child.widget);
this.ctx.request_layout();
pub fn remove_child(self: &mut WidgetMut<'_, Self>, idx: usize) {
let child = self.widget.children.remove(idx);
self.ctx.remove_child(child.widget);
self.ctx.request_layout();
}
}

View File

@ -56,16 +56,16 @@ impl Image {
impl Image {
/// Modify the widget's object fit.
#[inline]
pub fn set_fit_mode(this: &mut WidgetMut<'_, Self>, new_object_fit: ObjectFit) {
this.widget.object_fit = new_object_fit;
this.ctx.request_layout();
pub fn set_fit_mode(self: &mut WidgetMut<'_, Self>, new_object_fit: ObjectFit) {
self.widget.object_fit = new_object_fit;
self.ctx.request_layout();
}
/// Set new `ImageBuf`.
#[inline]
pub fn set_image_data(this: &mut WidgetMut<'_, Self>, image_data: ImageBuf) {
this.widget.image_data = image_data;
this.ctx.request_layout();
pub fn set_image_data(self: &mut WidgetMut<'_, Self>, image_data: ImageBuf) {
self.widget.image_data = image_data;
self.ctx.request_layout();
}
}

View File

@ -213,13 +213,13 @@ impl Label {
/// Setting [`StyleProperty::Brush`](parley::StyleProperty::Brush) is not supported.
/// Use [`set_brush`](Self::set_brush) instead.
pub fn insert_style(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
property: impl Into<StyleProperty>,
) -> Option<StyleProperty> {
let old = this.widget.insert_style_inner(property.into());
let old = self.widget.insert_style_inner(property.into());
this.widget.styles_changed = true;
this.ctx.request_layout();
self.widget.styles_changed = true;
self.ctx.request_layout();
old
}
@ -229,11 +229,11 @@ impl Label {
/// In most cases, these are the defaults for this widget.
///
/// Of note, behaviour is unspecified for unsetting the [`FontSize`](parley::StyleProperty::FontSize).
pub fn retain_styles(this: &mut WidgetMut<'_, Self>, f: impl FnMut(&StyleProperty) -> bool) {
this.widget.styles.retain(f);
pub fn retain_styles(self: &mut WidgetMut<'_, Self>, f: impl FnMut(&StyleProperty) -> bool) {
self.widget.styles.retain(f);
this.widget.styles_changed = true;
this.ctx.request_layout();
self.widget.styles_changed = true;
self.ctx.request_layout();
}
/// Remove the style with the discriminant `property`.
@ -247,65 +247,65 @@ impl Label {
///
/// Of note, behaviour is unspecified for unsetting the [`FontSize`](parley::StyleProperty::FontSize).
pub fn remove_style(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
property: Discriminant<StyleProperty>,
) -> Option<StyleProperty> {
let old = this.widget.styles.remove(property);
let old = self.widget.styles.remove(property);
this.widget.styles_changed = true;
this.ctx.request_layout();
self.widget.styles_changed = true;
self.ctx.request_layout();
old
}
/// Replace the text of this widget.
pub fn set_text(this: &mut WidgetMut<'_, Self>, new_text: impl Into<ArcStr>) {
this.widget.text = new_text.into();
pub fn set_text(self: &mut WidgetMut<'_, Self>, new_text: impl Into<ArcStr>) {
self.widget.text = new_text.into();
this.widget.styles_changed = true;
this.ctx.request_layout();
self.widget.styles_changed = true;
self.ctx.request_layout();
}
/// The runtime requivalent of [`with_line_break_mode`](Self::with_line_break_mode).
pub fn set_line_break_mode(this: &mut WidgetMut<'_, Self>, line_break_mode: LineBreaking) {
this.widget.line_break_mode = line_break_mode;
pub fn set_line_break_mode(self: &mut WidgetMut<'_, Self>, line_break_mode: LineBreaking) {
self.widget.line_break_mode = line_break_mode;
// We don't need to set an internal invalidation, as `max_advance` is always recalculated
this.ctx.request_layout();
self.ctx.request_layout();
}
/// The runtime requivalent of [`with_alignment`](Self::with_alignment).
pub fn set_alignment(this: &mut WidgetMut<'_, Self>, alignment: Alignment) {
this.widget.alignment = alignment;
pub fn set_alignment(self: &mut WidgetMut<'_, Self>, alignment: Alignment) {
self.widget.alignment = alignment;
this.widget.alignment_changed = true;
this.ctx.request_layout();
self.widget.alignment_changed = true;
self.ctx.request_layout();
}
#[doc(alias = "set_color")]
/// The runtime requivalent of [`with_brush`](Self::with_brush).
pub fn set_brush(this: &mut WidgetMut<'_, Self>, brush: impl Into<Brush>) {
pub fn set_brush(self: &mut WidgetMut<'_, Self>, brush: impl Into<Brush>) {
let brush = brush.into();
this.widget.brush = brush;
self.widget.brush = brush;
// We need to repaint unless the disabled brush is currently being used.
if this.widget.disabled_brush.is_none() || this.ctx.is_disabled() {
this.ctx.request_paint_only();
if self.widget.disabled_brush.is_none() || self.ctx.is_disabled() {
self.ctx.request_paint_only();
}
}
/// The runtime requivalent of [`with_disabled_brush`](Self::with_disabled_brush).
pub fn set_disabled_brush(this: &mut WidgetMut<'_, Self>, brush: impl Into<Option<Brush>>) {
pub fn set_disabled_brush(self: &mut WidgetMut<'_, Self>, brush: impl Into<Option<Brush>>) {
let brush = brush.into();
this.widget.disabled_brush = brush;
self.widget.disabled_brush = brush;
if this.ctx.is_disabled() {
this.ctx.request_paint_only();
if self.ctx.is_disabled() {
self.ctx.request_paint_only();
}
}
/// The runtime requivalent of [`with_hint`](Self::with_hint).
pub fn set_hint(this: &mut WidgetMut<'_, Self>, hint: bool) {
this.widget.hint = hint;
this.ctx.request_paint_only();
pub fn set_hint(self: &mut WidgetMut<'_, Self>, hint: bool) {
self.widget.hint = hint;
self.ctx.request_paint_only();
}
}

View File

@ -171,33 +171,33 @@ impl<W: Widget + ?Sized> Portal<W> {
// --- MARK: WIDGETMUT ---
impl<W: Widget + FromDynWidget + ?Sized> Portal<W> {
pub fn child_mut<'t>(this: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, W> {
this.ctx.get_mut(&mut this.widget.child)
pub fn child_mut<'t>(self: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, W> {
self.ctx.get_mut(&mut self.widget.child)
}
pub fn horizontal_scrollbar_mut<'t>(
this: &'t mut WidgetMut<'_, Self>,
self: &'t mut WidgetMut<'_, Self>,
) -> WidgetMut<'t, ScrollBar> {
this.ctx.get_mut(&mut this.widget.scrollbar_horizontal)
self.ctx.get_mut(&mut self.widget.scrollbar_horizontal)
}
pub fn vertical_scrollbar_mut<'t>(
this: &'t mut WidgetMut<'_, Self>,
self: &'t mut WidgetMut<'_, Self>,
) -> WidgetMut<'t, ScrollBar> {
this.ctx.get_mut(&mut this.widget.scrollbar_vertical)
self.ctx.get_mut(&mut self.widget.scrollbar_vertical)
}
// TODO - rewrite doc
/// Set whether to constrain the child horizontally.
pub fn set_constrain_horizontal(this: &mut WidgetMut<'_, Self>, constrain: bool) {
this.widget.constrain_horizontal = constrain;
this.ctx.request_layout();
pub fn set_constrain_horizontal(self: &mut WidgetMut<'_, Self>, constrain: bool) {
self.widget.constrain_horizontal = constrain;
self.ctx.request_layout();
}
/// Set whether to constrain the child vertically.
pub fn set_constrain_vertical(this: &mut WidgetMut<'_, Self>, constrain: bool) {
this.widget.constrain_vertical = constrain;
this.ctx.request_layout();
pub fn set_constrain_vertical(self: &mut WidgetMut<'_, Self>, constrain: bool) {
self.widget.constrain_vertical = constrain;
self.ctx.request_layout();
}
/// Set whether the child's size must be greater than or equal the size of
@ -206,42 +206,42 @@ impl<W: Widget + FromDynWidget + ?Sized> Portal<W> {
/// See [`content_must_fill`] for more details.
///
/// [`content_must_fill`]: Portal::content_must_fill
pub fn set_content_must_fill(this: &mut WidgetMut<'_, Self>, must_fill: bool) {
this.widget.must_fill = must_fill;
this.ctx.request_layout();
pub fn set_content_must_fill(self: &mut WidgetMut<'_, Self>, must_fill: bool) {
self.widget.must_fill = must_fill;
self.ctx.request_layout();
}
pub fn set_viewport_pos(this: &mut WidgetMut<'_, Self>, position: Point) -> bool {
let portal_size = this.ctx.layout_rect().size();
let content_size = this
pub fn set_viewport_pos(self: &mut WidgetMut<'_, Self>, position: Point) -> bool {
let portal_size = self.ctx.layout_rect().size();
let content_size = self
.ctx
.get_mut(&mut this.widget.child)
.get_mut(&mut self.widget.child)
.ctx
.layout_rect()
.size();
let pos_changed = this
let pos_changed = self
.widget
.set_viewport_pos_raw(portal_size, content_size, position);
if pos_changed {
let progress_x = this.widget.viewport_pos.x / (content_size - portal_size).width;
Self::horizontal_scrollbar_mut(this).widget.cursor_progress = progress_x;
Self::horizontal_scrollbar_mut(this).ctx.request_render();
let progress_y = this.widget.viewport_pos.y / (content_size - portal_size).height;
Self::vertical_scrollbar_mut(this).widget.cursor_progress = progress_y;
Self::vertical_scrollbar_mut(this).ctx.request_render();
this.ctx.request_layout();
let progress_x = self.widget.viewport_pos.x / (content_size - portal_size).width;
self.horizontal_scrollbar_mut().widget.cursor_progress = progress_x;
self.horizontal_scrollbar_mut().ctx.request_render();
let progress_y = self.widget.viewport_pos.y / (content_size - portal_size).height;
self.vertical_scrollbar_mut().widget.cursor_progress = progress_y;
self.vertical_scrollbar_mut().ctx.request_render();
self.ctx.request_layout();
}
pos_changed
}
pub fn pan_viewport_by(this: &mut WidgetMut<'_, Self>, translation: Vec2) -> bool {
Self::set_viewport_pos(this, this.widget.viewport_pos + translation)
pub fn pan_viewport_by(self: &mut WidgetMut<'_, Self>, translation: Vec2) -> bool {
self.set_viewport_pos(self.widget.viewport_pos + translation)
}
// Note - Rect is in child coordinates
pub fn pan_viewport_to(this: &mut WidgetMut<'_, Self>, target: Rect) -> bool {
let viewport = Rect::from_origin_size(this.widget.viewport_pos, this.ctx.widget_state.size);
pub fn pan_viewport_to(self: &mut WidgetMut<'_, Self>, target: Rect) -> bool {
let viewport = Rect::from_origin_size(self.widget.viewport_pos, self.ctx.widget_state.size);
let new_pos_x = compute_pan_range(
viewport.min_x()..viewport.max_x(),
@ -254,7 +254,7 @@ impl<W: Widget + FromDynWidget + ?Sized> Portal<W> {
)
.start;
Self::set_viewport_pos(this, Point::new(new_pos_x, new_pos_y))
self.set_viewport_pos(Point::new(new_pos_x, new_pos_y))
}
}

View File

@ -62,16 +62,16 @@ impl ProgressBar {
// --- MARK: WIDGETMUT ---
impl ProgressBar {
pub fn set_progress(this: &mut WidgetMut<'_, Self>, mut progress: Option<f64>) {
pub fn set_progress(self: &mut WidgetMut<'_, Self>, mut progress: Option<f64>) {
clamp_progress(&mut progress);
let progress_changed = this.widget.progress != progress;
let progress_changed = self.widget.progress != progress;
if progress_changed {
this.widget.progress = progress;
let mut label = this.ctx.get_mut(&mut this.widget.label);
self.widget.progress = progress;
let mut label = self.ctx.get_mut(&mut self.widget.label);
Label::set_text(&mut label, Self::value(progress));
}
this.ctx.request_layout();
this.ctx.request_render();
self.ctx.request_layout();
self.ctx.request_render();
}
}

View File

@ -93,8 +93,8 @@ impl Prose {
/// Edit the underlying text area.
///
/// Used to modify most properties of the text.
pub fn text_mut<'t>(this: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, TextArea<false>> {
this.ctx.get_mut(&mut this.widget.text)
pub fn text_mut<'t>(self: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, TextArea<false>> {
self.ctx.get_mut(&mut self.widget.text)
}
/// Whether to clip the text to the available space.
@ -103,9 +103,9 @@ impl Prose {
/// wraps a text area with [word wrapping](TextArea::set_word_wrap) enabled.
///
/// The runtime requivalent of [`with_clip`](Self::with_clip).
pub fn set_clip(this: &mut WidgetMut<'_, Self>, clip: bool) {
this.widget.clip = clip;
this.ctx.request_layout();
pub fn set_clip(self: &mut WidgetMut<'_, Self>, clip: bool) {
self.widget.clip = clip;
self.ctx.request_layout();
}
}

View File

@ -34,8 +34,8 @@ impl<W: Widget + FromDynWidget + ?Sized> RootWidget<W> {
}
impl<W: Widget + FromDynWidget + ?Sized> RootWidget<W> {
pub fn child_mut<'t>(this: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, W> {
this.ctx.get_mut(&mut this.widget.pod)
pub fn child_mut<'t>(self: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, W> {
self.ctx.get_mut(&mut self.widget.pod)
}
}

View File

@ -105,17 +105,17 @@ impl ScrollBar {
// --- MARK: WIDGETMUT ---
impl ScrollBar {
// TODO - Remove?
pub fn set_sizes(this: &mut WidgetMut<'_, Self>, portal_size: f64, content_size: f64) {
this.widget.portal_size = portal_size;
this.widget.content_size = content_size;
this.ctx.request_render();
pub fn set_sizes(self: &mut WidgetMut<'_, Self>, portal_size: f64, content_size: f64) {
self.widget.portal_size = portal_size;
self.widget.content_size = content_size;
self.ctx.request_render();
}
// TODO - Remove?
pub fn set_content_size(this: &mut WidgetMut<'_, Self>, content_size: f64) {
pub fn set_content_size(self: &mut WidgetMut<'_, Self>, content_size: f64) {
// TODO - cursor_progress
this.widget.content_size = content_size;
this.ctx.request_render();
self.widget.content_size = content_size;
self.ctx.request_render();
}
}

View File

@ -331,43 +331,43 @@ impl SizedBox {
// --- MARK: WIDGETMUT ---
impl SizedBox {
pub fn set_child(this: &mut WidgetMut<'_, Self>, child: impl Widget) {
if let Some(child) = this.widget.child.take() {
this.ctx.remove_child(child);
pub fn set_child(self: &mut WidgetMut<'_, Self>, child: impl Widget) {
if let Some(child) = self.widget.child.take() {
self.ctx.remove_child(child);
}
this.widget.child = Some(WidgetPod::new(child).erased());
this.ctx.children_changed();
this.ctx.request_layout();
self.widget.child = Some(WidgetPod::new(child).erased());
self.ctx.children_changed();
self.ctx.request_layout();
}
pub fn remove_child(this: &mut WidgetMut<'_, Self>) {
if let Some(child) = this.widget.child.take() {
this.ctx.remove_child(child);
pub fn remove_child(self: &mut WidgetMut<'_, Self>) {
if let Some(child) = self.widget.child.take() {
self.ctx.remove_child(child);
}
}
/// Set container's width.
pub fn set_width(this: &mut WidgetMut<'_, Self>, width: f64) {
this.widget.width = Some(width);
this.ctx.request_layout();
pub fn set_width(self: &mut WidgetMut<'_, Self>, width: f64) {
self.widget.width = Some(width);
self.ctx.request_layout();
}
/// Set container's height.
pub fn set_height(this: &mut WidgetMut<'_, Self>, height: f64) {
this.widget.height = Some(height);
this.ctx.request_layout();
pub fn set_height(self: &mut WidgetMut<'_, Self>, height: f64) {
self.widget.height = Some(height);
self.ctx.request_layout();
}
/// Set container's width.
pub fn unset_width(this: &mut WidgetMut<'_, Self>) {
this.widget.width = None;
this.ctx.request_layout();
pub fn unset_width(self: &mut WidgetMut<'_, Self>) {
self.widget.width = None;
self.ctx.request_layout();
}
/// Set container's height.
pub fn unset_height(this: &mut WidgetMut<'_, Self>) {
this.widget.height = None;
this.ctx.request_layout();
pub fn unset_height(self: &mut WidgetMut<'_, Self>) {
self.widget.height = None;
self.ctx.request_layout();
}
/// Set the background for this widget.
@ -377,57 +377,57 @@ impl SizedBox {
///
/// [`Image`]: vello::peniko::Image
/// [`Color`]: crate::peniko::Color
pub fn set_background(this: &mut WidgetMut<'_, Self>, brush: impl Into<Brush>) {
this.widget.background = Some(brush.into());
this.ctx.request_paint_only();
pub fn set_background(self: &mut WidgetMut<'_, Self>, brush: impl Into<Brush>) {
self.widget.background = Some(brush.into());
self.ctx.request_paint_only();
}
/// Clears background.
pub fn clear_background(this: &mut WidgetMut<'_, Self>) {
this.widget.background = None;
this.ctx.request_paint_only();
pub fn clear_background(self: &mut WidgetMut<'_, Self>) {
self.widget.background = None;
self.ctx.request_paint_only();
}
/// Paint a border around the widget with a brush and width.
pub fn set_border(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
brush: impl Into<Brush>,
width: impl Into<f64>,
) {
this.widget.border = Some(BorderStyle {
self.widget.border = Some(BorderStyle {
brush: brush.into(),
width: width.into(),
});
this.ctx.request_layout();
self.ctx.request_layout();
}
/// Clears border.
pub fn clear_border(this: &mut WidgetMut<'_, Self>) {
this.widget.border = None;
this.ctx.request_layout();
pub fn clear_border(self: &mut WidgetMut<'_, Self>) {
self.widget.border = None;
self.ctx.request_layout();
}
/// Round off corners of this container by setting a corner radius
pub fn set_rounded(this: &mut WidgetMut<'_, Self>, radius: impl Into<RoundedRectRadii>) {
this.widget.corner_radius = radius.into();
this.ctx.request_paint_only();
pub fn set_rounded(self: &mut WidgetMut<'_, Self>, radius: impl Into<RoundedRectRadii>) {
self.widget.corner_radius = radius.into();
self.ctx.request_paint_only();
}
/// Clears padding.
pub fn clear_padding(this: &mut WidgetMut<'_, Self>) {
Self::set_padding(this, Padding::ZERO);
pub fn clear_padding(self: &mut WidgetMut<'_, Self>) {
self.set_padding(Padding::ZERO);
}
/// Set the padding around this widget.
pub fn set_padding(this: &mut WidgetMut<'_, Self>, padding: impl Into<Padding>) {
this.widget.padding = padding.into();
this.ctx.request_layout();
pub fn set_padding(self: &mut WidgetMut<'_, Self>, padding: impl Into<Padding>) {
self.widget.padding = padding.into();
self.ctx.request_layout();
}
// TODO - Doc
pub fn child_mut<'t>(this: &'t mut WidgetMut<'_, Self>) -> Option<WidgetMut<'t, dyn Widget>> {
let child = this.widget.child.as_mut()?;
Some(this.ctx.get_mut(child))
pub fn child_mut<'t>(self: &'t mut WidgetMut<'_, Self>) -> Option<WidgetMut<'t, dyn Widget>> {
let child = self.widget.child.as_mut()?;
Some(self.ctx.get_mut(child))
}
}

View File

@ -60,14 +60,14 @@ impl Default for Spinner {
// --- MARK: WIDGETMUT ---
impl Spinner {
/// Set the spinner's color.
pub fn set_color(this: &mut WidgetMut<'_, Self>, color: impl Into<Color>) {
this.widget.color = color.into();
this.ctx.request_paint_only();
pub fn set_color(self: &mut WidgetMut<'_, Self>, color: impl Into<Color>) {
self.widget.color = color.into();
self.ctx.request_paint_only();
}
/// Reset the spinner's color to its default value.
pub fn reset_color(this: &mut WidgetMut<'_, Self>) {
Self::set_color(this, DEFAULT_SPINNER_COLOR);
pub fn reset_color(self: &mut WidgetMut<'_, Self>) {
self.set_color(DEFAULT_SPINNER_COLOR);
}
}

View File

@ -298,24 +298,24 @@ impl Split {
///
/// The value must be between `0.0` and `1.0`, inclusive.
/// The default split point is `0.5`.
pub fn set_split_point(this: &mut WidgetMut<'_, Self>, split_point: f64) {
pub fn set_split_point(self: &mut WidgetMut<'_, Self>, split_point: f64) {
assert!(
(0.0..=1.0).contains(&split_point),
"split_point must be in the range [0.0-1.0]!"
);
this.widget.split_point_chosen = split_point;
this.ctx.request_layout();
self.widget.split_point_chosen = split_point;
self.ctx.request_layout();
}
/// Set the minimum size for both sides of the split axis.
///
/// The value must be greater than or equal to `0.0`.
/// The value will be rounded up to the nearest integer.
pub fn set_min_size(this: &mut WidgetMut<'_, Self>, first: f64, second: f64) {
pub fn set_min_size(self: &mut WidgetMut<'_, Self>, first: f64, second: f64) {
assert!(first >= 0.0);
assert!(second >= 0.0);
this.widget.min_size = (first.ceil(), second.ceil());
this.ctx.request_layout();
self.widget.min_size = (first.ceil(), second.ceil());
self.ctx.request_layout();
}
/// Set the size of the splitter bar.
@ -323,10 +323,10 @@ impl Split {
/// The value must be positive or zero.
/// The value will be rounded up to the nearest integer.
/// The default splitter bar size is `6.0`.
pub fn set_bar_size(this: &mut WidgetMut<'_, Self>, bar_size: f64) {
pub fn set_bar_size(self: &mut WidgetMut<'_, Self>, bar_size: f64) {
assert!(bar_size >= 0.0, "bar_size must be 0.0 or greater!");
this.widget.bar_size = bar_size.ceil();
this.ctx.request_layout();
self.widget.bar_size = bar_size.ceil();
self.ctx.request_layout();
}
/// Set the minimum size of the splitter bar area.
@ -341,27 +341,27 @@ impl Split {
/// The value must be positive or zero.
/// The value will be rounded up to the nearest integer.
/// The default minimum splitter bar area is `6.0`.
pub fn set_min_bar_area(this: &mut WidgetMut<'_, Self>, min_bar_area: f64) {
pub fn set_min_bar_area(self: &mut WidgetMut<'_, Self>, min_bar_area: f64) {
assert!(min_bar_area >= 0.0, "min_bar_area must be 0.0 or greater!");
this.widget.min_bar_area = min_bar_area.ceil();
this.ctx.request_layout();
self.widget.min_bar_area = min_bar_area.ceil();
self.ctx.request_layout();
}
/// Set whether the split point can be changed by dragging.
pub fn set_draggable(this: &mut WidgetMut<'_, Self>, draggable: bool) {
this.widget.draggable = draggable;
pub fn set_draggable(self: &mut WidgetMut<'_, Self>, draggable: bool) {
self.widget.draggable = draggable;
// Bar mutability impacts appearance, but not accessibility node
// TODO - This might change in a future implementation
this.ctx.request_paint_only();
self.ctx.request_paint_only();
}
/// Set whether the splitter bar is drawn as a solid rectangle.
///
/// If this is `false` (the default), the bar will be drawn as two parallel lines.
pub fn set_bar_solid(this: &mut WidgetMut<'_, Self>, solid: bool) {
this.widget.solid = solid;
pub fn set_bar_solid(self: &mut WidgetMut<'_, Self>, solid: bool) {
self.widget.solid = solid;
// Bar solidity impacts appearance, but not accessibility node
this.ctx.request_paint_only();
self.ctx.request_paint_only();
}
}

View File

@ -335,12 +335,12 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
/// This is the runtime equivalent of [`with_style`](Self::with_style).
#[track_caller]
pub fn insert_style(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
property: impl Into<StyleProperty>,
) -> Option<StyleProperty> {
let old = this.widget.insert_style_inner(property.into());
let old = self.widget.insert_style_inner(property.into());
this.ctx.request_layout();
self.ctx.request_layout();
old
}
@ -350,10 +350,10 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
/// In most cases, these are the defaults for this widget.
///
/// Of note, behaviour is unspecified for unsetting the [`FontSize`](parley::StyleProperty::FontSize).
pub fn retain_styles(this: &mut WidgetMut<'_, Self>, f: impl FnMut(&StyleProperty) -> bool) {
this.widget.editor.edit_styles().retain(f);
pub fn retain_styles(self: &mut WidgetMut<'_, Self>, f: impl FnMut(&StyleProperty) -> bool) {
self.widget.editor.edit_styles().retain(f);
this.ctx.request_layout();
self.ctx.request_layout();
}
/// Remove the style with the discriminant `property`.
@ -367,12 +367,12 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
///
/// Of note, behaviour is unspecified for unsetting the [`FontSize`](parley::StyleProperty::FontSize).
pub fn remove_style(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
property: Discriminant<StyleProperty>,
) -> Option<StyleProperty> {
let old = this.widget.editor.edit_styles().remove(property);
let old = self.widget.editor.edit_styles().remove(property);
this.ctx.request_layout();
self.ctx.request_layout();
old
}
@ -380,20 +380,20 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
///
/// This is likely to be disruptive if the user is focused on this widget,
/// as it does not retain selections, and may cause undesirable interactions with IME.
pub fn reset_text(this: &mut WidgetMut<'_, Self>, new_text: &str) {
pub fn reset_text(self: &mut WidgetMut<'_, Self>, new_text: &str) {
// If the IME is currently composing, we need to clear the compose first. This is quite
// disruptive, but we've warned about that. The platform's state is not reset, and the
// preedit will show up again when the platform updates it.
if this.widget.editor.is_composing() {
let (fctx, lctx) = this.ctx.text_contexts();
this.widget.editor.driver(fctx, lctx).clear_compose();
if self.widget.editor.is_composing() {
let (fctx, lctx) = self.ctx.text_contexts();
self.widget.editor.driver(fctx, lctx).clear_compose();
}
this.widget.editor.set_text(new_text);
self.widget.editor.set_text(new_text);
let (fctx, lctx) = this.ctx.text_contexts();
this.widget.editor.driver(fctx, lctx).move_to_text_end();
let (fctx, lctx) = self.ctx.text_contexts();
self.widget.editor.driver(fctx, lctx).move_to_text_end();
this.ctx.request_layout();
self.ctx.request_layout();
}
/// Control [word wrapping](https://en.wikipedia.org/wiki/Line_wrap_and_word_wrap) for the text area.
@ -406,15 +406,15 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
/// so it is recommended to leave word wrapping enabled.
///
/// The runtime equivalent of [`with_word_wrap`](Self::with_word_wrap).
pub fn set_word_wrap(this: &mut WidgetMut<'_, Self>, wrap_words: bool) {
this.widget.word_wrap = wrap_words;
pub fn set_word_wrap(self: &mut WidgetMut<'_, Self>, wrap_words: bool) {
self.widget.word_wrap = wrap_words;
let width = if wrap_words {
this.widget.last_available_width
self.widget.last_available_width
} else {
None
};
this.widget.editor.set_width(width);
this.ctx.request_layout();
self.widget.editor.set_width(width);
self.ctx.request_layout();
}
/// Set the [alignment](https://en.wikipedia.org/wiki/Typographic_alignment) of the text.
@ -422,10 +422,10 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
/// Text alignment might have unexpected results when the text area has no horizontal constraints.
///
/// The runtime equivalent of [`with_alignment`](Self::with_alignment).
pub fn set_alignment(this: &mut WidgetMut<'_, Self>, alignment: Alignment) {
this.widget.editor.set_alignment(alignment);
pub fn set_alignment(self: &mut WidgetMut<'_, Self>, alignment: Alignment) {
self.widget.editor.set_alignment(alignment);
this.ctx.request_layout();
self.ctx.request_layout();
}
#[doc(alias = "set_color")]
@ -434,13 +434,13 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
/// In most cases, this will be the text's color, but gradients and images are also supported.
///
/// The runtime equivalent of [`with_brush`](Self::with_brush).
pub fn set_brush(this: &mut WidgetMut<'_, Self>, brush: impl Into<Brush>) {
pub fn set_brush(self: &mut WidgetMut<'_, Self>, brush: impl Into<Brush>) {
let brush = brush.into();
this.widget.brush = brush;
self.widget.brush = brush;
// We need to repaint unless the disabled brush is currently being used.
if this.widget.disabled_brush.is_none() || !this.ctx.is_disabled() {
this.ctx.request_paint_only();
if self.widget.disabled_brush.is_none() || !self.ctx.is_disabled() {
self.ctx.request_paint_only();
}
}
@ -449,12 +449,12 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
/// If this is `None`, the [normal brush](Self::set_brush) will be used.
///
/// The runtime equivalent of [`with_disabled_brush`](Self::with_disabled_brush).
pub fn set_disabled_brush(this: &mut WidgetMut<'_, Self>, brush: impl Into<Option<Brush>>) {
pub fn set_disabled_brush(self: &mut WidgetMut<'_, Self>, brush: impl Into<Option<Brush>>) {
let brush = brush.into();
this.widget.disabled_brush = brush;
self.widget.disabled_brush = brush;
if this.ctx.is_disabled() {
this.ctx.request_paint_only();
if self.ctx.is_disabled() {
self.ctx.request_paint_only();
}
}
@ -462,9 +462,9 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
///
/// The runtime equivalent of [`with_hint`](Self::with_hint).
/// For full documentation, see that method.
pub fn set_hint(this: &mut WidgetMut<'_, Self>, hint: bool) {
this.widget.hint = hint;
this.ctx.request_paint_only();
pub fn set_hint(self: &mut WidgetMut<'_, Self>, hint: bool) {
self.widget.hint = hint;
self.ctx.request_paint_only();
}
/// Set the padding around the text.
@ -472,23 +472,23 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
/// This is the area outside the tight bound on the text where pointer events will be detected.
///
/// The runtime equivalent of [`with_padding`](Self::with_padding).
pub fn set_padding(this: &mut WidgetMut<'_, Self>, padding: impl Into<Padding>) {
this.widget.padding = padding.into();
pub fn set_padding(self: &mut WidgetMut<'_, Self>, padding: impl Into<Padding>) {
self.widget.padding = padding.into();
// TODO: We could reset the width available to the editor here directly.
// Determine whether there's any advantage to that
this.ctx.request_layout();
self.ctx.request_layout();
}
/// Set the selection to the given byte range.
///
/// No-op if either index is not a char boundary.
pub fn select_byte_range(this: &mut WidgetMut<'_, Self>, start: usize, end: usize) {
let (fctx, lctx) = this.ctx.text_contexts();
this.widget
pub fn select_byte_range(self: &mut WidgetMut<'_, Self>, start: usize, end: usize) {
let (fctx, lctx) = self.ctx.text_contexts();
self.widget
.editor
.driver(fctx, lctx)
.select_byte_range(start, end);
this.ctx.request_render();
self.ctx.request_render();
}
/// Set the selection to the first instance of the given text.
@ -496,12 +496,12 @@ impl<const EDITABLE: bool> TextArea<EDITABLE> {
/// This is mostly useful for testing.
///
/// No-op if the text isn't found.
pub fn select_text(this: &mut WidgetMut<'_, Self>, text: &str) {
let Some(start) = this.widget.text().to_string().find(text) else {
pub fn select_text(self: &mut WidgetMut<'_, Self>, text: &str) {
let Some(start) = self.widget.text().to_string().find(text) else {
return;
};
let end = start + text.len();
Self::select_byte_range(this, start, end);
self.select_byte_range(start, end);
}
}

View File

@ -92,8 +92,8 @@ impl Textbox {
/// Edit the underlying text area.
///
/// Used to modify most properties of the text.
pub fn text_mut<'t>(this: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, TextArea<true>> {
this.ctx.get_mut(&mut this.widget.text)
pub fn text_mut<'t>(self: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, TextArea<true>> {
self.ctx.get_mut(&mut self.widget.text)
}
/// Whether to clip the text to the drawn boundaries.
@ -102,9 +102,9 @@ impl Textbox {
/// wraps a text area with [word wrapping](TextArea::set_word_wrap) enabled.
///
/// The runtime requivalent of [`with_clip`](Self::with_clip).
pub fn set_clip(this: &mut WidgetMut<'_, Self>, clip: bool) {
this.widget.clip = clip;
this.ctx.request_layout();
pub fn set_clip(self: &mut WidgetMut<'_, Self>, clip: bool) {
self.widget.clip = clip;
self.ctx.request_layout();
}
}

View File

@ -154,20 +154,20 @@ impl VariableLabel {
// --- MARK: WIDGETMUT ---
impl VariableLabel {
/// Get the underlying label for this widget.
pub fn label_mut<'t>(this: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, Label> {
this.ctx.get_mut(&mut this.widget.label)
pub fn label_mut<'t>(self: &'t mut WidgetMut<'_, Self>) -> WidgetMut<'t, Label> {
self.ctx.get_mut(&mut self.widget.label)
}
/// Set the text of this label.
pub fn set_text(this: &mut WidgetMut<'_, Self>, new_text: impl Into<ArcStr>) {
Label::set_text(&mut Self::label_mut(this), new_text);
pub fn set_text(self: &mut WidgetMut<'_, Self>, new_text: impl Into<ArcStr>) {
Label::set_text(&mut self.label_mut(), new_text);
}
/// Set the weight which this font will target.
pub fn set_target_weight(this: &mut WidgetMut<'_, Self>, target: f32, over_millis: f32) {
this.widget.weight.move_to(target, over_millis);
this.ctx.request_layout();
this.ctx.request_anim_frame();
pub fn set_target_weight(self: &mut WidgetMut<'_, Self>, target: f32, over_millis: f32) {
self.widget.weight.move_to(target, over_millis);
self.ctx.request_layout();
self.ctx.request_anim_frame();
}
}

View File

@ -227,72 +227,72 @@ impl ZStack {
///
/// See also [`with_child`][Self::with_child].
pub fn add_child(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
child: impl Widget,
alignment: impl Into<ChildAlignment>,
) {
let child_pod: WidgetPod<dyn Widget> = WidgetPod::new(child).erased();
Self::insert_child_pod(this, child_pod, alignment);
self.insert_child_pod(child_pod, alignment);
}
/// Add a child widget with a given `id` to the `ZStack`.
///
/// See [`Self::add_child`] for more details.
pub fn add_child_id(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
child: impl Widget,
id: WidgetId,
alignment: impl Into<ChildAlignment>,
) {
let child_pod: WidgetPod<dyn Widget> = WidgetPod::new_with_id(child, id).erased();
Self::insert_child_pod(this, child_pod, alignment);
self.insert_child_pod(child_pod, alignment);
}
/// Add a child widget to the `ZStack`.
pub fn insert_child_pod(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
widget: WidgetPod<dyn Widget>,
alignment: impl Into<ChildAlignment>,
) {
let child = Child::new(widget, alignment.into());
this.widget.children.push(child);
this.ctx.children_changed();
this.ctx.request_layout();
self.widget.children.push(child);
self.ctx.children_changed();
self.ctx.request_layout();
}
/// Remove a child from the `ZStack`.
pub fn remove_child(this: &mut WidgetMut<'_, Self>, idx: usize) {
let child = this.widget.children.remove(idx);
this.ctx.remove_child(child.widget);
this.ctx.request_layout();
pub fn remove_child(self: &mut WidgetMut<'_, Self>, idx: usize) {
let child = self.widget.children.remove(idx);
self.ctx.remove_child(child.widget);
self.ctx.request_layout();
}
/// Get a mutable reference to a child of the `ZStack`.
pub fn child_mut<'t>(
this: &'t mut WidgetMut<'_, Self>,
self: &'t mut WidgetMut<'_, Self>,
idx: usize,
) -> Option<WidgetMut<'t, dyn Widget>> {
let child = &mut this.widget.children[idx].widget;
Some(this.ctx.get_mut(child))
let child = &mut self.widget.children[idx].widget;
Some(self.ctx.get_mut(child))
}
/// Change the alignment of the `ZStack`.
///
/// See also [`with_alignment`][Self::with_alignment].
pub fn set_alignment(this: &mut WidgetMut<'_, Self>, alignment: impl Into<Alignment>) {
this.widget.alignment = alignment.into();
this.ctx.request_layout();
pub fn set_alignment(self: &mut WidgetMut<'_, Self>, alignment: impl Into<Alignment>) {
self.widget.alignment = alignment.into();
self.ctx.request_layout();
}
/// Change the alignment of a child of the `ZStack`.
pub fn update_child_alignment(
this: &mut WidgetMut<'_, Self>,
self: &mut WidgetMut<'_, Self>,
idx: usize,
alignment: impl Into<ChildAlignment>,
) {
let child = &mut this.widget.children[idx];
let child = &mut self.widget.children[idx];
child.update_alignment(alignment.into());
this.ctx.request_layout();
self.ctx.request_layout();
}
}