Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ViewportHeader widget #2312

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
reformat
  • Loading branch information
xarvic committed Jan 15, 2023
commit 7d0fef1cab2ec923564794c9a37fc2d872872f7c
59 changes: 41 additions & 18 deletions druid/examples/viewport_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@

use druid::lens::Unit;
use druid::widget::prelude::*;
use druid::widget::{BackgroundBrush, Button, ClipBox, Controller, Flex, Label, List, Padding, Side, Slider, Tabs, TextBox, ViewportHeader};
use druid::{AppLauncher, Color, Data, Insets, Lens, LocalizedString, Point, Rect, RoundedRectRadii, Selector, Vec2, WidgetExt, WidgetPod, WindowDesc};
use druid::widget::{
BackgroundBrush, Button, ClipBox, Controller, Flex, Label, List, Padding, Side, Slider, Tabs,
TextBox, ViewportHeader,
};
use druid::{
AppLauncher, Color, Data, Insets, Lens, LocalizedString, Point, Rect, RoundedRectRadii,
Selector, Vec2, WidgetExt, WidgetPod, WindowDesc,
};
use im::Vector;
use std::sync::Arc;

Expand Down Expand Up @@ -67,7 +73,14 @@ fn build_widget() -> impl Widget<AppData> {
.with_default_spacer()
.with_child(Label::new("Info:").align_left())
.with_default_spacer()
.with_child(List::new(|| TextBox::new().padding(Insets::new(15.0, 0.0, 0.0, 10.0)).expand_width()).lens(Contact::info))
.with_child(
List::new(|| {
TextBox::new()
.padding(Insets::new(15.0, 0.0, 0.0, 10.0))
.expand_width()
})
.lens(Contact::info),
)
.with_child(
Button::new("Add Info").on_click(|_, data: &mut Contact, _| {
data.info.push_back(Arc::new(String::new()))
Expand All @@ -80,22 +93,25 @@ fn build_widget() -> impl Widget<AppData> {
.rounded(RoundedRectRadii::new(0.0, 0.0, 10.0, 10.0));

let header = Flex::row()
.with_flex_child(Label::dynamic(|data: &Contact, _| format!("Contact \"{}\"", &data.name)).center(), 1.0)
.with_child(Button::new("X").on_click(|ctx, data: &mut Contact, _|{
ctx.submit_notification(REMOVE_ID.with(data.id))
}).padding(5.0))
.with_flex_child(
Label::dynamic(|data: &Contact, _| format!("Contact \"{}\"", &data.name)).center(),
1.0,
)
.with_child(
Button::new("X")
.on_click(|ctx, data: &mut Contact, _| {
ctx.submit_notification(REMOVE_ID.with(data.id))
})
.padding(5.0),
)
.center()
.background(Color::grey8(15))
.rounded(RoundedRectRadii::new(10.0, 10.0, 0.0, 0.0));

ViewportHeader::new(
body,
header,
Side::Top,
)
.clipped_content(true)
.with_minimum_visible_content(20.0)
.padding(Insets::uniform_xy(0.0, 5.0))
ViewportHeader::new(body, header, Side::Top)
.clipped_content(true)
.with_minimum_visible_content(20.0)
.padding(Insets::uniform_xy(0.0, 5.0))
})
.lens(AppData::list)
.controller(RemoveID)
Expand Down Expand Up @@ -128,14 +144,21 @@ const REMOVE_ID: Selector<usize> = Selector::new("org.druid.example.remove_id");
struct RemoveID;

impl<W: Widget<AppData>> Controller<AppData, W> for RemoveID {
fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut AppData, env: &Env) {
fn event(
&mut self,
child: &mut W,
ctx: &mut EventCtx,
event: &Event,
data: &mut AppData,
env: &Env,
) {
if let Event::Notification(notification) = event {
if let Some(id) = notification.get(REMOVE_ID) {
ctx.set_handled();
data.list.retain(|c|c.id != *id);
data.list.retain(|c| c.id != *id);
}
} else {
child.event(ctx, event, data, env);
}
}
}
}
2 changes: 1 addition & 1 deletion druid/src/widget/align.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@

//! A widget that aligns its child (for example, centering it).

use crate::contexts::ChangeCtx;
use crate::debug_state::DebugState;
use crate::widget::prelude::*;
use crate::{Data, Rect, Size, UnitPoint, WidgetPod};
use tracing::{instrument, trace};
use crate::contexts::ChangeCtx;

/// A widget that aligns its child.
pub struct Align<T> {
Expand Down
11 changes: 8 additions & 3 deletions druid/src/widget/viewport_header.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::commands::SCROLL_TO_VIEW;
use crate::widget::flex::{Orientation, Side};
use crate::{BoxConstraints, Data, Env, Event, EventCtx, InternalEvent, LayoutCtx, LifeCycle, LifeCycleCtx, PaintCtx, Point, Rect, Size, UpdateCtx, ViewContext, Widget, WidgetPod};
use crate::{
BoxConstraints, Data, Env, Event, EventCtx, InternalEvent, LayoutCtx, LifeCycle, LifeCycleCtx,
PaintCtx, Point, Rect, Size, UpdateCtx, ViewContext, Widget, WidgetPod,
};
use druid::RenderContext;

/// A widget, containing two widgets with horizontal or vertical layout.
Expand Down Expand Up @@ -43,7 +46,8 @@ impl ViewportHeaderConfig {
}

pub fn minimum_visible(&self) -> f64 {
self.minimum_visible_content.min(self.header_side.axis().major(self.content_size))
self.minimum_visible_content
.min(self.header_side.axis().major(self.content_size))
}

/// The the layout size of header and content together, when both are fully in view.
Expand Down Expand Up @@ -186,7 +190,8 @@ impl<T: Data> Widget<T> for ViewportHeader<T> {
if self.content.is_active() {
ctx.set_handled();
} else {
self.content.event(ctx, &Event::Internal(InternalEvent::MouseLeave), data, env);
self.content
.event(ctx, &Event::Internal(InternalEvent::MouseLeave), data, env);
return;
}
}
Expand Down