improv(circular): prevent caps from touching
Some checks failed
Continuous Integration / format (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "applet") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "desktop,smol") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "desktop,tokio") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "wayland") (push) Has been cancelled
Pages / pages (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "winit") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "winit_debug") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "winit_tokio") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "winit_wgpu") (push) Has been cancelled
Continuous Integration / tests (-p cosmic-theme) (push) Has been cancelled
Continuous Integration / examples (application) (push) Has been cancelled
Continuous Integration / examples (context-menu) (push) Has been cancelled
Continuous Integration / examples (nav-context) (push) Has been cancelled
Continuous Integration / examples (open-dialog) (push) Has been cancelled
Some checks failed
Continuous Integration / format (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "applet") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "desktop,smol") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "desktop,tokio") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "wayland") (push) Has been cancelled
Pages / pages (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "winit") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "winit_debug") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "winit_tokio") (push) Has been cancelled
Continuous Integration / tests (--no-default-features --features "winit_wgpu") (push) Has been cancelled
Continuous Integration / tests (-p cosmic-theme) (push) Has been cancelled
Continuous Integration / examples (application) (push) Has been cancelled
Continuous Integration / examples (context-menu) (push) Has been cancelled
Continuous Integration / examples (nav-context) (push) Has been cancelled
Continuous Integration / examples (open-dialog) (push) Has been cancelled
This commit is contained in:
parent
c423ad1bfc
commit
95756b1a57
3 changed files with 36 additions and 25 deletions
|
|
@ -21,4 +21,5 @@ features = [
|
||||||
"single-instance",
|
"single-instance",
|
||||||
"surface-message",
|
"surface-message",
|
||||||
"multi-window",
|
"multi-window",
|
||||||
|
"wgpu",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ impl cosmic::Application for App {
|
||||||
.map_or("No page selected", String::as_str);
|
.map_or("No page selected", String::as_str);
|
||||||
|
|
||||||
let centered = widget::container(
|
let centered = widget::container(
|
||||||
widget::column::with_capacity(5)
|
widget::column::with_capacity(14)
|
||||||
.push(widget::text::body(page_content))
|
.push(widget::text::body(page_content))
|
||||||
.push(
|
.push(
|
||||||
widget::text_input::text_input("", &self.input_1)
|
widget::text_input::text_input("", &self.input_1)
|
||||||
|
|
@ -223,6 +223,7 @@ impl cosmic::Application for App {
|
||||||
.on_clear(Message::Ignore),
|
.on_clear(Message::Ignore),
|
||||||
)
|
)
|
||||||
.push(widget::progress_bar::circular::Circular::new().size(50.0))
|
.push(widget::progress_bar::circular::Circular::new().size(50.0))
|
||||||
|
.push(widget::progress_bar::circular::Circular::new().size(20.0))
|
||||||
.push(
|
.push(
|
||||||
widget::progress_bar::linear::Linear::new()
|
widget::progress_bar::linear::Linear::new()
|
||||||
.girth(10.0)
|
.girth(10.0)
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ use std::f32::consts::PI;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
const MIN_ANGLE: Radians = Radians(PI / 8.0);
|
const MIN_ANGLE: Radians = Radians(PI / 8.0);
|
||||||
const WRAP_ANGLE: Radians = Radians(2.0 * PI - PI / 4.0);
|
|
||||||
const BASE_ROTATION_SPEED: u32 = u32::MAX / 80;
|
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct Circular<Theme>
|
pub struct Circular<Theme>
|
||||||
|
|
@ -83,6 +81,12 @@ where
|
||||||
self.progress = Some(progress.clamp(0.0, 1.0));
|
self.progress = Some(progress.clamp(0.0, 1.0));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn min_wrap_angle(&self, track_radius: f32) -> (f32, f32) {
|
||||||
|
let cap_angle = self.bar_height / track_radius;
|
||||||
|
let gap = MIN_ANGLE.0.max(cap_angle);
|
||||||
|
(gap - cap_angle, 2.0 * PI - gap * 2.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Theme> Default for Circular<Theme>
|
impl<Theme> Default for Circular<Theme>
|
||||||
|
|
@ -122,7 +126,7 @@ impl Default for Animation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Animation {
|
impl Animation {
|
||||||
fn next(&self, additional_rotation: u32, now: Instant) -> Self {
|
fn next(&self, additional_rotation: u32, wrap_angle: f32, now: Instant) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Expanding { rotation, .. } => Self::Contracting {
|
Self::Expanding { rotation, .. } => Self::Contracting {
|
||||||
start: now,
|
start: now,
|
||||||
|
|
@ -133,9 +137,9 @@ impl Animation {
|
||||||
Self::Contracting { rotation, .. } => Self::Expanding {
|
Self::Contracting { rotation, .. } => Self::Expanding {
|
||||||
start: now,
|
start: now,
|
||||||
progress: 0.0,
|
progress: 0.0,
|
||||||
rotation: rotation.wrapping_add(BASE_ROTATION_SPEED.wrapping_add(
|
rotation: rotation.wrapping_add(
|
||||||
(f64::from(WRAP_ANGLE / (2.0 * Radians::PI)) * f64::from(u32::MAX)) as u32,
|
(f64::from((wrap_angle) / (2.0 * PI)) * f64::from(u32::MAX)) as u32,
|
||||||
)),
|
),
|
||||||
last: now,
|
last: now,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -157,6 +161,7 @@ impl Animation {
|
||||||
&self,
|
&self,
|
||||||
cycle_duration: Duration,
|
cycle_duration: Duration,
|
||||||
rotation_duration: Duration,
|
rotation_duration: Duration,
|
||||||
|
wrap_angle: f32,
|
||||||
now: Instant,
|
now: Instant,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let elapsed = now.duration_since(self.start());
|
let elapsed = now.duration_since(self.start());
|
||||||
|
|
@ -165,7 +170,7 @@ impl Animation {
|
||||||
* (u32::MAX) as f32) as u32;
|
* (u32::MAX) as f32) as u32;
|
||||||
|
|
||||||
match elapsed {
|
match elapsed {
|
||||||
elapsed if elapsed > cycle_duration => self.next(additional_rotation, now),
|
elapsed if elapsed > cycle_duration => self.next(additional_rotation, wrap_angle, now),
|
||||||
_ => self.with_elapsed(cycle_duration, additional_rotation, elapsed, now),
|
_ => self.with_elapsed(cycle_duration, additional_rotation, elapsed, now),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -267,10 +272,13 @@ where
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Event::Window(window::Event::RedrawRequested(now)) = event {
|
if let Event::Window(window::Event::RedrawRequested(now)) = event {
|
||||||
state.animation =
|
let (_, wrap_angle) = self.min_wrap_angle(self.size / 2.0 - self.bar_height);
|
||||||
state
|
state.animation = state.animation.timed_transition(
|
||||||
.animation
|
self.cycle_duration,
|
||||||
.timed_transition(self.cycle_duration, self.rotation_duration, *now);
|
self.rotation_duration,
|
||||||
|
wrap_angle,
|
||||||
|
*now,
|
||||||
|
);
|
||||||
|
|
||||||
state.cache.clear();
|
state.cache.clear();
|
||||||
shell.request_redraw();
|
shell.request_redraw();
|
||||||
|
|
@ -380,22 +388,23 @@ where
|
||||||
} else {
|
} else {
|
||||||
let mut builder = canvas::path::Builder::new();
|
let mut builder = canvas::path::Builder::new();
|
||||||
|
|
||||||
let start = Radians(state.animation.rotation() * 2.0 * PI);
|
let start = state.animation.rotation() * 2.0 * PI;
|
||||||
|
let (min_angle, wrap_angle) = self.min_wrap_angle(track_radius);
|
||||||
let (start_angle, end_angle) = match state.animation {
|
let (start_angle, end_angle) = match state.animation {
|
||||||
Animation::Expanding { progress, .. } => (
|
Animation::Expanding { progress, .. } => (
|
||||||
start,
|
start,
|
||||||
start + MIN_ANGLE + WRAP_ANGLE * (smootherstep(progress)),
|
start + min_angle + wrap_angle * smootherstep(progress),
|
||||||
),
|
),
|
||||||
Animation::Contracting { progress, .. } => (
|
Animation::Contracting { progress, .. } => (
|
||||||
start + WRAP_ANGLE * (smootherstep(progress)),
|
start + wrap_angle * smootherstep(progress),
|
||||||
start + MIN_ANGLE + WRAP_ANGLE,
|
start + min_angle + wrap_angle,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
builder.arc(canvas::path::Arc {
|
builder.arc(canvas::path::Arc {
|
||||||
center: frame.center(),
|
center: frame.center(),
|
||||||
radius: track_radius,
|
radius: track_radius,
|
||||||
start_angle,
|
start_angle: Radians(start_angle),
|
||||||
end_angle,
|
end_angle: Radians(end_angle),
|
||||||
});
|
});
|
||||||
|
|
||||||
let bar_path = builder.build();
|
let bar_path = builder.build();
|
||||||
|
|
@ -410,23 +419,23 @@ where
|
||||||
let mut builder = canvas::path::Builder::new();
|
let mut builder = canvas::path::Builder::new();
|
||||||
|
|
||||||
// get center of end of arc for rounded cap
|
// get center of end of arc for rounded cap
|
||||||
let end_center = frame.center()
|
let end_center =
|
||||||
+ Vector::new(end_angle.0.cos(), end_angle.0.sin()) * track_radius;
|
frame.center() + Vector::new(end_angle.cos(), end_angle.sin()) * track_radius;
|
||||||
builder.arc(canvas::path::Arc {
|
builder.arc(canvas::path::Arc {
|
||||||
center: end_center,
|
center: end_center,
|
||||||
radius: self.bar_height / 2.0,
|
radius: self.bar_height / 2.0,
|
||||||
start_angle: Radians(end_angle.0),
|
start_angle: Radians(end_angle),
|
||||||
end_angle: Radians(end_angle.0 + PI),
|
end_angle: Radians(end_angle + PI),
|
||||||
});
|
});
|
||||||
|
|
||||||
// get center of start of arc for rounded cap
|
// get center of start of arc for rounded cap
|
||||||
let start_center = frame.center()
|
let start_center = frame.center()
|
||||||
+ Vector::new(start_angle.0.cos(), start_angle.0.sin()) * track_radius;
|
+ Vector::new(start_angle.cos(), start_angle.sin()) * track_radius;
|
||||||
builder.arc(canvas::path::Arc {
|
builder.arc(canvas::path::Arc {
|
||||||
center: start_center,
|
center: start_center,
|
||||||
radius: self.bar_height / 2.0,
|
radius: self.bar_height / 2.0,
|
||||||
start_angle: Radians(start_angle.0 - PI),
|
start_angle: Radians(start_angle - PI),
|
||||||
end_angle: Radians(start_angle.0),
|
end_angle: Radians(start_angle),
|
||||||
});
|
});
|
||||||
|
|
||||||
let cap_path = builder.build();
|
let cap_path = builder.build();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue