diff --git a/examples/application/src/main.rs b/examples/application/src/main.rs index 85182f58..bceece6e 100644 --- a/examples/application/src/main.rs +++ b/examples/application/src/main.rs @@ -230,6 +230,7 @@ impl cosmic::Application for App { ) .push( widget::progress_bar::circular::Circular::new() + .bar_height(10.0) .size(50.0) .progress(self.progress), ) diff --git a/src/widget/progress_bar/circular.rs b/src/widget/progress_bar/circular.rs index 9af56237..4ed5785c 100644 --- a/src/widget/progress_bar/circular.rs +++ b/src/widget/progress_bar/circular.rs @@ -306,6 +306,33 @@ where ); if let Some(progress) = self.progress { + // outer border + if let Some(border_color) = custom_style.border_color { + let border_path = + canvas::Path::circle(frame.center(), track_radius + self.bar_height / 2.0); + + frame.stroke( + &border_path, + canvas::Stroke::default() + .with_color(border_color) + .with_width(1.0), + ); + } + + // inner border + if let Some(border_color) = custom_style.border_color { + let border_path = + canvas::Path::circle(frame.center(), track_radius - self.bar_height / 2.0); + + frame.stroke( + &border_path, + canvas::Stroke::default() + .with_color(border_color) + .with_width(1.0), + ); + } + + // bar let mut builder = canvas::path::Builder::new(); builder.arc(canvas::path::Arc { @@ -323,29 +350,53 @@ where .with_color(custom_style.bar_color) .with_width(self.bar_height), ); + + let mut builder = canvas::path::Builder::new(); + + // get center of end of arc for rounded cap + let end_angle = -PI / 2.0 + progress * 2.0 * PI; + let end_center = + frame.center() + Vector::new(end_angle.cos(), end_angle.sin()) * track_radius; + builder.arc(canvas::path::Arc { + center: end_center, + radius: self.bar_height / 2.0, + start_angle: Radians(end_angle), + end_angle: Radians(end_angle + PI), + }); + + // get center of start of arc for rounded cap + let start_angle = -PI / 2.0; + let start_center = frame.center() + + Vector::new(start_angle.cos(), start_angle.sin()) * track_radius; + builder.arc(canvas::path::Arc { + center: start_center, + radius: self.bar_height / 2.0, + start_angle: Radians(start_angle - PI), + end_angle: Radians(start_angle), + }); + + let cap_path = builder.build(); + frame.fill(&cap_path, custom_style.bar_color); } else { let mut builder = canvas::path::Builder::new(); let start = Radians(state.animation.rotation() * 2.0 * PI); - - match state.animation { - Animation::Expanding { progress, .. } => { - builder.arc(canvas::path::Arc { - center: frame.center(), - radius: track_radius, - start_angle: start, - end_angle: start + MIN_ANGLE + WRAP_ANGLE * (smootherstep(progress)), - }); - } - Animation::Contracting { progress, .. } => { - builder.arc(canvas::path::Arc { - center: frame.center(), - radius: track_radius, - start_angle: start + WRAP_ANGLE * (smootherstep(progress)), - end_angle: start + MIN_ANGLE + WRAP_ANGLE, - }); - } - } + let (start_angle, end_angle) = match state.animation { + Animation::Expanding { progress, .. } => ( + start, + start + MIN_ANGLE + WRAP_ANGLE * (smootherstep(progress)), + ), + Animation::Contracting { progress, .. } => ( + start + WRAP_ANGLE * (smootherstep(progress)), + start + MIN_ANGLE + WRAP_ANGLE, + ), + }; + builder.arc(canvas::path::Arc { + center: frame.center(), + radius: track_radius, + start_angle, + end_angle, + }); let bar_path = builder.build(); @@ -355,6 +406,31 @@ where .with_color(custom_style.bar_color) .with_width(self.bar_height), ); + + let mut builder = canvas::path::Builder::new(); + + // get center of end of arc for rounded cap + let end_center = frame.center() + + Vector::new(end_angle.0.cos(), end_angle.0.sin()) * track_radius; + builder.arc(canvas::path::Arc { + center: end_center, + radius: self.bar_height / 2.0, + start_angle: Radians(end_angle.0), + end_angle: Radians(end_angle.0 + PI), + }); + + // get center of start of arc for rounded cap + let start_center = frame.center() + + Vector::new(start_angle.0.cos(), start_angle.0.sin()) * track_radius; + builder.arc(canvas::path::Arc { + center: start_center, + radius: self.bar_height / 2.0, + start_angle: Radians(start_angle.0 - PI), + end_angle: Radians(start_angle.0), + }); + + let cap_path = builder.build(); + frame.fill(&cap_path, custom_style.bar_color); } }); diff --git a/src/widget/progress_bar/linear.rs b/src/widget/progress_bar/linear.rs index f15d2855..255b4142 100644 --- a/src/widget/progress_bar/linear.rs +++ b/src/widget/progress_bar/linear.rs @@ -216,6 +216,16 @@ where width: bounds.width, height: bounds.height, }, + border: iced::Border { + width: if custom_style.border_color.is_some() { + 1.0 + } else { + 0.0 + }, + color: custom_style.border_color.unwrap_or(custom_style.bar_color), + radius: custom_style.border_radius.into(), + }, + snap: true, ..renderer::Quad::default() }, Background::Color(custom_style.track_color), @@ -230,6 +240,12 @@ where width: progress * bounds.width, height: bounds.height, }, + border: iced::Border { + width: 0., + color: iced::Color::TRANSPARENT, + radius: custom_style.border_radius.into(), + }, + snap: true, ..renderer::Quad::default() }, Background::Color(custom_style.bar_color), @@ -244,6 +260,12 @@ where width: smootherstep(*progress) * bounds.width, height: bounds.height, }, + border: iced::Border { + width: 0., + color: iced::Color::TRANSPARENT, + radius: custom_style.border_radius.into(), + }, + snap: true, ..renderer::Quad::default() }, Background::Color(custom_style.bar_color), @@ -257,6 +279,12 @@ where width: (1.0 - smootherstep(*progress)) * bounds.width, height: bounds.height, }, + border: iced::Border { + width: 0., + color: iced::Color::TRANSPARENT, + radius: custom_style.border_radius.into(), + }, + snap: true, ..renderer::Quad::default() }, Background::Color(custom_style.bar_color), diff --git a/src/widget/progress_bar/style.rs b/src/widget/progress_bar/style.rs index b4387d98..db2fe64d 100644 --- a/src/widget/progress_bar/style.rs +++ b/src/widget/progress_bar/style.rs @@ -8,6 +8,8 @@ pub struct Appearance { pub bar_color: Color, /// The border [`Color`] of the progress indicator. pub border_color: Option, + /// The border radius of the progress indicator. + pub border_radius: f32, } impl std::default::Default for Appearance { @@ -16,6 +18,7 @@ impl std::default::Default for Appearance { track_color: Color::TRANSPARENT, bar_color: Color::BLACK, border_color: None, + border_radius: 0.0, } } } @@ -49,6 +52,7 @@ impl StyleSheet for iced::Theme { track_color: palette.background.weak.color, bar_color: palette.primary.base.color, border_color: None, + border_radius: 0.0, } } } @@ -63,7 +67,8 @@ impl StyleSheet for crate::Theme { is_circular: bool, ) -> Appearance { let cur = self.current_container(); - let cur_divider = cur.divider; + let mut cur_divider = cur.divider; + cur_divider.alpha = 0.5; let theme = self.cosmic(); let (mut track_color, bar_color) = if theme.is_dark && theme.is_high_contrast { @@ -94,6 +99,7 @@ impl StyleSheet for crate::Theme { } else { None }, + border_radius: theme.corner_radii.radius_xl[0], } } } diff --git a/src/widget/segmented_button/widget.rs b/src/widget/segmented_button/widget.rs index a2efdfb8..5d862e9f 100644 --- a/src/widget/segmented_button/widget.rs +++ b/src/widget/segmented_button/widget.rs @@ -262,10 +262,10 @@ where font.hash(&mut hasher); let text_hash = hasher.finish(); - if let Some(prev_hash) = state.text_hashes.insert(key, text_hash) { - if prev_hash == text_hash { - return; - } + if let Some(prev_hash) = state.text_hashes.insert(key, text_hash) + && prev_hash == text_hash + { + return; } if let Some(paragraph) = state.paragraphs.get_mut(key) { @@ -928,7 +928,6 @@ where fn diff(&mut self, tree: &mut Tree) { let state = tree.state.downcast_mut::(); - for key in self.model.order.iter().copied() { self.update_entity_paragraph(state, key); }