Ditch the hot reloading approach
This commit is contained in:
parent
0bf607cd2d
commit
d6eaa3c6b8
14 changed files with 340 additions and 275 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -5291,24 +5291,13 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||||
name = "playground"
|
name = "playground"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gpui",
|
|
||||||
"log",
|
|
||||||
"playground_ui",
|
|
||||||
"simplelog",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "playground_ui"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"collections",
|
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"gpui",
|
"gpui",
|
||||||
"log",
|
"log",
|
||||||
"optional_struct",
|
"optional_struct",
|
||||||
"serde",
|
"serde",
|
||||||
|
"simplelog",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"util",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -29,7 +29,6 @@ members = [
|
||||||
"crates/go_to_line",
|
"crates/go_to_line",
|
||||||
"crates/gpui",
|
"crates/gpui",
|
||||||
"crates/gpui/playground",
|
"crates/gpui/playground",
|
||||||
"crates/gpui/playground/ui",
|
|
||||||
"crates/gpui_macros",
|
"crates/gpui_macros",
|
||||||
"crates/install_cli",
|
"crates/install_cli",
|
||||||
"crates/journal",
|
"crates/journal",
|
||||||
|
|
|
@ -8,11 +8,13 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
playground_ui = { path = "ui" }
|
derive_more.workspace = true
|
||||||
|
|
||||||
gpui = { path = ".." }
|
gpui = { path = ".." }
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
optional_struct = "0.3.1"
|
||||||
|
serde.workspace = true
|
||||||
simplelog = "0.9"
|
simplelog = "0.9"
|
||||||
|
smallvec.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
gpui = { path = "..", features = ["test-support"] }
|
gpui = { path = "..", features = ["test-support"] }
|
||||||
|
|
|
@ -35,6 +35,12 @@ impl Lerp for Range<Hsla> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<gpui::color::Color> for Rgba {
|
||||||
|
fn from(value: gpui::color::Color) -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Hsla> for Rgba {
|
impl From<Hsla> for Rgba {
|
||||||
fn from(color: Hsla) -> Self {
|
fn from(color: Hsla) -> Self {
|
||||||
let h = color.h;
|
let h = color.h;
|
||||||
|
@ -88,7 +94,7 @@ impl Into<gpui::color::Color> for Rgba {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub struct Hsla {
|
pub struct Hsla {
|
||||||
pub h: f32,
|
pub h: f32,
|
||||||
pub s: f32,
|
pub s: f32,
|
||||||
|
@ -97,7 +103,12 @@ pub struct Hsla {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hsla(h: f32, s: f32, l: f32, a: f32) -> Hsla {
|
pub fn hsla(h: f32, s: f32, l: f32, a: f32) -> Hsla {
|
||||||
Hsla { h, s, l, a }
|
Hsla {
|
||||||
|
h: h.clamp(0., 1.),
|
||||||
|
s: s.clamp(0., 1.),
|
||||||
|
l: l.clamp(0., 1.),
|
||||||
|
a: a.clamp(0., 1.),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rgba> for Hsla {
|
impl From<Rgba> for Hsla {
|
||||||
|
@ -182,6 +193,12 @@ impl Hsla {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<gpui::color::Color> for Hsla {
|
||||||
|
fn from(value: gpui::color::Color) -> Self {
|
||||||
|
Rgba::from(value).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ColorScale {
|
pub struct ColorScale {
|
||||||
colors: SmallVec<[Hsla; 2]>,
|
colors: SmallVec<[Hsla; 2]>,
|
||||||
positions: SmallVec<[f32; 2]>,
|
positions: SmallVec<[f32; 2]>,
|
|
@ -1,10 +1,9 @@
|
||||||
#![allow(unused_variables, dead_code)]
|
#![allow(unused_variables, dead_code)]
|
||||||
|
|
||||||
use derive_more::{Add, Deref, DerefMut};
|
use derive_more::{Add, Deref, DerefMut};
|
||||||
use gpui::elements::layout_highlighted_chunks;
|
|
||||||
use gpui::Entity;
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
color::Color,
|
color::Color,
|
||||||
|
elements::layout_highlighted_chunks,
|
||||||
fonts::HighlightStyle,
|
fonts::HighlightStyle,
|
||||||
geometry::{
|
geometry::{
|
||||||
rect::RectF,
|
rect::RectF,
|
||||||
|
@ -14,15 +13,17 @@ use gpui::{
|
||||||
scene,
|
scene,
|
||||||
serde_json::Value,
|
serde_json::Value,
|
||||||
text_layout::{Line, ShapedBoundary},
|
text_layout::{Line, ShapedBoundary},
|
||||||
AnyElement, AppContext, Element, LayoutContext, PaintContext, Quad, SceneBuilder,
|
AnyElement, AppContext, Element, Entity, LayoutContext, PaintContext, Quad, SceneBuilder,
|
||||||
SizeConstraint, View, ViewContext,
|
SizeConstraint, View, ViewContext, WindowContext,
|
||||||
};
|
};
|
||||||
use length::{Length, Rems};
|
use length::{Length, Rems};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use optional_struct::*;
|
use optional_struct::*;
|
||||||
use std::{any::Any, borrow::Cow, f32, ops::Range, sync::Arc};
|
use std::{any::Any, borrow::Cow, f32, ops::Range, sync::Arc};
|
||||||
|
|
||||||
use crate::color::Rgba;
|
use crate::color::{Hsla, Rgba};
|
||||||
|
|
||||||
|
use self::length::rems;
|
||||||
|
|
||||||
pub struct Frame<V> {
|
pub struct Frame<V> {
|
||||||
style: FrameStyle,
|
style: FrameStyle,
|
||||||
|
@ -76,6 +77,12 @@ impl<V: 'static> Element<V> for Frame<V> {
|
||||||
view: &mut V,
|
view: &mut V,
|
||||||
cx: &mut LayoutContext<V>,
|
cx: &mut LayoutContext<V>,
|
||||||
) -> (Vector2F, Self::LayoutState) {
|
) -> (Vector2F, Self::LayoutState) {
|
||||||
|
if self.style.text.is_some() {
|
||||||
|
let mut style = TextStyle::from_legacy(&cx.text_style(), cx);
|
||||||
|
self.style.text.clone().apply_to(&mut style);
|
||||||
|
cx.push_text_style(style.to_legacy());
|
||||||
|
}
|
||||||
|
|
||||||
let layout = if let Some(axis) = self.style.axis.to_2d() {
|
let layout = if let Some(axis) = self.style.axis.to_2d() {
|
||||||
self.layout_xy(axis, constraint, cx.rem_pixels(), view, cx)
|
self.layout_xy(axis, constraint, cx.rem_pixels(), view, cx)
|
||||||
} else {
|
} else {
|
||||||
|
@ -263,6 +270,11 @@ impl<V: 'static> Frame<V> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn text_color(mut self, color: Hsla) -> Self {
|
||||||
|
self.style.text.color = Some(color);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn margins(mut self, margins: impl Into<Edges<Length>>) -> Self {
|
pub fn margins(mut self, margins: impl Into<Edges<Length>>) -> Self {
|
||||||
self.style.margins = margins.into();
|
self.style.margins = margins.into();
|
||||||
self
|
self
|
||||||
|
@ -327,6 +339,8 @@ impl<V: 'static> Frame<V> {
|
||||||
view: &mut V,
|
view: &mut V,
|
||||||
cx: &mut LayoutContext<V>,
|
cx: &mut LayoutContext<V>,
|
||||||
) -> FrameLayout {
|
) -> FrameLayout {
|
||||||
|
self.style.text.is_some();
|
||||||
|
|
||||||
let cross_axis = primary_axis.rotate();
|
let cross_axis = primary_axis.rotate();
|
||||||
let total_flex = self.style.flex();
|
let total_flex = self.style.flex();
|
||||||
let mut layout = FrameLayout {
|
let mut layout = FrameLayout {
|
||||||
|
@ -608,8 +622,67 @@ struct TextStyle {
|
||||||
font_family: Arc<str>,
|
font_family: Arc<str>,
|
||||||
weight: FontWeight,
|
weight: FontWeight,
|
||||||
style: FontStyle,
|
style: FontStyle,
|
||||||
|
color: Hsla,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TextStyle {
|
||||||
|
fn from_legacy(text_style: &gpui::fonts::TextStyle, _cx: &WindowContext) -> Self {
|
||||||
|
Self {
|
||||||
|
size: rems(text_style.font_size / 16.), // TODO: Get this from the context!
|
||||||
|
font_family: text_style.font_family_name.clone(),
|
||||||
|
weight: text_style.font_properties.weight.into(),
|
||||||
|
style: text_style.font_properties.style.into(),
|
||||||
|
color: text_style.color.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_legacy(&self, cx: &WindowContext) -> Result<gpui::fonts::TextStyle> {
|
||||||
|
let font_family_id = cx.font_cache().load_family(
|
||||||
|
&[self.font_family.as_ref()],
|
||||||
|
&gpui::fonts::Features::default(),
|
||||||
|
)?;
|
||||||
|
let font_properties = gpui::fonts::Properties {
|
||||||
|
style: self.style.into(),
|
||||||
|
weight: self.weight.into(),
|
||||||
|
stretch: Default::default(),
|
||||||
|
};
|
||||||
|
let font_id = cx
|
||||||
|
.font_cache()
|
||||||
|
.select_font(font_family_id, &font_properties);
|
||||||
|
|
||||||
|
Ok(gpui::fonts::TextStyle {
|
||||||
|
color: self.color.into(),
|
||||||
|
font_family_name: self.font_family.clone(),
|
||||||
|
font_family_id,
|
||||||
|
font_id,
|
||||||
|
font_size: todo!(),
|
||||||
|
font_properties,
|
||||||
|
underline: todo!(),
|
||||||
|
soft_wrap: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OptionalTextStyle {
|
||||||
|
pub fn is_some(&self) -> bool {
|
||||||
|
self.size.is_some()
|
||||||
|
&& self.font_family.is_some()
|
||||||
|
&& self.weight.is_some()
|
||||||
|
&& self.style.is_some()
|
||||||
|
&& self.color.is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub color: Color,
|
||||||
|
// pub font_family_name: Arc<str>,
|
||||||
|
// pub font_family_id: FamilyId,
|
||||||
|
// pub font_id: FontId,
|
||||||
|
// pub font_size: f32,
|
||||||
|
// #[schemars(with = "PropertiesDef")]
|
||||||
|
// pub font_properties: Properties,
|
||||||
|
// pub underline: Underline,
|
||||||
|
// pub soft_wrap: bool,
|
||||||
|
|
||||||
#[derive(Add, Default, Clone)]
|
#[derive(Add, Default, Clone)]
|
||||||
pub struct Size<T> {
|
pub struct Size<T> {
|
||||||
width: T,
|
width: T,
|
||||||
|
@ -1126,6 +1199,18 @@ enum FontStyle {
|
||||||
Oblique,
|
Oblique,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<gpui::fonts::Style> for FontStyle {
|
||||||
|
fn from(value: gpui::fonts::Style) -> Self {
|
||||||
|
use gpui::fonts::Style;
|
||||||
|
|
||||||
|
match value {
|
||||||
|
Style::Normal => FontStyle::Normal,
|
||||||
|
Style::Italic => FontStyle::Italic,
|
||||||
|
Style::Oblique => FontStyle::Oblique,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
|
||||||
enum FontWeight {
|
enum FontWeight {
|
||||||
Thin,
|
Thin,
|
||||||
|
@ -1140,6 +1225,24 @@ enum FontWeight {
|
||||||
Black,
|
Black,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<gpui::fonts::Weight> for FontWeight {
|
||||||
|
fn from(value: gpui::fonts::Weight) -> Self {
|
||||||
|
use gpui::fonts::Weight;
|
||||||
|
|
||||||
|
match value {
|
||||||
|
Weight::THIN => FontWeight::Thin,
|
||||||
|
Weight::EXTRA_LIGHT => FontWeight::ExtraLight,
|
||||||
|
Weight::LIGHT => FontWeight::Light,
|
||||||
|
Weight::NORMAL => FontWeight::Normal,
|
||||||
|
Weight::MEDIUM => FontWeight::Medium,
|
||||||
|
Weight::SEMIBOLD => FontWeight::Semibold,
|
||||||
|
Weight::BOLD => FontWeight::Bold,
|
||||||
|
Weight::EXTRA_BOLD => FontWeight::ExtraBold,
|
||||||
|
Weight::BLACK => FontWeight::Black,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Text {
|
pub struct Text {
|
||||||
text: Cow<'static, str>,
|
text: Cow<'static, str>,
|
|
@ -1,17 +1,11 @@
|
||||||
|
#![allow(dead_code, unused_variables)]
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
platform::{TitlebarOptions, WindowOptions},
|
platform::{TitlebarOptions, WindowOptions},
|
||||||
AnyElement, Element, Entity, View,
|
AnyElement, Element,
|
||||||
};
|
};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use simplelog::SimpleLogger;
|
use simplelog::SimpleLogger;
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
|
|
||||||
// dymod! {
|
|
||||||
// #[path = "../ui/src/playground_ui.rs"]
|
|
||||||
// pub mod ui {
|
|
||||||
// // fn workspace<V>(theme: &ThemeColors) -> impl Element<V>;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
||||||
|
@ -26,38 +20,213 @@ fn main() {
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|_| Playground::default(),
|
|_| view(|_| Playground::new()),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
use frame::{length::auto, *};
|
||||||
struct Playground(playground_ui::Playground<Self>);
|
use gpui::{LayoutContext, ViewContext};
|
||||||
|
use std::{borrow::Cow, cell::RefCell, marker::PhantomData, rc::Rc};
|
||||||
|
use themes::{rose_pine, ThemeColors};
|
||||||
|
use tokens::{margin::m4, text::lg};
|
||||||
|
|
||||||
impl Deref for Playground {
|
mod color;
|
||||||
type Target = playground_ui::Playground<Self>;
|
mod frame;
|
||||||
|
mod themes;
|
||||||
|
mod tokens;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
#[derive(Element, Clone)]
|
||||||
&self.0
|
pub struct Playground<V: 'static>(PhantomData<V>);
|
||||||
|
|
||||||
|
impl<V> Playground<V> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(PhantomData)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> impl Element<V> {
|
||||||
|
workspace(&rose_pine::dawn())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for Playground {
|
fn workspace<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
column()
|
||||||
&mut self.0
|
.size(auto())
|
||||||
|
.fill(theme.base(0.5))
|
||||||
|
.text_color(theme.text(0.5))
|
||||||
|
.child(title_bar(theme))
|
||||||
|
.child(stage(theme))
|
||||||
|
.child(status_bar(theme))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title_bar<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
||||||
|
row()
|
||||||
|
.fill(theme.base(0.2))
|
||||||
|
.justify(0.)
|
||||||
|
.width(auto())
|
||||||
|
.child(text("Zed Playground"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stage<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
||||||
|
row().fill(theme.surface(0.9))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn status_bar<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
||||||
|
row().fill(theme.surface(0.1))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DialogDelegate<V>: 'static {}
|
||||||
|
|
||||||
|
impl<V> DialogDelegate<V> for () {}
|
||||||
|
|
||||||
|
#[derive(Element)]
|
||||||
|
pub struct Dialog<V: 'static, D: DialogDelegate<V>> {
|
||||||
|
title: Cow<'static, str>,
|
||||||
|
description: Cow<'static, str>,
|
||||||
|
delegate: Option<Rc<RefCell<D>>>,
|
||||||
|
buttons: Vec<Box<dyn FnOnce() -> AnyElement<V>>>,
|
||||||
|
view_type: PhantomData<V>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dialog<V>(
|
||||||
|
title: impl Into<Cow<'static, str>>,
|
||||||
|
description: impl Into<Cow<'static, str>>,
|
||||||
|
) -> Dialog<V, ()> {
|
||||||
|
Dialog {
|
||||||
|
title: title.into(),
|
||||||
|
description: description.into(),
|
||||||
|
delegate: None,
|
||||||
|
buttons: Vec::new(),
|
||||||
|
view_type: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for Playground {
|
impl<V, D: DialogDelegate<V>> Dialog<V, D> {
|
||||||
type Event = ();
|
pub fn delegate(mut self, delegate: D) -> Dialog<V, D> {
|
||||||
}
|
let old_delegate = self.delegate.replace(Rc::new(RefCell::new(delegate)));
|
||||||
|
debug_assert!(old_delegate.is_none(), "delegate already set");
|
||||||
impl View for Playground {
|
self
|
||||||
fn ui_name() -> &'static str {
|
|
||||||
"PlaygroundView"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> AnyElement<Playground> {
|
pub fn button<L, Data, H>(mut self, label: L, data: Data, handler: H) -> Self
|
||||||
self.0.clone().into_any()
|
where
|
||||||
|
L: 'static + Into<Cow<'static, str>>,
|
||||||
|
Data: 'static + Clone,
|
||||||
|
H: ClickHandler<V, Data>,
|
||||||
|
{
|
||||||
|
let label = label.into();
|
||||||
|
self.buttons.push(Box::new(move || {
|
||||||
|
button(label).data(data).click(handler).into_any()
|
||||||
|
}));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Element)]
|
||||||
|
struct Button<V: 'static, D: 'static, H: ClickHandler<V, D>> {
|
||||||
|
label: Cow<'static, str>,
|
||||||
|
click_handler: Option<H>,
|
||||||
|
data: Option<D>,
|
||||||
|
view_type: PhantomData<V>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ClickHandler<V, D>: 'static {
|
||||||
|
fn handle(&self, view: &mut V, data: &D, cx: &mut ViewContext<V>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, M, F: 'static + Fn(&mut V, &M, &mut ViewContext<V>)> ClickHandler<V, M> for F {
|
||||||
|
fn handle(&self, view: &mut V, data: &M, cx: &mut ViewContext<V>) {
|
||||||
|
self(view, data, cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, D> ClickHandler<V, D> for () {
|
||||||
|
fn handle(&self, view: &mut V, data: &D, cx: &mut ViewContext<V>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn button<V>(label: impl Into<Cow<'static, str>>) -> Button<V, (), ()> {
|
||||||
|
Button {
|
||||||
|
label: label.into(),
|
||||||
|
click_handler: None,
|
||||||
|
data: None,
|
||||||
|
view_type: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, D, F> Button<V, D, F>
|
||||||
|
where
|
||||||
|
F: ClickHandler<V, D>,
|
||||||
|
{
|
||||||
|
fn render(&mut self, _: &mut V, _: &mut LayoutContext<V>) -> AnyElement<V> {
|
||||||
|
// TODO! Handle click etc
|
||||||
|
row().child(text(self.label.clone())).into_any()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl<V, D, F> Button<V, D, F>
|
||||||
|
// where
|
||||||
|
// V,
|
||||||
|
// F: ClickHandler<V, D>,
|
||||||
|
// {
|
||||||
|
// fn render(&mut self, _: &mut V, _: &mut LayoutContext<V>) -> impl Element<V> {
|
||||||
|
// // TODO! Handle click etc
|
||||||
|
// row()
|
||||||
|
// .fill(theme.colors.primary(5))
|
||||||
|
// .child(text(self.label.clone()).text_color(theme.colors.on_primary()))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// struct Tab<V> {
|
||||||
|
// active: bool,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<V> Tab<V>
|
||||||
|
// where
|
||||||
|
// V,
|
||||||
|
// {
|
||||||
|
// fn tab(&mut self, _: &mut V, _: &mut LayoutContext<V>) -> impl Element<V> {
|
||||||
|
// let theme = todo!();
|
||||||
|
// // TODO! Handle click etc
|
||||||
|
// row()
|
||||||
|
// .fill(theme.colors.neutral(6))
|
||||||
|
// .child(text(self.label.clone()).text_color(theme.colors.on_neutral()))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl<V> Button<V, (), ()> {
|
||||||
|
fn data<D>(self, data: D) -> Button<V, D, ()>
|
||||||
|
where
|
||||||
|
D: 'static,
|
||||||
|
{
|
||||||
|
Button {
|
||||||
|
label: self.label,
|
||||||
|
click_handler: self.click_handler,
|
||||||
|
data: Some(data),
|
||||||
|
view_type: self.view_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, D> Button<V, D, ()> {
|
||||||
|
fn click<H>(self, handler: H) -> Button<V, D, H>
|
||||||
|
where
|
||||||
|
H: 'static + ClickHandler<V, D>,
|
||||||
|
{
|
||||||
|
Button {
|
||||||
|
label: self.label,
|
||||||
|
click_handler: Some(handler),
|
||||||
|
data: self.data,
|
||||||
|
view_type: self.view_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, D: DialogDelegate<V>> Dialog<V, D> {
|
||||||
|
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
|
||||||
|
column()
|
||||||
|
.child(text(self.title.clone()).text_size(lg()))
|
||||||
|
.child(text(self.description.clone()).margins((m4(), auto())))
|
||||||
|
.child(row().children(self.buttons.drain(..).map(|button| (button)())))
|
||||||
|
.into_any()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "playground_ui"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "playground_ui"
|
|
||||||
path = "src/playground_ui.rs"
|
|
||||||
crate-type = ["dylib"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
collections = { path = "../../../collections" }
|
|
||||||
util = { path = "../../../util" }
|
|
||||||
gpui = { path = "../.." }
|
|
||||||
derive_more = "0.99.17"
|
|
||||||
log.workspace = true
|
|
||||||
optional_struct = "0.3.1"
|
|
||||||
smallvec.workspace = true
|
|
||||||
serde.workspace = true
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
gpui = { path = "../..", features = ["test-support"] }
|
|
|
@ -1,200 +0,0 @@
|
||||||
#![allow(dead_code, unused_variables)]
|
|
||||||
|
|
||||||
use frame::{length::auto, *};
|
|
||||||
use gpui::{AnyElement, Element, LayoutContext, ViewContext};
|
|
||||||
use std::{borrow::Cow, cell::RefCell, marker::PhantomData, rc::Rc};
|
|
||||||
use themes::{rose_pine, ThemeColors};
|
|
||||||
use tokens::{margin::m4, text::lg};
|
|
||||||
|
|
||||||
mod color;
|
|
||||||
mod frame;
|
|
||||||
mod themes;
|
|
||||||
mod tokens;
|
|
||||||
|
|
||||||
#[derive(Element, Clone, Default)]
|
|
||||||
pub struct Playground<V: 'static>(PhantomData<V>);
|
|
||||||
|
|
||||||
impl<V> Frame<V> {}
|
|
||||||
|
|
||||||
impl<V> Playground<V> {
|
|
||||||
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> impl Element<V> {
|
|
||||||
workspace(&rose_pine::dawn())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn workspace<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
|
||||||
column()
|
|
||||||
.size(auto())
|
|
||||||
.fill(theme.base(0.1))
|
|
||||||
.child(title_bar(theme))
|
|
||||||
.child(stage(theme))
|
|
||||||
.child(status_bar(theme))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title_bar<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
|
||||||
row().fill(theme.surface(1.0))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stage<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
|
||||||
row().fill(theme.surface(0.9))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn status_bar<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
|
||||||
row().fill(theme.surface(0.1))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DialogDelegate<V>: 'static {}
|
|
||||||
|
|
||||||
impl<V> DialogDelegate<V> for () {}
|
|
||||||
|
|
||||||
#[derive(Element)]
|
|
||||||
pub struct Dialog<V: 'static, D: DialogDelegate<V>> {
|
|
||||||
title: Cow<'static, str>,
|
|
||||||
description: Cow<'static, str>,
|
|
||||||
delegate: Option<Rc<RefCell<D>>>,
|
|
||||||
buttons: Vec<Box<dyn FnOnce() -> AnyElement<V>>>,
|
|
||||||
view_type: PhantomData<V>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dialog<V>(
|
|
||||||
title: impl Into<Cow<'static, str>>,
|
|
||||||
description: impl Into<Cow<'static, str>>,
|
|
||||||
) -> Dialog<V, ()> {
|
|
||||||
Dialog {
|
|
||||||
title: title.into(),
|
|
||||||
description: description.into(),
|
|
||||||
delegate: None,
|
|
||||||
buttons: Vec::new(),
|
|
||||||
view_type: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, D: DialogDelegate<V>> Dialog<V, D> {
|
|
||||||
pub fn delegate(mut self, delegate: D) -> Dialog<V, D> {
|
|
||||||
let old_delegate = self.delegate.replace(Rc::new(RefCell::new(delegate)));
|
|
||||||
debug_assert!(old_delegate.is_none(), "delegate already set");
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn button<L, Data, H>(mut self, label: L, data: Data, handler: H) -> Self
|
|
||||||
where
|
|
||||||
L: 'static + Into<Cow<'static, str>>,
|
|
||||||
Data: 'static + Clone,
|
|
||||||
H: ClickHandler<V, Data>,
|
|
||||||
{
|
|
||||||
let label = label.into();
|
|
||||||
self.buttons.push(Box::new(move || {
|
|
||||||
button(label).data(data).click(handler).into_any()
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Element)]
|
|
||||||
struct Button<V: 'static, D: 'static, H: ClickHandler<V, D>> {
|
|
||||||
label: Cow<'static, str>,
|
|
||||||
click_handler: Option<H>,
|
|
||||||
data: Option<D>,
|
|
||||||
view_type: PhantomData<V>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ClickHandler<V, D>: 'static {
|
|
||||||
fn handle(&self, view: &mut V, data: &D, cx: &mut ViewContext<V>);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, M, F: 'static + Fn(&mut V, &M, &mut ViewContext<V>)> ClickHandler<V, M> for F {
|
|
||||||
fn handle(&self, view: &mut V, data: &M, cx: &mut ViewContext<V>) {
|
|
||||||
self(view, data, cx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, D> ClickHandler<V, D> for () {
|
|
||||||
fn handle(&self, view: &mut V, data: &D, cx: &mut ViewContext<V>) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn button<V>(label: impl Into<Cow<'static, str>>) -> Button<V, (), ()> {
|
|
||||||
Button {
|
|
||||||
label: label.into(),
|
|
||||||
click_handler: None,
|
|
||||||
data: None,
|
|
||||||
view_type: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, D, F> Button<V, D, F>
|
|
||||||
where
|
|
||||||
F: ClickHandler<V, D>,
|
|
||||||
{
|
|
||||||
fn render(&mut self, _: &mut V, _: &mut LayoutContext<V>) -> AnyElement<V> {
|
|
||||||
// TODO! Handle click etc
|
|
||||||
row().child(text(self.label.clone())).into_any()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl<V, D, F> Button<V, D, F>
|
|
||||||
// where
|
|
||||||
// V,
|
|
||||||
// F: ClickHandler<V, D>,
|
|
||||||
// {
|
|
||||||
// fn render(&mut self, _: &mut V, _: &mut LayoutContext<V>) -> impl Element<V> {
|
|
||||||
// // TODO! Handle click etc
|
|
||||||
// row()
|
|
||||||
// .fill(theme.colors.primary(5))
|
|
||||||
// .child(text(self.label.clone()).text_color(theme.colors.on_primary()))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// struct Tab<V> {
|
|
||||||
// active: bool,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl<V> Tab<V>
|
|
||||||
// where
|
|
||||||
// V,
|
|
||||||
// {
|
|
||||||
// fn tab(&mut self, _: &mut V, _: &mut LayoutContext<V>) -> impl Element<V> {
|
|
||||||
// let theme = todo!();
|
|
||||||
// // TODO! Handle click etc
|
|
||||||
// row()
|
|
||||||
// .fill(theme.colors.neutral(6))
|
|
||||||
// .child(text(self.label.clone()).text_color(theme.colors.on_neutral()))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl<V> Button<V, (), ()> {
|
|
||||||
fn data<D>(self, data: D) -> Button<V, D, ()>
|
|
||||||
where
|
|
||||||
D: 'static,
|
|
||||||
{
|
|
||||||
Button {
|
|
||||||
label: self.label,
|
|
||||||
click_handler: self.click_handler,
|
|
||||||
data: Some(data),
|
|
||||||
view_type: self.view_type,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, D> Button<V, D, ()> {
|
|
||||||
fn click<H>(self, handler: H) -> Button<V, D, H>
|
|
||||||
where
|
|
||||||
H: 'static + ClickHandler<V, D>,
|
|
||||||
{
|
|
||||||
Button {
|
|
||||||
label: self.label,
|
|
||||||
click_handler: Some(handler),
|
|
||||||
data: self.data,
|
|
||||||
view_type: self.view_type,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, D: DialogDelegate<V>> Dialog<V, D> {
|
|
||||||
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
|
|
||||||
column()
|
|
||||||
.child(text(self.title.clone()).text_size(lg()))
|
|
||||||
.child(text(self.description.clone()).margins((m4(), auto())))
|
|
||||||
.child(row().children(self.buttons.drain(..).map(|button| (button)())))
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3440,14 +3440,22 @@ impl<'a, 'b, 'c, V> LayoutContext<'a, 'b, 'c, V> {
|
||||||
.unwrap_or(Arc::new(TextStyle::default(&self.font_cache)))
|
.unwrap_or(Arc::new(TextStyle::default(&self.font_cache)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_text_style<S: Into<Arc<TextStyle>>>(&mut self, style: S) {
|
||||||
|
self.text_style_stack.push(style.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_text_style(&mut self) {
|
||||||
|
self.text_style_stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_text_style<S, F, T>(&mut self, style: S, f: F) -> T
|
pub fn with_text_style<S, F, T>(&mut self, style: S, f: F) -> T
|
||||||
where
|
where
|
||||||
S: Into<Arc<TextStyle>>,
|
S: Into<Arc<TextStyle>>,
|
||||||
F: FnOnce(&mut Self) -> T,
|
F: FnOnce(&mut Self) -> T,
|
||||||
{
|
{
|
||||||
self.text_style_stack.push(style.into());
|
self.push_text_style(style);
|
||||||
let result = f(self);
|
let result = f(self);
|
||||||
self.text_style_stack.pop();
|
self.pop_text_style();
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use serde_json::json;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord, JsonSchema)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord, JsonSchema)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Color(#[schemars(with = "String")] ColorU);
|
pub struct Color(#[schemars(with = "String")] pub ColorU);
|
||||||
|
|
||||||
pub fn color(rgba: u32) -> Color {
|
pub fn color(rgba: u32) -> Color {
|
||||||
Color::from_u32(rgba)
|
Color::from_u32(rgba)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue