Detailed changes
@@ -1291,9 +1291,6 @@ impl<'a> WindowContext<'a> {
pub fn push_text_style(&mut self, refinement: &TextStyleRefinement) -> Result<()> {
let mut style = self.text_style();
style.refine(refinement, self.font_cache())?;
-
- dbg!(&style);
-
self.window.text_style_stack.push(style);
Ok(())
}
@@ -5,7 +5,7 @@ use gpui::geometry::vector::Vector2F;
pub use gpui::{Layout, LayoutId};
use smallvec::SmallVec;
-pub trait Element<V: 'static>: 'static {
+pub trait Element<V: 'static>: 'static + IntoElement<V> {
type PaintState;
fn layout(
@@ -1,6 +1,8 @@
pub mod div;
pub mod hoverable;
pub mod pressable;
+pub mod svg;
pub mod text;
pub use div::div;
+pub use svg::svg;
@@ -0,0 +1,81 @@
+use crate::{
+ self as gpui2, scene,
+ style::{Style, StyleHelpers, Styleable},
+ Element, IntoElement, Layout, LayoutId, Rgba,
+};
+use refineable::RefinementCascade;
+use std::borrow::Cow;
+
+#[derive(IntoElement)]
+pub struct Svg {
+ path: Option<Cow<'static, str>>,
+ style: RefinementCascade<Style>,
+}
+
+pub fn svg() -> Svg {
+ Svg {
+ path: None,
+ style: RefinementCascade::<Style>::default(),
+ }
+}
+
+impl Svg {
+ pub fn path(mut self, path: impl Into<Cow<'static, str>>) -> Self {
+ self.path = Some(path.into());
+ self
+ }
+}
+
+impl<V: 'static> Element<V> for Svg {
+ type PaintState = ();
+
+ fn layout(
+ &mut self,
+ _: &mut V,
+ cx: &mut crate::LayoutContext<V>,
+ ) -> anyhow::Result<(LayoutId, Self::PaintState)>
+ where
+ Self: Sized,
+ {
+ let style = self.computed_style();
+ Ok((cx.add_layout_node(style, [])?, ()))
+ }
+
+ fn paint(
+ &mut self,
+ _: &mut V,
+ layout: &Layout,
+ _: &mut Self::PaintState,
+ cx: &mut crate::paint_context::PaintContext<V>,
+ ) where
+ Self: Sized,
+ {
+ let fill_color = self.computed_style().fill.and_then(|fill| fill.color());
+ if let Some((path, fill_color)) = self.path.as_ref().zip(fill_color) {
+ if let Ok(svg_tree) = cx.asset_cache.svg(path) {
+ let icon = scene::Icon {
+ bounds: layout.bounds,
+ svg: svg_tree,
+ path: path.clone(),
+ color: Rgba::from(fill_color).into(),
+ };
+
+ cx.scene.push_icon(icon);
+ }
+ }
+ }
+}
+
+impl Styleable for Svg {
+ type Style = Style;
+
+ fn style_cascade(&mut self) -> &mut refineable::RefinementCascade<Self::Style> {
+ &mut self.style
+ }
+
+ fn declared_style(&mut self) -> &mut <Self::Style as refineable::Refineable>::Refinement {
+ self.style.base()
+ }
+}
+
+impl StyleHelpers for Svg {}
@@ -90,6 +90,14 @@ impl<V: 'static> Element<V> for Text {
}
}
+impl<V: 'static> IntoElement<V> for Text {
+ type Element = Self;
+
+ fn into_element(self) -> Self::Element {
+ self
+ }
+}
+
pub struct TextLayout {
line_layout: Arc<LineLayout>,
line_height: f32,
@@ -1,5 +1,9 @@
-use crate::theme::theme;
-use gpui2::{elements::div, style::StyleHelpers, Element, IntoElement, ParentElement, ViewContext};
+use crate::theme::{theme, Theme};
+use gpui2::{
+ elements::{div, svg},
+ style::StyleHelpers,
+ Element, IntoElement, ParentElement, ViewContext,
+};
use std::marker::PhantomData;
#[derive(Element)]
@@ -112,10 +116,11 @@ impl<V: 'static> CollabPanelElement<V> {
)
.child(
div().flex().h_full().gap_1().items_center().child(
- div()
- .w_3p5()
- .h_3p5()
- .fill(theme.middle.positive.default.foreground),
+ svg()
+ .path("icons/radix/caret-down.svg")
+ .h_3()
+ .w_3()
+ .fill(theme.middle.variant.default.foreground),
),
),
)
@@ -159,23 +164,7 @@ impl<V: 'static> CollabPanelElement<V> {
.flex_col()
.gap_y_1()
// List Section Header
- .child(
- div()
- .h_7()
- .px_2()
- .flex()
- .justify_between()
- .items_center()
- .child(div().flex().gap_1().text_sm().child("CHANNELS"))
- .child(
- div().flex().h_full().gap_1().items_center().child(
- div()
- .w_3p5()
- .h_3p5()
- .fill(theme.middle.positive.default.foreground),
- ),
- ),
- ),
+ .child(self.list_section_header(theme)),
)
// Large List Item
.child(
@@ -196,4 +185,22 @@ impl<V: 'static> CollabPanelElement<V> {
),
)
}
+
+ fn list_section_header(&self, theme: &Theme) -> impl Element<V> {
+ div()
+ .h_7()
+ .px_2()
+ .flex()
+ .justify_between()
+ .items_center()
+ .child(div().flex().gap_1().text_sm().child("CHANNELS"))
+ .child(
+ div().flex().h_full().gap_1().items_center().child(
+ div()
+ .w_3p5()
+ .h_3p5()
+ .fill(theme.middle.positive.default.foreground),
+ ),
+ )
+ }
}
@@ -69,6 +69,7 @@ use rust_embed::RustEmbed;
#[folder = "../../assets"]
#[include = "themes/**/*"]
#[include = "fonts/**/*"]
+#[include = "icons/**/*"]
#[exclude = "*.DS_Store"]
pub struct Assets;
@@ -2,7 +2,7 @@ use gpui2::{
color::Hsla,
element::{Element, PaintContext},
layout_context::LayoutContext,
- serde_json, AppContext, WindowContext,
+ serde_json, AppContext, IntoElement, WindowContext,
};
use serde::{de::Visitor, Deserialize, Deserializer};
use std::{collections::HashMap, fmt, marker::PhantomData};
@@ -133,7 +133,8 @@ where
deserializer.deserialize_map(SyntaxVisitor)
}
-pub struct Themed<V: 'static, E> {
+#[derive(IntoElement)]
+pub struct Themed<V: 'static, E: Element<V>> {
pub(crate) theme: Theme,
pub(crate) child: E,
pub(crate) view_type: PhantomData<V>,