mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
WIP
This commit is contained in:
parent
19e4cad7a9
commit
54a7419fa2
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -3041,6 +3041,7 @@ dependencies = [
|
|||||||
name = "gpui_macros"
|
name = "gpui_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
@ -5043,9 +5044,17 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"gpui",
|
"gpui",
|
||||||
"log",
|
"log",
|
||||||
|
"playground_ui",
|
||||||
"simplelog",
|
"simplelog",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "playground_ui"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"gpui",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "plist"
|
name = "plist"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
@ -29,6 +29,7 @@ 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,6 +8,8 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
playground_ui = { path = "ui" }
|
||||||
|
|
||||||
gpui = { path = ".." }
|
gpui = { path = ".." }
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
simplelog = "0.9"
|
simplelog = "0.9"
|
||||||
|
@ -1,52 +1,45 @@
|
|||||||
use elements::{Length, Node, NodeStyle};
|
use std::ops::{Deref, DerefMut};
|
||||||
use gpui::{color::Color, AnyElement, Element, Entity, View, ViewContext};
|
|
||||||
|
use gpui::{AnyElement, Element, Entity, View};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use simplelog::SimpleLogger;
|
use simplelog::SimpleLogger;
|
||||||
|
|
||||||
mod elements;
|
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
gpui::App::new(()).unwrap().run(|cx| {
|
gpui::App::new(()).unwrap().run(|cx| {
|
||||||
cx.platform().activate(true);
|
cx.platform().activate(true);
|
||||||
cx.add_window(Default::default(), |_| PlaygroundView);
|
cx.add_window(Default::default(), |_| Playground::default());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PlaygroundView;
|
#[derive(Clone, Default)]
|
||||||
|
struct Playground(playground_ui::Playground);
|
||||||
|
|
||||||
impl Entity for PlaygroundView {
|
impl Deref for Playground {
|
||||||
|
type Target = playground_ui::Playground;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for Playground {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entity for Playground {
|
||||||
type Event = ();
|
type Event = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for PlaygroundView {
|
impl View for Playground {
|
||||||
fn ui_name() -> &'static str {
|
fn ui_name() -> &'static str {
|
||||||
"PlaygroundView"
|
"PlaygroundView"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> AnyElement<PlaygroundView> {
|
fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> AnyElement<Playground> {
|
||||||
// Node::with_style(NodeStyle)
|
self.0.clone().into_any()
|
||||||
// Node::new().width(100.0).fill(Color::red())
|
|
||||||
//
|
|
||||||
Node::new()
|
|
||||||
.width(Length::auto(1.))
|
|
||||||
.fill(Color::red())
|
|
||||||
.row()
|
|
||||||
.children([
|
|
||||||
Node::new().width(20.).height(20.).fill(Color::green()),
|
|
||||||
Node::new().width(20.).height(20.).fill(Color::blue()),
|
|
||||||
Node::new().width(30.).height(30.).fill(Color::yellow()),
|
|
||||||
Node::new().width(50.).height(50.).fill(Color::yellow()),
|
|
||||||
])
|
|
||||||
.into_any()
|
|
||||||
|
|
||||||
// Node::with_style(
|
|
||||||
// NodeStyle::default()
|
|
||||||
// .width(100.)
|
|
||||||
// .height(100.)
|
|
||||||
// .fill(Color::red()),
|
|
||||||
// )
|
|
||||||
// .into_any()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
crates/gpui/playground/ui/Cargo.toml
Normal file
12
crates/gpui/playground/ui/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "playground_ui"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "playground_ui"
|
||||||
|
path = "src/playground_ui.rs"
|
||||||
|
crate-type = ["dylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gpui = { path = "../.." }
|
91
crates/gpui/playground/ui/src/playground_ui.rs
Normal file
91
crates/gpui/playground/ui/src/playground_ui.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use gpui::{
|
||||||
|
elements::{
|
||||||
|
node::{column, length::auto, row},
|
||||||
|
Text,
|
||||||
|
},
|
||||||
|
AnyElement, Element, View, ViewContext,
|
||||||
|
};
|
||||||
|
use std::{borrow::Cow, marker::PhantomData};
|
||||||
|
use tokens::{margin::m4, text::lg};
|
||||||
|
|
||||||
|
mod tokens;
|
||||||
|
|
||||||
|
#[derive(Element, Clone, Default)]
|
||||||
|
pub struct Playground;
|
||||||
|
|
||||||
|
impl Playground {
|
||||||
|
pub fn render<V: View>(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
|
||||||
|
column()
|
||||||
|
.width(auto())
|
||||||
|
.child(dialog(
|
||||||
|
"This is a dialog",
|
||||||
|
"You would see a description here.",
|
||||||
|
))
|
||||||
|
.into_any()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DialogDelegate<V: View>: 'static {
|
||||||
|
fn handle_submit<B>(&mut self, view: &mut V, button: B);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: View> DialogDelegate<V> for () {
|
||||||
|
fn handle_submit<B>(&mut self, _: &mut V, _: B) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Element)]
|
||||||
|
pub struct Dialog<V: View, D: DialogDelegate<V>> {
|
||||||
|
title: Cow<'static, str>,
|
||||||
|
description: Cow<'static, str>,
|
||||||
|
delegate: Option<D>,
|
||||||
|
view_type: PhantomData<V>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dialog<V: View>(
|
||||||
|
title: impl Into<Cow<'static, str>>,
|
||||||
|
description: impl Into<Cow<'static, str>>,
|
||||||
|
) -> Dialog<V, ()> {
|
||||||
|
Dialog {
|
||||||
|
title: title.into(),
|
||||||
|
description: description.into(),
|
||||||
|
delegate: None,
|
||||||
|
view_type: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: View, D: DialogDelegate<V>> Dialog<V, D> {
|
||||||
|
pub fn with_delegate(mut self, delegate: D) -> Dialog<V, D> {
|
||||||
|
let old_delegate = self.delegate.replace(delegate);
|
||||||
|
debug_assert!(old_delegate.is_none(), "delegate already set");
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Button<V: View, F: FnOnce(&mut V, &mut ViewContext<V>)> {
|
||||||
|
label: Cow<'static, str>,
|
||||||
|
on_click: Option<F>,
|
||||||
|
view_type: PhantomData<V>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn button<V: View, F: FnOnce(&mut V, &mut ViewContext<V>)>(
|
||||||
|
label: impl Into<Cow<'static, str>>,
|
||||||
|
) -> Button<V, F> {
|
||||||
|
Button {
|
||||||
|
label: label.into(),
|
||||||
|
on_click: None,
|
||||||
|
view_type: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: View, 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([
|
||||||
|
button("Cancel").margin_left(auto()),
|
||||||
|
button("OK").margin_left(m4()),
|
||||||
|
]))
|
||||||
|
.into_any()
|
||||||
|
}
|
||||||
|
}
|
157
crates/gpui/playground/ui/src/tokens.rs
Normal file
157
crates/gpui/playground/ui/src/tokens.rs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
pub mod color {
|
||||||
|
use gpui::color::Color;
|
||||||
|
|
||||||
|
pub fn background(elevation: f32) -> Color {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod text {
|
||||||
|
pub fn xs() -> f32 {
|
||||||
|
0.75
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sm() -> f32 {
|
||||||
|
0.875
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn base() -> f32 {
|
||||||
|
1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lg() -> f32 {
|
||||||
|
1.125
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xl() -> f32 {
|
||||||
|
1.25
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xxl() -> f32 {
|
||||||
|
1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xxxl() -> f32 {
|
||||||
|
1.875
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xxxx() -> f32 {
|
||||||
|
2.25
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xxxxx() -> f32 {
|
||||||
|
3.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xxxxxx() -> f32 {
|
||||||
|
4.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod padding {
|
||||||
|
pub fn p1() -> f32 {
|
||||||
|
0.25
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p2() -> f32 {
|
||||||
|
0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p3() -> f32 {
|
||||||
|
0.75
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p4() -> f32 {
|
||||||
|
1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p5() -> f32 {
|
||||||
|
1.25
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p6() -> f32 {
|
||||||
|
1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p8() -> f32 {
|
||||||
|
2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p10() -> f32 {
|
||||||
|
2.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p12() -> f32 {
|
||||||
|
3.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p16() -> f32 {
|
||||||
|
4.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p20() -> f32 {
|
||||||
|
5.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p24() -> f32 {
|
||||||
|
6.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p32() -> f32 {
|
||||||
|
8.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod margin {
|
||||||
|
pub fn m1() -> f32 {
|
||||||
|
0.25
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m2() -> f32 {
|
||||||
|
0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m3() -> f32 {
|
||||||
|
0.75
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m4() -> f32 {
|
||||||
|
1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m5() -> f32 {
|
||||||
|
1.25
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m6() -> f32 {
|
||||||
|
1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m8() -> f32 {
|
||||||
|
2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m10() -> f32 {
|
||||||
|
2.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m12() -> f32 {
|
||||||
|
3.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m16() -> f32 {
|
||||||
|
4.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m20() -> f32 {
|
||||||
|
5.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m24() -> f32 {
|
||||||
|
6.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m32() -> f32 {
|
||||||
|
8.0
|
||||||
|
}
|
||||||
|
}
|
@ -17,33 +17,73 @@ use serde_json::json;
|
|||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Color(#[schemars(with = "String")] ColorU);
|
pub struct Color(#[schemars(with = "String")] ColorU);
|
||||||
|
|
||||||
|
pub fn color(rgba: u32) -> Color {
|
||||||
|
color(rgba)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rgb(r: f32, g: f32, b: f32) -> Color {
|
||||||
|
Color(ColorF::new(r, g, b, 1.).to_u8())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color {
|
||||||
|
Color(ColorF::new(r, g, b, a).to_u8())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transparent_black() -> Color {
|
||||||
|
Color(ColorU::transparent_black())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn black() -> Color {
|
||||||
|
Color(ColorU::black())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn white() -> Color {
|
||||||
|
Color(ColorU::white())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn red() -> Color {
|
||||||
|
color(0xff0000ff)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn green() -> Color {
|
||||||
|
color(0x00ff00ff)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn blue() -> Color {
|
||||||
|
color(0x0000ffff)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn yellow() -> Color {
|
||||||
|
color(0xffff00ff)
|
||||||
|
}
|
||||||
|
|
||||||
impl Color {
|
impl Color {
|
||||||
pub fn transparent_black() -> Self {
|
pub fn transparent_black() -> Self {
|
||||||
Self(ColorU::transparent_black())
|
transparent_black()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn black() -> Self {
|
pub fn black() -> Self {
|
||||||
Self(ColorU::black())
|
black()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn white() -> Self {
|
pub fn white() -> Self {
|
||||||
Self(ColorU::white())
|
white()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn red() -> Self {
|
pub fn red() -> Self {
|
||||||
Self(ColorU::from_u32(0xff0000ff))
|
Color::from_u32(0xff0000ff)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn green() -> Self {
|
pub fn green() -> Self {
|
||||||
Self(ColorU::from_u32(0x00ff00ff))
|
Color::from_u32(0x00ff00ff)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blue() -> Self {
|
pub fn blue() -> Self {
|
||||||
Self(ColorU::from_u32(0x0000ffff))
|
Color::from_u32(0x0000ffff)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn yellow() -> Self {
|
pub fn yellow() -> Self {
|
||||||
Self(ColorU::from_u32(0xffff00ff))
|
Color::from_u32(0xffff00ff)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
|
pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||||
|
@ -12,6 +12,7 @@ mod keystroke_label;
|
|||||||
mod label;
|
mod label;
|
||||||
mod list;
|
mod list;
|
||||||
mod mouse_event_handler;
|
mod mouse_event_handler;
|
||||||
|
pub mod node;
|
||||||
mod overlay;
|
mod overlay;
|
||||||
mod resizable;
|
mod resizable;
|
||||||
mod stack;
|
mod stack;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use gpui::{
|
use crate::{
|
||||||
color::Color,
|
color::Color,
|
||||||
geometry::{
|
geometry::{
|
||||||
rect::RectF,
|
rect::RectF,
|
||||||
@ -9,47 +9,62 @@ use gpui::{
|
|||||||
serde_json::Value,
|
serde_json::Value,
|
||||||
AnyElement, Element, LayoutContext, Quad, SceneBuilder, SizeConstraint, View, ViewContext,
|
AnyElement, Element, LayoutContext, Quad, SceneBuilder, SizeConstraint, View, ViewContext,
|
||||||
};
|
};
|
||||||
use std::{any::Any, f32, ops::Range};
|
use std::{any::Any, borrow::Cow, f32, ops::Range};
|
||||||
|
|
||||||
// Core idea is that everything is a channel, and channels are heirarchical.
|
use self::length::Length;
|
||||||
//
|
|
||||||
// Tree 🌲 of channels
|
|
||||||
// - (Potentially v0.2) All channels associated with a conversation (Slack model)
|
|
||||||
// - Audio
|
|
||||||
// - You can share projects into the channel
|
|
||||||
// - 1.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// - 2 thoughts:
|
|
||||||
// - Difference from where we are to the above:
|
|
||||||
// - Channels = rooms + chat + persistence
|
|
||||||
// - Chat = multiplayer assistant panel + server integrated persistence
|
|
||||||
// - The tree structure, is good for navigating chats, AND it's good for distributing permissions.
|
|
||||||
// #zed-public// /zed- <- Share a pointer (URL) for this
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
pub struct Node<V: View> {
|
pub struct Node<V: View> {
|
||||||
style: NodeStyle,
|
style: NodeStyle,
|
||||||
children: Vec<AnyElement<V>>,
|
content: Content<V>,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Content<V: View> {
|
||||||
|
Children(Vec<AnyElement<V>>),
|
||||||
|
Text(Cow<'static, str>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: View> Default for Content<V> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Children(Vec::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn column<V: View>() -> Node<V> {
|
||||||
|
Node::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn row<V: View>() -> Node<V> {
|
||||||
|
Node {
|
||||||
|
style: NodeStyle {
|
||||||
|
axis: Axis3d::X,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
content: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stack<V: View>() -> Node<V> {
|
||||||
|
Node {
|
||||||
|
style: NodeStyle {
|
||||||
|
axis: Axis3d::Z,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
content: Default::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: View> Default for Node<V> {
|
impl<V: View> Default for Node<V> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
children: Default::default(),
|
content: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: View> Node<V> {
|
impl<V: View> Node<V> {
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn child(mut self, child: impl Element<V>) -> Self {
|
pub fn child(mut self, child: impl Element<V>) -> Self {
|
||||||
self.children.push(child.into_any());
|
self.content.push(child.into_any());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +73,7 @@ impl<V: View> Node<V> {
|
|||||||
I: IntoIterator<Item = E>,
|
I: IntoIterator<Item = E>,
|
||||||
E: Element<V>,
|
E: Element<V>,
|
||||||
{
|
{
|
||||||
self.children
|
self.content
|
||||||
.extend(children.into_iter().map(|child| child.into_any()));
|
.extend(children.into_iter().map(|child| child.into_any()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -100,7 +115,7 @@ impl<V: View> Node<V> {
|
|||||||
let mut cross_axis_max: f32 = 0.0;
|
let mut cross_axis_max: f32 = 0.0;
|
||||||
|
|
||||||
// First pass: Layout non-flex children only
|
// First pass: Layout non-flex children only
|
||||||
for child in &mut self.children {
|
for child in &mut self.content {
|
||||||
let child_flex = child.metadata::<NodeStyle>().and_then(|style| match axis {
|
let child_flex = child.metadata::<NodeStyle>().and_then(|style| match axis {
|
||||||
Axis2d::X => style.width.flex(),
|
Axis2d::X => style.width.flex(),
|
||||||
Axis2d::Y => style.height.flex(),
|
Axis2d::Y => style.height.flex(),
|
||||||
@ -138,7 +153,7 @@ impl<V: View> Node<V> {
|
|||||||
if total_flex > 0. {
|
if total_flex > 0. {
|
||||||
let space_per_flex = remaining_space.max(0.) / total_flex;
|
let space_per_flex = remaining_space.max(0.) / total_flex;
|
||||||
|
|
||||||
for child in &mut self.children {
|
for child in &mut self.content {
|
||||||
let child_flex = child.metadata::<NodeStyle>().and_then(|style| match axis {
|
let child_flex = child.metadata::<NodeStyle>().and_then(|style| match axis {
|
||||||
Axis2d::X => style.width.flex(),
|
Axis2d::X => style.width.flex(),
|
||||||
Axis2d::Y => style.height.flex(),
|
Axis2d::Y => style.height.flex(),
|
||||||
@ -209,7 +224,7 @@ impl<V: View> Node<V> {
|
|||||||
align_vertically,
|
align_vertically,
|
||||||
);
|
);
|
||||||
|
|
||||||
for child in &mut self.children {
|
for child in &mut self.content {
|
||||||
// Align each child along the cross axis
|
// Align each child along the cross axis
|
||||||
align_horizontally = !align_horizontally;
|
align_horizontally = !align_horizontally;
|
||||||
align_vertically = !align_vertically;
|
align_vertically = !align_vertically;
|
||||||
@ -400,7 +415,7 @@ impl<V: View> Element<V> for Node<V> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.children.is_empty() {
|
if !self.content.is_empty() {
|
||||||
// Account for padding first.
|
// Account for padding first.
|
||||||
let padding = &self.style.padding;
|
let padding = &self.style.padding;
|
||||||
let padded_bounds = RectF::from_points(
|
let padded_bounds = RectF::from_points(
|
||||||
@ -442,7 +457,7 @@ impl<V: View> Element<V> for Node<V> {
|
|||||||
view: &V,
|
view: &V,
|
||||||
cx: &ViewContext<V>,
|
cx: &ViewContext<V>,
|
||||||
) -> Option<RectF> {
|
) -> Option<RectF> {
|
||||||
self.children
|
self.content
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
|
.find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
|
||||||
}
|
}
|
||||||
@ -456,9 +471,10 @@ impl<V: View> Element<V> for Node<V> {
|
|||||||
cx: &ViewContext<V>,
|
cx: &ViewContext<V>,
|
||||||
) -> Value {
|
) -> Value {
|
||||||
json!({
|
json!({
|
||||||
"type": "Cell",
|
"type": "Node",
|
||||||
"bounds": bounds.to_json(),
|
"bounds": bounds.to_json(),
|
||||||
"children": self.children.iter().map(|child| child.debug(view, cx)).collect::<Vec<Value>>()
|
// TODO!
|
||||||
|
// "children": self.content.iter().map(|child| child.debug(view, cx)).collect::<Vec<Value>>()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,26 +590,30 @@ impl Border {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default)]
|
pub mod length {
|
||||||
pub enum Length {
|
#[derive(Clone, Copy, Default)]
|
||||||
#[default]
|
pub enum Length {
|
||||||
Hug,
|
#[default]
|
||||||
Fixed(f32),
|
Hug,
|
||||||
Auto {
|
Fixed(f32),
|
||||||
flex: f32,
|
Auto {
|
||||||
min: f32,
|
flex: f32,
|
||||||
max: f32,
|
min: f32,
|
||||||
},
|
max: f32,
|
||||||
}
|
},
|
||||||
|
|
||||||
impl From<f32> for Length {
|
|
||||||
fn from(value: f32) -> Self {
|
|
||||||
Length::Fixed(value)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Length {
|
impl From<f32> for Length {
|
||||||
pub fn auto(flex: f32) -> Self {
|
fn from(value: f32) -> Self {
|
||||||
|
Length::Fixed(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn auto() -> Length {
|
||||||
|
flex(1.)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flex(flex: f32) -> Length {
|
||||||
Length::Auto {
|
Length::Auto {
|
||||||
flex,
|
flex,
|
||||||
min: 0.,
|
min: 0.,
|
||||||
@ -601,7 +621,7 @@ impl Length {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn auto_constrained(flex: f32, min: Option<f32>, max: Option<f32>) -> Self {
|
pub fn constrained(flex: f32, min: Option<f32>, max: Option<f32>) -> Length {
|
||||||
Length::Auto {
|
Length::Auto {
|
||||||
flex,
|
flex,
|
||||||
min: min.unwrap_or(0.),
|
min: min.unwrap_or(0.),
|
||||||
@ -609,10 +629,12 @@ impl Length {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flex(&self) -> Option<f32> {
|
impl Length {
|
||||||
match self {
|
pub fn flex(&self) -> Option<f32> {
|
||||||
Length::Auto { flex, .. } => Some(*flex),
|
match self {
|
||||||
_ => None,
|
Length::Auto { flex, .. } => Some(*flex),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -400,6 +400,58 @@ fn layout_highlighted_chunks<'a>(
|
|||||||
layouts
|
layouts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to figure out how fonts flow through the tree to implement this.
|
||||||
|
impl<V: View> Element<V> for Cow<'static, str> {
|
||||||
|
type LayoutState = ();
|
||||||
|
|
||||||
|
type PaintState = ();
|
||||||
|
|
||||||
|
fn layout(
|
||||||
|
&mut self,
|
||||||
|
constraint: SizeConstraint,
|
||||||
|
view: &mut V,
|
||||||
|
cx: &mut LayoutContext<V>,
|
||||||
|
) -> (Vector2F, Self::LayoutState) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(
|
||||||
|
&mut self,
|
||||||
|
scene: &mut SceneBuilder,
|
||||||
|
bounds: RectF,
|
||||||
|
visible_bounds: RectF,
|
||||||
|
layout: &mut Self::LayoutState,
|
||||||
|
view: &mut V,
|
||||||
|
cx: &mut ViewContext<V>,
|
||||||
|
) -> Self::PaintState {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rect_for_text_range(
|
||||||
|
&self,
|
||||||
|
range_utf16: Range<usize>,
|
||||||
|
bounds: RectF,
|
||||||
|
visible_bounds: RectF,
|
||||||
|
layout: &Self::LayoutState,
|
||||||
|
paint: &Self::PaintState,
|
||||||
|
view: &V,
|
||||||
|
cx: &ViewContext<V>,
|
||||||
|
) -> Option<RectF> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug(
|
||||||
|
&self,
|
||||||
|
bounds: RectF,
|
||||||
|
layout: &Self::LayoutState,
|
||||||
|
paint: &Self::PaintState,
|
||||||
|
view: &V,
|
||||||
|
cx: &ViewContext<V>,
|
||||||
|
) -> crate::serde_json::Value {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -10,7 +10,7 @@ proc-macro = true
|
|||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
lazy_static.workspace = true
|
||||||
|
proc-macro2 = "1.0"
|
||||||
syn = "1.0"
|
syn = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
proc-macro2 = "1.0"
|
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::Ident;
|
use proc_macro2::Ident;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote, ToTokens};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use syn::{
|
use syn::{
|
||||||
parse_macro_input, parse_quote, spanned::Spanned as _, AttributeArgs, DeriveInput, FnArg,
|
parse_macro_input, parse_quote, spanned::Spanned as _, AttributeArgs, DeriveInput, FnArg,
|
||||||
ItemFn, Lit, Meta, NestedMeta, Type,
|
GenericParam, Generics, ItemFn, Lit, Meta, NestedMeta, Type, TypeGenerics, TypeParam,
|
||||||
|
WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
@ -278,14 +279,44 @@ fn parse_bool(literal: &Lit) -> Result<bool, TokenStream> {
|
|||||||
|
|
||||||
#[proc_macro_derive(Element)]
|
#[proc_macro_derive(Element)]
|
||||||
pub fn element_derive(input: TokenStream) -> TokenStream {
|
pub fn element_derive(input: TokenStream) -> TokenStream {
|
||||||
// Parse the input tokens into a syntax tree
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let type_name = ast.ident;
|
||||||
|
|
||||||
// The name of the struct/enum
|
let placeholder_view_generics: Generics = parse_quote! { <V: View> };
|
||||||
let name = input.ident;
|
let placeholder_view_type_name: Ident = parse_quote! { V };
|
||||||
|
let view_type_name: Ident;
|
||||||
|
let impl_generics: syn::ImplGenerics<'_>;
|
||||||
|
let type_generics: Option<syn::TypeGenerics<'_>>;
|
||||||
|
let where_clause: Option<&'_ WhereClause>;
|
||||||
|
|
||||||
|
match ast.generics.params.iter().find_map(|param| {
|
||||||
|
if let GenericParam::Type(type_param) = param {
|
||||||
|
Some(type_param.ident.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Some(type_name) => {
|
||||||
|
view_type_name = type_name;
|
||||||
|
let generics = ast.generics.split_for_impl();
|
||||||
|
impl_generics = generics.0;
|
||||||
|
type_generics = Some(generics.1);
|
||||||
|
where_clause = generics.2;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
view_type_name = placeholder_view_type_name;
|
||||||
|
let generics = placeholder_view_generics.split_for_impl();
|
||||||
|
impl_generics = generics.0;
|
||||||
|
type_generics = None;
|
||||||
|
where_clause = generics.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let gen = quote! {
|
||||||
|
impl #impl_generics Element<#view_type_name> for #type_name #type_generics
|
||||||
|
#where_clause
|
||||||
|
{
|
||||||
|
|
||||||
let expanded = quote! {
|
|
||||||
impl<V: gpui::View> gpui::elements::Element<V> for #name {
|
|
||||||
type LayoutState = gpui::elements::AnyElement<V>;
|
type LayoutState = gpui::elements::AnyElement<V>;
|
||||||
type PaintState = ();
|
type PaintState = ();
|
||||||
|
|
||||||
@ -337,6 +368,6 @@ pub fn element_derive(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Return generated code
|
|
||||||
TokenStream::from(expanded)
|
gen.into()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user