druid-shell
Druid 工具包使用 Druid-shell 作为平台抽象应用程序 shell。Druid-shell 负责启动本机平台运行循环,监听事件,将它们转换为与平台无关的表示,并用它们调用用户提供的处理程序。
piet
Druid依赖 Piet 库进行绘图和文本布局。Piet 是一个具有多个后端的2D 图形抽象: Piet-direct2d、 Piet-coregraphy、 Piet-cairo、 Piet-web 和 Piet-svg 目前可用,并且计划使用 GPU 后端。在通过 Piet 对 Druid 平台的支持方面,macOS 使用 Piet-coregraph,Linux 和 OpenBSD 使用 Piet-cairo,Windows 使用 Piet-direct2d,web 使用 Piet-web。
use druid::kurbo::{BezPath, Point, Rect};use druid::piet::Color;// Create an arbitrary bezier path// (ctx.size() returns the size of the layout rect we’re painting in)let mut path = BezPath::new();path.move_to(Point::ORIGIN);path.quad_to( (80.0, 90.0), (ctx.size().width, ctx.size().height),);// Create a colorlet stroke_color = Color::rgb8(0x00, 0x80, 0x00);// Stroke the path with thickness 1.0ctx.stroke(path, &stroke_color, 1.0);// Rectangles: the path for practical peoplelet rect = Rect::from_origin_size((10., 10.), (100., 100.));// Note the Color:rgba8 which includes an alpha channel (7F in this case)let fill_color = Color::rgba8(0x00, 0x00, 0x00, 0x7F);ctx.fill(rect, &fill_color);
widgets
Druid 中的 Widget (文本框、按钮、布局组件等)是实现 Widget 特性的对象。Trait 由关联数据的类型(T)参数化。所有 trait 方法(事件、生命周期、更新、绘制和布局)都提供了对这些数据的访问,并且在事件的情况下,引用是可变的,因此事件可以直接更新数据。
只要应用程序数据发生变化,框架就会使用 update 方法遍历小部件层次结构。
所有小部件 trait 方法都提供了相应的上下文(EventCtx、 LifeCycleCtx、 UpdateCtx、 LayoutCtx、 PaintCtx)。小部件可以通过调用上下文中的方法来请求事物并导致操作。
此外,所有 trait 方法都提供了一个环境 Env,其中包括当前主题参数(颜色、尺寸等)。
impl Widget for Button { fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) { … } fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) { … } fn update(&mut self, ctx: &mut UpdateCtx, old_data: &T, data: &T, env: &Env) { … } fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &T, env: &Env) -> Size { … } fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) { … }}
Druid 提供了许多基本的实用工具和布局小部件,并且很容易实现自己的小部件。您还可以将小部件组装成新的小部件:
fn build_widget() -> impl Widget { let mut col = Flex::column(); for i in 0..30 { let button = Button::new(format!(“Button {}”, i).padding(5.0); col.add_child(button); } Scroll::new(col)}
layout
Druid的布局协议是强烈的灵感来自扑动的盒子布局模型。在 Druid 中,小部件被传递一个 BoxConstraint,它为它们提供了布局的最小和最大大小。如果适用,小部件还负责为其子级计算适当的约束。
data
Druid 使用数据特征来表示值类型。这些值类型应该比较便宜,克隆起来也便宜。通常,可以使用派生为类型生成 Data impl。
#[derive(Clone, Data)]struct AppState { which: bool, value: f64,}
Lens
Lens 数据类型提供了对更大数据结构的一部分的访问。和 Data 一样,这也可以派生出来。Derive lens 作为与字段同名的关联常数访问。
#[derive(Clone, Data, Lens)]struct AppState { which: bool, value: f64,}
要使用Lens,用 LensWrap (注意 CamelCase 到 Snake _ case 的转换)包装你的小部件:
LensWrap::new(WidgetThatExpectsf64::new(), AppState::value);
或者,用于结构、元组和可转位容器的Lens可以根据需要用Lens宏来构造:
LensWrap::new(WidgetThatExpectsf64::new(), lens!(AppState, value));