mirror of
https://github.com/danbulant/cushy
synced 2026-09-18 05:53:46 +00:00
WrapperWidget, Space
This commit is contained in:
parent
9596eaac17
commit
8e268615a1
10 changed files with 379 additions and 123 deletions
|
|
@ -468,7 +468,17 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, '
|
|||
|
||||
/// Invokes [`Widget::redraw()`](crate::widget::Widget::redraw) on this
|
||||
/// context's widget.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the widget being drawn has no layout set (via
|
||||
/// [`LayoutContext::set_child_layout()`]).
|
||||
pub fn redraw(&mut self) {
|
||||
assert!(
|
||||
self.last_layout().is_some(),
|
||||
"redraw called without set_widget_layout"
|
||||
);
|
||||
|
||||
self.current_node
|
||||
.tree
|
||||
.note_widget_rendered(self.current_node.id());
|
||||
|
|
|
|||
33
src/value.rs
33
src/value.rs
|
|
@ -264,17 +264,7 @@ impl<T> DynamicData<T> {
|
|||
let mut changed = true;
|
||||
let result = map(&mut state.wrapped.value, &mut changed);
|
||||
if changed {
|
||||
state.wrapped.generation = state.wrapped.generation.next();
|
||||
|
||||
for callback in &mut state.callbacks {
|
||||
callback.update(&state.wrapped);
|
||||
}
|
||||
for window in state.windows.drain(..) {
|
||||
window.redraw();
|
||||
}
|
||||
for waker in state.wakers.drain(..) {
|
||||
waker.wake();
|
||||
}
|
||||
state.note_changed();
|
||||
}
|
||||
|
||||
result
|
||||
|
|
@ -321,6 +311,22 @@ struct State<T> {
|
|||
readers: usize,
|
||||
}
|
||||
|
||||
impl<T> State<T> {
|
||||
fn note_changed(&mut self) {
|
||||
self.wrapped.generation = self.wrapped.generation.next();
|
||||
|
||||
for callback in &mut self.callbacks {
|
||||
callback.update(&self.wrapped);
|
||||
}
|
||||
for window in self.windows.drain(..) {
|
||||
window.redraw();
|
||||
}
|
||||
for waker in self.wakers.drain(..) {
|
||||
waker.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Debug for State<T>
|
||||
where
|
||||
T: Debug,
|
||||
|
|
@ -353,6 +359,9 @@ struct GenerationalValue<T> {
|
|||
}
|
||||
|
||||
/// An exclusive reference to the contents of a [`Dynamic`].
|
||||
///
|
||||
/// If the contents are accessed through [`DerefMut`], all obververs will be
|
||||
/// notified of a change when this guard is dropped.
|
||||
#[derive(Debug)]
|
||||
pub struct DynamicGuard<'a, T> {
|
||||
guard: MutexGuard<'a, State<T>>,
|
||||
|
|
@ -377,7 +386,7 @@ impl<'a, T> DerefMut for DynamicGuard<'a, T> {
|
|||
impl<T> Drop for DynamicGuard<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
if self.accessed_mut {
|
||||
todo!("trigger callbacks")
|
||||
self.guard.note_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
259
src/widget.rs
259
src/widget.rs
|
|
@ -12,7 +12,7 @@ use kludgine::app::winit::event::{
|
|||
DeviceId, Ime, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
};
|
||||
use kludgine::figures::units::{Px, UPx};
|
||||
use kludgine::figures::{Point, Rect, Size};
|
||||
use kludgine::figures::{IntoSigned, IntoUnsigned, Point, Rect, Size};
|
||||
|
||||
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext};
|
||||
use crate::styles::components::VisualOrder;
|
||||
|
|
@ -167,6 +167,263 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Widget`] that contains a single child.
|
||||
pub trait WrapperWidget: Debug + Send + UnwindSafe + 'static {
|
||||
/// Returns the child widget.
|
||||
fn child(&mut self) -> &mut WidgetRef;
|
||||
|
||||
/// Returns the rectangle that the child widget should occupy given
|
||||
/// `available_space`.
|
||||
#[allow(unused_variables)]
|
||||
fn layout_child(
|
||||
&mut self,
|
||||
available_space: Size<ConstraintLimit>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> Rect<Px> {
|
||||
let child = self.child().mounted(&mut context.as_event_context());
|
||||
|
||||
context
|
||||
.for_other(&child)
|
||||
.layout(available_space)
|
||||
.into_signed()
|
||||
.into()
|
||||
}
|
||||
|
||||
/// The widget has been mounted into a parent widget.
|
||||
#[allow(unused_variables)]
|
||||
fn mounted(&mut self, context: &mut EventContext<'_, '_>) {}
|
||||
|
||||
/// The widget has been removed from its parent widget.
|
||||
#[allow(unused_variables)]
|
||||
fn unmounted(&mut self, context: &mut EventContext<'_, '_>) {}
|
||||
|
||||
/// Returns true if this widget should respond to mouse input at `location`.
|
||||
#[allow(unused_variables)]
|
||||
fn hit_test(&mut self, location: Point<Px>, context: &mut EventContext<'_, '_>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// The widget is currently has a cursor hovering it at `location`.
|
||||
#[allow(unused_variables)]
|
||||
fn hover(&mut self, location: Point<Px>, context: &mut EventContext<'_, '_>) {}
|
||||
|
||||
/// The widget is no longer being hovered.
|
||||
#[allow(unused_variables)]
|
||||
fn unhover(&mut self, context: &mut EventContext<'_, '_>) {}
|
||||
|
||||
/// This widget has been targeted to be focused. If this function returns
|
||||
/// true, the widget will be focused. If false, Gooey will continue
|
||||
/// searching for another focus target.
|
||||
#[allow(unused_variables)]
|
||||
fn accept_focus(&mut self, context: &mut EventContext<'_, '_>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// The widget has received focus for user input.
|
||||
#[allow(unused_variables)]
|
||||
fn focus(&mut self, context: &mut EventContext<'_, '_>) {}
|
||||
|
||||
/// The widget is no longer focused for user input.
|
||||
#[allow(unused_variables)]
|
||||
fn blur(&mut self, context: &mut EventContext<'_, '_>) {}
|
||||
|
||||
/// The widget has become the active widget.
|
||||
#[allow(unused_variables)]
|
||||
fn activate(&mut self, context: &mut EventContext<'_, '_>) {}
|
||||
|
||||
/// The widget is no longer active.
|
||||
#[allow(unused_variables)]
|
||||
fn deactivate(&mut self, context: &mut EventContext<'_, '_>) {}
|
||||
|
||||
/// A mouse button event has occurred at `location`. Returns whether the
|
||||
/// event has been handled or not.
|
||||
///
|
||||
/// If an event is handled, the widget will receive callbacks for
|
||||
/// [`mouse_drag`](Self::mouse_drag) and [`mouse_up`](Self::mouse_up).
|
||||
#[allow(unused_variables)]
|
||||
fn mouse_down(
|
||||
&mut self,
|
||||
location: Point<Px>,
|
||||
device_id: DeviceId,
|
||||
button: MouseButton,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) -> EventHandling {
|
||||
IGNORED
|
||||
}
|
||||
|
||||
/// A mouse button is being held down as the cursor is moved across the
|
||||
/// widget.
|
||||
#[allow(unused_variables)]
|
||||
fn mouse_drag(
|
||||
&mut self,
|
||||
location: Point<Px>,
|
||||
device_id: DeviceId,
|
||||
button: MouseButton,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) {
|
||||
}
|
||||
|
||||
/// A mouse button is no longer being pressed.
|
||||
#[allow(unused_variables)]
|
||||
fn mouse_up(
|
||||
&mut self,
|
||||
location: Option<Point<Px>>,
|
||||
device_id: DeviceId,
|
||||
button: MouseButton,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) {
|
||||
}
|
||||
|
||||
/// A keyboard event has been sent to this widget. Returns whether the event
|
||||
/// has been handled or not.
|
||||
#[allow(unused_variables)]
|
||||
fn keyboard_input(
|
||||
&mut self,
|
||||
device_id: DeviceId,
|
||||
input: KeyEvent,
|
||||
is_synthetic: bool,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) -> EventHandling {
|
||||
IGNORED
|
||||
}
|
||||
|
||||
/// An input manager event has been sent to this widget. Returns whether the
|
||||
/// event has been handled or not.
|
||||
#[allow(unused_variables)]
|
||||
fn ime(&mut self, ime: Ime, context: &mut EventContext<'_, '_>) -> EventHandling {
|
||||
IGNORED
|
||||
}
|
||||
|
||||
/// A mouse wheel event has been sent to this widget. Returns whether the
|
||||
/// event has been handled or not.
|
||||
#[allow(unused_variables)]
|
||||
fn mouse_wheel(
|
||||
&mut self,
|
||||
device_id: DeviceId,
|
||||
delta: MouseScrollDelta,
|
||||
phase: TouchPhase,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) -> EventHandling {
|
||||
IGNORED
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Widget for T
|
||||
where
|
||||
T: WrapperWidget,
|
||||
{
|
||||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
let child = self.child().mounted(&mut context.as_event_context());
|
||||
context.for_other(&child).redraw();
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
available_space: Size<ConstraintLimit>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> Size<UPx> {
|
||||
let child = self.child().mounted(&mut context.as_event_context());
|
||||
|
||||
let layout = self.layout_child(available_space, context);
|
||||
context.set_child_layout(&child, layout);
|
||||
layout.size.into_unsigned()
|
||||
}
|
||||
|
||||
fn mounted(&mut self, context: &mut EventContext<'_, '_>) {
|
||||
T::mounted(self, context);
|
||||
}
|
||||
|
||||
fn unmounted(&mut self, context: &mut EventContext<'_, '_>) {
|
||||
T::unmounted(self, context);
|
||||
}
|
||||
|
||||
fn hit_test(&mut self, location: Point<Px>, context: &mut EventContext<'_, '_>) -> bool {
|
||||
T::hit_test(self, location, context)
|
||||
}
|
||||
|
||||
fn hover(&mut self, location: Point<Px>, context: &mut EventContext<'_, '_>) {
|
||||
T::hover(self, location, context);
|
||||
}
|
||||
|
||||
fn unhover(&mut self, context: &mut EventContext<'_, '_>) {
|
||||
T::unhover(self, context);
|
||||
}
|
||||
|
||||
fn accept_focus(&mut self, context: &mut EventContext<'_, '_>) -> bool {
|
||||
T::accept_focus(self, context)
|
||||
}
|
||||
|
||||
fn focus(&mut self, context: &mut EventContext<'_, '_>) {
|
||||
T::focus(self, context);
|
||||
}
|
||||
|
||||
fn blur(&mut self, context: &mut EventContext<'_, '_>) {
|
||||
T::blur(self, context);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: &mut EventContext<'_, '_>) {
|
||||
T::activate(self, context);
|
||||
}
|
||||
|
||||
fn deactivate(&mut self, context: &mut EventContext<'_, '_>) {
|
||||
T::deactivate(self, context);
|
||||
}
|
||||
|
||||
fn mouse_down(
|
||||
&mut self,
|
||||
location: Point<Px>,
|
||||
device_id: DeviceId,
|
||||
button: MouseButton,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) -> EventHandling {
|
||||
T::mouse_down(self, location, device_id, button, context)
|
||||
}
|
||||
|
||||
fn mouse_drag(
|
||||
&mut self,
|
||||
location: Point<Px>,
|
||||
device_id: DeviceId,
|
||||
button: MouseButton,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) {
|
||||
T::mouse_drag(self, location, device_id, button, context);
|
||||
}
|
||||
|
||||
fn mouse_up(
|
||||
&mut self,
|
||||
location: Option<Point<Px>>,
|
||||
device_id: DeviceId,
|
||||
button: MouseButton,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) {
|
||||
T::mouse_up(self, location, device_id, button, context);
|
||||
}
|
||||
|
||||
fn keyboard_input(
|
||||
&mut self,
|
||||
device_id: DeviceId,
|
||||
input: KeyEvent,
|
||||
is_synthetic: bool,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) -> EventHandling {
|
||||
T::keyboard_input(self, device_id, input, is_synthetic, context)
|
||||
}
|
||||
|
||||
fn ime(&mut self, ime: Ime, context: &mut EventContext<'_, '_>) -> EventHandling {
|
||||
T::ime(self, ime, context)
|
||||
}
|
||||
|
||||
fn mouse_wheel(
|
||||
&mut self,
|
||||
device_id: DeviceId,
|
||||
delta: MouseScrollDelta,
|
||||
phase: TouchPhase,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) -> EventHandling {
|
||||
T::mouse_wheel(self, device_id, delta, phase, context)
|
||||
}
|
||||
}
|
||||
|
||||
/// A type that can create a [`WidgetInstance`].
|
||||
pub trait MakeWidget: Sized {
|
||||
/// Returns a new widget.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ mod input;
|
|||
mod label;
|
||||
mod resize;
|
||||
pub mod scroll;
|
||||
mod space;
|
||||
pub mod stack;
|
||||
mod style;
|
||||
mod tilemap;
|
||||
|
|
@ -20,6 +21,7 @@ pub use input::Input;
|
|||
pub use label::Label;
|
||||
pub use resize::Resize;
|
||||
pub use scroll::Scroll;
|
||||
pub use space::Space;
|
||||
pub use stack::Stack;
|
||||
pub use style::Style;
|
||||
pub use tilemap::TileMap;
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ use std::fmt::Debug;
|
|||
use kludgine::figures::units::UPx;
|
||||
use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, Point, Rect, ScreenScale, Size};
|
||||
|
||||
use crate::context::{AsEventContext, GraphicsContext, LayoutContext};
|
||||
use crate::context::{AsEventContext, LayoutContext};
|
||||
use crate::styles::{Dimension, Edges, FlexibleDimension};
|
||||
use crate::value::{IntoValue, Value};
|
||||
use crate::widget::{MakeWidget, Widget, WidgetRef};
|
||||
use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
|
||||
use crate::ConstraintLimit;
|
||||
|
||||
/// A widget aligns its contents to its container's boundaries.
|
||||
|
|
@ -145,31 +145,31 @@ impl FrameInfo {
|
|||
}
|
||||
}
|
||||
|
||||
impl Widget for Align {
|
||||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
let child = self.child.mounted(&mut context.as_event_context());
|
||||
context.for_other(&child).redraw();
|
||||
impl WrapperWidget for Align {
|
||||
fn child(&mut self) -> &mut WidgetRef {
|
||||
&mut self.child
|
||||
}
|
||||
|
||||
fn layout(
|
||||
fn layout_child(
|
||||
&mut self,
|
||||
available_space: Size<ConstraintLimit>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> Size<UPx> {
|
||||
let child = self.child.mounted(&mut context.as_event_context());
|
||||
) -> Rect<kludgine::figures::units::Px> {
|
||||
let layout = self.measure(available_space, context);
|
||||
context.set_child_layout(
|
||||
&child,
|
||||
Rect::new(
|
||||
Point::new(
|
||||
layout.margin.left.into_signed(),
|
||||
layout.margin.top.into_signed(),
|
||||
),
|
||||
layout.content.into_signed(),
|
||||
),
|
||||
);
|
||||
|
||||
layout.size().into_unsigned()
|
||||
Rect::new(
|
||||
Point::new(
|
||||
layout.margin.left.into_signed(),
|
||||
layout.margin.top.into_signed(),
|
||||
),
|
||||
layout.content.into_signed(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<WidgetRef> for Align {
|
||||
fn as_mut(&mut self) -> &mut WidgetRef {
|
||||
&mut self.child
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,9 +178,3 @@ struct Layout {
|
|||
margin: Edges<UPx>,
|
||||
content: Size<UPx>,
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
pub fn size(&self) -> Size<UPx> {
|
||||
self.margin.size() + self.content
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use kludgine::figures::units::UPx;
|
||||
use kludgine::figures::units::{Px, UPx};
|
||||
use kludgine::figures::{IntoSigned, Rect, Size};
|
||||
|
||||
use crate::context::{AsEventContext, GraphicsContext, LayoutContext};
|
||||
use crate::widget::{MakeWidget, Widget, WidgetRef};
|
||||
use crate::context::{AsEventContext, LayoutContext};
|
||||
use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
|
||||
use crate::widgets::Space;
|
||||
use crate::ConstraintLimit;
|
||||
|
||||
/// A widget that expands its child widget to fill the parent.
|
||||
|
|
@ -14,7 +15,7 @@ pub struct Expand {
|
|||
/// The weight to use when splitting available space with multiple
|
||||
/// [`Expand`] widgets.
|
||||
pub weight: u8,
|
||||
child: Option<WidgetRef>,
|
||||
child: WidgetRef,
|
||||
}
|
||||
|
||||
impl Default for Expand {
|
||||
|
|
@ -28,7 +29,7 @@ impl Expand {
|
|||
#[must_use]
|
||||
pub fn new(child: impl MakeWidget) -> Self {
|
||||
Self {
|
||||
child: Some(WidgetRef::new(child)),
|
||||
child: WidgetRef::new(child),
|
||||
weight: 1,
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +38,7 @@ impl Expand {
|
|||
#[must_use]
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
child: None,
|
||||
child: WidgetRef::new(Space),
|
||||
weight: 1,
|
||||
}
|
||||
}
|
||||
|
|
@ -49,57 +50,44 @@ impl Expand {
|
|||
#[must_use]
|
||||
pub fn weighted(weight: u8, child: impl MakeWidget) -> Self {
|
||||
Self {
|
||||
child: Some(WidgetRef::new(child)),
|
||||
child: WidgetRef::new(child),
|
||||
weight,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the child widget.
|
||||
#[must_use]
|
||||
pub fn child(&self) -> Option<&WidgetRef> {
|
||||
self.child.as_ref()
|
||||
pub const fn child(&self) -> &WidgetRef {
|
||||
&self.child
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Expand {
|
||||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
let Some(child) = &mut self.child else { return };
|
||||
let child = child.mounted(&mut context.as_event_context());
|
||||
context.for_other(&child).redraw();
|
||||
impl WrapperWidget for Expand {
|
||||
fn child(&mut self) -> &mut WidgetRef {
|
||||
&mut self.child
|
||||
}
|
||||
|
||||
fn layout(
|
||||
fn layout_child(
|
||||
&mut self,
|
||||
available_space: Size<ConstraintLimit>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> Size<UPx> {
|
||||
) -> Rect<Px> {
|
||||
let available_space = Size::new(
|
||||
ConstraintLimit::Known(available_space.width.max()),
|
||||
ConstraintLimit::Known(available_space.height.max()),
|
||||
);
|
||||
let child = self
|
||||
.child
|
||||
.as_mut()
|
||||
.map(|child| child.mounted(&mut context.as_event_context()));
|
||||
let size = if let Some(child) = &child {
|
||||
context.for_other(child).layout(available_space)
|
||||
} else {
|
||||
Size::default()
|
||||
};
|
||||
let child = self.child.mounted(&mut context.as_event_context());
|
||||
let size = context.for_other(&child).layout(available_space);
|
||||
|
||||
let expanded_size = Size::new(
|
||||
Size::<UPx>::new(
|
||||
available_space
|
||||
.width
|
||||
.fit_measured(size.width, context.graphics.scale()),
|
||||
available_space
|
||||
.height
|
||||
.fit_measured(size.height, context.graphics.scale()),
|
||||
);
|
||||
|
||||
if let Some(child) = child {
|
||||
context.set_child_layout(&child, Rect::from(expanded_size.into_signed()));
|
||||
}
|
||||
|
||||
expanded_size
|
||||
)
|
||||
.into_signed()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use kludgine::figures::units::UPx;
|
||||
use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, Rect, ScreenScale, Size};
|
||||
|
||||
use crate::context::{AsEventContext, GraphicsContext, LayoutContext};
|
||||
use crate::context::{AsEventContext, LayoutContext};
|
||||
use crate::styles::Dimension;
|
||||
use crate::widget::{MakeWidget, Widget, WidgetRef};
|
||||
use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
|
||||
use crate::ConstraintLimit;
|
||||
|
||||
/// A widget that resizes its contained widget to an explicit size.
|
||||
|
|
@ -57,17 +56,16 @@ impl Resize {
|
|||
}
|
||||
}
|
||||
|
||||
impl Widget for Resize {
|
||||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
let child = self.child.mounted(&mut context.as_event_context());
|
||||
context.for_other(&child).redraw();
|
||||
impl WrapperWidget for Resize {
|
||||
fn child(&mut self) -> &mut WidgetRef {
|
||||
&mut self.child
|
||||
}
|
||||
|
||||
fn layout(
|
||||
fn layout_child(
|
||||
&mut self,
|
||||
available_space: Size<ConstraintLimit>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> Size<UPx> {
|
||||
) -> Rect<kludgine::figures::units::Px> {
|
||||
let child = self.child.mounted(&mut context.as_event_context());
|
||||
let size = if let (Some(width), Some(height)) = (self.width, self.height) {
|
||||
Size::new(
|
||||
|
|
@ -85,8 +83,7 @@ impl Widget for Resize {
|
|||
);
|
||||
context.for_other(&child).layout(available_space)
|
||||
};
|
||||
context.set_child_layout(&child, Rect::from(size.into_signed()));
|
||||
size
|
||||
Rect::from(size.into_signed())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
22
src/widgets/space.rs
Normal file
22
src/widgets/space.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use kludgine::figures::units::UPx;
|
||||
use kludgine::figures::Size;
|
||||
|
||||
use crate::context::{GraphicsContext, LayoutContext};
|
||||
use crate::widget::Widget;
|
||||
use crate::ConstraintLimit;
|
||||
|
||||
/// A widget that does nothing and draws nothing.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Space;
|
||||
|
||||
impl Widget for Space {
|
||||
fn redraw(&mut self, _context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {}
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_available_space: Size<ConstraintLimit>,
|
||||
_context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> Size<UPx> {
|
||||
Size::default()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
//! A widget that combines an array of [`Widgets`] into one.
|
||||
// TODO on scale change, all Lp children need to resize
|
||||
//! A widget that combines a collection of [`Children`] widgets into one.
|
||||
// TODO on scale change, all `Lp` children need to resize
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
|
|
@ -11,10 +11,10 @@ use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContex
|
|||
use crate::styles::Dimension;
|
||||
use crate::value::{Generation, IntoValue, Value};
|
||||
use crate::widget::{Children, ManagedWidget, Widget, WidgetRef};
|
||||
use crate::widgets::{Expand, Label, Resize};
|
||||
use crate::widgets::{Expand, Resize};
|
||||
use crate::ConstraintLimit;
|
||||
|
||||
/// A widget that displays a collection of [`Widgets`] in a
|
||||
/// A widget that displays a collection of [`Children`] widgets in a
|
||||
/// [direction](StackDirection).
|
||||
#[derive(Debug)]
|
||||
pub struct Stack {
|
||||
|
|
@ -87,21 +87,12 @@ impl Stack {
|
|||
let guard = widget.lock();
|
||||
let (mut widget, dimension) =
|
||||
if let Some(expand) = guard.downcast_ref::<Expand>() {
|
||||
if let Some(child) = expand.child() {
|
||||
(
|
||||
child.clone(),
|
||||
StackDimension::Fractional {
|
||||
weight: expand.weight,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(
|
||||
WidgetRef::new(Label::new("")), // TODO this should be an empty widget.
|
||||
StackDimension::Fractional {
|
||||
weight: expand.weight,
|
||||
},
|
||||
)
|
||||
}
|
||||
(
|
||||
expand.child().clone(),
|
||||
StackDimension::Fractional {
|
||||
weight: expand.weight,
|
||||
},
|
||||
)
|
||||
} else if let Some((child, size)) =
|
||||
guard.downcast_ref::<Resize>().and_then(|r| {
|
||||
match self.layout.orientation.orientation {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
use kludgine::figures::units::UPx;
|
||||
use kludgine::figures::Size;
|
||||
|
||||
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext};
|
||||
use crate::context::EventContext;
|
||||
use crate::styles::Styles;
|
||||
use crate::widget::{MakeWidget, Widget, WidgetRef};
|
||||
use crate::ConstraintLimit;
|
||||
use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
|
||||
|
||||
/// A widget that applies a set of [`Styles`] to all contained widgets.
|
||||
#[derive(Debug)]
|
||||
|
|
@ -24,22 +20,12 @@ impl Style {
|
|||
}
|
||||
}
|
||||
|
||||
impl Widget for Style {
|
||||
impl WrapperWidget for Style {
|
||||
fn child(&mut self) -> &mut WidgetRef {
|
||||
&mut self.child
|
||||
}
|
||||
|
||||
fn mounted(&mut self, context: &mut EventContext<'_, '_>) {
|
||||
context.attach_styles(self.styles.clone());
|
||||
}
|
||||
|
||||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
let child = self.child.mounted(&mut context.as_event_context());
|
||||
context.for_other(&child).redraw();
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
available_space: Size<ConstraintLimit>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> Size<UPx> {
|
||||
let child = self.child.mounted(&mut context.as_event_context());
|
||||
context.for_other(&child).layout(available_space)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue