mirror of
https://github.com/danbulant/cushy
synced 2026-09-18 05:53:46 +00:00
Vertical sliders/progress bars
Also fixed checkbox layout after Label no longer pads itself.
This commit is contained in:
parent
eee336eab0
commit
46a0758d09
6 changed files with 109 additions and 121 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -643,7 +643,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "figures"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/khonsulabs/figures#40045fa1940f6212bc4876a4ef9ae2cd0bd89808"
|
||||
source = "git+https://github.com/khonsulabs/figures#4de8f5965bc7f9fc12369b2af93068e9da7a2446"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"euclid",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ use gooey::widgets::progress::Progressable;
|
|||
use gooey::widgets::slider::Slidable;
|
||||
use gooey::widgets::Checkbox;
|
||||
use gooey::Run;
|
||||
use kludgine::figures::units::Lp;
|
||||
use kludgine::figures::Size;
|
||||
|
||||
fn main() -> gooey::Result {
|
||||
let indeterminant = Dynamic::new(false);
|
||||
|
|
@ -12,10 +14,18 @@ fn main() -> gooey::Result {
|
|||
.map_each(|(&indeterminant, &value)| (!indeterminant).then_some(value));
|
||||
|
||||
value
|
||||
.clone()
|
||||
.slider()
|
||||
.and(progress.progress_bar())
|
||||
.and(progress.clone().progress_bar())
|
||||
.and(Checkbox::new(indeterminant.clone(), "Indeterminant"))
|
||||
.into_rows()
|
||||
.fit_horizontally()
|
||||
.expand()
|
||||
.and(value.slider())
|
||||
.and(progress.progress_bar())
|
||||
.into_columns()
|
||||
.pad()
|
||||
.size(Size::squared(Lp::inches(3)))
|
||||
.centered()
|
||||
.expand()
|
||||
.run()
|
||||
|
|
|
|||
|
|
@ -708,6 +708,15 @@ pub trait MakeWidget: Sized {
|
|||
Expand::horizontal(self)
|
||||
}
|
||||
|
||||
/// Resizes `self` to `size`.
|
||||
#[must_use]
|
||||
fn size<T>(self, size: Size<T>) -> Resize
|
||||
where
|
||||
T: Into<DimensionRange>,
|
||||
{
|
||||
Resize::to(size, self)
|
||||
}
|
||||
|
||||
/// Resizes `self` to `width`.
|
||||
///
|
||||
/// `width` can be an any of:
|
||||
|
|
|
|||
|
|
@ -159,10 +159,15 @@ impl WrapperWidget for CheckboxLabel {
|
|||
) -> WrappedLayout {
|
||||
let checkbox_size = context.get(&LineHeight).into_px(context.gfx.scale()); // TODO create a component?
|
||||
let padding = context.get(&IntrinsicPadding).into_px(context.gfx.scale());
|
||||
let label_inset = checkbox_size + padding;
|
||||
let size_with_checkbox = Size::new(size.width + label_inset, size.height).into_unsigned();
|
||||
let label_inset = checkbox_size + padding * 2;
|
||||
let effective_height = size.height.max(label_inset);
|
||||
let size_with_checkbox =
|
||||
Size::new(size.width + label_inset + padding, effective_height).into_unsigned();
|
||||
WrappedLayout {
|
||||
child: Rect::new(Point::new(label_inset, Px::ZERO), size),
|
||||
child: Rect::new(
|
||||
Point::new(label_inset, Px::ZERO),
|
||||
Size::new(size.width, effective_height),
|
||||
),
|
||||
size: size_with_checkbox,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::time::Duration;
|
|||
|
||||
use kludgine::figures::Ranged;
|
||||
|
||||
use crate::animation::easings::EaseInOutSine;
|
||||
use crate::animation::easings::EaseInOutQuadradic;
|
||||
use crate::animation::{
|
||||
AnimationHandle, AnimationTarget, IntoAnimate, PercentBetween, Spawn, ZeroToOne,
|
||||
};
|
||||
|
|
@ -82,37 +82,39 @@ fn update_progress_bar(
|
|||
) {
|
||||
match progress {
|
||||
Progress::Indeterminant => {
|
||||
*indeterminant_animation = Some(
|
||||
end.transition_to(ZeroToOne::new(0.66))
|
||||
.over(Duration::from_millis(500))
|
||||
.with_easing(EaseInOutSine)
|
||||
.and_then(
|
||||
start
|
||||
.transition_to(ZeroToOne::new(0.33))
|
||||
.over(Duration::from_millis(500))
|
||||
.with_easing(EaseInOutSine),
|
||||
if indeterminant_animation.is_none() {
|
||||
*indeterminant_animation = Some(
|
||||
(
|
||||
start.transition_to(ZeroToOne::ZERO),
|
||||
end.transition_to(ZeroToOne::ZERO),
|
||||
)
|
||||
.and_then(
|
||||
end.transition_to(ZeroToOne::ONE)
|
||||
.over(Duration::from_millis(500))
|
||||
.with_easing(EaseInOutSine),
|
||||
)
|
||||
.and_then(
|
||||
start
|
||||
.transition_to(ZeroToOne::ONE)
|
||||
.over(Duration::from_millis(500))
|
||||
.with_easing(EaseInOutSine),
|
||||
)
|
||||
.and_then(
|
||||
(
|
||||
start.transition_to(ZeroToOne::ZERO),
|
||||
end.transition_to(ZeroToOne::ZERO),
|
||||
.over(Duration::ZERO)
|
||||
.and_then(
|
||||
end.transition_to(ZeroToOne::new(0.66))
|
||||
.over(Duration::from_millis(500))
|
||||
.with_easing(EaseInOutQuadradic),
|
||||
)
|
||||
.over(Duration::ZERO),
|
||||
)
|
||||
.cycle()
|
||||
.spawn(),
|
||||
);
|
||||
.and_then(
|
||||
start
|
||||
.transition_to(ZeroToOne::new(0.33))
|
||||
.over(Duration::from_millis(500))
|
||||
.with_easing(EaseInOutQuadradic),
|
||||
)
|
||||
.and_then(
|
||||
end.transition_to(ZeroToOne::ONE)
|
||||
.over(Duration::from_millis(500))
|
||||
.with_easing(EaseInOutQuadradic),
|
||||
)
|
||||
.and_then(
|
||||
start
|
||||
.transition_to(ZeroToOne::ONE)
|
||||
.over(Duration::from_millis(500))
|
||||
.with_easing(EaseInOutQuadradic),
|
||||
)
|
||||
.cycle()
|
||||
.spawn(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Progress::Percent(value) => {
|
||||
let _stopped_animation = indeterminant_animation.take();
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ use kludgine::app::winit::event::{DeviceId, MouseButton, MouseScrollDelta, Touch
|
|||
use kludgine::app::winit::keyboard::{Key, NamedKey};
|
||||
use kludgine::figures::units::{Lp, Px, UPx};
|
||||
use kludgine::figures::{
|
||||
FloatConversion, FromComponents, IntoComponents, IntoSigned, Point, Ranged, Rect, Round,
|
||||
ScreenScale, Size,
|
||||
FloatConversion, IntoSigned, Point, Ranged, Rect, Round, ScreenScale, Size,
|
||||
};
|
||||
use kludgine::shapes::{Shape, StrokeOptions};
|
||||
use kludgine::{Color, DrawableExt, Origin};
|
||||
|
|
@ -155,7 +154,7 @@ where
|
|||
let half_focus_ring =
|
||||
spec.if_knobbed(|| (Lp::points(2).into_px(context.gfx.scale()) / 2).ceil());
|
||||
let focus_ring = half_focus_ring * 2;
|
||||
let track_length = self.rendered_size - spec.if_knobbed(|| spec.knob_size - focus_ring);
|
||||
let track_length = self.rendered_size - spec.if_knobbed(|| spec.knob_size + focus_ring);
|
||||
let (start, end) = if let Some(end) = spec.end {
|
||||
(track_length * spec.start, track_length * end)
|
||||
} else {
|
||||
|
|
@ -169,10 +168,10 @@ where
|
|||
if start > 0 {
|
||||
context.gfx.draw_shape(
|
||||
Shape::filled_round_rect(
|
||||
Rect::new(
|
||||
flipped(!self.horizontal, Point::new(start_inset, start_inset)),
|
||||
flipped(!self.horizontal, Size::new(start, spec.track_size)),
|
||||
),
|
||||
self.orient_rectangle(Rect::new(
|
||||
Point::new(start_inset, start_inset),
|
||||
Size::new(start, spec.track_size),
|
||||
)),
|
||||
half_track,
|
||||
spec.inactive_track_color,
|
||||
)
|
||||
|
|
@ -182,19 +181,13 @@ where
|
|||
if end < track_length {
|
||||
context.gfx.draw_shape(
|
||||
Shape::filled_round_rect(
|
||||
Rect::new(
|
||||
flipped(
|
||||
!self.horizontal,
|
||||
Point::new(end + spec.if_knobbed(|| spec.half_knob), start_inset),
|
||||
self.orient_rectangle(Rect::new(
|
||||
Point::new(end + spec.if_knobbed(|| spec.half_knob), start_inset),
|
||||
Size::new(
|
||||
track_length - end + spec.if_knobbed(|| half_track),
|
||||
spec.track_size,
|
||||
),
|
||||
flipped(
|
||||
!self.horizontal,
|
||||
Size::new(
|
||||
track_length - end + spec.if_knobbed(|| half_track),
|
||||
spec.track_size,
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
half_track,
|
||||
spec.inactive_track_color,
|
||||
)
|
||||
|
|
@ -205,22 +198,16 @@ where
|
|||
if start != end {
|
||||
context.gfx.draw_shape(
|
||||
Shape::filled_round_rect(
|
||||
Rect::new(
|
||||
flipped(
|
||||
!self.horizontal,
|
||||
Point::new(
|
||||
start + spec.if_knobbed(|| spec.half_knob - half_track),
|
||||
start_inset,
|
||||
),
|
||||
self.orient_rectangle(Rect::new(
|
||||
Point::new(
|
||||
start + spec.if_knobbed(|| spec.half_knob - half_track),
|
||||
start_inset,
|
||||
),
|
||||
flipped(
|
||||
!self.horizontal,
|
||||
Size::new(
|
||||
end - start + spec.if_knobbed(|| spec.track_size),
|
||||
spec.track_size,
|
||||
),
|
||||
Size::new(
|
||||
end - start + spec.if_knobbed(|| spec.track_size),
|
||||
spec.track_size,
|
||||
),
|
||||
),
|
||||
)),
|
||||
half_track,
|
||||
spec.track_color,
|
||||
)
|
||||
|
|
@ -231,14 +218,10 @@ where
|
|||
// Draw the knob
|
||||
if spec.knob_size > 0 {
|
||||
let focus = context.focused().then_some(self.focused_knob).flatten();
|
||||
self.draw_knobs(
|
||||
flipped(
|
||||
!self.horizontal,
|
||||
Point::new(end + spec.half_knob, spec.half_knob) + inset,
|
||||
),
|
||||
Self::draw_knobs(
|
||||
self.flip_pt_if_vertical(Point::new(end + spec.half_knob, spec.half_knob) + inset),
|
||||
spec.end.map(|_| {
|
||||
flipped(
|
||||
!self.horizontal,
|
||||
self.flip_pt_if_vertical(
|
||||
Point::new(start + spec.half_knob, spec.half_knob) + inset,
|
||||
)
|
||||
}),
|
||||
|
|
@ -247,39 +230,10 @@ where
|
|||
spec,
|
||||
context,
|
||||
);
|
||||
// let this_knob_role = if spec.end.is_some() {
|
||||
// Knob::End
|
||||
// } else {
|
||||
// Knob::Start
|
||||
// };
|
||||
// self.draw_knob(
|
||||
// flipped(
|
||||
// !self.horizontal,
|
||||
// Point::new(end + spec.half_knob, spec.half_knob) + inset,
|
||||
// ),
|
||||
// focused && self.focused_knob == Some(this_knob_role),
|
||||
// focus_ring,
|
||||
// spec,
|
||||
// context,
|
||||
// );
|
||||
|
||||
// if spec.end.is_some() {
|
||||
// self.draw_knob(
|
||||
// flipped(
|
||||
// !self.horizontal,
|
||||
// Point::new(start + spec.half_knob, spec.half_knob) + inset,
|
||||
// ),
|
||||
// focused && matches!(self.focused_knob, Some(Knob::Start)),
|
||||
// focus_ring,
|
||||
// spec,
|
||||
// context,
|
||||
// );
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_knobs(
|
||||
&mut self,
|
||||
end_knob: Point<Px>,
|
||||
start_knob: Option<Point<Px>>,
|
||||
focus: Option<Knob>,
|
||||
|
|
@ -293,14 +247,13 @@ where
|
|||
(None, focus) => (end_knob, focus.is_some(), None),
|
||||
};
|
||||
|
||||
self.draw_knob(a, a_is_focused, focus_ring_width, spec, context);
|
||||
Self::draw_knob(a, a_is_focused, focus_ring_width, spec, context);
|
||||
if let Some((b, b_is_focused)) = b {
|
||||
self.draw_knob(b, b_is_focused, focus_ring_width, spec, context);
|
||||
Self::draw_knob(b, b_is_focused, focus_ring_width, spec, context);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_knob(
|
||||
&mut self,
|
||||
knob_center: Point<Px>,
|
||||
is_focused: bool,
|
||||
focus_ring_width: Px,
|
||||
|
|
@ -309,7 +262,7 @@ where
|
|||
) {
|
||||
context.gfx.draw_shape(
|
||||
Shape::filled_circle(spec.half_knob, spec.knob_color, Origin::Center)
|
||||
.translate_by(flipped(!self.horizontal, knob_center)),
|
||||
.translate_by(knob_center),
|
||||
);
|
||||
|
||||
if is_focused {
|
||||
|
|
@ -336,7 +289,7 @@ where
|
|||
let position = if self.horizontal {
|
||||
position.x - knob_size / 2
|
||||
} else {
|
||||
position.y - knob_size / 2
|
||||
self.rendered_size - position.y - knob_size / 2
|
||||
};
|
||||
let track_width = self.rendered_size - knob_size;
|
||||
let position = position.clamp(Px::ZERO, track_width);
|
||||
|
|
@ -439,6 +392,27 @@ where
|
|||
self.value.update(T::from_parts(start, end));
|
||||
}
|
||||
}
|
||||
|
||||
fn orient_rectangle(&self, rect: Rect<Px>) -> Rect<Px> {
|
||||
if self.horizontal {
|
||||
rect
|
||||
} else {
|
||||
let (tl, br) = rect.extents();
|
||||
|
||||
Rect::from_extents(
|
||||
Point::new(tl.y, self.rendered_size - tl.x),
|
||||
Point::new(br.y, self.rendered_size - br.x),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn flip_pt_if_vertical(&self, pt: Point<Px>) -> Point<Px> {
|
||||
if self.horizontal {
|
||||
pt
|
||||
} else {
|
||||
Point::new(pt.y, self.rendered_size - pt.x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Widget for Slider<T>
|
||||
|
|
@ -742,18 +716,6 @@ impl TrackSpec {
|
|||
}
|
||||
}
|
||||
|
||||
fn flipped<T, Unit>(flip: bool, value: T) -> T
|
||||
where
|
||||
T: IntoComponents<Unit> + FromComponents<Unit>,
|
||||
{
|
||||
if flip {
|
||||
let (a, b) = value.into_components();
|
||||
T::from_components((b, a))
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
define_components! {
|
||||
Slider {
|
||||
/// The size of the track that the knob of a [`Slider`] traversesq.
|
||||
|
|
|
|||
Loading…
Reference in a new issue