Put Theme
behind an Arc
(#3017)
This PR puts the `Theme` returned from the `theme` function behind an `Arc`. ### Motivation While working on wiring up window focus events for the `TitleBar` component we ran into issues where `theme` was holding an immutable borrow to the `ViewContext` for the entirety of the `render` scope, which prevented having mutable borrows in the same scope. ### Explanation To avoid this, we can make `theme` return an `Arc<Theme>` to allow for cheap clones and avoiding the issues with the borrow checker. Release Notes: - N/A Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This commit is contained in:
parent
d8c6adf338
commit
71c1e36d1e
5 changed files with 27 additions and 22 deletions
|
@ -33,6 +33,7 @@ use std::{
|
||||||
any::{type_name, Any, TypeId},
|
any::{type_name, Any, TypeId},
|
||||||
mem,
|
mem,
|
||||||
ops::{Deref, DerefMut, Range, Sub},
|
ops::{Deref, DerefMut, Range, Sub},
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use taffy::{
|
use taffy::{
|
||||||
tree::{Measurable, MeasureFunc},
|
tree::{Measurable, MeasureFunc},
|
||||||
|
@ -56,7 +57,7 @@ pub struct Window {
|
||||||
pub(crate) rendered_views: HashMap<usize, Box<dyn AnyRootElement>>,
|
pub(crate) rendered_views: HashMap<usize, Box<dyn AnyRootElement>>,
|
||||||
scene: SceneBuilder,
|
scene: SceneBuilder,
|
||||||
pub(crate) text_style_stack: Vec<TextStyle>,
|
pub(crate) text_style_stack: Vec<TextStyle>,
|
||||||
pub(crate) theme_stack: Vec<Box<dyn Any>>,
|
pub(crate) theme_stack: Vec<Arc<dyn Any + Send + Sync>>,
|
||||||
pub(crate) new_parents: HashMap<usize, usize>,
|
pub(crate) new_parents: HashMap<usize, usize>,
|
||||||
pub(crate) views_to_notify_if_ancestors_change: HashMap<usize, SmallVec<[usize; 2]>>,
|
pub(crate) views_to_notify_if_ancestors_change: HashMap<usize, SmallVec<[usize; 2]>>,
|
||||||
titlebar_height: f32,
|
titlebar_height: f32,
|
||||||
|
@ -1336,18 +1337,21 @@ impl<'a> WindowContext<'a> {
|
||||||
self.window.text_style_stack.pop();
|
self.window.text_style_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn theme<T: 'static>(&self) -> &T {
|
pub fn theme<T: 'static + Send + Sync>(&self) -> Arc<T> {
|
||||||
self.window
|
self.window
|
||||||
.theme_stack
|
.theme_stack
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|theme| theme.downcast_ref())
|
.find_map(|theme| {
|
||||||
|
let entry = Arc::clone(theme);
|
||||||
|
entry.downcast::<T>().ok()
|
||||||
|
})
|
||||||
.ok_or_else(|| anyhow!("no theme provided of type {}", type_name::<T>()))
|
.ok_or_else(|| anyhow!("no theme provided of type {}", type_name::<T>()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_theme<T: 'static>(&mut self, theme: T) {
|
pub fn push_theme<T: 'static + Send + Sync>(&mut self, theme: T) {
|
||||||
self.window.theme_stack.push(Box::new(theme));
|
self.window.theme_stack.push(Arc::new(theme));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_theme(&mut self) {
|
pub fn pop_theme(&mut self) {
|
||||||
|
|
|
@ -52,12 +52,12 @@ impl<V: 'static> CollabPanelElement<V> {
|
||||||
//:: https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
|
//:: https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
|
||||||
// .group()
|
// .group()
|
||||||
// List Section Header
|
// List Section Header
|
||||||
.child(self.list_section_header("#CRDB", true, theme))
|
.child(self.list_section_header("#CRDB", true, &theme))
|
||||||
// List Item Large
|
// List Item Large
|
||||||
.child(self.list_item(
|
.child(self.list_item(
|
||||||
"http://github.com/maxbrunsfeld.png?s=50",
|
"http://github.com/maxbrunsfeld.png?s=50",
|
||||||
"maxbrunsfeld",
|
"maxbrunsfeld",
|
||||||
theme,
|
&theme,
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
|
@ -65,31 +65,31 @@ impl<V: 'static> CollabPanelElement<V> {
|
||||||
.py_2()
|
.py_2()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_col()
|
.flex_col()
|
||||||
.child(self.list_section_header("CHANNELS", true, theme)),
|
.child(self.list_section_header("CHANNELS", true, &theme)),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.py_2()
|
.py_2()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_col()
|
.flex_col()
|
||||||
.child(self.list_section_header("CONTACTS", true, theme))
|
.child(self.list_section_header("CONTACTS", true, &theme))
|
||||||
.children(
|
.children(
|
||||||
std::iter::repeat_with(|| {
|
std::iter::repeat_with(|| {
|
||||||
vec![
|
vec![
|
||||||
self.list_item(
|
self.list_item(
|
||||||
"http://github.com/as-cii.png?s=50",
|
"http://github.com/as-cii.png?s=50",
|
||||||
"as-cii",
|
"as-cii",
|
||||||
theme,
|
&theme,
|
||||||
),
|
),
|
||||||
self.list_item(
|
self.list_item(
|
||||||
"http://github.com/nathansobo.png?s=50",
|
"http://github.com/nathansobo.png?s=50",
|
||||||
"nathansobo",
|
"nathansobo",
|
||||||
theme,
|
&theme,
|
||||||
),
|
),
|
||||||
self.list_item(
|
self.list_item(
|
||||||
"http://github.com/maxbrunsfeld.png?s=50",
|
"http://github.com/maxbrunsfeld.png?s=50",
|
||||||
"maxbrunsfeld",
|
"maxbrunsfeld",
|
||||||
theme,
|
&theme,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
|
@ -52,12 +52,12 @@ impl<V: 'static> CollabPanelElement<V> {
|
||||||
//:: https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
|
//:: https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
|
||||||
// .group()
|
// .group()
|
||||||
// List Section Header
|
// List Section Header
|
||||||
.child(self.list_section_header("#CRDB", true, theme))
|
.child(self.list_section_header("#CRDB", true, &theme))
|
||||||
// List Item Large
|
// List Item Large
|
||||||
.child(self.list_item(
|
.child(self.list_item(
|
||||||
"http://github.com/maxbrunsfeld.png?s=50",
|
"http://github.com/maxbrunsfeld.png?s=50",
|
||||||
"maxbrunsfeld",
|
"maxbrunsfeld",
|
||||||
theme,
|
&theme,
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
|
@ -65,31 +65,31 @@ impl<V: 'static> CollabPanelElement<V> {
|
||||||
.py_2()
|
.py_2()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_col()
|
.flex_col()
|
||||||
.child(self.list_section_header("CHANNELS", true, theme)),
|
.child(self.list_section_header("CHANNELS", true, &theme)),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.py_2()
|
.py_2()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_col()
|
.flex_col()
|
||||||
.child(self.list_section_header("CONTACTS", true, theme))
|
.child(self.list_section_header("CONTACTS", true, &theme))
|
||||||
.children(
|
.children(
|
||||||
std::iter::repeat_with(|| {
|
std::iter::repeat_with(|| {
|
||||||
vec![
|
vec![
|
||||||
self.list_item(
|
self.list_item(
|
||||||
"http://github.com/as-cii.png?s=50",
|
"http://github.com/as-cii.png?s=50",
|
||||||
"as-cii",
|
"as-cii",
|
||||||
theme,
|
&theme,
|
||||||
),
|
),
|
||||||
self.list_item(
|
self.list_item(
|
||||||
"http://github.com/nathansobo.png?s=50",
|
"http://github.com/nathansobo.png?s=50",
|
||||||
"nathansobo",
|
"nathansobo",
|
||||||
theme,
|
&theme,
|
||||||
),
|
),
|
||||||
self.list_item(
|
self.list_item(
|
||||||
"http://github.com/maxbrunsfeld.png?s=50",
|
"http://github.com/maxbrunsfeld.png?s=50",
|
||||||
"maxbrunsfeld",
|
"maxbrunsfeld",
|
||||||
theme,
|
&theme,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
|
@ -96,8 +96,8 @@ impl<V: 'static> StatusBar<V> {
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.w_full()
|
.w_full()
|
||||||
.fill(theme.lowest.base.default.background)
|
.fill(theme.lowest.base.default.background)
|
||||||
.child(self.left_tools(theme))
|
.child(self.left_tools(&theme))
|
||||||
.child(self.right_tools(theme))
|
.child(self.right_tools(&theme))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn left_tools(&self, theme: &Theme) -> impl Element<V> {
|
fn left_tools(&self, theme: &Theme) -> impl Element<V> {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use gpui2::color::Hsla;
|
use gpui2::color::Hsla;
|
||||||
use gpui2::element::Element;
|
use gpui2::element::Element;
|
||||||
|
@ -190,6 +191,6 @@ fn preferred_theme<V: 'static>(cx: &AppContext) -> Theme {
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn theme<'a>(cx: &'a WindowContext) -> &'a Theme {
|
pub fn theme(cx: &WindowContext) -> Arc<Theme> {
|
||||||
cx.theme::<Theme>()
|
cx.theme::<Theme>()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue