From a026e917d3364e58fd827995261158d8cb356ce9 Mon Sep 17 00:00:00 2001
From: Héctor Ramón Jiménez <hector0193@gmail.com>
Date: Wed, 30 Aug 2023 06:36:24 +0200
Subject: Make `widget::Tree` mutable in `Widget::layout`

---
 widget/src/button.rs              | 10 +++++----
 widget/src/canvas.rs              |  2 +-
 widget/src/checkbox.rs            |  4 ++--
 widget/src/column.rs              |  4 ++--
 widget/src/combo_box.rs           |  2 +-
 widget/src/container.rs           |  2 +-
 widget/src/image.rs               |  2 +-
 widget/src/image/viewer.rs        |  2 +-
 widget/src/lazy.rs                |  4 ++--
 widget/src/lazy/component.rs      |  4 ++--
 widget/src/lazy/responsive.rs     |  6 ++---
 widget/src/mouse_area.rs          |  2 +-
 widget/src/overlay/menu.rs        |  4 ++--
 widget/src/pane_grid.rs           | 13 +++++++----
 widget/src/pane_grid/content.rs   | 14 +++++++-----
 widget/src/pane_grid/title_bar.rs |  6 ++---
 widget/src/pick_list.rs           | 28 ++++++++++--------------
 widget/src/progress_bar.rs        |  2 +-
 widget/src/qr_code.rs             |  2 +-
 widget/src/radio.rs               |  4 ++--
 widget/src/row.rs                 |  4 ++--
 widget/src/rule.rs                |  2 +-
 widget/src/scrollable.rs          |  4 ++--
 widget/src/slider.rs              |  2 +-
 widget/src/space.rs               |  2 +-
 widget/src/svg.rs                 |  2 +-
 widget/src/text_input.rs          | 46 ++++++++++++++++-----------------------
 widget/src/toggler.rs             |  4 ++--
 widget/src/tooltip.rs             |  6 ++---
 widget/src/vertical_slider.rs     |  2 +-
 30 files changed, 94 insertions(+), 97 deletions(-)

(limited to 'widget/src')

diff --git a/widget/src/button.rs b/widget/src/button.rs
index 1788b6c4..8ca4a542 100644
--- a/widget/src/button.rs
+++ b/widget/src/button.rs
@@ -159,14 +159,16 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
         layout(limits, self.width, self.height, self.padding, |limits| {
-            self.content
-                .as_widget()
-                .layout(&tree.children[0], renderer, limits)
+            self.content.as_widget().layout(
+                &mut tree.children[0],
+                renderer,
+                limits,
+            )
         })
     }
 
diff --git a/widget/src/canvas.rs b/widget/src/canvas.rs
index d749355b..390f4d92 100644
--- a/widget/src/canvas.rs
+++ b/widget/src/canvas.rs
@@ -129,7 +129,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         _renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs
index 0158f15c..2860d496 100644
--- a/widget/src/checkbox.rs
+++ b/widget/src/checkbox.rs
@@ -184,7 +184,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -195,7 +195,7 @@ where
             |limits| {
                 let state = tree
                     .state
-                    .downcast_ref::<widget::text::State<Renderer::Paragraph>>();
+                    .downcast_mut::<widget::text::State<Renderer::Paragraph>>();
 
                 widget::text::layout(
                     state,
diff --git a/widget/src/column.rs b/widget/src/column.rs
index 107c3475..f2347cc9 100644
--- a/widget/src/column.rs
+++ b/widget/src/column.rs
@@ -122,7 +122,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -139,7 +139,7 @@ where
             self.spacing,
             self.align_items,
             &self.children,
-            &tree.children,
+            &mut tree.children,
         )
     }
 
