mirror of
https://github.com/danbulant/cushy
synced 2026-07-06 11:40:37 +00:00
Fixed odd padding rounding issues
The Container code was causing small rounding errors when laying out that would cause the layout to sometimes me larger by a pixel. I searched for all locations we are applying padding and added rounding calls. Refs #92
This commit is contained in:
parent
c117b1527e
commit
27d5594776
6 changed files with 65 additions and 38 deletions
|
|
@ -5,7 +5,7 @@ use std::time::Duration;
|
||||||
use kludgine::app::winit::event::{DeviceId, ElementState, KeyEvent, MouseButton};
|
use kludgine::app::winit::event::{DeviceId, ElementState, KeyEvent, MouseButton};
|
||||||
use kludgine::app::winit::window::CursorIcon;
|
use kludgine::app::winit::window::CursorIcon;
|
||||||
use kludgine::figures::units::{Lp, Px, UPx};
|
use kludgine::figures::units::{Lp, Px, UPx};
|
||||||
use kludgine::figures::{IntoSigned, Point, Rect, ScreenScale, Size};
|
use kludgine::figures::{IntoSigned, Point, Rect, Round, ScreenScale, Size};
|
||||||
use kludgine::shapes::{Shape, StrokeOptions};
|
use kludgine::shapes::{Shape, StrokeOptions};
|
||||||
use kludgine::Color;
|
use kludgine::Color;
|
||||||
|
|
||||||
|
|
@ -467,7 +467,10 @@ impl Widget for Button {
|
||||||
available_space: Size<crate::ConstraintLimit>,
|
available_space: Size<crate::ConstraintLimit>,
|
||||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||||
) -> Size<UPx> {
|
) -> Size<UPx> {
|
||||||
let padding = context.get(&IntrinsicPadding).into_upx(context.gfx.scale());
|
let padding = context
|
||||||
|
.get(&IntrinsicPadding)
|
||||||
|
.into_upx(context.gfx.scale())
|
||||||
|
.round();
|
||||||
let double_padding = padding * 2;
|
let double_padding = padding * 2;
|
||||||
let mounted = self.content.mounted(&mut context.as_event_context());
|
let mounted = self.content.mounted(&mut context.as_event_context());
|
||||||
let available_space = available_space.map(|space| space - double_padding);
|
let available_space = available_space.map(|space| space - double_padding);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use std::ops::Div;
|
||||||
|
|
||||||
use kludgine::figures::units::{Lp, Px, UPx};
|
use kludgine::figures::units::{Lp, Px, UPx};
|
||||||
use kludgine::figures::{
|
use kludgine::figures::{
|
||||||
Abs, Angle, IntoSigned, IntoUnsigned, Point, Rect, ScreenScale, Size, Zero,
|
Abs, Angle, IntoSigned, IntoUnsigned, Point, Rect, Round, ScreenScale, Size, Zero,
|
||||||
};
|
};
|
||||||
use kludgine::shapes::{CornerRadii, PathBuilder, Shape};
|
use kludgine::shapes::{CornerRadii, PathBuilder, Shape};
|
||||||
use kludgine::Color;
|
use kludgine::Color;
|
||||||
|
|
@ -165,7 +165,7 @@ impl Container {
|
||||||
Some(padding) => padding.get(),
|
Some(padding) => padding.get(),
|
||||||
None => Edges::from(context.get(&IntrinsicPadding)),
|
None => Edges::from(context.get(&IntrinsicPadding)),
|
||||||
}
|
}
|
||||||
.map(|dim| dim.into_px(context.gfx.scale()))
|
.map(|dim| dim.into_px(context.gfx.scale()).round())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn effective_background_color(&mut self, context: &WidgetContext<'_, '_>) -> kludgine::Color {
|
fn effective_background_color(&mut self, context: &WidgetContext<'_, '_>) -> kludgine::Color {
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,10 @@ impl<const COLUMNS: usize> Widget for Grid<COLUMNS> {
|
||||||
|
|
||||||
let content_size = self.layout.update(
|
let content_size = self.layout.update(
|
||||||
available_space,
|
available_space,
|
||||||
context.get(&IntrinsicPadding).into_upx(context.gfx.scale()),
|
context
|
||||||
|
.get(&IntrinsicPadding)
|
||||||
|
.into_upx(context.gfx.scale())
|
||||||
|
.round(),
|
||||||
context.gfx.scale(),
|
context.gfx.scale(),
|
||||||
|row, column, constraints, persist| {
|
|row, column, constraints, persist| {
|
||||||
let mut context = context.for_other(&self.live_rows[column][row]);
|
let mut context = context.for_other(&self.live_rows[column][row]);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use kludgine::app::winit::keyboard::{Key, NamedKey};
|
||||||
use kludgine::app::winit::window::{CursorIcon, ImePurpose};
|
use kludgine::app::winit::window::{CursorIcon, ImePurpose};
|
||||||
use kludgine::figures::units::{Lp, Px, UPx};
|
use kludgine::figures::units::{Lp, Px, UPx};
|
||||||
use kludgine::figures::{
|
use kludgine::figures::{
|
||||||
Abs, FloatConversion, IntoSigned, IntoUnsigned, Point, Rect, ScreenScale, Size,
|
Abs, FloatConversion, IntoSigned, IntoUnsigned, Point, Rect, Round, ScreenScale, Size,
|
||||||
};
|
};
|
||||||
use kludgine::shapes::{Shape, StrokeOptions};
|
use kludgine::shapes::{Shape, StrokeOptions};
|
||||||
use kludgine::text::{MeasuredText, Text, TextOrigin};
|
use kludgine::text::{MeasuredText, Text, TextOrigin};
|
||||||
|
|
@ -340,7 +340,8 @@ where
|
||||||
Self::point_from_cursor(&cache.measured, self.selection.cursor, cache.bytes);
|
Self::point_from_cursor(&cache.measured, self.selection.cursor, cache.bytes);
|
||||||
position.y += context
|
position.y += context
|
||||||
.get(&IntrinsicPadding)
|
.get(&IntrinsicPadding)
|
||||||
.into_px(context.kludgine.scale());
|
.into_px(context.kludgine.scale())
|
||||||
|
.round();
|
||||||
match affinity {
|
match affinity {
|
||||||
Affinity::Before => position.x = Px::ZERO,
|
Affinity::Before => position.x = Px::ZERO,
|
||||||
Affinity::After => {
|
Affinity::After => {
|
||||||
|
|
@ -361,7 +362,8 @@ where
|
||||||
position += Point::squared(
|
position += Point::squared(
|
||||||
context
|
context
|
||||||
.get(&IntrinsicPadding)
|
.get(&IntrinsicPadding)
|
||||||
.into_px(context.kludgine.scale()),
|
.into_px(context.kludgine.scale())
|
||||||
|
.round(),
|
||||||
);
|
);
|
||||||
if let Some(target_x) = self.line_navigation_x_target {
|
if let Some(target_x) = self.line_navigation_x_target {
|
||||||
position.x = target_x;
|
position.x = target_x;
|
||||||
|
|
@ -819,7 +821,8 @@ where
|
||||||
|
|
||||||
let padding = context
|
let padding = context
|
||||||
.get(&IntrinsicPadding)
|
.get(&IntrinsicPadding)
|
||||||
.into_px(context.kludgine.scale());
|
.into_px(context.kludgine.scale())
|
||||||
|
.round();
|
||||||
let mut location = location - padding;
|
let mut location = location - padding;
|
||||||
if location.y < 0 {
|
if location.y < 0 {
|
||||||
location.y = Px::ZERO;
|
location.y = Px::ZERO;
|
||||||
|
|
@ -1029,8 +1032,11 @@ where
|
||||||
|
|
||||||
let cursor_state = self.blink_state;
|
let cursor_state = self.blink_state;
|
||||||
let size = context.gfx.size();
|
let size = context.gfx.size();
|
||||||
let padding = context.get(&IntrinsicPadding).into_px(context.gfx.scale());
|
let padding = context
|
||||||
let padding = Point::<Px>::new(padding, padding);
|
.get(&IntrinsicPadding)
|
||||||
|
.into_px(context.gfx.scale())
|
||||||
|
.round();
|
||||||
|
let padding = Point::squared(padding);
|
||||||
|
|
||||||
let cache = self.layout_text(Some(size.width.into_signed()), context);
|
let cache = self.layout_text(Some(size.width.into_signed()), context);
|
||||||
|
|
||||||
|
|
@ -1147,7 +1153,10 @@ where
|
||||||
available_space: Size<ConstraintLimit>,
|
available_space: Size<ConstraintLimit>,
|
||||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||||
) -> Size<UPx> {
|
) -> Size<UPx> {
|
||||||
let padding = context.get(&IntrinsicPadding).into_upx(context.gfx.scale());
|
let padding = context
|
||||||
|
.get(&IntrinsicPadding)
|
||||||
|
.into_upx(context.gfx.scale())
|
||||||
|
.round();
|
||||||
|
|
||||||
let width = available_space.width.max().saturating_sub(padding * 2);
|
let width = available_space.width.max().saturating_sub(padding * 2);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! A widget that combines a collection of [`Children`] widgets into one.
|
//! A widget that combines a collection of [`Children`] widgets into one.
|
||||||
|
|
||||||
use kludgine::figures::units::UPx;
|
use kludgine::figures::units::UPx;
|
||||||
use kludgine::figures::{IntoSigned, Rect, ScreenScale, Size};
|
use kludgine::figures::{IntoSigned, Rect, Round, ScreenScale, Size};
|
||||||
|
|
||||||
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext};
|
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext};
|
||||||
use crate::styles::components::IntrinsicPadding;
|
use crate::styles::components::IntrinsicPadding;
|
||||||
|
|
@ -142,7 +142,8 @@ impl Widget for Stack {
|
||||||
FlexibleDimension::Auto => context.get(&IntrinsicPadding),
|
FlexibleDimension::Auto => context.get(&IntrinsicPadding),
|
||||||
FlexibleDimension::Dimension(dimension) => dimension,
|
FlexibleDimension::Dimension(dimension) => dimension,
|
||||||
}
|
}
|
||||||
.into_upx(context.gfx.scale());
|
.into_upx(context.gfx.scale())
|
||||||
|
.round();
|
||||||
|
|
||||||
let content_size = self.layout.update(
|
let content_size = self.layout.update(
|
||||||
available_space,
|
available_space,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use intentional::Cast;
|
use intentional::Cast;
|
||||||
use kludgine::figures::units::{Px, UPx};
|
use kludgine::figures::units::{Px, UPx};
|
||||||
use kludgine::figures::{IntoSigned, IntoUnsigned, Point, Rect, ScreenScale, Size, Zero};
|
use kludgine::figures::{IntoSigned, IntoUnsigned, Point, Rect, Round, ScreenScale, Size, Zero};
|
||||||
|
|
||||||
use crate::context::{AsEventContext, GraphicsContext, LayoutContext};
|
use crate::context::{AsEventContext, GraphicsContext, LayoutContext};
|
||||||
use crate::styles::components::{IntrinsicPadding, LayoutOrder};
|
use crate::styles::components::{IntrinsicPadding, LayoutOrder};
|
||||||
|
|
@ -64,6 +64,36 @@ impl Wrap {
|
||||||
self.vertical_align = align.into_value();
|
self.vertical_align = align.into_value();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn horizontal_alignment(
|
||||||
|
align: WrapAlign,
|
||||||
|
order: HorizontalOrder,
|
||||||
|
remaining: Px,
|
||||||
|
row_children_len: usize,
|
||||||
|
) -> (Px, Px) {
|
||||||
|
match (align, order) {
|
||||||
|
(WrapAlign::Start, HorizontalOrder::LeftToRight)
|
||||||
|
| (WrapAlign::End, HorizontalOrder::RightToLeft) => (Px::ZERO, Px::ZERO),
|
||||||
|
(WrapAlign::End, HorizontalOrder::LeftToRight)
|
||||||
|
| (WrapAlign::Start, HorizontalOrder::RightToLeft) => (remaining, Px::ZERO),
|
||||||
|
(WrapAlign::Center, _) => (remaining / 2, Px::ZERO),
|
||||||
|
(WrapAlign::SpaceBetween, _) => {
|
||||||
|
if row_children_len > 1 {
|
||||||
|
(Px::ZERO, remaining / (row_children_len - 1).cast::<i32>())
|
||||||
|
} else {
|
||||||
|
(Px::ZERO, Px::ZERO)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(WrapAlign::SpaceEvenly, _) => {
|
||||||
|
let spacing = remaining / row_children_len.cast::<i32>();
|
||||||
|
(spacing / 2, spacing)
|
||||||
|
}
|
||||||
|
(WrapAlign::SpaceAround, _) => {
|
||||||
|
let spacing = remaining / (row_children_len + 1).cast::<i32>();
|
||||||
|
(spacing, spacing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Wrap {
|
impl Widget for Wrap {
|
||||||
|
|
@ -73,6 +103,7 @@ impl Widget for Wrap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
available_space: Size<ConstraintLimit>,
|
available_space: Size<ConstraintLimit>,
|
||||||
|
|
@ -96,7 +127,8 @@ impl Widget for Wrap {
|
||||||
FlexibleDimension::Auto => context.get(&IntrinsicPadding),
|
FlexibleDimension::Auto => context.get(&IntrinsicPadding),
|
||||||
FlexibleDimension::Dimension(dimension) => dimension,
|
FlexibleDimension::Dimension(dimension) => dimension,
|
||||||
})
|
})
|
||||||
.into_px(context.gfx.scale());
|
.into_px(context.gfx.scale())
|
||||||
|
.round();
|
||||||
self.mounted
|
self.mounted
|
||||||
.synchronize_with(&self.children, &mut context.as_event_context());
|
.synchronize_with(&self.children, &mut context.as_event_context());
|
||||||
|
|
||||||
|
|
@ -144,28 +176,7 @@ impl Widget for Wrap {
|
||||||
// Calculate the horizontal alignment.
|
// Calculate the horizontal alignment.
|
||||||
let remaining = (width - x).max(Px::ZERO);
|
let remaining = (width - x).max(Px::ZERO);
|
||||||
let (x, space_between) = if remaining > 0 {
|
let (x, space_between) = if remaining > 0 {
|
||||||
match (align, order) {
|
Self::horizontal_alignment(align, order, remaining, row_children.len())
|
||||||
(WrapAlign::Start, HorizontalOrder::LeftToRight)
|
|
||||||
| (WrapAlign::End, HorizontalOrder::RightToLeft) => (Px::ZERO, Px::ZERO),
|
|
||||||
(WrapAlign::End, HorizontalOrder::LeftToRight)
|
|
||||||
| (WrapAlign::Start, HorizontalOrder::RightToLeft) => (remaining, Px::ZERO),
|
|
||||||
(WrapAlign::Center, _) => (remaining / 2, Px::ZERO),
|
|
||||||
(WrapAlign::SpaceBetween, _) => {
|
|
||||||
if row_children.len() > 1 {
|
|
||||||
(Px::ZERO, remaining / (row_children.len() - 1).cast::<i32>())
|
|
||||||
} else {
|
|
||||||
(Px::ZERO, Px::ZERO)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(WrapAlign::SpaceEvenly, _) => {
|
|
||||||
let spacing = remaining / row_children.len().cast::<i32>();
|
|
||||||
(spacing / 2, spacing)
|
|
||||||
}
|
|
||||||
(WrapAlign::SpaceAround, _) => {
|
|
||||||
let spacing = remaining / (row_children.len() + 1).cast::<i32>();
|
|
||||||
(spacing, spacing)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
(Px::ZERO, Px::ZERO)
|
(Px::ZERO, Px::ZERO)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue