From 96775b1e55917df538c729eef90b4680759f2559 Mon Sep 17 00:00:00 2001
From: Héctor Ramón Jiménez <hector@hecrj.dev>
Date: Thu, 15 Feb 2024 01:18:00 +0100
Subject: Add `clip` property to `Container`, `Column`, and `Row`

---
 widget/src/column.rs    | 23 +++++++++++++++++++++--
 widget/src/container.rs | 17 +++++++++++++++--
 widget/src/row.rs       | 23 +++++++++++++++++++++--
 3 files changed, 57 insertions(+), 6 deletions(-)

(limited to 'widget/src')

diff --git a/widget/src/column.rs b/widget/src/column.rs
index 1e9841ee..8154ad85 100644
--- a/widget/src/column.rs
+++ b/widget/src/column.rs
@@ -20,6 +20,7 @@ pub struct Column<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer>
     height: Length,
     max_width: f32,
     align_items: Alignment,
+    clip: bool,
     children: Vec<Element<'a, Message, Theme, Renderer>>,
 }
 
@@ -36,6 +37,7 @@ where
             height: Length::Shrink,
             max_width: f32::INFINITY,
             align_items: Alignment::Start,
+            clip: false,
             children: Vec::new(),
         }
     }
@@ -87,6 +89,13 @@ where
         self
     }
 
+    /// Sets whether the contents of the [`Column`] should be clipped on
+    /// overflow.
+    pub fn clip(mut self, clip: bool) -> Self {
+        self.clip = clip;
+        self
+    }
+
     /// Adds an element to the [`Column`].
     pub fn push(
         mut self,
@@ -240,7 +249,7 @@ where
         cursor: mouse::Cursor,
         viewport: &Rectangle,
     ) {
-        if let Some(viewport) = layout.bounds().intersection(viewport) {
+        if let Some(clipped_viewport) = layout.bounds().intersection(viewport) {
             for ((child, state), layout) in self
                 .children
                 .iter()
@@ -248,7 +257,17 @@ where
                 .zip(layout.children())
             {
                 child.as_widget().draw(
-                    state, renderer, theme, style, layout, cursor, &viewport,
+                    state,
+                    renderer,
+                    theme,
+                    style,
+                    layout,
+                    cursor,
+                    if self.clip {
+                        &clipped_viewport
+                    } else {
+                        viewport
+                    },
                 );
             }
         }
diff --git a/widget/src/container.rs b/widget/src/container.rs
index 4eb4a5d9..e0174177 100644
--- a/widget/src/container.rs
+++ b/widget/src/container.rs
@@ -37,6 +37,7 @@ pub struct Container<
     horizontal_alignment: alignment::Horizontal,
     vertical_alignment: alignment::Vertical,
     style: Theme::Style,
+    clip: bool,
     content: Element<'a, Message, Theme, Renderer>,
 }
 
@@ -63,6 +64,7 @@ where
             horizontal_alignment: alignment::Horizontal::Left,
             vertical_alignment: alignment::Vertical::Top,
             style: Default::default(),
+            clip: false,
             content,
         }
     }
@@ -132,6 +134,13 @@ where
         self.style = style.into();
         self
     }
+
+    /// Sets whether the contents of the [`Container`] should be clipped on
+    /// overflow.
+    pub fn clip(mut self, clip: bool) -> Self {
+        self.clip = clip;
+        self
+    }
 }
 
 impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
@@ -255,7 +264,7 @@ where
     ) {
         let style = theme.appearance(&self.style);
 
-        if let Some(viewport) = layout.bounds().intersection(viewport) {
+        if let Some(clipped_viewport) = layout.bounds().intersection(viewport) {
             draw_background(renderer, &style, layout.bounds());
 
             self.content.as_widget().draw(
@@ -269,7 +278,11 @@ where
                 },
                 layout.children().next().unwrap(),
                 cursor,
-                &viewport,
+                if self.clip {
+                    &clipped_viewport
+                } else {
+                    viewport
+                },
             );
         }
     }
diff --git a/widget/src/row.rs b/widget/src/row.rs
index 7f8c3354..460b6b0c 100644
--- a/widget/src/row.rs
+++ b/widget/src/row.rs
@@ -18,6 +18,7 @@ pub struct Row<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer> {
     width: Length,
     height: Length,
     align_items: Alignment,
+    clip: bool,
     children: Vec<Element<'a, Message, Theme, Renderer>>,
 }
 
@@ -33,6 +34,7 @@ where
             width: Length::Shrink,
             height: Length::Shrink,
             align_items: Alignment::Start,
+            clip: false,
             children: Vec::new(),
         }
     }
@@ -78,6 +80,13 @@ where
         self
     }
 
+    /// Sets whether the contents of the [`Column`] should be clipped on
+    /// overflow.
+    pub fn clip(mut self, clip: bool) -> Self {
+        self.clip = clip;
+        self
+    }
+
     /// Adds an [`Element`] to the [`Row`].
     pub fn push(
         mut self,
@@ -229,7 +238,7 @@ where
         cursor: mouse::Cursor,
         viewport: &Rectangle,
     ) {
-        if let Some(viewport) = layout.bounds().intersection(viewport) {
+        if let Some(clipped_viewport) = layout.bounds().intersection(viewport) {
             for ((child, state), layout) in self
                 .children
                 .iter()
@@ -237,7 +246,17 @@ where
                 .zip(layout.children())
             {
                 child.as_widget().draw(
-                    state, renderer, theme, style, layout, cursor, &viewport,
+                    state,
+                    renderer,
+                    theme,
+                    style,
+                    layout,
+                    cursor,
+                    if self.clip {
+                        &clipped_viewport
+                    } else {
+                        viewport
+                    },
                 );
             }
         }
-- 
cgit