The Env
The Env represents the environment; it is intended as a way of managing
and accessing state about your specific application, such as color schemes,
localized strings, and other resources.
The Env is created when the application is launched, and is passed down to all
widgets. The Env may be modified at various points in the tree; values in the
environment can be overridden with other values of the same type, but they can
never be removed. If something exists in the Env at a given level of the tree,
it will exist for everything 'below' that level; that is, for all children of that
widget.
Keys, Values, and themes
The most prominent role of Env is to store a set of typed keys and values. The
Env can only store a few types of things; these are represented by the
Value type, which looks like this:
pub enum Value {
Point(Point),
Size(Size),
Rect(Rect),
Insets(Insets),
Color(Color),
Float(f64),
Bool(bool),
UnsignedInt(u64),
String(ArcStr),
Font(FontDescriptor),
RoundedRectRadii(RoundedRectRadii),
Other(Arc<dyn Any + Send + Sync>),
}
The only way to get an item out of the Env is with a Key. A Key is
a combination of a string identifier and a type.
You can think of this as strict types, enforced at runtime. It is the programmer's responsibility to ensure that the key used to get a value has the same type as the one used to set it. The API is aggressive about checking for misuse, and many methods will panic if anything is amiss. In practice this shouldn't almost never happen if you follow these guidelines:
-
Keys should beconsts with unique names. If you need to use a custom key, you should declare it as aconst, and give it a unique name. By convention, you should namespace your keys using something like reverse-DNS notation, or even just prefixing them with the name of your app.const BAD_NAME: Key<f64> = Key::new("height"); const GOOD_NAME: Key<f64> = Key::new("com.example.my-app.main-view-height"); -
Keys must always be set before they are used. In practice this means that most keys are set when your application launches, usingAppLauncher::configure_env. Once a key has been added to theEnv, it cannot be deleted, although it can be overwritten. -
Values can only be overwritten by values of the same type. If you have a
Key<f64>, assuming that key has already been added to theEnv, you cannot replace it with any other type.
Assuming these rules are followed, Env should just work.
KeyOrValue
Druid includes a KeyOrValue type that is used for setting certain properties
of widgets. This is a type that can be either a concrete instance of some
type, or a Key that can be used to get that type from the Env.
const IMPORTANT_LABEL_COLOR: Key<Color> = Key::new("org.linebender.example.important-label-color");
const RED: Color = Color::rgb8(0xFF, 0, 0);
fn make_labels() {
let with_value = Label::<()>::new("Warning!").with_text_color(RED);
let with_key = Label::<()>::new("Warning!").with_text_color(IMPORTANT_LABEL_COLOR);
}
EnvScope
You may override values in the environment for a given widget (and all of its
children) by using the EnvScope widget. This is easiest when combined with
the env_scope method on WidgetExt:
fn scoped_label() {
let my_label = Label::<()>::new("Warning!").env_scope(|env, _| {
env.set(druid::theme::TEXT_COLOR, Color::BLACK);
env.set(druid::theme::TEXT_SIZE_NORMAL, 18.0);
});
}
Localization
Localization is currently half-baked.
The Env contains the localization resources for the current locale. A
LocalizedString can be resolved to a given string in the current locale by
calling its resolve method.