Druid Documentation
repository·master·Indexed 27 days ago
https://github.com/linebender/druidA data-oriented, Rust-native UI design toolkit for high-performance desktop applications. Druid utilizes a widget-based architecture and a two-way dataflow system centered around the Data, Widget, and Lens traits. It integrates with piet for 2D graphics and kurbo for geometry. Note: The project is currently unmaintained and discontinued, with development having moved to Xilem.
What's inside druid
- The Druid project has been discontinued and is no longer being actively maintained. New development efforts have moved to [Xilem], which is considered the future of Druid. Developers looking for a modern, high-performance successor should explore Xilem.
Manage application state and themes with `Env`
masterThe
Envrepresents the application environment, used for managing and accessing resources like color schemes, localized strings, and other application-specific state. It is created at launch and passed down to all widgets.Key behaviors:
- Inheritance: Values in the
Envare inherited by all child widgets. If a value is overridden at a specific level in the widget tree, that new value applies to all children of that widget. - Immutability of Existence: Values can be overwritten with new values of the same type, but they can never be removed from the
Envonce set. - Type Safety: The
Envuses typed keys. You must ensure the type used to set a value matches the type used to retrieve it via aKeyto avoid runtime panics.
- Inheritance: Values in the
Understand Druid's core architecture and components
masterDruid is a data-oriented framework for building cross-platform desktop applications. It is composed of several specialized libraries:
druid: An opinionated set of high-level APIs for building applications.druid-shell: A low-level library providing abstractions for interacting with the OS and window manager.piet: An abstraction for 2D graphics.kurbo: A library for 2D geometry.
Understand the Widget lifecycle and the Widget trait
masterThe
Widgettrait defines the components of a Druid UI. A UI is structured as a widget tree starting from a single root widget. TheWidgettrait is generic overT, which represents the [Data] handled by the widget.Druid operates through a specific lifecycle of method calls:
- event: Receives an
Event(e.g., key press, mouse movement). This method provides mutable access to your application model and is the only place where the model can be changed. Events are delivered recursively down the tree. - update: Called after an event if the data was mutated. It receives both the new and previous data. Widgets use this to update internal state (non-model data) and can request
layoutorpaintcalls. - layout: Determines widget positioning. Druid uses a box layout model where widgets are passed constraints (minimum and maximum allowed size) and must return a size within that range.
- paint: The imperative 2D graphics phase where the widget draws itself.
- lifecycle: Called in response to framework state changes (e.g., a widget gaining focus). It is not called predictably during event handling.
- event: Receives an
Explore related Druid ecosystem projects
masterDruid relies on several foundational libraries for graphics, curves, and text layout. If you need to extend Druid's capabilities or understand its low-level primitives, explore these projects:
- Piet: An abstraction for 2D graphics.
- Kurbo: A Rust library for manipulating curves.
- Skribo: A Rust library for low-level text layout.
Core Druid concepts: Data, Widget, and Lens
masterDruid's architecture is built around three primary concepts:
Datatrait: Used to represent your application's model.Widgettrait: Used to represent the user interface elements.Lenstrait: Used to associate specific parts of your model with specific parts of your UI.
Understand the druid-shell architecture
masterThe
druid-shellarchitecture is split into two layers:- Platform-agnostic code and types: These are the primary types exposed directly to users.
- Platform-specific implementations: These reside in per-backend directories in
src/backend. The implementation for the active backend is re-exported viadruid-shell::backend.
To maintain a consistent API,
druid-shelluses wrapper structs that define a common interface. When you call methods on these wrappers, they internally invoke the corresponding methods on the concrete backend-specific type.Use the `Controller` trait to customize widget behavior
masterThe
Controllertrait is used to create widgets that handle events, updates, or lifecycle changes without performing layout or drawing. This is useful for adding logic to existing widgets (e.g., intercepting keypresses in a textbox).Key characteristics:
- It implements
event,update, andlifecyclemethods (all are optional). - It does not implement
paintorlayout. - Each method receives a mutable reference to the child widget, allowing the controller to modify the child or forward events.
Example: A controller that triggers an action after a delay following a keypress:
// Conceptual example of a Controller implementation impl<W: Widget<T>, T> Controller<T, W> for MyController { fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) { // Handle event and potentially modify child or data child.event(ctx, event, data, env); } // ... other optional methods }- It implements
Prerequisites for using Druid
masterTo use Druid, you need:
- A working Rust environment (Rustup and Cargo).
- Familiarity with Rust.
- Stable Rust (v1.65.0 or later recommended).
- Druid v0.8 or later.
Install Druid dependencies on Linux and OpenBSD
masterDruid requires GTK-3's development kit on Linux and OpenBSD platforms.
Linux
- Ubuntu: Install via
apt-get. - Fedora: Install via
dnf.
OpenBSD
- Install via
pkg_add.
# Ubuntu sudo apt-get install libgtk-3-dev # Fedora sudo dnf install gtk3-devel glib2-devel # OpenBSD pkg_add gtk+3- Ubuntu: Install via
Start a new Druid project
masterTo start a new project, create a new Rust binary crate and add
druidas a dependency usingcargo.cargo new my-druid-app cd my-druid-app cargo add druidCompose UIs using modular widgets
masterDruid widgets are designed to be modular and composable rather than monolithic. Instead of a single widget handling its own alignment or padding, you should wrap specialized widgets in layout or decorator widgets.
For example, to add padding to a
Label, you do not configure the label itself; instead, you wrap the label in a widget that provides padding.