mirror of
https://github.com/danbulant/cushy
synced 2026-05-24 12:28:23 +00:00
Rounded rect drawing
This commit is contained in:
parent
8ae315e229
commit
aea9def07d
5 changed files with 107 additions and 11 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -623,7 +623,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "figures"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/khonsulabs/figures#52d06f3623cdb47128f1537fdadfe190f7afa88e"
|
||||
source = "git+https://github.com/khonsulabs/figures#4712514fbed861ad530bd48d4e62f8efcaa4df1f"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"euclid",
|
||||
|
|
@ -1089,7 +1089,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
|||
[[package]]
|
||||
name = "kludgine"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/khonsulabs/kludgine#74db2e6be9c79f384eafbe57af8fa92de8b8d03c"
|
||||
source = "git+https://github.com/khonsulabs/kludgine#ca138e79a4b8ebc3bdd463006b1dadd3269183f3"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"alot",
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ use kludgine::app::winit::event::{
|
|||
DeviceId, Ime, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
};
|
||||
use kludgine::figures::units::{Lp, Px, UPx};
|
||||
use kludgine::figures::{IntoSigned, Point, Rect, ScreenScale, Size};
|
||||
use kludgine::figures::{IntoSigned, IsZero, Point, Rect, ScreenScale, Size};
|
||||
use kludgine::shapes::{Shape, StrokeOptions};
|
||||
use kludgine::{Color, Kludgine};
|
||||
|
||||
use crate::graphics::Graphics;
|
||||
use crate::styles::components::{HighlightColor, LayoutOrder, WidgetBackground};
|
||||
use crate::styles::components::{CornerRadius, HighlightColor, LayoutOrder, WidgetBackground};
|
||||
use crate::styles::{ComponentDefinition, Styles, Theme, ThemePair};
|
||||
use crate::utils::IgnorePoison;
|
||||
use crate::value::{Dynamic, IntoValue, Value};
|
||||
|
|
@ -519,15 +519,49 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, '
|
|||
}
|
||||
}
|
||||
|
||||
/// Fills the background of this widget with `color`, honoring the current
|
||||
/// [`CornerRadius`] setting.
|
||||
///
|
||||
/// If the alpha channel of `color` is 0, this function does nothing.
|
||||
pub fn fill(&mut self, color: Color) {
|
||||
if color.alpha() > 0 {
|
||||
let visible_rect = Rect::from(self.gfx.region().size - (Px(1), Px(1)));
|
||||
|
||||
let radii = self.get(&CornerRadius);
|
||||
let radii = radii.map(|r| r.into_px(self.gfx.scale()));
|
||||
|
||||
let focus_ring = if radii.is_zero() {
|
||||
Shape::filled_rect(visible_rect, color)
|
||||
} else {
|
||||
Shape::filled_round_rect(visible_rect, radii, color)
|
||||
};
|
||||
self.gfx.draw_shape(&focus_ring);
|
||||
}
|
||||
}
|
||||
|
||||
/// Strokes an outline around this widget's contents.
|
||||
pub fn stroke_outline<Unit>(&mut self, color: Color, options: StrokeOptions<Unit>)
|
||||
where
|
||||
Unit: ScreenScale<Px = Px, Lp = Lp, UPx = UPx>,
|
||||
Unit: ScreenScale<Px = Px, Lp = Lp, UPx = UPx> + IsZero,
|
||||
{
|
||||
let visible_rect = Rect::from(self.gfx.region().size - (Px(1), Px(1)));
|
||||
let focus_ring =
|
||||
Shape::stroked_rect(visible_rect, color, options.into_px(self.gfx.scale()));
|
||||
self.gfx.draw_shape(&focus_ring);
|
||||
if color.alpha() > 0 {
|
||||
let visible_rect = Rect::from(self.gfx.region().size - (Px(1), Px(1)));
|
||||
|
||||
let radii = self.get(&CornerRadius);
|
||||
let radii = radii.map(|r| r.into_px(self.gfx.scale()));
|
||||
|
||||
let focus_ring = if radii.is_zero() {
|
||||
Shape::stroked_rect(visible_rect, color, options.into_px(self.gfx.scale()))
|
||||
} else {
|
||||
Shape::stroked_round_rect(
|
||||
visible_rect,
|
||||
radii,
|
||||
color,
|
||||
options.into_px(self.gfx.scale()),
|
||||
)
|
||||
};
|
||||
self.gfx.draw_shape(&focus_ring);
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders the default focus ring for this widget.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ use std::sync::Arc;
|
|||
|
||||
use ahash::AHashMap;
|
||||
use kludgine::figures::units::{Lp, Px, UPx};
|
||||
use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, Rect, ScreenScale, Size};
|
||||
use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, IsZero, Rect, ScreenScale, Size};
|
||||
use kludgine::shapes::CornerRadii;
|
||||
use kludgine::Color;
|
||||
use palette::{IntoColor, Okhsl, OklabHue, Srgb};
|
||||
|
||||
|
|
@ -211,6 +212,18 @@ pub enum Component {
|
|||
Custom(CustomComponent),
|
||||
}
|
||||
|
||||
impl Component {
|
||||
/// Returns a [`CustomComponent`] created from `component`.
|
||||
///
|
||||
/// Custom components allow storing nearly any type in the style system.
|
||||
pub fn custom<T>(component: T) -> Self
|
||||
where
|
||||
T: RequireInvalidation + RefUnwindSafe + UnwindSafe + Debug + Send + Sync + 'static,
|
||||
{
|
||||
Self::Custom(CustomComponent::new(component))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for Component {
|
||||
fn from(value: Color) -> Self {
|
||||
Self::Color(value)
|
||||
|
|
@ -303,6 +316,42 @@ impl RequireInvalidation for Lp {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Unit> From<CornerRadii<Unit>> for Component
|
||||
where
|
||||
Dimension: From<Unit>,
|
||||
Unit: Debug + UnwindSafe + RefUnwindSafe + Send + Sync + 'static,
|
||||
{
|
||||
fn from(radii: CornerRadii<Unit>) -> Self {
|
||||
let radii = CornerRadii {
|
||||
top_left: Dimension::from(radii.top_left),
|
||||
top_right: Dimension::from(radii.top_right),
|
||||
bottom_right: Dimension::from(radii.bottom_right),
|
||||
bottom_left: Dimension::from(radii.bottom_left),
|
||||
};
|
||||
Component::custom(radii)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit> RequireInvalidation for CornerRadii<Unit> {
|
||||
fn requires_invalidation(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Component> for CornerRadii<Dimension> {
|
||||
type Error = Component;
|
||||
|
||||
fn try_from(value: Component) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Component::Custom(custom) => custom
|
||||
.downcast()
|
||||
.copied()
|
||||
.ok_or_else(|| Component::Custom(custom)),
|
||||
other => Err(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A 1-dimensional measurement that may be automatically calculated.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FlexibleDimension {
|
||||
|
|
@ -373,6 +422,15 @@ impl From<Lp> for Dimension {
|
|||
}
|
||||
}
|
||||
|
||||
impl IsZero for Dimension {
|
||||
fn is_zero(&self) -> bool {
|
||||
match self {
|
||||
Dimension::Px(x) => x.is_zero(),
|
||||
Dimension::Lp(x) => x.is_zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ScreenScale for Dimension {
|
||||
type Lp = Lp;
|
||||
type Px = Px;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//! All style components supported by the built-in widgets.
|
||||
|
||||
use kludgine::figures::units::Lp;
|
||||
use kludgine::shapes::CornerRadii;
|
||||
use kludgine::Color;
|
||||
|
||||
use crate::animation::easings::{EaseInOutQuadradic, EaseInQuadradic, EaseOutQuadradic};
|
||||
|
|
@ -133,5 +134,8 @@ define_components! {
|
|||
/// A [`Color`] to be used as a background color for widgets that render an
|
||||
/// opaque background.
|
||||
OpaqueWidgetColor(Color, "opaque_color", .surface.opaque_widget)
|
||||
/// A set of radius descriptions for how much roundness to apply to the
|
||||
/// shapes of widgets.
|
||||
CornerRadius(CornerRadii<Dimension>, "corner_radius", CornerRadii::from(Dimension::Lp(Lp::points(100))))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ impl Widget for Button {
|
|||
}
|
||||
|
||||
let style = self.current_style(context);
|
||||
context.gfx.fill(style.background);
|
||||
context.fill(style.background);
|
||||
|
||||
let two_lp_stroke = StrokeOptions::lp_wide(Lp::points(2));
|
||||
context.stroke_outline(style.outline, two_lp_stroke);
|
||||
|
|
|
|||
Loading…
Reference in a new issue