diff --git a/CHANGELOG.md b/CHANGELOG.md index 14e72d07a5..2b5dc7769a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support for generic `Element` in `Tooltip`. [#2228](https://github.com/iced-rs/iced/pull/2228) - Container and `gap` styling for `Scrollable`. [#2239](https://github.com/iced-rs/iced/pull/2239) - Use `Borrow` for both `options` and `selected` in PickList. [#2251](https://github.com/iced-rs/iced/pull/2251) +- `clip` property for `Container`, `Column`, `Row`, and `Button`. #[2252](https://github.com/iced-rs/iced/pull/2252) ### Changed - Enable WebGPU backend in `wgpu` by default instead of WebGL. [#2068](https://github.com/iced-rs/iced/pull/2068) diff --git a/widget/src/button.rs b/widget/src/button.rs index d16e8c6787..867fbfaf59 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -61,6 +61,7 @@ where width: Length, height: Length, padding: Padding, + clip: bool, style: Theme::Style, } @@ -82,6 +83,7 @@ where width: size.width.fluid(), height: size.height.fluid(), padding: Padding::new(5.0), + clip: false, style: Theme::Style::default(), } } @@ -126,6 +128,13 @@ where self.style = style.into(); self } + + /// Sets whether the contents of the [`Button`] should be clipped on + /// overflow. + pub fn clip(mut self, clip: bool) -> Self { + self.clip = clip; + self + } } impl<'a, Message, Theme, Renderer> Widget @@ -227,7 +236,7 @@ where _style: &renderer::Style, layout: Layout<'_>, cursor: mouse::Cursor, - _viewport: &Rectangle, + viewport: &Rectangle, ) { let bounds = layout.bounds(); let content_layout = layout.children().next().unwrap(); @@ -242,6 +251,12 @@ where || tree.state.downcast_ref::(), ); + let viewport = if self.clip { + bounds.intersection(viewport).unwrap_or(*viewport) + } else { + *viewport + }; + self.content.as_widget().draw( &tree.children[0], renderer, @@ -251,7 +266,7 @@ where }, content_layout, cursor, - &bounds, + &viewport, ); } diff --git a/widget/src/column.rs b/widget/src/column.rs index 1e9841eee8..8154ad8532 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>, } @@ -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 4eb4a5d9bb..e01741778d 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 @@ -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 7f8c335418..735fbbc076 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>, } @@ -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 [`Row`] 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 + }, ); } }