Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
xarvic committed Jan 15, 2023
1 parent 9aa6ab7 commit b199525
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 10 deletions.
18 changes: 12 additions & 6 deletions druid/src/widget/align.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,17 @@ impl<T> Align<T> {
}
}

/// The `Align` widget should only consider the visible space for alignment.
///
/// When the `Align` widget is fully visible, this option has no effect. When the align widget
/// gets scrolled out of view, the wrapped widget will move to stay inside the visible area.
/// The wrapped widget will always stay inside the bounds of the `Align` widget.
fn in_viewport(mut self) -> Self {
self.in_viewport = true;
self
}

fn align<'b, C: CommandCtx<'b>>(&mut self, ctx: &mut C, data: &T, env: &Env, my_size: Size) {
fn align<'b, C: CommandCtx<'b>>(&mut self, ctx: &mut C, my_size: Size) {
let size = self.child.layout_rect().size();

let extra_width = (my_size.width - size.width).max(0.);
Expand All @@ -105,8 +110,8 @@ impl<T> Align<T> {
let viewport = Rect::from_origin_size(self.viewport.origin(), self.viewport.size() - size);

// Essentially Rect::intersect but this implementation chooses the point closed to viewport
// inside extra_space to give the child a valid origin even if this widget is not inside
// the viewport
// inside extra_space to give the child a valid origin even if extra_space and viewport
// dont intersect.
extra_space.x0 = extra_space.x0.max(viewport.x0).min(extra_space.x1);
extra_space.y0 = extra_space.y0.max(viewport.y0).min(extra_space.y1);
extra_space.x1 = extra_space.x1.min(viewport.x1).max(extra_space.x0);
Expand All @@ -117,7 +122,7 @@ impl<T> Align<T> {
.align
.resolve(extra_space)
.expand();
self.child.set_origin(ctx, data, env, origin);
self.child.set_origin(ctx, origin);
}
}

Expand All @@ -129,10 +134,11 @@ impl<T: Data> Widget<T> for Align<T> {

#[instrument(name = "Align", level = "trace", skip(self, ctx, event, data, env))]
fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) {
// THis needs to happen before passing the event to the child.
if let LifeCycle::ViewContextChanged(view_ctx) = event {
self.viewport = view_ctx.clip;
if self.in_viewport {
self.align(ctx, data, env, ctx.size());
self.align(ctx, ctx.size());
}
}

Expand Down Expand Up @@ -169,7 +175,7 @@ impl<T: Data> Widget<T> for Align<T> {
}

let my_size = bc.constrain(my_size);
self.align(ctx, data, env, my_size);
self.align(ctx, my_size);

let my_insets = self.child.compute_parent_paint_insets(my_size);
ctx.set_paint_insets(my_insets);
Expand Down
35 changes: 31 additions & 4 deletions druid/src/widget/viewport_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{BoxConstraints, Color, Data, Env, Event, EventCtx, Insets, LayoutCtx
use crate::commands::SCROLL_TO_VIEW;
use crate::widget::flex::{Orientation, Side};


/// A widget, containing two widgets with horizontal or vertical layout.
///
/// When the `ViewportHeader` is moved out of the viewport, the `header` widget tries to stay inside
/// the viewport by moving over the `content` if necessary.
pub struct ViewportHeader<T> {
header: WidgetPod<T, Box<dyn Widget<T>>>,
content: WidgetPod<T, Box<dyn Widget<T>>>,
Expand All @@ -12,6 +15,7 @@ pub struct ViewportHeader<T> {
clip_content: bool,
}

/// ViewportHeaderConfig contains the information necessary to create the layout of [`ViewportHeader`]
pub struct ViewportHeaderConfig {
content_size: Size,
viewport: Rect,
Expand All @@ -21,6 +25,9 @@ pub struct ViewportHeaderConfig {
}

impl ViewportHeaderConfig {
/// creates a new config.
///
/// side: the side at which the header is located.
pub fn new(side: Side) -> Self {
Self {
content_size: Size::ZERO,
Expand All @@ -34,10 +41,12 @@ impl ViewportHeaderConfig {
}
}

/// The the layout size of header and content together, when both are fully in view.
pub fn size(&self) -> Size {
self.content_size + Size::from(self.header_side.axis().pack(self.header_size, 0.0))
}

/// The side of the header.
pub fn side(&self) -> Side {
self.header_side
}
Expand Down Expand Up @@ -83,6 +92,10 @@ impl ViewportHeaderConfig {
(content_origin, header_origin)
}

/// Updates a `scroll_to_view` request of the content to take the additional viewport crop into
/// account.
///
/// Dont call call this with requests of the header widget.
pub fn transform_content_scroll_to_view(&self, ctx: &mut EventCtx, rect: Rect) {
let axis = self.header_side.axis();
// The length on the major axis with is overlapped by the header.
Expand All @@ -96,26 +109,37 @@ impl ViewportHeaderConfig {
}
}

/// Updates the ViewContext of the widget.
///
/// Should be called when the widget receives a `Lifecycle::ViewContextChanged` event.
pub fn update_context(&mut self, view_context: ViewContext) {
self.viewport = view_context.clip;
}

/// Updates the content size.
///
/// Should be called in layout.
pub fn set_content_size(&mut self, content_size: Size) {
self.content_size = content_size;
}

/// Updates the header size.
///
/// should be called in layout
pub fn set_header_size(&mut self, header_size: Size) {
let axis = self.header_side.axis();
self.header_size = axis.major(header_size);
}

/// Sets the minimum visible content.
pub fn set_minimum_visible_content(&mut self, visible: f64) {
self.minimum_visible_content = visible;
}

}

impl<T: Data> ViewportHeader<T> {
/// Creates a new ViewportHeader widget with a given side for the header.
pub fn new(content: impl Widget<T> + 'static, header: impl Widget<T> + 'static, side: Side) -> Self {
Self {
header: WidgetPod::new(Box::new(header)),
Expand All @@ -125,11 +149,14 @@ impl<T: Data> ViewportHeader<T> {
}
}

/// The amount of Pixels
pub fn with_minimum_visible_content(mut self, minimum_visible_content: f64) -> Self {
self.header_config.set_minimum_visible_content(minimum_visible_content);
self
}

/// Builder-style method to set whether the additional cropped viewport should be clipped from
/// from the content.
pub fn clipped_content(mut self, clipped_content: bool) -> Self {
self.clip_content = clipped_content;
self
Expand Down Expand Up @@ -163,7 +190,7 @@ impl<T: Data> Widget<T> for ViewportHeader<T> {
self.header_config.update_context(*view_context);
let (_, header_origin) = self.header_config.origins();

self.header.set_origin(ctx, data, env, header_origin);
self.header.set_origin(ctx, header_origin);
self.header.lifecycle(ctx, event, data, env);

let mut content_view_context = *view_context;
Expand Down Expand Up @@ -206,8 +233,8 @@ impl<T: Data> Widget<T> for ViewportHeader<T> {

let (content_origin, header_origin) = self.header_config.origins();

self.header.set_origin(ctx, data, env, header_origin);
self.content.set_origin(ctx, data, env, content_origin);
self.header.set_origin(ctx, header_origin);
self.content.set_origin(ctx, content_origin);

self.header_config.size()
}
Expand Down

0 comments on commit b199525

Please sign in to comment.