WIP
This commit is contained in:
parent
70c9959ebc
commit
2ef19e48bc
3 changed files with 80 additions and 79 deletions
|
@ -14,10 +14,10 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
struct Playground(playground_ui::Playground);
|
struct Playground(playground_ui::Playground<Self>);
|
||||||
|
|
||||||
impl Deref for Playground {
|
impl Deref for Playground {
|
||||||
type Target = playground_ui::Playground;
|
type Target = playground_ui::Playground<Self>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
|
|
|
@ -2,16 +2,16 @@ use gpui::{
|
||||||
elements::node::{column, length::auto, row, text},
|
elements::node::{column, length::auto, row, text},
|
||||||
AnyElement, Element, LayoutContext, View, ViewContext,
|
AnyElement, Element, LayoutContext, View, ViewContext,
|
||||||
};
|
};
|
||||||
use std::{borrow::Cow, marker::PhantomData};
|
use std::{borrow::Cow, cell::RefCell, marker::PhantomData, rc::Rc};
|
||||||
use tokens::{margin::m4, text::lg};
|
use tokens::{margin::m4, text::lg};
|
||||||
|
|
||||||
mod tokens;
|
mod tokens;
|
||||||
|
|
||||||
#[derive(Element, Clone, Default)]
|
#[derive(Element, Clone, Default)]
|
||||||
pub struct Playground;
|
pub struct Playground<V: View>(PhantomData<V>);
|
||||||
|
|
||||||
impl Playground {
|
impl<V: View> Playground<V> {
|
||||||
pub fn render<V: View>(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
|
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
|
||||||
column()
|
column()
|
||||||
.width(auto())
|
.width(auto())
|
||||||
.child(
|
.child(
|
||||||
|
@ -22,30 +22,25 @@ impl Playground {
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_1(&mut self, data: &usize, _: &mut ViewContext<Self>) {
|
fn action_1(_: &mut V, data: &usize, _: &mut ViewContext<V>) {
|
||||||
println!("action 1: data is {}", *data);
|
println!("action 1: data is {}", *data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_2(&mut self, data: &usize, _: &mut ViewContext<Self>) {
|
fn action_2(_: &mut V, data: &usize, _: &mut ViewContext<V>) {
|
||||||
println!("action 1: data is {}", *data);
|
println!("action 1: data is {}", *data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DialogDelegate<V: View>: 'static {
|
pub trait DialogDelegate<V: View>: 'static {}
|
||||||
fn handle_confirm<B>(&mut self, view: &mut V, button: B);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: View> DialogDelegate<V> for () {
|
impl<V: View> DialogDelegate<V> for () {}
|
||||||
fn handle_cancel<B>(&mut self, view: &mut V, button: B) {}
|
|
||||||
fn handle_confirm<B>(&mut self, _: &mut V, _: B) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Element)]
|
#[derive(Element)]
|
||||||
pub struct Dialog<V: View, D: DialogDelegate<V>> {
|
pub struct Dialog<V: View, D: DialogDelegate<V>> {
|
||||||
title: Cow<'static, str>,
|
title: Cow<'static, str>,
|
||||||
description: Cow<'static, str>,
|
description: Cow<'static, str>,
|
||||||
delegate: Option<Rc<RefCell<D>>>,
|
delegate: Option<Rc<RefCell<D>>>,
|
||||||
buttons: Vec<Box<dyn Fn() -> Button>>,
|
buttons: Vec<Box<dyn FnOnce() -> AnyElement<V>>>,
|
||||||
view_type: PhantomData<V>,
|
view_type: PhantomData<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,19 +59,21 @@ pub fn dialog<V: View>(
|
||||||
|
|
||||||
impl<V: View, D: DialogDelegate<V>> Dialog<V, D> {
|
impl<V: View, D: DialogDelegate<V>> Dialog<V, D> {
|
||||||
pub fn delegate(mut self, delegate: D) -> Dialog<V, D> {
|
pub fn delegate(mut self, delegate: D) -> Dialog<V, D> {
|
||||||
let old_delegate = self.delegate.replace(delegate);
|
let old_delegate = self.delegate.replace(Rc::new(RefCell::new(delegate)));
|
||||||
debug_assert!(old_delegate.is_none(), "delegate already set");
|
debug_assert!(old_delegate.is_none(), "delegate already set");
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn button<L, D, H>(mut self, label: L, data: D, handler: H) -> Self
|
pub fn button<L, Data, H>(mut self, label: L, data: Data, handler: H) -> Self
|
||||||
where
|
where
|
||||||
L: Into<Cow<'static, str>>,
|
L: 'static + Into<Cow<'static, str>>,
|
||||||
D: 'static,
|
Data: 'static + Clone,
|
||||||
H: ClickHandler<V, D>,
|
H: ClickHandler<V, Data>,
|
||||||
{
|
{
|
||||||
self.buttons
|
let label = label.into();
|
||||||
.push(|| button(label).data(data).click(handler));
|
self.buttons.push(Box::new(move || {
|
||||||
|
button(label).data(data).click(handler).into_any()
|
||||||
|
}));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,7 +125,7 @@ where
|
||||||
impl<V: View> Button<V, (), ()> {
|
impl<V: View> Button<V, (), ()> {
|
||||||
fn data<D>(self, data: D) -> Button<V, D, ()>
|
fn data<D>(self, data: D) -> Button<V, D, ()>
|
||||||
where
|
where
|
||||||
D: 'static + FnOnce(&mut V, &D, &mut ViewContext<V>),
|
D: 'static,
|
||||||
{
|
{
|
||||||
Button {
|
Button {
|
||||||
label: self.label,
|
label: self.label,
|
||||||
|
@ -142,7 +139,7 @@ impl<V: View> Button<V, (), ()> {
|
||||||
impl<V: View, D> Button<V, D, ()> {
|
impl<V: View, D> Button<V, D, ()> {
|
||||||
fn click<H>(self, handler: H) -> Button<V, D, H>
|
fn click<H>(self, handler: H) -> Button<V, D, H>
|
||||||
where
|
where
|
||||||
H: 'static + Fn(&mut V, &D, &mut ViewContext<V>),
|
H: 'static + ClickHandler<V, D>,
|
||||||
{
|
{
|
||||||
Button {
|
Button {
|
||||||
label: self.label,
|
label: self.label,
|
||||||
|
@ -155,12 +152,10 @@ impl<V: View, D> Button<V, D, ()> {
|
||||||
|
|
||||||
impl<V: View, D: DialogDelegate<V>> Dialog<V, D> {
|
impl<V: View, D: DialogDelegate<V>> Dialog<V, D> {
|
||||||
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
|
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
|
||||||
let delegate = self.delegate.clone();
|
|
||||||
|
|
||||||
column()
|
column()
|
||||||
.child(text(self.title.clone()).text_size(lg()))
|
.child(text(self.title.clone()).text_size(lg()))
|
||||||
.child(text(self.description.clone()).margins(m4(), auto()))
|
.child(text(self.description.clone()).margins(m4(), auto()))
|
||||||
.child(row().children(self.buttons.iter().map(|button| (button)())))
|
.child(row().children(self.buttons.drain(..).map(|button| (button)())))
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,7 +273,7 @@ impl<V: View> Node<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint_2d_children(
|
fn paint_children_xy(
|
||||||
&mut self,
|
&mut self,
|
||||||
scene: &mut SceneBuilder,
|
scene: &mut SceneBuilder,
|
||||||
axis: Axis2d,
|
axis: Axis2d,
|
||||||
|
@ -395,15 +395,7 @@ impl<V: View> Element<V> for Node<V> {
|
||||||
let mut layout = NodeLayout::default();
|
let mut layout = NodeLayout::default();
|
||||||
|
|
||||||
let size = if let Some(axis) = self.style.axis.to_2d() {
|
let size = if let Some(axis) = self.style.axis.to_2d() {
|
||||||
self.layout_xy(
|
self.layout_xy(axis, constraint.max, cx.rem_pixels(), &mut layout, view, cx)
|
||||||
axis,
|
|
||||||
constraint.max,
|
|
||||||
cx.rem_pixels(),
|
|
||||||
&mut layout,
|
|
||||||
&mut layout.padding,
|
|
||||||
view,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
todo!()
|
todo!()
|
||||||
};
|
};
|
||||||
|
@ -421,11 +413,6 @@ impl<V: View> Element<V> for Node<V> {
|
||||||
cx: &mut PaintContext<V>,
|
cx: &mut PaintContext<V>,
|
||||||
) -> Self::PaintState {
|
) -> Self::PaintState {
|
||||||
let rem_pixels = cx.rem_pixels();
|
let rem_pixels = cx.rem_pixels();
|
||||||
// let margin: Edges<f32> = todo!(); // &self.style.margin.to_pixels(rem_size);
|
|
||||||
//
|
|
||||||
|
|
||||||
let size = bounds.size();
|
|
||||||
|
|
||||||
let margined_bounds = RectF::from_points(
|
let margined_bounds = RectF::from_points(
|
||||||
bounds.origin() + vec2f(layout.margins.left, layout.margins.top),
|
bounds.origin() + vec2f(layout.margins.left, layout.margins.top),
|
||||||
bounds.lower_right() - vec2f(layout.margins.right, layout.margins.bottom),
|
bounds.lower_right() - vec2f(layout.margins.right, layout.margins.bottom),
|
||||||
|
@ -434,7 +421,7 @@ impl<V: View> Element<V> for Node<V> {
|
||||||
// Paint drop shadow
|
// Paint drop shadow
|
||||||
for shadow in &self.style.shadows {
|
for shadow in &self.style.shadows {
|
||||||
scene.push_shadow(scene::Shadow {
|
scene.push_shadow(scene::Shadow {
|
||||||
bounds: margin_bounds + shadow.offset,
|
bounds: margined_bounds + shadow.offset,
|
||||||
corner_radius: self.style.corner_radius,
|
corner_radius: self.style.corner_radius,
|
||||||
sigma: shadow.blur,
|
sigma: shadow.blur,
|
||||||
color: shadow.color,
|
color: shadow.color,
|
||||||
|
@ -451,7 +438,7 @@ impl<V: View> Element<V> for Node<V> {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Render the background and/or the border (if it not an overlay border).
|
// Render the background and/or the border.
|
||||||
let Fill::Color(fill_color) = self.style.fill;
|
let Fill::Color(fill_color) = self.style.fill;
|
||||||
let is_fill_visible = !fill_color.is_fully_transparent();
|
let is_fill_visible = !fill_color.is_fully_transparent();
|
||||||
if is_fill_visible || self.style.borders.is_visible() {
|
if is_fill_visible || self.style.borders.is_visible() {
|
||||||
|
@ -472,38 +459,25 @@ impl<V: View> Element<V> for Node<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.children.is_empty() {
|
if !self.children.is_empty() {
|
||||||
let padded_bounds = RectF::from_points(
|
|
||||||
margined_bounds.origin() + vec2f(layout.padding.left, layout.padding.top),
|
|
||||||
margined_bounds.lower_right() - vec2f(layout.padding.right, layout.padding.bottom),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Account for padding first.
|
// Account for padding first.
|
||||||
let padding: Edges<f32> = todo!(); // &self.style.padding.to_pixels(rem_size);
|
let borders = &self.style.borders;
|
||||||
let padded_bounds = RectF::from_points(
|
let padded_bounds = RectF::from_points(
|
||||||
margined_bounds.origin() + vec2f(padding.left, padding.top),
|
margined_bounds.origin()
|
||||||
margined_bounds.lower_right() - vec2f(padding.right, padding.top),
|
+ vec2f(
|
||||||
|
borders.left_width() + layout.padding.left,
|
||||||
|
borders.top_width() + layout.padding.top,
|
||||||
|
),
|
||||||
|
margined_bounds.lower_right()
|
||||||
|
- vec2f(
|
||||||
|
layout.padding.right + borders.right_width(),
|
||||||
|
layout.padding.bottom + borders.bottom_width(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
match self.style.axis {
|
if let Some(axis) = self.style.axis.to_2d() {
|
||||||
Axis3d::X => self.paint_2d_children(
|
self.paint_children_xy(scene, axis, padded_bounds, visible_bounds, layout, view, cx)
|
||||||
scene,
|
} else {
|
||||||
Axis2d::X,
|
todo!();
|
||||||
padded_bounds,
|
|
||||||
visible_bounds,
|
|
||||||
layout,
|
|
||||||
view,
|
|
||||||
cx,
|
|
||||||
),
|
|
||||||
Axis3d::Y => self.paint_2d_children(
|
|
||||||
scene,
|
|
||||||
Axis2d::Y,
|
|
||||||
padded_bounds,
|
|
||||||
visible_bounds,
|
|
||||||
layout,
|
|
||||||
view,
|
|
||||||
cx,
|
|
||||||
),
|
|
||||||
Axis3d::Z => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -631,7 +605,7 @@ pub struct NodeStyle {
|
||||||
text: OptionalTextStyle,
|
text: OptionalTextStyle,
|
||||||
opacity: f32,
|
opacity: f32,
|
||||||
fill: Fill,
|
fill: Fill,
|
||||||
borders: Border,
|
borders: Borders,
|
||||||
corner_radius: f32,
|
corner_radius: f32,
|
||||||
shadows: Vec<Shadow>,
|
shadows: Vec<Shadow>,
|
||||||
}
|
}
|
||||||
|
@ -673,7 +647,7 @@ struct Size<T> {
|
||||||
height: T,
|
height: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Size<T> {
|
impl<T: Copy> Size<T> {
|
||||||
fn get(&self, axis: Axis2d) -> T {
|
fn get(&self, axis: Axis2d) -> T {
|
||||||
match axis {
|
match axis {
|
||||||
Axis2d::X => self.width,
|
Axis2d::X => self.width,
|
||||||
|
@ -682,7 +656,7 @@ impl<T> Size<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Add<Output = T>> Size<Option<T>> {
|
impl<T: Copy + Add<Output = T>> Size<Option<T>> {
|
||||||
fn add_assign_optional(&mut self, rhs: Size<Option<T>>) {
|
fn add_assign_optional(&mut self, rhs: Size<Option<T>>) {
|
||||||
self.width = optional_add(self.width, rhs.width);
|
self.width = optional_add(self.width, rhs.width);
|
||||||
self.height = optional_add(self.height, rhs.height);
|
self.height = optional_add(self.height, rhs.height);
|
||||||
|
@ -843,7 +817,7 @@ impl Default for Fill {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
struct Border {
|
struct Borders {
|
||||||
color: Color,
|
color: Color,
|
||||||
width: f32,
|
width: f32,
|
||||||
top: bool,
|
top: bool,
|
||||||
|
@ -852,13 +826,45 @@ struct Border {
|
||||||
right: bool,
|
right: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Border {
|
impl Borders {
|
||||||
fn is_visible(&self) -> bool {
|
fn is_visible(&self) -> bool {
|
||||||
self.width > 0.
|
self.width > 0.
|
||||||
&& !self.color.is_fully_transparent()
|
&& !self.color.is_fully_transparent()
|
||||||
&& (self.top || self.bottom || self.left || self.right)
|
&& (self.top || self.bottom || self.left || self.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn top_width(&self) -> f32 {
|
||||||
|
if self.top {
|
||||||
|
self.width
|
||||||
|
} else {
|
||||||
|
0.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bottom_width(&self) -> f32 {
|
||||||
|
if self.bottom {
|
||||||
|
self.width
|
||||||
|
} else {
|
||||||
|
0.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn left_width(&self) -> f32 {
|
||||||
|
if self.left {
|
||||||
|
self.width
|
||||||
|
} else {
|
||||||
|
0.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn right_width(&self) -> f32 {
|
||||||
|
if self.right {
|
||||||
|
self.width
|
||||||
|
} else {
|
||||||
|
0.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn size(&self) -> Vector2F {
|
fn size(&self) -> Vector2F {
|
||||||
let width =
|
let width =
|
||||||
if self.left { self.width } else { 0. } + if self.right { self.width } else { 0. };
|
if self.left { self.width } else { 0. } + if self.right { self.width } else { 0. };
|
||||||
|
@ -1078,7 +1084,7 @@ pub fn text<V: View>(text: impl Into<Cow<'static, str>>) -> Node<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct NodeLayout {
|
pub struct NodeLayout {
|
||||||
content_size: Vector2F,
|
content_size: Vector2F,
|
||||||
margins: Edges<f32>,
|
margins: Edges<f32>,
|
||||||
padding: Edges<f32>,
|
padding: Edges<f32>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue