Merge branch 'main' into collab-panel
This commit is contained in:
commit
a90c0e0326
30 changed files with 410 additions and 100 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3175,6 +3175,7 @@ dependencies = [
|
|||
name = "gpui_macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gpui",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
|
|
|
@ -363,7 +363,7 @@ impl AssistantPanel {
|
|||
this.set_active_editor_index(this.prev_active_editor_index, cx);
|
||||
}
|
||||
})
|
||||
.with_tooltip::<History>(1, "History".into(), None, tooltip_style, cx)
|
||||
.with_tooltip::<History>(1, "History", None, tooltip_style, cx)
|
||||
}
|
||||
|
||||
fn render_editor_tools(&self, cx: &mut ViewContext<Self>) -> Vec<AnyElement<Self>> {
|
||||
|
@ -395,7 +395,7 @@ impl AssistantPanel {
|
|||
})
|
||||
.with_tooltip::<Split>(
|
||||
1,
|
||||
"Split Message".into(),
|
||||
"Split Message",
|
||||
Some(Box::new(Split)),
|
||||
tooltip_style,
|
||||
cx,
|
||||
|
@ -417,13 +417,7 @@ impl AssistantPanel {
|
|||
active_editor.update(cx, |editor, cx| editor.assist(&Default::default(), cx));
|
||||
}
|
||||
})
|
||||
.with_tooltip::<Assist>(
|
||||
1,
|
||||
"Assist".into(),
|
||||
Some(Box::new(Assist)),
|
||||
tooltip_style,
|
||||
cx,
|
||||
)
|
||||
.with_tooltip::<Assist>(1, "Assist", Some(Box::new(Assist)), tooltip_style, cx)
|
||||
}
|
||||
|
||||
fn render_quote_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
|
||||
|
@ -447,7 +441,7 @@ impl AssistantPanel {
|
|||
})
|
||||
.with_tooltip::<QuoteSelection>(
|
||||
1,
|
||||
"Quote Selection".into(),
|
||||
"Quote Selection",
|
||||
Some(Box::new(QuoteSelection)),
|
||||
tooltip_style,
|
||||
cx,
|
||||
|
@ -469,7 +463,7 @@ impl AssistantPanel {
|
|||
})
|
||||
.with_tooltip::<NewConversation>(
|
||||
1,
|
||||
"New Conversation".into(),
|
||||
"New Conversation",
|
||||
Some(Box::new(NewConversation)),
|
||||
tooltip_style,
|
||||
cx,
|
||||
|
@ -499,11 +493,7 @@ impl AssistantPanel {
|
|||
})
|
||||
.with_tooltip::<ToggleZoom>(
|
||||
0,
|
||||
if self.zoomed {
|
||||
"Zoom Out".into()
|
||||
} else {
|
||||
"Zoom In".into()
|
||||
},
|
||||
if self.zoomed { "Zoom Out" } else { "Zoom In" },
|
||||
Some(Box::new(ToggleZoom)),
|
||||
tooltip_style,
|
||||
cx,
|
||||
|
|
|
@ -988,7 +988,7 @@ impl CollabPanel {
|
|||
),
|
||||
background: Some(tree_branch.color),
|
||||
border: gpui::Border::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: (0.).into(),
|
||||
});
|
||||
scene.push_quad(gpui::Quad {
|
||||
bounds: RectF::from_points(
|
||||
|
@ -997,7 +997,7 @@ impl CollabPanel {
|
|||
),
|
||||
background: Some(tree_branch.color),
|
||||
border: gpui::Border::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: (0.).into(),
|
||||
});
|
||||
}))
|
||||
.constrained()
|
||||
|
@ -1085,7 +1085,7 @@ impl CollabPanel {
|
|||
),
|
||||
background: Some(tree_branch.color),
|
||||
border: gpui::Border::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: (0.).into(),
|
||||
});
|
||||
scene.push_quad(gpui::Quad {
|
||||
bounds: RectF::from_points(
|
||||
|
@ -1094,7 +1094,7 @@ impl CollabPanel {
|
|||
),
|
||||
background: Some(tree_branch.color),
|
||||
border: gpui::Border::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: (0.).into(),
|
||||
});
|
||||
}))
|
||||
.constrained()
|
||||
|
@ -1188,7 +1188,7 @@ impl CollabPanel {
|
|||
})
|
||||
.with_tooltip::<AddContact>(
|
||||
0,
|
||||
"Leave call".into(),
|
||||
"Leave call",
|
||||
None,
|
||||
tooltip_style.clone(),
|
||||
cx,
|
||||
|
@ -1210,7 +1210,7 @@ impl CollabPanel {
|
|||
})
|
||||
.with_tooltip::<LeaveCallContactList>(
|
||||
0,
|
||||
"Search for new contact".into(),
|
||||
"Search for new contact",
|
||||
None,
|
||||
tooltip_style.clone(),
|
||||
cx,
|
||||
|
@ -1230,7 +1230,7 @@ impl CollabPanel {
|
|||
.on_click(MouseButton::Left, |_, this, cx| this.new_root_channel(cx))
|
||||
.with_tooltip::<AddChannel>(
|
||||
0,
|
||||
"Add or join a channel".into(),
|
||||
"Add or join a channel",
|
||||
None,
|
||||
tooltip_style.clone(),
|
||||
cx,
|
||||
|
|
|
@ -231,7 +231,7 @@ impl CollabTitlebarItem {
|
|||
.left()
|
||||
.with_tooltip::<RecentProjectsTooltip>(
|
||||
0,
|
||||
"Recent projects".into(),
|
||||
"Recent projects",
|
||||
Some(Box::new(recent_projects::OpenRecent)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
|
@ -275,7 +275,7 @@ impl CollabTitlebarItem {
|
|||
.left()
|
||||
.with_tooltip::<BranchPopoverTooltip>(
|
||||
0,
|
||||
"Recent branches".into(),
|
||||
"Recent branches",
|
||||
Some(Box::new(ToggleVcsMenu)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
|
@ -528,7 +528,7 @@ impl CollabTitlebarItem {
|
|||
})
|
||||
.with_tooltip::<ToggleScreenSharing>(
|
||||
0,
|
||||
tooltip.into(),
|
||||
tooltip,
|
||||
Some(Box::new(ToggleScreenSharing)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
|
@ -581,7 +581,7 @@ impl CollabTitlebarItem {
|
|||
})
|
||||
.with_tooltip::<ToggleMute>(
|
||||
0,
|
||||
tooltip.into(),
|
||||
tooltip,
|
||||
Some(Box::new(ToggleMute)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
|
@ -629,7 +629,7 @@ impl CollabTitlebarItem {
|
|||
})
|
||||
.with_tooltip::<ToggleDeafen>(
|
||||
0,
|
||||
tooltip.into(),
|
||||
tooltip,
|
||||
Some(Box::new(ToggleDeafen)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
|
@ -663,7 +663,7 @@ impl CollabTitlebarItem {
|
|||
})
|
||||
.with_tooltip::<LeaveCall>(
|
||||
0,
|
||||
tooltip.into(),
|
||||
tooltip,
|
||||
Some(Box::new(LeaveCall)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
|
|
|
@ -140,7 +140,7 @@ impl View for CopilotButton {
|
|||
})
|
||||
.with_tooltip::<Self>(
|
||||
0,
|
||||
"GitHub Copilot".into(),
|
||||
"GitHub Copilot",
|
||||
None,
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
|
|
|
@ -173,7 +173,7 @@ impl View for DiagnosticIndicator {
|
|||
})
|
||||
.with_tooltip::<Summary>(
|
||||
0,
|
||||
"Project Diagnostics".to_string(),
|
||||
"Project Diagnostics",
|
||||
Some(Box::new(crate::Deploy)),
|
||||
tooltip_style,
|
||||
cx,
|
||||
|
|
|
@ -8685,7 +8685,7 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend
|
|||
// We really need to rethink this ID system...
|
||||
.with_tooltip::<BlockContextToolip>(
|
||||
cx.block_id,
|
||||
"Copy diagnostic message".to_string(),
|
||||
"Copy diagnostic message",
|
||||
None,
|
||||
tooltip_style,
|
||||
cx,
|
||||
|
|
|
@ -488,13 +488,13 @@ impl EditorElement {
|
|||
bounds: gutter_bounds,
|
||||
background: Some(self.style.gutter_background),
|
||||
border: Border::new(0., Color::transparent_black()),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
scene.push_quad(Quad {
|
||||
bounds: text_bounds,
|
||||
background: Some(self.style.background),
|
||||
border: Border::new(0., Color::transparent_black()),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
|
||||
if let EditorMode::Full = layout.mode {
|
||||
|
@ -522,7 +522,7 @@ impl EditorElement {
|
|||
bounds: RectF::new(origin, size),
|
||||
background: Some(self.style.active_line_background),
|
||||
border: Border::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -542,7 +542,7 @@ impl EditorElement {
|
|||
bounds: RectF::new(origin, size),
|
||||
background: Some(self.style.highlighted_line_background),
|
||||
border: Border::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -572,7 +572,7 @@ impl EditorElement {
|
|||
),
|
||||
background: Some(color),
|
||||
border: Border::new(0., Color::transparent_black()),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -673,7 +673,7 @@ impl EditorElement {
|
|||
bounds: highlight_bounds,
|
||||
background: Some(diff_style.modified),
|
||||
border: Border::new(0., Color::transparent_black()),
|
||||
corner_radius: 1. * line_height,
|
||||
corner_radii: (1. * line_height).into(),
|
||||
});
|
||||
|
||||
continue;
|
||||
|
@ -706,7 +706,7 @@ impl EditorElement {
|
|||
bounds: highlight_bounds,
|
||||
background: Some(diff_style.deleted),
|
||||
border: Border::new(0., Color::transparent_black()),
|
||||
corner_radius: 1. * line_height,
|
||||
corner_radii: (1. * line_height).into(),
|
||||
});
|
||||
|
||||
continue;
|
||||
|
@ -728,7 +728,7 @@ impl EditorElement {
|
|||
bounds: highlight_bounds,
|
||||
background: Some(color),
|
||||
border: Border::new(0., Color::transparent_black()),
|
||||
corner_radius: diff_style.corner_radius * line_height,
|
||||
corner_radii: (diff_style.corner_radius * line_height).into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1129,7 +1129,7 @@ impl EditorElement {
|
|||
bounds,
|
||||
background: Some(color),
|
||||
border,
|
||||
corner_radius: style.thumb.corner_radius,
|
||||
corner_radii: style.thumb.corner_radii.into(),
|
||||
})
|
||||
};
|
||||
let background_ranges = editor
|
||||
|
@ -1189,7 +1189,7 @@ impl EditorElement {
|
|||
bounds,
|
||||
background: Some(color),
|
||||
border,
|
||||
corner_radius: style.thumb.corner_radius,
|
||||
corner_radii: style.thumb.corner_radii.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1198,7 +1198,7 @@ impl EditorElement {
|
|||
bounds: thumb_bounds,
|
||||
border: style.thumb.border,
|
||||
background: style.thumb.background_color,
|
||||
corner_radius: style.thumb.corner_radius,
|
||||
corner_radii: style.thumb.corner_radii.into(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2725,14 +2725,14 @@ impl Cursor {
|
|||
bounds,
|
||||
background: None,
|
||||
border: Border::all(1., self.color),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
} else {
|
||||
scene.push_quad(Quad {
|
||||
bounds,
|
||||
background: Some(self.color),
|
||||
border: Default::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -599,7 +599,7 @@ impl InfoPopover {
|
|||
bounds,
|
||||
background: Some(code_span_background_color),
|
||||
border: Default::default(),
|
||||
corner_radius: 2.0,
|
||||
corner_radii: (2.0).into(),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -66,7 +66,7 @@ impl View for DeployFeedbackButton {
|
|||
})
|
||||
.with_tooltip::<Self>(
|
||||
0,
|
||||
"Send Feedback".into(),
|
||||
"Send Feedback",
|
||||
Some(Box::new(GiveFeedback)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
|
|
|
@ -80,7 +80,7 @@ impl View for SubmitFeedbackButton {
|
|||
.with_margin_left(theme.feedback.button_margin)
|
||||
.with_tooltip::<Self>(
|
||||
0,
|
||||
"cmd-s".into(),
|
||||
"cmd-s",
|
||||
Some(Box::new(SubmitFeedback)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
|
|
155
crates/gpui/examples/corner_radii.rs
Normal file
155
crates/gpui/examples/corner_radii.rs
Normal file
|
@ -0,0 +1,155 @@
|
|||
use gpui::{
|
||||
color::Color, geometry::rect::RectF, scene::Shadow, AnyElement, App, Element, Entity, Quad,
|
||||
View,
|
||||
};
|
||||
use log::LevelFilter;
|
||||
use pathfinder_geometry::vector::vec2f;
|
||||
use simplelog::SimpleLogger;
|
||||
|
||||
fn main() {
|
||||
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
||||
|
||||
App::new(()).unwrap().run(|cx| {
|
||||
cx.platform().activate(true);
|
||||
cx.add_window(Default::default(), |_| CornersView);
|
||||
});
|
||||
}
|
||||
|
||||
struct CornersView;
|
||||
|
||||
impl Entity for CornersView {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
impl View for CornersView {
|
||||
fn ui_name() -> &'static str {
|
||||
"CornersView"
|
||||
}
|
||||
|
||||
fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> AnyElement<CornersView> {
|
||||
CornersElement.into_any()
|
||||
}
|
||||
}
|
||||
|
||||
struct CornersElement;
|
||||
|
||||
impl<V: View> gpui::Element<V> for CornersElement {
|
||||
type LayoutState = ();
|
||||
|
||||
type PaintState = ();
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: gpui::SizeConstraint,
|
||||
_: &mut V,
|
||||
_: &mut gpui::LayoutContext<V>,
|
||||
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
|
||||
(constraint.max, ())
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
scene: &mut gpui::SceneBuilder,
|
||||
bounds: pathfinder_geometry::rect::RectF,
|
||||
_: pathfinder_geometry::rect::RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut V,
|
||||
_: &mut gpui::PaintContext<V>,
|
||||
) -> Self::PaintState {
|
||||
scene.push_quad(Quad {
|
||||
bounds,
|
||||
background: Some(Color::white()),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
scene.push_layer(None);
|
||||
|
||||
scene.push_quad(Quad {
|
||||
bounds: RectF::new(vec2f(100., 100.), vec2f(100., 100.)),
|
||||
background: Some(Color::red()),
|
||||
border: Default::default(),
|
||||
corner_radii: gpui::scene::CornerRadii {
|
||||
top_left: 20.,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
|
||||
scene.push_quad(Quad {
|
||||
bounds: RectF::new(vec2f(200., 100.), vec2f(100., 100.)),
|
||||
background: Some(Color::green()),
|
||||
border: Default::default(),
|
||||
corner_radii: gpui::scene::CornerRadii {
|
||||
top_right: 20.,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
|
||||
scene.push_quad(Quad {
|
||||
bounds: RectF::new(vec2f(100., 200.), vec2f(100., 100.)),
|
||||
background: Some(Color::blue()),
|
||||
border: Default::default(),
|
||||
corner_radii: gpui::scene::CornerRadii {
|
||||
bottom_left: 20.,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
|
||||
scene.push_quad(Quad {
|
||||
bounds: RectF::new(vec2f(200., 200.), vec2f(100., 100.)),
|
||||
background: Some(Color::yellow()),
|
||||
border: Default::default(),
|
||||
corner_radii: gpui::scene::CornerRadii {
|
||||
bottom_right: 20.,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
|
||||
scene.push_shadow(Shadow {
|
||||
bounds: RectF::new(vec2f(400., 100.), vec2f(100., 100.)),
|
||||
corner_radii: gpui::scene::CornerRadii {
|
||||
bottom_right: 20.,
|
||||
..Default::default()
|
||||
},
|
||||
sigma: 20.0,
|
||||
color: Color::black(),
|
||||
});
|
||||
|
||||
scene.push_layer(None);
|
||||
scene.push_quad(Quad {
|
||||
bounds: RectF::new(vec2f(400., 100.), vec2f(100., 100.)),
|
||||
background: Some(Color::red()),
|
||||
border: Default::default(),
|
||||
corner_radii: gpui::scene::CornerRadii {
|
||||
bottom_right: 20.,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
|
||||
scene.pop_layer();
|
||||
scene.pop_layer();
|
||||
}
|
||||
|
||||
fn rect_for_text_range(
|
||||
&self,
|
||||
_: std::ops::Range<usize>,
|
||||
_: pathfinder_geometry::rect::RectF,
|
||||
_: pathfinder_geometry::rect::RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
_: &V,
|
||||
_: &gpui::ViewContext<V>,
|
||||
) -> Option<pathfinder_geometry::rect::RectF> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn debug(
|
||||
&self,
|
||||
_: pathfinder_geometry::rect::RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
_: &V,
|
||||
_: &gpui::ViewContext<V>,
|
||||
) -> serde_json::Value {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
|
@ -174,7 +174,7 @@ pub trait Element<V: View>: 'static {
|
|||
fn with_tooltip<Tag: 'static>(
|
||||
self,
|
||||
id: usize,
|
||||
text: String,
|
||||
text: impl Into<Cow<'static, str>>,
|
||||
action: Option<Box<dyn Action>>,
|
||||
style: TooltipStyle,
|
||||
cx: &mut ViewContext<V>,
|
||||
|
@ -182,7 +182,7 @@ pub trait Element<V: View>: 'static {
|
|||
where
|
||||
Self: 'static + Sized,
|
||||
{
|
||||
Tooltip::new::<Tag, V>(id, text, action, style, self.into_any(), cx)
|
||||
Tooltip::new::<Tag>(id, text, action, style, self.into_any(), cx)
|
||||
}
|
||||
|
||||
fn resizable(
|
||||
|
@ -205,6 +205,10 @@ pub trait Element<V: View>: 'static {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait RenderElement {
|
||||
fn render<V: View>(&mut self, view: &mut V, cx: &mut ViewContext<V>) -> AnyElement<V>;
|
||||
}
|
||||
|
||||
trait AnyElementState<V: View> {
|
||||
fn layout(
|
||||
&mut self,
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
},
|
||||
json::ToJson,
|
||||
platform::CursorStyle,
|
||||
scene::{self, Border, CursorRegion, Quad},
|
||||
scene::{self, Border, CornerRadii, CursorRegion, Quad},
|
||||
AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, View,
|
||||
ViewContext,
|
||||
};
|
||||
|
@ -30,7 +30,8 @@ pub struct ContainerStyle {
|
|||
#[serde(default)]
|
||||
pub border: Border,
|
||||
#[serde(default)]
|
||||
pub corner_radius: f32,
|
||||
#[serde(alias = "corner_radius")]
|
||||
pub corner_radii: CornerRadii,
|
||||
#[serde(default)]
|
||||
pub shadow: Option<Shadow>,
|
||||
#[serde(default)]
|
||||
|
@ -133,7 +134,10 @@ impl<V: View> Container<V> {
|
|||
}
|
||||
|
||||
pub fn with_corner_radius(mut self, radius: f32) -> Self {
|
||||
self.style.corner_radius = radius;
|
||||
self.style.corner_radii.top_left = radius;
|
||||
self.style.corner_radii.top_right = radius;
|
||||
self.style.corner_radii.bottom_right = radius;
|
||||
self.style.corner_radii.bottom_left = radius;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -225,7 +229,7 @@ impl<V: View> Element<V> for Container<V> {
|
|||
if let Some(shadow) = self.style.shadow.as_ref() {
|
||||
scene.push_shadow(scene::Shadow {
|
||||
bounds: quad_bounds + shadow.offset,
|
||||
corner_radius: self.style.corner_radius,
|
||||
corner_radii: self.style.corner_radii,
|
||||
sigma: shadow.blur,
|
||||
color: shadow.color,
|
||||
});
|
||||
|
@ -248,7 +252,7 @@ impl<V: View> Element<V> for Container<V> {
|
|||
bounds: quad_bounds,
|
||||
background: self.style.background_color,
|
||||
border: Default::default(),
|
||||
corner_radius: self.style.corner_radius,
|
||||
corner_radii: self.style.corner_radii.into(),
|
||||
});
|
||||
|
||||
self.child
|
||||
|
@ -259,7 +263,7 @@ impl<V: View> Element<V> for Container<V> {
|
|||
bounds: quad_bounds,
|
||||
background: self.style.overlay_color,
|
||||
border: self.style.border,
|
||||
corner_radius: self.style.corner_radius,
|
||||
corner_radii: self.style.corner_radii.into(),
|
||||
});
|
||||
scene.pop_layer();
|
||||
} else {
|
||||
|
@ -267,7 +271,7 @@ impl<V: View> Element<V> for Container<V> {
|
|||
bounds: quad_bounds,
|
||||
background: self.style.background_color,
|
||||
border: self.style.border,
|
||||
corner_radius: self.style.corner_radius,
|
||||
corner_radii: self.style.corner_radii.into(),
|
||||
});
|
||||
|
||||
let child_origin = child_origin
|
||||
|
@ -284,7 +288,7 @@ impl<V: View> Element<V> for Container<V> {
|
|||
bounds: quad_bounds,
|
||||
background: self.style.overlay_color,
|
||||
border: Default::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: self.style.corner_radii.into(),
|
||||
});
|
||||
scene.pop_layer();
|
||||
}
|
||||
|
@ -328,7 +332,7 @@ impl ToJson for ContainerStyle {
|
|||
"padding": self.padding.to_json(),
|
||||
"background_color": self.background_color.to_json(),
|
||||
"border": self.border.to_json(),
|
||||
"corner_radius": self.corner_radius,
|
||||
"corner_radius": self.corner_radii,
|
||||
"shadow": self.shadow.to_json(),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ impl<V: View> Element<V> for Image {
|
|||
scene.push_image(scene::Image {
|
||||
bounds,
|
||||
border: self.style.border,
|
||||
corner_radius: self.style.corner_radius,
|
||||
corner_radii: self.style.corner_radius.into(),
|
||||
grayscale: self.style.grayscale,
|
||||
data: data.clone(),
|
||||
});
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::{
|
|||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cell::{Cell, RefCell},
|
||||
ops::Range,
|
||||
rc::Rc,
|
||||
|
@ -52,9 +53,9 @@ pub struct KeystrokeStyle {
|
|||
}
|
||||
|
||||
impl<V: View> Tooltip<V> {
|
||||
pub fn new<Tag: 'static, T: View>(
|
||||
pub fn new<Tag: 'static>(
|
||||
id: usize,
|
||||
text: String,
|
||||
text: impl Into<Cow<'static, str>>,
|
||||
action: Option<Box<dyn Action>>,
|
||||
style: TooltipStyle,
|
||||
child: AnyElement<V>,
|
||||
|
@ -66,6 +67,8 @@ impl<V: View> Tooltip<V> {
|
|||
|
||||
let state_handle = cx.default_element_state::<ElementState<Tag>, Rc<TooltipState>>(id);
|
||||
let state = state_handle.read(cx).clone();
|
||||
let text = text.into();
|
||||
|
||||
let tooltip = if state.visible.get() {
|
||||
let mut collapsed_tooltip = Self::render_tooltip(
|
||||
focused_view_id,
|
||||
|
@ -127,7 +130,7 @@ impl<V: View> Tooltip<V> {
|
|||
|
||||
pub fn render_tooltip(
|
||||
focused_view_id: Option<usize>,
|
||||
text: String,
|
||||
text: impl Into<Cow<'static, str>>,
|
||||
style: TooltipStyle,
|
||||
action: Option<Box<dyn Action>>,
|
||||
measure: bool,
|
||||
|
|
|
@ -509,10 +509,14 @@ impl Renderer {
|
|||
};
|
||||
for (ix, shadow) in shadows.iter().enumerate() {
|
||||
let shape_bounds = shadow.bounds * scale_factor;
|
||||
let corner_radii = shadow.corner_radii * scale_factor;
|
||||
let shader_shadow = shaders::GPUIShadow {
|
||||
origin: shape_bounds.origin().to_float2(),
|
||||
size: shape_bounds.size().to_float2(),
|
||||
corner_radius: shadow.corner_radius * scale_factor,
|
||||
corner_radius_top_left: corner_radii.top_left,
|
||||
corner_radius_top_right: corner_radii.top_right,
|
||||
corner_radius_bottom_right: corner_radii.bottom_right,
|
||||
corner_radius_bottom_left: corner_radii.bottom_left,
|
||||
sigma: shadow.sigma,
|
||||
color: shadow.color.to_uchar4(),
|
||||
};
|
||||
|
@ -586,7 +590,10 @@ impl Renderer {
|
|||
border_bottom: border_width * (quad.border.bottom as usize as f32),
|
||||
border_left: border_width * (quad.border.left as usize as f32),
|
||||
border_color: quad.border.color.to_uchar4(),
|
||||
corner_radius: quad.corner_radius * scale_factor,
|
||||
corner_radius_top_left: quad.corner_radii.top_left * scale_factor,
|
||||
corner_radius_top_right: quad.corner_radii.top_right * scale_factor,
|
||||
corner_radius_bottom_right: quad.corner_radii.bottom_right * scale_factor,
|
||||
corner_radius_bottom_left: quad.corner_radii.bottom_left * scale_factor,
|
||||
};
|
||||
unsafe {
|
||||
*(buffer_contents.add(ix)) = shader_quad;
|
||||
|
@ -738,7 +745,7 @@ impl Renderer {
|
|||
for image in images {
|
||||
let origin = image.bounds.origin() * scale_factor;
|
||||
let target_size = image.bounds.size() * scale_factor;
|
||||
let corner_radius = image.corner_radius * scale_factor;
|
||||
let corner_radii = image.corner_radii * scale_factor;
|
||||
let border_width = image.border.width * scale_factor;
|
||||
let (alloc_id, atlas_bounds) = self.image_cache.render(&image.data);
|
||||
images_by_atlas
|
||||
|
@ -754,7 +761,10 @@ impl Renderer {
|
|||
border_bottom: border_width * (image.border.bottom as usize as f32),
|
||||
border_left: border_width * (image.border.left as usize as f32),
|
||||
border_color: image.border.color.to_uchar4(),
|
||||
corner_radius,
|
||||
corner_radius_top_left: corner_radii.top_left,
|
||||
corner_radius_top_right: corner_radii.top_right,
|
||||
corner_radius_bottom_right: corner_radii.bottom_right,
|
||||
corner_radius_bottom_left: corner_radii.bottom_left,
|
||||
grayscale: image.grayscale as u8,
|
||||
});
|
||||
}
|
||||
|
@ -777,7 +787,10 @@ impl Renderer {
|
|||
border_bottom: 0.,
|
||||
border_left: 0.,
|
||||
border_color: Default::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radius_top_left: 0.,
|
||||
corner_radius_top_right: 0.,
|
||||
corner_radius_bottom_right: 0.,
|
||||
corner_radius_bottom_left: 0.,
|
||||
grayscale: false as u8,
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -19,7 +19,10 @@ typedef struct {
|
|||
float border_bottom;
|
||||
float border_left;
|
||||
vector_uchar4 border_color;
|
||||
float corner_radius;
|
||||
float corner_radius_top_left;
|
||||
float corner_radius_top_right;
|
||||
float corner_radius_bottom_right;
|
||||
float corner_radius_bottom_left;
|
||||
} GPUIQuad;
|
||||
|
||||
typedef enum {
|
||||
|
@ -31,7 +34,10 @@ typedef enum {
|
|||
typedef struct {
|
||||
vector_float2 origin;
|
||||
vector_float2 size;
|
||||
float corner_radius;
|
||||
float corner_radius_top_left;
|
||||
float corner_radius_top_right;
|
||||
float corner_radius_bottom_right;
|
||||
float corner_radius_bottom_left;
|
||||
float sigma;
|
||||
vector_uchar4 color;
|
||||
} GPUIShadow;
|
||||
|
@ -89,7 +95,10 @@ typedef struct {
|
|||
float border_bottom;
|
||||
float border_left;
|
||||
vector_uchar4 border_color;
|
||||
float corner_radius;
|
||||
float corner_radius_top_left;
|
||||
float corner_radius_top_right;
|
||||
float corner_radius_bottom_right;
|
||||
float corner_radius_bottom_left;
|
||||
uint8_t grayscale;
|
||||
} GPUIImage;
|
||||
|
||||
|
|
|
@ -43,7 +43,10 @@ struct QuadFragmentInput {
|
|||
float border_bottom;
|
||||
float border_left;
|
||||
float4 border_color;
|
||||
float corner_radius;
|
||||
float corner_radius_top_left;
|
||||
float corner_radius_top_right;
|
||||
float corner_radius_bottom_right;
|
||||
float corner_radius_bottom_left;
|
||||
uchar grayscale; // only used in image shader
|
||||
};
|
||||
|
||||
|
@ -51,12 +54,27 @@ float4 quad_sdf(QuadFragmentInput input) {
|
|||
float2 half_size = input.size / 2.;
|
||||
float2 center = input.origin + half_size;
|
||||
float2 center_to_point = input.position.xy - center;
|
||||
float2 rounded_edge_to_point = abs(center_to_point) - half_size + input.corner_radius;
|
||||
float distance = length(max(0., rounded_edge_to_point)) + min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y)) - input.corner_radius;
|
||||
float corner_radius;
|
||||
if (center_to_point.x < 0.) {
|
||||
if (center_to_point.y < 0.) {
|
||||
corner_radius = input.corner_radius_top_left;
|
||||
} else {
|
||||
corner_radius = input.corner_radius_bottom_left;
|
||||
}
|
||||
} else {
|
||||
if (center_to_point.y < 0.) {
|
||||
corner_radius = input.corner_radius_top_right;
|
||||
} else {
|
||||
corner_radius = input.corner_radius_bottom_right;
|
||||
}
|
||||
}
|
||||
|
||||
float2 rounded_edge_to_point = abs(center_to_point) - half_size + corner_radius;
|
||||
float distance = length(max(0., rounded_edge_to_point)) + min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y)) - corner_radius;
|
||||
|
||||
float vertical_border = center_to_point.x <= 0. ? input.border_left : input.border_right;
|
||||
float horizontal_border = center_to_point.y <= 0. ? input.border_top : input.border_bottom;
|
||||
float2 inset_size = half_size - input.corner_radius - float2(vertical_border, horizontal_border);
|
||||
float2 inset_size = half_size - corner_radius - float2(vertical_border, horizontal_border);
|
||||
float2 point_to_inset_corner = abs(center_to_point) - inset_size;
|
||||
float border_width;
|
||||
if (point_to_inset_corner.x < 0. && point_to_inset_corner.y < 0.) {
|
||||
|
@ -110,7 +128,10 @@ vertex QuadFragmentInput quad_vertex(
|
|||
quad.border_bottom,
|
||||
quad.border_left,
|
||||
coloru_to_colorf(quad.border_color),
|
||||
quad.corner_radius,
|
||||
quad.corner_radius_top_left,
|
||||
quad.corner_radius_top_right,
|
||||
quad.corner_radius_bottom_right,
|
||||
quad.corner_radius_bottom_left,
|
||||
0,
|
||||
};
|
||||
}
|
||||
|
@ -125,7 +146,10 @@ struct ShadowFragmentInput {
|
|||
float4 position [[position]];
|
||||
vector_float2 origin;
|
||||
vector_float2 size;
|
||||
float corner_radius;
|
||||
float corner_radius_top_left;
|
||||
float corner_radius_top_right;
|
||||
float corner_radius_bottom_right;
|
||||
float corner_radius_bottom_left;
|
||||
float sigma;
|
||||
vector_uchar4 color;
|
||||
};
|
||||
|
@ -148,7 +172,10 @@ vertex ShadowFragmentInput shadow_vertex(
|
|||
device_position,
|
||||
shadow.origin,
|
||||
shadow.size,
|
||||
shadow.corner_radius,
|
||||
shadow.corner_radius_top_left,
|
||||
shadow.corner_radius_top_right,
|
||||
shadow.corner_radius_bottom_right,
|
||||
shadow.corner_radius_bottom_left,
|
||||
shadow.sigma,
|
||||
shadow.color,
|
||||
};
|
||||
|
@ -158,10 +185,24 @@ fragment float4 shadow_fragment(
|
|||
ShadowFragmentInput input [[stage_in]]
|
||||
) {
|
||||
float sigma = input.sigma;
|
||||
float corner_radius = input.corner_radius;
|
||||
float2 half_size = input.size / 2.;
|
||||
float2 center = input.origin + half_size;
|
||||
float2 point = input.position.xy - center;
|
||||
float2 center_to_point = input.position.xy - center;
|
||||
float corner_radius;
|
||||
if (center_to_point.x < 0.) {
|
||||
if (center_to_point.y < 0.) {
|
||||
corner_radius = input.corner_radius_top_left;
|
||||
} else {
|
||||
corner_radius = input.corner_radius_bottom_left;
|
||||
}
|
||||
} else {
|
||||
if (center_to_point.y < 0.) {
|
||||
corner_radius = input.corner_radius_top_right;
|
||||
} else {
|
||||
corner_radius = input.corner_radius_bottom_right;
|
||||
}
|
||||
}
|
||||
|
||||
// The signal is only non-zero in a limited range, so don't waste samples
|
||||
float low = point.y - half_size.y;
|
||||
|
@ -252,7 +293,10 @@ vertex QuadFragmentInput image_vertex(
|
|||
image.border_bottom,
|
||||
image.border_left,
|
||||
coloru_to_colorf(image.border_color),
|
||||
image.corner_radius,
|
||||
image.corner_radius_top_left,
|
||||
image.corner_radius_top_right,
|
||||
image.corner_radius_bottom_right,
|
||||
image.corner_radius_bottom_left,
|
||||
image.grayscale,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@ mod mouse_region;
|
|||
|
||||
#[cfg(debug_assertions)]
|
||||
use collections::HashSet;
|
||||
use derive_more::Mul;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde_derive::Serialize;
|
||||
use serde_json::json;
|
||||
use std::{borrow::Cow, sync::Arc};
|
||||
|
||||
|
@ -65,13 +67,73 @@ pub struct Quad {
|
|||
pub bounds: RectF,
|
||||
pub background: Option<Color>,
|
||||
pub border: Border,
|
||||
pub corner_radius: f32,
|
||||
pub corner_radii: CornerRadii,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Mul, Clone, Copy, Serialize, JsonSchema)]
|
||||
pub struct CornerRadii {
|
||||
pub top_left: f32,
|
||||
pub top_right: f32,
|
||||
pub bottom_right: f32,
|
||||
pub bottom_left: f32,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for CornerRadii {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
pub struct CornerRadiiHelper {
|
||||
pub top_left: Option<f32>,
|
||||
pub top_right: Option<f32>,
|
||||
pub bottom_right: Option<f32>,
|
||||
pub bottom_left: Option<f32>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum RadiusOrRadii {
|
||||
Radius(f32),
|
||||
Radii(CornerRadiiHelper),
|
||||
}
|
||||
|
||||
let json = RadiusOrRadii::deserialize(deserializer)?;
|
||||
|
||||
let result = match json {
|
||||
RadiusOrRadii::Radius(radius) => CornerRadii::from(radius),
|
||||
RadiusOrRadii::Radii(CornerRadiiHelper {
|
||||
top_left,
|
||||
top_right,
|
||||
bottom_right,
|
||||
bottom_left,
|
||||
}) => CornerRadii {
|
||||
top_left: top_left.unwrap_or(0.0),
|
||||
top_right: top_right.unwrap_or(0.0),
|
||||
bottom_right: bottom_right.unwrap_or(0.0),
|
||||
bottom_left: bottom_left.unwrap_or(0.0),
|
||||
},
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for CornerRadii {
|
||||
fn from(radius: f32) -> Self {
|
||||
Self {
|
||||
top_left: radius,
|
||||
top_right: radius,
|
||||
bottom_right: radius,
|
||||
bottom_left: radius,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Shadow {
|
||||
pub bounds: RectF,
|
||||
pub corner_radius: f32,
|
||||
pub corner_radii: CornerRadii,
|
||||
pub sigma: f32,
|
||||
pub color: Color,
|
||||
}
|
||||
|
@ -177,7 +239,7 @@ pub struct PathVertex {
|
|||
pub struct Image {
|
||||
pub bounds: RectF,
|
||||
pub border: Border,
|
||||
pub corner_radius: f32,
|
||||
pub corner_radii: CornerRadii,
|
||||
pub grayscale: bool,
|
||||
pub data: Arc<ImageData>,
|
||||
}
|
||||
|
|
|
@ -14,3 +14,5 @@ syn = "1.0"
|
|||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
gpui = { path = "../gpui" }
|
||||
|
|
|
@ -283,8 +283,12 @@ pub fn element_derive(input: TokenStream) -> TokenStream {
|
|||
|
||||
// The name of the struct/enum
|
||||
let name = input.ident;
|
||||
let must_implement = format_ident!("{}MustImplementRenderElement", name);
|
||||
|
||||
let expanded = quote! {
|
||||
trait #must_implement : gpui::elements::RenderElement {}
|
||||
impl #must_implement for #name {}
|
||||
|
||||
impl<V: gpui::View> gpui::elements::Element<V> for #name {
|
||||
type LayoutState = gpui::elements::AnyElement<V>;
|
||||
type PaintState = ();
|
||||
|
@ -307,7 +311,7 @@ pub fn element_derive(input: TokenStream) -> TokenStream {
|
|||
visible_bounds: gpui::geometry::rect::RectF,
|
||||
element: &mut gpui::elements::AnyElement<V>,
|
||||
view: &mut V,
|
||||
cx: &mut gpui::ViewContext<V>,
|
||||
cx: &mut gpui::PaintContext<V>,
|
||||
) {
|
||||
element.paint(scene, bounds.origin(), visible_bounds, view, cx);
|
||||
}
|
||||
|
@ -332,7 +336,7 @@ pub fn element_derive(input: TokenStream) -> TokenStream {
|
|||
_: &(),
|
||||
view: &V,
|
||||
cx: &gpui::ViewContext<V>,
|
||||
) -> serde_json::Value {
|
||||
) -> gpui::serde_json::Value {
|
||||
element.debug(view, cx)
|
||||
}
|
||||
}
|
||||
|
|
14
crates/gpui_macros/tests/test.rs
Normal file
14
crates/gpui_macros/tests/test.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use gpui::{elements::RenderElement, View, ViewContext};
|
||||
use gpui_macros::Element;
|
||||
|
||||
#[test]
|
||||
fn test_derive_render_element() {
|
||||
#[derive(Element)]
|
||||
struct TestElement {}
|
||||
|
||||
impl RenderElement for TestElement {
|
||||
fn render<V: View>(&mut self, _: &mut V, _: &mut ViewContext<V>) -> gpui::AnyElement<V> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -153,7 +153,7 @@ impl LayoutRect {
|
|||
bounds: RectF::new(position, size),
|
||||
background: Some(self.color),
|
||||
border: Default::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -763,7 +763,7 @@ impl Element<TerminalView> for TerminalElement {
|
|||
bounds: RectF::new(bounds.origin(), bounds.size()),
|
||||
background: Some(layout.background_color),
|
||||
border: Default::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
|
||||
for rect in &layout.rects {
|
||||
|
|
|
@ -72,10 +72,7 @@ impl TerminalPanel {
|
|||
0,
|
||||
"icons/plus_12.svg",
|
||||
false,
|
||||
Some((
|
||||
"New Terminal".into(),
|
||||
Some(Box::new(workspace::NewTerminal)),
|
||||
)),
|
||||
Some(("New Terminal", Some(Box::new(workspace::NewTerminal)))),
|
||||
cx,
|
||||
move |_, cx| {
|
||||
let this = this.clone();
|
||||
|
|
|
@ -303,10 +303,10 @@ impl Pane {
|
|||
let tooltip_label;
|
||||
if pane.is_zoomed() {
|
||||
icon_path = "icons/minimize_8.svg";
|
||||
tooltip_label = "Zoom In".into();
|
||||
tooltip_label = "Zoom In";
|
||||
} else {
|
||||
icon_path = "icons/maximize_8.svg";
|
||||
tooltip_label = "Zoom In".into();
|
||||
tooltip_label = "Zoom In";
|
||||
}
|
||||
|
||||
Pane::render_tab_bar_button(
|
||||
|
@ -1397,7 +1397,7 @@ impl Pane {
|
|||
bounds: square,
|
||||
background: Some(color),
|
||||
border: Default::default(),
|
||||
corner_radius: diameter / 2.,
|
||||
corner_radii: (diameter / 2.).into(),
|
||||
});
|
||||
}
|
||||
})
|
||||
|
@ -1477,7 +1477,7 @@ impl Pane {
|
|||
index: usize,
|
||||
icon: &'static str,
|
||||
is_active: bool,
|
||||
tooltip: Option<(String, Option<Box<dyn Action>>)>,
|
||||
tooltip: Option<(&'static str, Option<Box<dyn Action>>)>,
|
||||
cx: &mut ViewContext<Pane>,
|
||||
on_click: F1,
|
||||
on_down: F2,
|
||||
|
|
|
@ -61,7 +61,7 @@ where
|
|||
bounds: overlay_region,
|
||||
background: Some(overlay_color(cx)),
|
||||
border: Default::default(),
|
||||
corner_radius: 0.,
|
||||
corner_radii: Default::default(),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>
|
|||
spacing: f32,
|
||||
on_click: F,
|
||||
tooltip_action: A,
|
||||
action_name: &str,
|
||||
action_name: &'static str,
|
||||
cx: &mut ViewContext<Toolbar>,
|
||||
) -> AnyElement<Toolbar> {
|
||||
MouseEventHandler::<A, _>::new(0, cx, |state, _| {
|
||||
|
@ -252,7 +252,7 @@ fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>
|
|||
})
|
||||
.with_tooltip::<A>(
|
||||
0,
|
||||
action_name.to_string(),
|
||||
action_name,
|
||||
Some(Box::new(tooltip_action)),
|
||||
tooltip_style,
|
||||
cx,
|
||||
|
|
|
@ -3624,7 +3624,7 @@ fn notify_of_new_dock(workspace: &WeakViewHandle<Workspace>, cx: &mut AsyncAppCo
|
|||
bounds,
|
||||
background: Some(code_span_background_color),
|
||||
border: Default::default(),
|
||||
corner_radius: 2.0,
|
||||
corner_radii: (2.0).into(),
|
||||
})
|
||||
})
|
||||
.into_any()
|
||||
|
|
|
@ -27,9 +27,17 @@ export default function channel_modal(): any {
|
|||
header: {
|
||||
background: background(theme.middle, "accent"),
|
||||
border: border(theme.middle, { "bottom": true, "top": false, left: false, right: false }),
|
||||
corner_radii: {
|
||||
top_right: 12,
|
||||
top_left: 12,
|
||||
}
|
||||
},
|
||||
body: {
|
||||
background: background(theme.middle),
|
||||
corner_radii: {
|
||||
bottom_right: 12,
|
||||
bottom_left: 12,
|
||||
}
|
||||
},
|
||||
modal: {
|
||||
background: background(theme.middle),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue