Constrain offered boxes with independent widget size bounds
This commit is contained in:
1 parent
4cb6f6882a
commit
2ac0843cb2
18 files changed
+554
-379
No files matched your search
@@ -1,68 +0,0 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
/// Asks its child in the shorter of a cap and the box this widget was given,
|
||||
/// and answers what the child used, held to the same cap.
|
||||
///
|
||||
/// A cap on the box is a widget rather than a [`SizeRule`] because a box is
|
||||
/// whoever asked's to decide: a rule that read the box it was given would be
|
||||
/// decided again by every path that hands a widget one, including the ones
|
||||
/// that re-place a drawing without asking it anything, and the decision would
|
||||
/// then depend on which path arrived last. A widget is drawn again whenever
|
||||
/// its own box changes, so the comparison is made where the answer can be
|
||||
/// kept -- `longer_than` narrows the windows this drawing holds for, and
|
||||
/// `holds` says the box lengths.
|
||||
///
|
||||
/// The box is what a text wraps at and what a scroll takes its viewport from,
|
||||
/// which is why capping the answer alone is not the same thing.
|
||||
pub struct MaxSize {
|
||||
pub inner: StrongWidget,
|
||||
pub x: Option<Len>,
|
||||
pub y: Option<Len>,
|
||||
}
|
||||
|
||||
impl MaxSize {
|
||||
fn max(&self, axis: Axis) -> Option<Len> {
|
||||
match axis {
|
||||
Axis::X => self.x,
|
||||
Axis::Y => self.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for MaxSize {
|
||||
fn size_request(&self, requests: &mut SizeRequests, axis: Axis) -> Option<RequestedLen> {
|
||||
let inner = requests.widget(&self.inner, axis)?;
|
||||
Some(match self.max(axis) {
|
||||
Some(max) => requests.min(inner, max.into()),
|
||||
None => inner,
|
||||
})
|
||||
}
|
||||
|
||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||
let align = painter.alignment();
|
||||
let mut region = UiRegion::FULL;
|
||||
for axis in Axis::BOTH {
|
||||
let Some(max) = self.max(axis) else {
|
||||
continue;
|
||||
};
|
||||
let own = painter.region_len(axis);
|
||||
if painter.longer_than(own, max, axis) {
|
||||
region[axis] = max.align(align[axis]);
|
||||
}
|
||||
}
|
||||
let mut size = painter.widget_at(&self.inner, region).size();
|
||||
for axis in Axis::BOTH {
|
||||
// The child may draw past the box it was given -- a text too tall
|
||||
// for it -- and the cap is a promise about the length as well. A
|
||||
// share passes through: it is a length only to whoever divides
|
||||
// one, and that is this widget's parent rather than this widget,
|
||||
// which has already given the share the box the cap allows.
|
||||
if let Some(max) = self.max(axis)
|
||||
&& painter.longer_than(size[axis].without_leftover(), max, axis)
|
||||
{
|
||||
size[axis] = max.into();
|
||||
}
|
||||
}
|
||||
size
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
mod layer;
|
||||
mod max_size;
|
||||
mod offset;
|
||||
mod pad;
|
||||
mod scroll;
|
||||
@@ -7,7 +6,6 @@ mod span;
|
||||
mod stack;
|
||||
|
||||
pub use layer::*;
|
||||
pub use max_size::*;
|
||||
pub use offset::*;
|
||||
pub use pad::*;
|
||||
pub use scroll::*;
|
||||
|
||||
Reference in new issue
Block a user