diff --git a/widget/src/combo_box.rs b/widget/src/combo_box.rs
index 8c20ae8e..650954ef 100644
--- a/widget/src/combo_box.rs
+++ b/widget/src/combo_box.rs
@@ -305,7 +305,7 @@ where
 
     fn layout(
         &self,
-        tree: &widget::Tree,
+        tree: &mut widget::Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/container.rs b/widget/src/container.rs
index c16c1117..ee7a4965 100644
--- a/widget/src/container.rs
+++ b/widget/src/container.rs
@@ -162,7 +162,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/image.rs b/widget/src/image.rs
index f73ee5d7..3c83c87b 100644
--- a/widget/src/image.rs
+++ b/widget/src/image.rs
@@ -167,7 +167,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/image/viewer.rs b/widget/src/image/viewer.rs
index 1f52bf2f..724d121e 100644
--- a/widget/src/image/viewer.rs
+++ b/widget/src/image/viewer.rs
@@ -105,7 +105,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/lazy.rs b/widget/src/lazy.rs
index 412254f5..d980a934 100644
--- a/widget/src/lazy.rs
+++ b/widget/src/lazy.rs
@@ -152,7 +152,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -327,7 +327,7 @@ where
     Renderer: core::Renderer,
 {
     fn layout(
-        &self,
+        &mut self,
         renderer: &Renderer,
         bounds: Size,
         position: Point,
diff --git a/widget/src/lazy/component.rs b/widget/src/lazy/component.rs
index 9b3b13b2..fba057ee 100644
--- a/widget/src/lazy/component.rs
+++ b/widget/src/lazy/component.rs
@@ -254,7 +254,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -567,7 +567,7 @@ where
     S: 'static + Default,
 {
     fn layout(
-        &self,
+        &mut self,
         renderer: &Renderer,
         bounds: Size,
         position: Point,
diff --git a/widget/src/lazy/responsive.rs b/widget/src/lazy/responsive.rs
index 5ab8ed1a..0b819455 100644
--- a/widget/src/lazy/responsive.rs
+++ b/widget/src/lazy/responsive.rs
@@ -60,7 +60,7 @@ impl<'a, Message, Renderer> Content<'a, Message, Renderer>
 where
     Renderer: core::Renderer,
 {
-    fn layout(&mut self, tree: &Tree, renderer: &Renderer) {
+    fn layout(&mut self, tree: &mut Tree, renderer: &Renderer) {
         if self.layout.is_none() {
             self.layout = Some(self.element.as_widget().layout(
                 tree,
@@ -144,7 +144,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         _renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -363,7 +363,7 @@ where
     Renderer: core::Renderer,
 {
     fn layout(
-        &self,
+        &mut self,
         renderer: &Renderer,
         bounds: Size,
         position: Point,
diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs
index 95b45b02..65d44dd5 100644
--- a/widget/src/mouse_area.rs
+++ b/widget/src/mouse_area.rs
@@ -120,7 +120,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs
index 71703e71..5a2e1bf0 100644
--- a/widget/src/overlay/menu.rs
+++ b/widget/src/overlay/menu.rs
@@ -232,7 +232,7 @@ where
     Renderer::Theme: StyleSheet + container::StyleSheet,
 {
     fn layout(
-        &self,
+        &mut self,
         renderer: &Renderer,
         bounds: Size,
         position: Point,
@@ -352,7 +352,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs
index 366d9a66..6e2b39a4 100644
--- a/widget/src/pane_grid.rs
+++ b/widget/src/pane_grid.rs
@@ -275,7 +275,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -475,7 +475,7 @@ where
 
 /// Calculates the [`Layout`] of a [`PaneGrid`].
 pub fn layout<Renderer, T>(
-    tree: &Tree,
+    tree: &mut Tree,
     renderer: &Renderer,
     limits: &layout::Limits,
     node: &Node,
@@ -483,14 +483,19 @@ pub fn layout<Renderer, T>(
     height: Length,
     spacing: f32,
     contents: impl Iterator<Item = (Pane, T)>,
-    layout_content: impl Fn(T, &Tree, &Renderer, &layout::Limits) -> layout::Node,
+    layout_content: impl Fn(
+        T,
+        &mut Tree,
+        &Renderer,
+        &layout::Limits,
+    ) -> layout::Node,
 ) -> layout::Node {
     let limits = limits.width(width).height(height);
     let size = limits.resolve(Size::ZERO);
 
     let regions = node.pane_regions(spacing, size);
     let children = contents
-        .zip(tree.children.iter())
+        .zip(tree.children.iter_mut())
         .filter_map(|((pane, content), tree)| {
             let region = regions.get(&pane)?;
             let size = Size::new(region.width, region.height);
diff --git a/widget/src/pane_grid/content.rs b/widget/src/pane_grid/content.rs
index 8a74b4b9..5dbc5496 100644
--- a/widget/src/pane_grid/content.rs
+++ b/widget/src/pane_grid/content.rs
@@ -150,7 +150,7 @@ where
 
     pub(crate) fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -158,7 +158,7 @@ where
             let max_size = limits.max();
 
             let title_bar_layout = title_bar.layout(
-                &tree.children[1],
+                &mut tree.children[1],
                 renderer,
                 &layout::Limits::new(Size::ZERO, max_size),
             );
@@ -166,7 +166,7 @@ where
             let title_bar_size = title_bar_layout.size();
 
             let mut body_layout = self.body.as_widget().layout(
-                &tree.children[0],
+                &mut tree.children[0],
                 renderer,
                 &layout::Limits::new(
                     Size::ZERO,
@@ -184,9 +184,11 @@ where
                 vec![title_bar_layout, body_layout],
             )
         } else {
-            self.body
-                .as_widget()
-                .layout(&tree.children[0], renderer, limits)
+            self.body.as_widget().layout(
+                &mut tree.children[0],
+                renderer,
+                limits,
+            )
         }
     }
 
diff --git a/widget/src/pane_grid/title_bar.rs b/widget/src/pane_grid/title_bar.rs
index c0fb9936..8a4523e8 100644
--- a/widget/src/pane_grid/title_bar.rs
+++ b/widget/src/pane_grid/title_bar.rs
@@ -213,7 +213,7 @@ where
 
     pub(crate) fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -221,7 +221,7 @@ where
         let max_size = limits.max();
 
         let title_layout = self.content.as_widget().layout(
-            &tree.children[0],
+            &mut tree.children[0],
             renderer,
             &layout::Limits::new(Size::ZERO, max_size),
         );
@@ -230,7 +230,7 @@ where
 
         let mut node = if let Some(controls) = &self.controls {
             let mut controls_layout = controls.as_widget().layout(
-                &tree.children[1],
+                &mut tree.children[1],
                 renderer,
                 &layout::Limits::new(Size::ZERO, max_size),
             );
diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs
index 719aa066..8feb1788 100644
--- a/widget/src/pick_list.rs
+++ b/widget/src/pick_list.rs
@@ -18,7 +18,6 @@ use crate::overlay::menu::{self, Menu};
 use crate::scrollable;
 
 use std::borrow::Cow;
-use std::cell::RefCell;
 
 pub use crate::style::pick_list::{Appearance, StyleSheet};
 
@@ -175,12 +174,12 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
         layout(
-            tree.state.downcast_ref::<State<Renderer::Paragraph>>(),
+            tree.state.downcast_mut::<State<Renderer::Paragraph>>(),
             renderer,
             limits,
             self.width,
@@ -305,8 +304,8 @@ pub struct State<P: text::Paragraph> {
     keyboard_modifiers: keyboard::Modifiers,
     is_open: bool,
     hovered_option: Option<usize>,
-    option_paragraphs: RefCell<Vec<P>>,
-    placeholder_paragraph: RefCell<P>,
+    options: Vec<P>,
+    placeholder: P,
 }
 
 impl<P: text::Paragraph> State<P> {
@@ -317,8 +316,8 @@ impl<P: text::Paragraph> State<P> {
             keyboard_modifiers: keyboard::Modifiers::default(),
             is_open: bool::default(),
             hovered_option: Option::default(),
-            option_paragraphs: RefCell::new(Vec::new()),
-            placeholder_paragraph: RefCell::new(Default::default()),
+            options: Vec::new(),
+            placeholder: P::default(),
         }
     }
 }
@@ -375,7 +374,7 @@ pub struct Icon<Font> {
 
 /// Computes the layout of a [`PickList`].
 pub fn layout<Renderer, T>(
-    state: &State<Renderer::Paragraph>,
+    state: &mut State<Renderer::Paragraph>,
     renderer: &Renderer,
     limits: &layout::Limits,
     width: Length,
@@ -397,9 +396,7 @@ where
     let font = font.unwrap_or_else(|| renderer.default_font());
     let text_size = text_size.unwrap_or_else(|| renderer.default_size());
 
-    let mut paragraphs = state.option_paragraphs.borrow_mut();
-
-    paragraphs.resize_with(options.len(), Default::default);
+    state.options.resize_with(options.len(), Default::default);
 
     let option_text = Text {
         content: "",
@@ -415,7 +412,7 @@ where
         shaping: text_shaping,
     };
 
-    for (option, paragraph) in options.iter().zip(paragraphs.iter_mut()) {
+    for (option, paragraph) in options.iter().zip(state.options.iter_mut()) {
         let label = option.to_string();
 
         renderer.update_paragraph(
@@ -428,9 +425,8 @@ where
     }
 
     if let Some(placeholder) = placeholder {
-        let mut paragraph = state.placeholder_paragraph.borrow_mut();
         renderer.update_paragraph(
-            &mut paragraph,
+            &mut state.placeholder,
             Text {
                 content: placeholder,
                 ..option_text
@@ -441,13 +437,13 @@ where
     let max_width = match width {
         Length::Shrink => {
             let labels_width =
-                paragraphs.iter().fold(0.0, |width, paragraph| {
+                state.options.iter().fold(0.0, |width, paragraph| {
                     f32::max(width, paragraph.min_width())
                 });
 
             labels_width.max(
                 placeholder
-                    .map(|_| state.placeholder_paragraph.borrow().min_width())
+                    .map(|_| state.placeholder.min_width())
                     .unwrap_or(0.0),
             )
         }
diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs
index 8b1490af..07de72d5 100644
--- a/widget/src/progress_bar.rs
+++ b/widget/src/progress_bar.rs
@@ -95,7 +95,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         _renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/qr_code.rs b/widget/src/qr_code.rs
index 589704a5..d176021d 100644
--- a/widget/src/qr_code.rs
+++ b/widget/src/qr_code.rs
@@ -60,7 +60,7 @@ impl<'a, Message, Theme> Widget<Message, Renderer<Theme>> for QRCode<'a> {
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         _renderer: &Renderer<Theme>,
         _limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/radio.rs b/widget/src/radio.rs
index cb908ec4..a85dad63 100644
--- a/widget/src/radio.rs
+++ b/widget/src/radio.rs
@@ -211,7 +211,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -222,7 +222,7 @@ where
             |limits| {
                 let state = tree
                     .state
-                    .downcast_ref::<widget::text::State<Renderer::Paragraph>>();
+                    .downcast_mut::<widget::text::State<Renderer::Paragraph>>();
 
                 widget::text::layout(
                     state,
diff --git a/widget/src/row.rs b/widget/src/row.rs
index 17c49e67..71cf0509 100644
--- a/widget/src/row.rs
+++ b/widget/src/row.rs
@@ -114,7 +114,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -128,7 +128,7 @@ where
             self.spacing,
             self.align_items,
             &self.children,
-            &tree.children,
+            &mut tree.children,
         )
     }
 
diff --git a/widget/src/rule.rs b/widget/src/rule.rs
index 032ff860..b5c5fa55 100644
--- a/widget/src/rule.rs
+++ b/widget/src/rule.rs
@@ -72,7 +72,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         _renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs
index ce96883d..5decfd9d 100644
--- a/widget/src/scrollable.rs
+++ b/widget/src/scrollable.rs
@@ -230,7 +230,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -242,7 +242,7 @@ where
             &self.direction,
             |renderer, limits| {
                 self.content.as_widget().layout(
-                    &tree.children[0],
+                    &mut tree.children[0],
                     renderer,
                     limits,
                 )
diff --git a/widget/src/slider.rs b/widget/src/slider.rs
index b4c9198a..a9727aa3 100644
--- a/widget/src/slider.rs
+++ b/widget/src/slider.rs
@@ -169,7 +169,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         _renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/space.rs b/widget/src/space.rs
index 84331870..e5a8f169 100644
--- a/widget/src/space.rs
+++ b/widget/src/space.rs
@@ -55,7 +55,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         _renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/svg.rs b/widget/src/svg.rs
index f61a4ce2..2d01d1ab 100644
--- a/widget/src/svg.rs
+++ b/widget/src/svg.rs
@@ -106,7 +106,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs
index 209ef968..75800a34 100644
--- a/widget/src/text_input.rs
+++ b/widget/src/text_input.rs
@@ -30,8 +30,6 @@ use crate::core::{
 };
 use crate::runtime::Command;
 
-use std::cell::RefCell;
-
 pub use iced_style::text_input::{Appearance, StyleSheet};
 
 /// A field that can be filled with text.
@@ -267,7 +265,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -280,7 +278,7 @@ where
             self.font,
             self.line_height,
             self.icon.as_ref(),
-            tree.state.downcast_ref::<State<Renderer::Paragraph>>(),
+            tree.state.downcast_mut::<State<Renderer::Paragraph>>(),
             &self.value,
             &self.placeholder,
             self.is_secure,
@@ -469,7 +467,7 @@ pub fn layout<Renderer>(
     font: Option<Renderer::Font>,
     line_height: text::LineHeight,
     icon: Option<&Icon<Renderer::Font>>,
-    state: &State<Renderer::Paragraph>,
+    state: &mut State<Renderer::Paragraph>,
     value: &Value,
     placeholder: &str,
     is_secure: bool,
@@ -499,14 +497,12 @@ where
         shaping: text::Shaping::Advanced,
     };
 
-    renderer.update_paragraph(
-        &mut state.placeholder_paragraph.borrow_mut(),
-        placeholder_text,
-    );
+    renderer
+        .update_paragraph(&mut state.placeholder_paragraph, placeholder_text);
 
     if is_secure {
         renderer.update_paragraph(
-            &mut state.paragraph.borrow_mut(),
+            &mut state.paragraph,
             Text {
                 content: &value.secure().to_string(),
                 ..placeholder_text
@@ -514,7 +510,7 @@ where
         );
     } else {
         renderer.update_paragraph(
-            &mut state.paragraph.borrow_mut(),
+            &mut state.paragraph,
             Text {
                 content: &value.to_string(),
                 ..placeholder_text
@@ -1072,7 +1068,6 @@ pub fn draw<Renderer>(
     }
 
     let text = value.to_string();
-    let paragraph = &state.paragraph.borrow() as &Renderer::Paragraph;
 
     let (cursor, offset) = if let Some(focus) = state
         .is_focused
@@ -1083,7 +1078,7 @@ pub fn draw<Renderer>(
             cursor::State::Index(position) => {
                 let (text_value_width, offset) =
                     measure_cursor_and_scroll_offset(
-                        paragraph,
+                        &state.paragraph,
                         text_bounds,
                         position,
                     );
@@ -1121,14 +1116,14 @@ pub fn draw<Renderer>(
 
                 let (left_position, left_offset) =
                     measure_cursor_and_scroll_offset(
-                        paragraph,
+                        &state.paragraph,
                         text_bounds,
                         left,
                     );
 
                 let (right_position, right_offset) =
                     measure_cursor_and_scroll_offset(
-                        paragraph,
+                        &state.paragraph,
                         text_bounds,
                         right,
                     );
@@ -1162,7 +1157,7 @@ pub fn draw<Renderer>(
         (None, 0.0)
     };
 
-    let text_width = paragraph.min_width();
+    let text_width = state.paragraph.min_width();
 
     let render = |renderer: &mut Renderer| {
         if let Some((cursor, color)) = cursor {
@@ -1171,13 +1166,11 @@ pub fn draw<Renderer>(
             renderer.with_translation(Vector::ZERO, |_| {});
         }
 
-        let placeholder_paragraph = state.placeholder_paragraph.borrow();
-
         renderer.fill_paragraph(
             if text.is_empty() {
-                &placeholder_paragraph
+                &state.placeholder_paragraph
             } else {
-                paragraph
+                &state.paragraph
             },
             Point::new(text_bounds.x, text_bounds.center_y()),
             if text.is_empty() {
@@ -1219,8 +1212,8 @@ pub fn mouse_interaction(
 /// The state of a [`TextInput`].
 #[derive(Debug, Default, Clone)]
 pub struct State<P: text::Paragraph> {
-    paragraph: RefCell<P>,
-    placeholder_paragraph: RefCell<P>,
+    paragraph: P,
+    placeholder_paragraph: P,
     is_focused: Option<Focus>,
     is_dragging: bool,
     is_pasting: Option<Value>,
@@ -1246,8 +1239,8 @@ impl<P: text::Paragraph> State<P> {
     /// Creates a new [`State`], representing a focused [`TextInput`].
     pub fn focused() -> Self {
         Self {
-            paragraph: RefCell::new(P::default()),
-            placeholder_paragraph: RefCell::new(P::default()),
+            paragraph: P::default(),
+            placeholder_paragraph: P::default(),
             is_focused: None,
             is_dragging: false,
             is_pasting: None,
@@ -1364,7 +1357,7 @@ fn offset<P: text::Paragraph>(
         };
 
         let (_, offset) = measure_cursor_and_scroll_offset(
-            &state.paragraph.borrow() as &P,
+            &state.paragraph,
             text_bounds,
             focus_position,
         );
@@ -1402,7 +1395,6 @@ fn find_cursor_position<P: text::Paragraph>(
 
     let char_offset = state
         .paragraph
-        .borrow()
         .hit_test(Point::new(x + offset, text_bounds.height / 2.0))
         .map(text::Hit::cursor)?;
 
@@ -1432,7 +1424,7 @@ fn replace_paragraph<Renderer>(
     let mut children_layout = layout.children();
     let text_bounds = children_layout.next().unwrap().bounds();
 
-    *state.paragraph.get_mut() = renderer.create_paragraph(Text {
+    state.paragraph = renderer.create_paragraph(Text {
         font,
         line_height,
         content: &value.to_string(),
diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs
index 89e6b5d3..acb9b25d 100644
--- a/widget/src/toggler.rs
+++ b/widget/src/toggler.rs
@@ -178,7 +178,7 @@ where
 
     fn layout(
         &self,
-        tree: &Tree,
+        tree: &mut Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -192,7 +192,7 @@ where
                 if let Some(label) = self.label.as_deref() {
                     let state = tree
                     .state
-                    .downcast_ref::<widget::text::State<Renderer::Paragraph>>();
+                    .downcast_mut::<widget::text::State<Renderer::Paragraph>>();
 
                     widget::text::layout(
                         state,
diff --git a/widget/src/tooltip.rs b/widget/src/tooltip.rs
index 0444850e..534d901a 100644
--- a/widget/src/tooltip.rs
+++ b/widget/src/tooltip.rs
@@ -135,7 +135,7 @@ where
 
     fn layout(
         &self,
-        tree: &widget::Tree,
+        tree: &mut widget::Tree,
         renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
@@ -302,7 +302,7 @@ where
     Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
 {
     tooltip: &'b Text<'a, Renderer>,
-    state: &'b widget::Tree,
+    state: &'b mut widget::Tree,
     cursor_position: Point,
     content_bounds: Rectangle,
     snap_within_viewport: bool,
@@ -319,7 +319,7 @@ where
     Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
 {
     fn layout(
-        &self,
+        &mut self,
         renderer: &Renderer,
         bounds: Size,
         position: Point,
diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs
index a11fec75..1efcd63b 100644
--- a/widget/src/vertical_slider.rs
+++ b/widget/src/vertical_slider.rs
@@ -166,7 +166,7 @@ where
 
     fn layout(
         &self,
-        _tree: &Tree,
+        _tree: &mut Tree,
         _renderer: &Renderer,
         limits: &layout::Limits,
     ) -> layout::Node {
-- 
cgit