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.
Key
s, Value
s, 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:
-
Key
s should beconst
s 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");
-
Key
s 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.