mirror of
https://github.com/danbulant/cushy
synced 2026-06-18 22:11:34 +00:00
Subpixels + Feathering + figures refactor
Much curves
This commit is contained in:
parent
aea9def07d
commit
d5bde44e27
20 changed files with 144 additions and 155 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -623,7 +623,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "figures"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/khonsulabs/figures#4712514fbed861ad530bd48d4e62f8efcaa4df1f"
|
||||
source = "git+https://github.com/khonsulabs/figures#0745fc0ff95e94ce2181aa1528a30bda3d6152f2"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"euclid",
|
||||
|
|
@ -1089,7 +1089,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
|||
[[package]]
|
||||
name = "kludgine"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/khonsulabs/kludgine#ca138e79a4b8ebc3bdd463006b1dadd3269183f3"
|
||||
source = "git+https://github.com/khonsulabs/kludgine#0530299bbe79431b5fa398182991c63e06d94b90"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"alot",
|
||||
|
|
@ -1974,9 +1974,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.24"
|
||||
version = "0.38.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234"
|
||||
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"errno",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use gooey::widgets::Canvas;
|
||||
use gooey::{Run, Tick};
|
||||
use kludgine::figures::units::Px;
|
||||
use kludgine::figures::{Angle, IntoSigned, Point, Rect, Size};
|
||||
use kludgine::figures::{Angle, IntoSigned, Point, Px2D, Rect, Size};
|
||||
use kludgine::shapes::Shape;
|
||||
use kludgine::text::{Text, TextOrigin};
|
||||
use kludgine::{Color, DrawableExt};
|
||||
|
|
@ -15,11 +14,11 @@ fn main() -> gooey::Result<()> {
|
|||
context.gfx.draw_text(
|
||||
Text::new("Canvas exposes the full power of Kludgine", Color::WHITE)
|
||||
.origin(TextOrigin::Center)
|
||||
.translate_by(center - Point::new(Px(0), Px(100))),
|
||||
.translate_by(center - Point::px(0, 100)),
|
||||
);
|
||||
context.gfx.draw_shape(
|
||||
Shape::filled_rect(
|
||||
Rect::new(Point::new(Px(-50), Px(-50)), Size::new(Px(100), Px(100))),
|
||||
Rect::new(Point::px(-50, -50), Size::px(100, 100)),
|
||||
Color::RED,
|
||||
)
|
||||
.translate_by(center)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ fn main() -> gooey::Result {
|
|||
.and("Masked Input Field:")
|
||||
.and(password.into_input())
|
||||
.into_rows()
|
||||
.width(Px(100)..Px(800))
|
||||
.width(Px::new(100)..Px::new(800))
|
||||
.scroll()
|
||||
.centered()
|
||||
.expand()
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ use gooey::kludgine::Color;
|
|||
use gooey::value::Dynamic;
|
||||
use gooey::widgets::TileMap;
|
||||
use gooey::{Run, Tick};
|
||||
use kludgine::figures::FloatConversion;
|
||||
use kludgine::DrawableExt;
|
||||
|
||||
const PLAYER_SIZE: Px = Px(16);
|
||||
const PLAYER_SIZE: Px = Px::new(16);
|
||||
|
||||
#[rustfmt::skip]
|
||||
const TILES: [TileKind; 64] = {
|
||||
|
|
@ -33,7 +34,7 @@ fn main() -> gooey::Result {
|
|||
|
||||
let myself = characters.push(Player {
|
||||
color: Color::RED,
|
||||
position: Point::new(TILE_SIZE.0 as f32, TILE_SIZE.0 as f32),
|
||||
position: Point::new(TILE_SIZE.into_float(), TILE_SIZE.into_float()),
|
||||
});
|
||||
|
||||
let layers = Dynamic::new((Tiles::new(8, 8, TILES), characters));
|
||||
|
|
@ -58,10 +59,11 @@ fn main() -> gooey::Result {
|
|||
direction.x -= 1.0;
|
||||
}
|
||||
|
||||
let one_second_movement = direction * TILE_SIZE.0 as f32;
|
||||
let one_second_movement = direction * TILE_SIZE.into_float();
|
||||
|
||||
layers.map_mut(|layers| {
|
||||
layers.1[myself].position += Point::new(
|
||||
// TODO fix this in figures
|
||||
one_second_movement.x * elapsed.as_secs_f32(),
|
||||
one_second_movement.y * elapsed.as_secs_f32(),
|
||||
)
|
||||
|
|
@ -85,10 +87,7 @@ impl Object for Player {
|
|||
let zoomed_size = PLAYER_SIZE * zoom;
|
||||
context.draw_shape(
|
||||
Shape::filled_rect(
|
||||
Rect::new(
|
||||
Point::new(-zoomed_size / 2, -zoomed_size / 2),
|
||||
Size::squared(zoomed_size),
|
||||
),
|
||||
Rect::new(Point::squared(-zoomed_size / 2), Size::squared(zoomed_size)),
|
||||
self.color,
|
||||
)
|
||||
.translate_by(center),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use kludgine::app::winit::event::{
|
|||
DeviceId, Ime, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
};
|
||||
use kludgine::figures::units::{Lp, Px, UPx};
|
||||
use kludgine::figures::{IntoSigned, IsZero, Point, Rect, ScreenScale, Size};
|
||||
use kludgine::figures::{IntoSigned, Point, Px2D, Rect, ScreenScale, Size, Zero};
|
||||
use kludgine::shapes::{Shape, StrokeOptions};
|
||||
use kludgine::{Color, Kludgine};
|
||||
|
||||
|
|
@ -525,7 +525,7 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, '
|
|||
/// 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 visible_rect = Rect::from(self.gfx.region().size - Size::px(1, 1));
|
||||
|
||||
let radii = self.get(&CornerRadius);
|
||||
let radii = radii.map(|r| r.into_px(self.gfx.scale()));
|
||||
|
|
@ -542,23 +542,23 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, '
|
|||
/// 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> + IsZero,
|
||||
Unit: ScreenScale<Px = Px, Lp = Lp, UPx = UPx> + Zero,
|
||||
{
|
||||
if color.alpha() > 0 {
|
||||
let visible_rect = Rect::from(self.gfx.region().size - (Px(1), Px(1)));
|
||||
let options = options.colored(color).into_px(self.gfx.scale());
|
||||
let inset = options.line_width;
|
||||
let visible_rect = Rect::new(
|
||||
Point::squared(inset),
|
||||
self.gfx.region().size - Point::new(inset * 2, inset * 2),
|
||||
);
|
||||
|
||||
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()))
|
||||
Shape::stroked_rect(visible_rect, options.into_px(self.gfx.scale()))
|
||||
} else {
|
||||
Shape::stroked_round_rect(
|
||||
visible_rect,
|
||||
radii,
|
||||
color,
|
||||
options.into_px(self.gfx.scale()),
|
||||
)
|
||||
Shape::stroked_round_rect(visible_rect, radii, options)
|
||||
};
|
||||
self.gfx.draw_shape(&focus_ring);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::ops::{Deref, DerefMut};
|
|||
|
||||
use kludgine::figures::units::{Px, UPx};
|
||||
use kludgine::figures::{
|
||||
self, Fraction, IntoSigned, IntoUnsigned, IsZero, Point, Rect, ScreenScale, ScreenUnit, Size,
|
||||
self, Fraction, IntoSigned, IntoUnsigned, Point, Rect, ScreenScale, ScreenUnit, Size, Zero,
|
||||
};
|
||||
use kludgine::render::Renderer;
|
||||
use kludgine::shapes::Shape;
|
||||
|
|
@ -45,12 +45,12 @@ impl<'clip, 'gfx, 'pass> Graphics<'clip, 'gfx, 'pass> {
|
|||
let clip_origin = self.renderer.clip_rect().origin.into_signed();
|
||||
-Point::new(
|
||||
if clip_origin.x <= self.region.origin.x {
|
||||
Px(0)
|
||||
Px::ZERO
|
||||
} else {
|
||||
clip_origin.x - self.region.origin.x
|
||||
},
|
||||
if clip_origin.y <= self.region.origin.y {
|
||||
Px(0)
|
||||
Px::ZERO
|
||||
} else {
|
||||
clip_origin.y - self.region.origin.y
|
||||
},
|
||||
|
|
@ -147,7 +147,7 @@ impl<'clip, 'gfx, 'pass> Graphics<'clip, 'gfx, 'pass> {
|
|||
/// Draws a shape at the origin, rotating and scaling as needed.
|
||||
pub fn draw_shape<'a, Unit>(&mut self, shape: impl Into<Drawable<&'a Shape<Unit, false>, Unit>>)
|
||||
where
|
||||
Unit: IsZero + ShaderScalable + figures::ScreenUnit + Copy,
|
||||
Unit: Zero + ShaderScalable + figures::ScreenUnit + Copy,
|
||||
{
|
||||
let mut shape = shape.into();
|
||||
shape.translation += Point::<Unit>::from_px(self.translation(), self.scale());
|
||||
|
|
@ -171,7 +171,7 @@ impl<'clip, 'gfx, 'pass> Graphics<'clip, 'gfx, 'pass> {
|
|||
shape: impl Into<Drawable<&'shape Shape, Unit>>,
|
||||
texture: &impl TextureSource,
|
||||
) where
|
||||
Unit: IsZero + ShaderScalable + figures::ScreenUnit + Copy,
|
||||
Unit: Zero + ShaderScalable + figures::ScreenUnit + Copy,
|
||||
i32: From<<Unit as IntoSigned>::Signed>,
|
||||
Shape: ShapeSource<Unit, true> + 'shape,
|
||||
{
|
||||
|
|
|
|||
23
src/lib.rs
23
src/lib.rs
|
|
@ -25,7 +25,7 @@ use std::ops::Sub;
|
|||
pub use kludgine;
|
||||
use kludgine::app::winit::error::EventLoopError;
|
||||
use kludgine::figures::units::UPx;
|
||||
use kludgine::figures::{Fraction, ScreenUnit};
|
||||
use kludgine::figures::{Fraction, ScreenUnit, Size};
|
||||
pub use names::Name;
|
||||
pub use utils::{Lazy, WithClone};
|
||||
|
||||
|
|
@ -68,6 +68,27 @@ impl ConstraintLimit {
|
|||
}
|
||||
}
|
||||
|
||||
/// An extension trait for `Size<ConstraintLimit>`.
|
||||
pub trait FitMeasuredSize {
|
||||
/// Returns the result of calling [`ConstraintLimit::fit_measured`] for each
|
||||
/// matching component in `self` and `measured`.
|
||||
fn fit_measured<Unit>(self, measured: Size<Unit>, scale: Fraction) -> Size<UPx>
|
||||
where
|
||||
Unit: ScreenUnit;
|
||||
}
|
||||
|
||||
impl FitMeasuredSize for Size<ConstraintLimit> {
|
||||
fn fit_measured<Unit>(self, measured: Size<Unit>, scale: Fraction) -> Size<UPx>
|
||||
where
|
||||
Unit: ScreenUnit,
|
||||
{
|
||||
Size::new(
|
||||
self.width.fit_measured(measured.width, scale),
|
||||
self.height.fit_measured(measured.height, scale),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<UPx> for ConstraintLimit {
|
||||
type Output = Self;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use std::sync::Arc;
|
|||
|
||||
use ahash::AHashMap;
|
||||
use kludgine::figures::units::{Lp, Px, UPx};
|
||||
use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, IsZero, Rect, ScreenScale, Size};
|
||||
use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, Rect, ScreenScale, Size, Zero};
|
||||
use kludgine::shapes::CornerRadii;
|
||||
use kludgine::Color;
|
||||
use palette::{IntoColor, Okhsl, OklabHue, Srgb};
|
||||
|
|
@ -399,11 +399,6 @@ pub enum Dimension {
|
|||
Lp(Lp),
|
||||
}
|
||||
|
||||
impl Dimension {
|
||||
/// A dimension of 0 pixels.
|
||||
pub const ZERO: Self = Self::Px(Px(0));
|
||||
}
|
||||
|
||||
impl Default for Dimension {
|
||||
fn default() -> Self {
|
||||
Self::ZERO
|
||||
|
|
@ -422,7 +417,9 @@ impl From<Lp> for Dimension {
|
|||
}
|
||||
}
|
||||
|
||||
impl IsZero for Dimension {
|
||||
impl Zero for Dimension {
|
||||
const ZERO: Self = Dimension::Px(Px::ZERO);
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
match self {
|
||||
Dimension::Px(x) => x.is_zero(),
|
||||
|
|
|
|||
|
|
@ -759,7 +759,7 @@ pub trait MakeWidget: Sized {
|
|||
|
||||
/// Returns a new widget that renders `color` behind `self`.
|
||||
fn background_color(self, color: impl IntoValue<Color>) -> Container {
|
||||
self.contain().pad_by(Px(0)).background_color(color)
|
||||
self.contain().pad_by(Px::ZERO).background_color(color)
|
||||
}
|
||||
|
||||
/// Wraps `self` with the default padding.
|
||||
|
|
|
|||
|
|
@ -186,10 +186,7 @@ impl WrapperWidget for Align {
|
|||
let layout = self.measure(available_space, context);
|
||||
|
||||
Rect::new(
|
||||
Point::new(
|
||||
layout.margin.left.into_signed(),
|
||||
layout.margin.top.into_signed(),
|
||||
),
|
||||
Point::new(layout.margin.left, layout.margin.top).into_signed(),
|
||||
layout.content.into_signed(),
|
||||
)
|
||||
.into()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use crate::styles::{ColorExt, Styles};
|
|||
use crate::utils::ModifiersExt;
|
||||
use crate::value::{Dynamic, IntoValue, Value};
|
||||
use crate::widget::{Callback, EventHandling, MakeWidget, Widget, WidgetRef, HANDLED, IGNORED};
|
||||
use crate::FitMeasuredSize;
|
||||
|
||||
/// A clickable button.
|
||||
#[derive(Debug)]
|
||||
|
|
@ -362,12 +363,8 @@ impl Widget for Button {
|
|||
let inset = context.get(&IntrinsicPadding).into_px(context.gfx.scale());
|
||||
|
||||
let focus_ring = Shape::stroked_rect(
|
||||
Rect::new(
|
||||
Point::new(inset, inset),
|
||||
context.gfx.region().size - inset * 2,
|
||||
),
|
||||
color,
|
||||
two_lp_stroke,
|
||||
Rect::new(Point::squared(inset), context.gfx.region().size - inset * 2),
|
||||
two_lp_stroke.colored(color),
|
||||
);
|
||||
context.gfx.draw_shape(&focus_ring);
|
||||
} else if context.is_default() {
|
||||
|
|
@ -452,22 +449,12 @@ impl Widget for Button {
|
|||
let padding = context.get(&IntrinsicPadding).into_upx(context.gfx.scale());
|
||||
let double_padding = padding * 2;
|
||||
let mounted = self.content.mounted(&mut context.as_event_context());
|
||||
let available_space = Size::new(
|
||||
available_space.width - double_padding,
|
||||
available_space.height - double_padding,
|
||||
);
|
||||
let available_space = available_space.map(|space| space - double_padding);
|
||||
let size = context.for_other(&mounted).layout(available_space);
|
||||
let size = Size::new(
|
||||
available_space
|
||||
.width
|
||||
.fit_measured(size.width, context.gfx.scale()),
|
||||
available_space
|
||||
.height
|
||||
.fit_measured(size.height, context.gfx.scale()),
|
||||
);
|
||||
let size = available_space.fit_measured(size, context.gfx.scale());
|
||||
context.set_child_layout(
|
||||
&mounted,
|
||||
Rect::new(Point::new(padding, padding), size).into_signed(),
|
||||
Rect::new(Point::squared(padding), size).into_signed(),
|
||||
);
|
||||
size + double_padding
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use kludgine::figures::Size;
|
|||
use crate::context::{GraphicsContext, LayoutContext};
|
||||
use crate::value::Dynamic;
|
||||
use crate::widget::Widget;
|
||||
use crate::Tick;
|
||||
use crate::{ConstraintLimit, Tick};
|
||||
|
||||
/// A 2d drawable surface.
|
||||
#[must_use]
|
||||
|
|
@ -55,7 +55,7 @@ impl Widget for Canvas {
|
|||
available_space: Size<crate::ConstraintLimit>,
|
||||
_context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> Size<UPx> {
|
||||
Size::new(available_space.width.max(), available_space.height.max())
|
||||
available_space.map(ConstraintLimit::max)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ impl WrapperWidget for CheckboxLabel {
|
|||
let label_inset = checkbox_size + padding;
|
||||
let size_with_checkbox = Size::new(size.width + label_inset, size.height).into_unsigned();
|
||||
WrappedLayout {
|
||||
child: Rect::new(Point::new(label_inset, Px(0)), size),
|
||||
child: Rect::new(Point::new(label_inset, Px::ZERO), size),
|
||||
size: size_with_checkbox,
|
||||
}
|
||||
}
|
||||
|
|
@ -170,10 +170,7 @@ impl WrapperWidget for CheckboxLabel {
|
|||
fn redraw_background(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
let checkbox_size = context.get(&LineHeight).into_px(context.gfx.scale());
|
||||
let padding = context.get(&IntrinsicPadding).into_px(context.gfx.scale());
|
||||
let checkbox_rect = Rect::new(
|
||||
Point::new(padding, padding),
|
||||
Size::new(checkbox_size, checkbox_size),
|
||||
);
|
||||
let checkbox_rect = Rect::new(Point::squared(padding), Size::squared(checkbox_size));
|
||||
let stroke_options = StrokeOptions::lp_wide(Lp::points(2)).into_px(context.gfx.scale());
|
||||
match self.value.get_tracking_refresh(context) {
|
||||
state @ (CheckboxState::Checked | CheckboxState::Indeterminant) => {
|
||||
|
|
@ -196,7 +193,7 @@ impl WrapperWidget for CheckboxLabel {
|
|||
icon_area.origin.y,
|
||||
))
|
||||
.build()
|
||||
.stroke(text_color, stroke_options),
|
||||
.stroke(stroke_options.colored(text_color)),
|
||||
);
|
||||
} else {
|
||||
context.gfx.draw_shape(
|
||||
|
|
@ -206,15 +203,16 @@ impl WrapperWidget for CheckboxLabel {
|
|||
center.y,
|
||||
))
|
||||
.build()
|
||||
.stroke(text_color, stroke_options),
|
||||
.stroke(stroke_options.colored(text_color)),
|
||||
);
|
||||
}
|
||||
}
|
||||
CheckboxState::Unchecked => {
|
||||
let color = context.get(&OutlineColor);
|
||||
context
|
||||
.gfx
|
||||
.draw_shape(&Shape::stroked_rect(checkbox_rect, color, stroke_options));
|
||||
context.gfx.draw_shape(&Shape::stroked_rect(
|
||||
checkbox_rect,
|
||||
stroke_options.colored(color),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,10 +102,7 @@ impl WrapperWidget for Expand {
|
|||
available_space: Size<ConstraintLimit>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> WrappedLayout {
|
||||
let available_space = Size::new(
|
||||
ConstraintLimit::Fill(available_space.width.max()),
|
||||
ConstraintLimit::Fill(available_space.height.max()),
|
||||
);
|
||||
let available_space = available_space.map(|lim| ConstraintLimit::Fill(lim.max()));
|
||||
let child = self.child.mounted(&mut context.as_event_context());
|
||||
let size = context.for_other(&child).layout(available_space);
|
||||
|
||||
|
|
|
|||
|
|
@ -522,7 +522,7 @@ where
|
|||
) -> (Point<Px>, Px) {
|
||||
if measured.glyphs.is_empty() || (cursor.offset == 0 && cursor.affinity == Affinity::Before)
|
||||
{
|
||||
return (Point::default(), Px(0));
|
||||
return (Point::default(), Px::ZERO);
|
||||
}
|
||||
|
||||
// Space between glyphs isn't represented in the glyphs. If the cursor rests
|
||||
|
|
@ -553,7 +553,7 @@ where
|
|||
) {
|
||||
(Ordering::Less | Ordering::Equal, Ordering::Less) => {
|
||||
// cosmic text may have grouped multiple graphemes into a single glyph.
|
||||
let mut grapheme_offset = Px(0);
|
||||
let mut grapheme_offset = Px::ZERO;
|
||||
if glyph.info.start < cursor.offset {
|
||||
let clustered_bytes = glyph.info.end - glyph.info.start;
|
||||
if clustered_bytes > 1 {
|
||||
|
|
@ -567,8 +567,8 @@ where
|
|||
return (
|
||||
Point::new(
|
||||
rect.origin.x + grapheme_offset,
|
||||
measured.line_height.saturating_mul(Px(
|
||||
i32::try_from(glyph.info.line).unwrap_or(i32::MAX)
|
||||
measured.line_height.saturating_mul(Px::new(
|
||||
i32::try_from(glyph.info.line).unwrap_or(i32::MAX),
|
||||
)),
|
||||
),
|
||||
rect.size.width,
|
||||
|
|
@ -586,9 +586,9 @@ where
|
|||
|
||||
if closest_after_index == usize::MAX {
|
||||
let bottom_right = &measured.glyphs[bottom_right_index];
|
||||
let bottom_y = measured
|
||||
.line_height
|
||||
.saturating_mul(Px(i32::try_from(bottom_right.info.line).unwrap_or(i32::MAX)));
|
||||
let bottom_y = measured.line_height.saturating_mul(Px::new(
|
||||
i32::try_from(bottom_right.info.line).unwrap_or(i32::MAX),
|
||||
));
|
||||
// No glyph could be found that started/contained the cursors offset.
|
||||
let mut bottom_right_cursor = Point::new(
|
||||
bottom_right_rect.origin.x + bottom_right_rect.size.width,
|
||||
|
|
@ -609,7 +609,7 @@ where
|
|||
}
|
||||
|
||||
// The cursor should be placed after the bottom_right glyph
|
||||
(bottom_right_cursor, Px(0))
|
||||
(bottom_right_cursor, Px::ZERO)
|
||||
} else {
|
||||
let before = &measured.glyphs[closest_before_index];
|
||||
let after = &measured.glyphs[closest_after_index];
|
||||
|
|
@ -617,7 +617,7 @@ where
|
|||
let after_rect = after.rect();
|
||||
let before_y = measured
|
||||
.line_height
|
||||
.saturating_mul(Px(i32::try_from(before.info.line).unwrap_or(i32::MAX)));
|
||||
.saturating_mul(Px::new(i32::try_from(before.info.line).unwrap_or(i32::MAX)));
|
||||
|
||||
if before.info.line == after.info.line {
|
||||
let before_right = before_rect.origin.x + before_rect.size.width;
|
||||
|
|
@ -639,7 +639,10 @@ where
|
|||
origin.x += before_rect.size.width;
|
||||
(origin, before_y)
|
||||
}
|
||||
Affinity::After => (Point::new(Px(0), before_y + measured.line_height), Px(0)),
|
||||
Affinity::After => (
|
||||
Point::new(Px::ZERO, before_y + measured.line_height),
|
||||
Px::ZERO,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -665,7 +668,7 @@ where
|
|||
|
||||
let mut closest: Option<(Cursor, i32)> = None;
|
||||
let mut current_line = usize::MAX;
|
||||
let mut current_line_y = Px(0);
|
||||
let mut current_line_y = Px::ZERO;
|
||||
for glyph in &cache.measured.glyphs {
|
||||
if current_line != glyph.info.line {
|
||||
current_line = glyph.info.line;
|
||||
|
|
@ -673,7 +676,7 @@ where
|
|||
current_line_y = cache
|
||||
.measured
|
||||
.line_height
|
||||
.saturating_mul(Px(i32::try_from(current_line).unwrap_or(i32::MAX)));
|
||||
.saturating_mul(Px::new(i32::try_from(current_line).unwrap_or(i32::MAX)));
|
||||
}
|
||||
let rect = glyph.rect();
|
||||
let relative = location - Point::new(rect.origin.x, current_line_y);
|
||||
|
|
@ -704,7 +707,7 @@ where
|
|||
|
||||
// Make relative be relative to the center of the glyph for a nearest search.
|
||||
let relative = relative + rect.size / 2;
|
||||
let xy = (relative.x.0.saturating_mul(relative.y.0)).saturating_abs();
|
||||
let xy = (relative.x.get().saturating_mul(relative.y.get())).saturating_abs();
|
||||
match closest {
|
||||
Some((_, closest_xy)) if xy < closest_xy => {
|
||||
closest = Some((
|
||||
|
|
@ -872,7 +875,7 @@ where
|
|||
context.gfx.draw_shape(
|
||||
Shape::filled_rect(
|
||||
Rect::new(
|
||||
Point::new(Px(0), bottom_of_first_line),
|
||||
Point::new(Px::ZERO, bottom_of_first_line),
|
||||
Size::new(size.width.into_signed(), distance_between),
|
||||
),
|
||||
highlight,
|
||||
|
|
@ -884,7 +887,7 @@ where
|
|||
context.gfx.draw_shape(
|
||||
Shape::filled_rect(
|
||||
Rect::new(
|
||||
Point::new(Px(0), end_position.y),
|
||||
Point::new(Px::ZERO, end_position.y),
|
||||
Size::new(end_position.x + end_width, cache.measured.line_height),
|
||||
),
|
||||
highlight,
|
||||
|
|
@ -939,7 +942,7 @@ where
|
|||
|
||||
let cache = self.layout_text(Some(width.into_signed()), &mut context.graphics);
|
||||
|
||||
cache.measured.size.into_unsigned() + Size::new(padding * 2, padding * 2)
|
||||
cache.measured.size.into_unsigned() + Size::squared(padding * 2)
|
||||
}
|
||||
|
||||
fn keyboard_input(
|
||||
|
|
|
|||
|
|
@ -98,10 +98,7 @@ impl WrapperWidget for Resize {
|
|||
let size = if let (Some(width), Some(height)) =
|
||||
(self.width.exact_dimension(), self.height.exact_dimension())
|
||||
{
|
||||
Size::new(
|
||||
width.into_upx(context.gfx.scale()),
|
||||
height.into_upx(context.gfx.scale()),
|
||||
)
|
||||
Size::new(width, height).map(|i| i.into_upx(context.gfx.scale()))
|
||||
} else {
|
||||
let available_space = Size::new(
|
||||
override_constraint(available_space.width, self.width, context.gfx.scale()),
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ impl Widget for Scroll {
|
|||
let max_scroll_x = if self.enabled.x {
|
||||
-self.horizontal_bar.amount_hidden
|
||||
} else {
|
||||
Px(0)
|
||||
Px::ZERO
|
||||
};
|
||||
|
||||
self.vertical_bar =
|
||||
|
|
@ -194,7 +194,7 @@ impl Widget for Scroll {
|
|||
let max_scroll_y = if self.enabled.y {
|
||||
-self.vertical_bar.amount_hidden
|
||||
} else {
|
||||
Px(0)
|
||||
Px::ZERO
|
||||
};
|
||||
let new_max_scroll = Point::new(max_scroll_x, max_scroll_y);
|
||||
if current_max_scroll != new_max_scroll {
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ impl<T> Slider<T> {
|
|||
value: value.into_dynamic(),
|
||||
minimum: min.into_value(),
|
||||
maximum: max.into_value(),
|
||||
knob_size: UPx(0),
|
||||
knob_size: UPx::ZERO,
|
||||
horizontal: true,
|
||||
rendered_size: Px(0),
|
||||
rendered_size: Px::ZERO,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ where
|
|||
} else {
|
||||
position.y
|
||||
};
|
||||
let position = position.clamp(Px(0), self.rendered_size);
|
||||
let position = position.clamp(Px::ZERO, self.rendered_size);
|
||||
let percent = position.into_float() / self.rendered_size.into_float();
|
||||
let min = self.minimum.get();
|
||||
let max = self.maximum.get();
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ impl Widget for Stack {
|
|||
Rect::new(
|
||||
self.layout
|
||||
.orientation
|
||||
.make_point(layout.offset, UPx(0))
|
||||
.make_point(layout.offset, UPx::ZERO)
|
||||
.into_signed(),
|
||||
self.layout
|
||||
.orientation
|
||||
|
|
@ -313,9 +313,9 @@ impl Layout {
|
|||
orientation,
|
||||
children: OrderedLots::new(),
|
||||
layouts: Vec::new(),
|
||||
other: UPx(0),
|
||||
other: UPx::ZERO,
|
||||
total_weights: 0,
|
||||
allocated_space: (UPx(0), Lp(0)),
|
||||
allocated_space: (UPx::ZERO, Lp::ZERO),
|
||||
fractional: Vec::new(),
|
||||
fit_to_content: Vec::new(),
|
||||
premeasured: Vec::new(),
|
||||
|
|
@ -370,12 +370,12 @@ impl Layout {
|
|||
let layout = match child {
|
||||
StackDimension::FitContent => {
|
||||
self.fit_to_content.push(id);
|
||||
UPx(0)
|
||||
UPx::ZERO
|
||||
}
|
||||
StackDimension::Fractional { weight } => {
|
||||
self.total_weights += u32::from(weight);
|
||||
self.fractional.push((id, weight));
|
||||
UPx(0)
|
||||
UPx::ZERO
|
||||
}
|
||||
StackDimension::Measured { min, .. } => {
|
||||
self.premeasured.push(id);
|
||||
|
|
@ -389,7 +389,7 @@ impl Layout {
|
|||
self.layouts.insert(
|
||||
index,
|
||||
StackLayout {
|
||||
offset: UPx(0),
|
||||
offset: UPx::ZERO,
|
||||
size: layout,
|
||||
},
|
||||
);
|
||||
|
|
@ -412,7 +412,7 @@ impl Layout {
|
|||
let needs_final_layout = !matches!(other_constraint, ConstraintLimit::Fill(_));
|
||||
|
||||
// Measure the children that fit their content
|
||||
self.other = UPx(0);
|
||||
self.other = UPx::ZERO;
|
||||
for &id in &self.fit_to_content {
|
||||
let index = self.children.index_of_id(id).expect("child not found");
|
||||
let (measured, other) = self.orientation.split_size(measure(
|
||||
|
|
@ -484,7 +484,7 @@ impl Layout {
|
|||
};
|
||||
|
||||
// Finally, compute the offsets of all of the widgets.
|
||||
let mut offset = UPx(0);
|
||||
let mut offset = UPx::ZERO;
|
||||
for index in 0..self.children.len() {
|
||||
self.layouts[index].offset = offset;
|
||||
offset += self.layouts[index].size;
|
||||
|
|
@ -593,7 +593,7 @@ mod tests {
|
|||
orientation.make_size(measured, other)
|
||||
});
|
||||
assert_eq!(computed_size, expected_size);
|
||||
let mut offset = UPx(0);
|
||||
let mut offset = UPx::ZERO;
|
||||
for ((index, &child), &expected) in flex.iter().enumerate().zip(expected) {
|
||||
assert_eq!(
|
||||
child.size,
|
||||
|
|
@ -635,11 +635,11 @@ mod tests {
|
|||
fn size_to_fit() {
|
||||
assert_measured_children(
|
||||
&[Child::new(3, 1), Child::new(3, 1), Child::new(3, 1)],
|
||||
ConstraintLimit::SizeToFit(UPx(10)),
|
||||
ConstraintLimit::SizeToFit(UPx(10)),
|
||||
&[UPx(3), UPx(3), UPx(3)],
|
||||
UPx(9),
|
||||
UPx(1),
|
||||
ConstraintLimit::SizeToFit(UPx::new(10)),
|
||||
ConstraintLimit::SizeToFit(UPx::new(10)),
|
||||
&[UPx::new(3), UPx::new(3), UPx::new(3)],
|
||||
UPx::new(9),
|
||||
UPx::new(1),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -660,11 +660,11 @@ mod tests {
|
|||
Child::new(3, 1).weighted(1),
|
||||
Child::new(3, 1).weighted(1),
|
||||
],
|
||||
ConstraintLimit::Fill(UPx(10)),
|
||||
ConstraintLimit::SizeToFit(UPx(10)),
|
||||
&[UPx(4), UPx(3), UPx(3)],
|
||||
UPx(10),
|
||||
UPx(7), // 20 / 3 = 6.666, rounded up is 7
|
||||
ConstraintLimit::Fill(UPx::new(10)),
|
||||
ConstraintLimit::SizeToFit(UPx::new(10)),
|
||||
&[UPx::new(4), UPx::new(3), UPx::new(3)],
|
||||
UPx::new(10),
|
||||
UPx::new(7), // 20 / 3 = 6.666, rounded up is 7
|
||||
);
|
||||
// Same as above, but with an 11px box. This creates a leftover of 3 px
|
||||
// (11 % 4), adding 1px to all three children.
|
||||
|
|
@ -674,11 +674,11 @@ mod tests {
|
|||
Child::new(3, 1).weighted(1),
|
||||
Child::new(3, 1).weighted(1),
|
||||
],
|
||||
ConstraintLimit::Fill(UPx(11)),
|
||||
ConstraintLimit::SizeToFit(UPx(11)),
|
||||
&[UPx(5), UPx(3), UPx(3)],
|
||||
UPx(11),
|
||||
UPx(7), // 20 / 3 = 6.666, rounded up is 7
|
||||
ConstraintLimit::Fill(UPx::new(11)),
|
||||
ConstraintLimit::SizeToFit(UPx::new(11)),
|
||||
&[UPx::new(5), UPx::new(3), UPx::new(3)],
|
||||
UPx::new(11),
|
||||
UPx::new(7), // 20 / 3 = 6.666, rounded up is 7
|
||||
);
|
||||
// 12px box. This creates no leftover.
|
||||
assert_measured_children(
|
||||
|
|
@ -687,11 +687,11 @@ mod tests {
|
|||
Child::new(3, 1).weighted(1),
|
||||
Child::new(3, 1).weighted(1),
|
||||
],
|
||||
ConstraintLimit::Fill(UPx(12)),
|
||||
ConstraintLimit::SizeToFit(UPx(12)),
|
||||
&[UPx(6), UPx(3), UPx(3)],
|
||||
UPx(12),
|
||||
UPx(4), // 20 / 6 = 3.666, rounded up is 4
|
||||
ConstraintLimit::Fill(UPx::new(12)),
|
||||
ConstraintLimit::SizeToFit(UPx::new(12)),
|
||||
&[UPx::new(6), UPx::new(3), UPx::new(3)],
|
||||
UPx::new(12),
|
||||
UPx::new(4), // 20 / 6 = 3.666, rounded up is 4
|
||||
);
|
||||
// 13px box. This creates a leftover of 1 px (13 % 4), adding 1px only
|
||||
// to the final child
|
||||
|
|
@ -701,11 +701,11 @@ mod tests {
|
|||
Child::new(3, 1).weighted(1),
|
||||
Child::new(3, 1).weighted(1),
|
||||
],
|
||||
ConstraintLimit::Fill(UPx(13)),
|
||||
ConstraintLimit::SizeToFit(UPx(13)),
|
||||
&[UPx(6), UPx(3), UPx(4)],
|
||||
UPx(13),
|
||||
UPx(4), // 20 / 6 = 3.666, rounded up is 4
|
||||
ConstraintLimit::Fill(UPx::new(13)),
|
||||
ConstraintLimit::SizeToFit(UPx::new(13)),
|
||||
&[UPx::new(6), UPx::new(3), UPx::new(4)],
|
||||
UPx::new(13),
|
||||
UPx::new(4), // 20 / 6 = 3.666, rounded up is 4
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -713,15 +713,15 @@ mod tests {
|
|||
fn fixed_size() {
|
||||
assert_measured_children(
|
||||
&[
|
||||
Child::new(3, 1).fixed_size(UPx(7)),
|
||||
Child::new(3, 1).fixed_size(UPx::new(7)),
|
||||
Child::new(3, 1).weighted(1),
|
||||
Child::new(3, 1).weighted(1),
|
||||
],
|
||||
ConstraintLimit::Fill(UPx(15)),
|
||||
ConstraintLimit::SizeToFit(UPx(15)),
|
||||
&[UPx(7), UPx(4), UPx(4)],
|
||||
UPx(15),
|
||||
UPx(1),
|
||||
ConstraintLimit::Fill(UPx::new(15)),
|
||||
ConstraintLimit::SizeToFit(UPx::new(15)),
|
||||
&[UPx::new(7), UPx::new(4), UPx::new(4)],
|
||||
UPx::new(15),
|
||||
UPx::new(1),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ where
|
|||
let min_width = resize
|
||||
.width
|
||||
.minimum()
|
||||
.map_or(Px(0), |width| width.into_px(graphics.scale()));
|
||||
.map_or(Px::ZERO, |width| width.into_px(graphics.scale()));
|
||||
let max_width = resize
|
||||
.width
|
||||
.maximum()
|
||||
|
|
@ -404,7 +404,7 @@ where
|
|||
let min_height = resize
|
||||
.height
|
||||
.minimum()
|
||||
.map_or(Px(0), |height| height.into_px(graphics.scale()));
|
||||
.map_or(Px::ZERO, |height| height.into_px(graphics.scale()));
|
||||
let max_height = resize
|
||||
.height
|
||||
.maximum()
|
||||
|
|
@ -566,15 +566,9 @@ where
|
|||
}
|
||||
|
||||
let actual_size = layout_context.layout(if is_expanded {
|
||||
Size::new(
|
||||
ConstraintLimit::Fill(window_size.width),
|
||||
ConstraintLimit::Fill(window_size.height),
|
||||
)
|
||||
window_size.map(ConstraintLimit::Fill)
|
||||
} else {
|
||||
Size::new(
|
||||
ConstraintLimit::SizeToFit(window_size.width),
|
||||
ConstraintLimit::SizeToFit(window_size.height),
|
||||
)
|
||||
window_size.map(ConstraintLimit::SizeToFit)
|
||||
});
|
||||
let render_size = actual_size.min(window_size);
|
||||
if actual_size != window_size && !resizable {
|
||||
|
|
|
|||
Loading…
Reference in a new issue