Add child item alignment to flex implementation

Fix checkbox styling

co-authored-by: Nathan <nathan@zed.dev>
This commit is contained in:
Mikayla Maki 2023-03-06 11:51:58 -08:00
parent 4c179875ab
commit 4a8527478d
4 changed files with 72 additions and 19 deletions

View file

@ -22,6 +22,7 @@ pub struct Flex {
axis: Axis, axis: Axis,
children: Vec<ElementBox>, children: Vec<ElementBox>,
scroll_state: Option<(ElementStateHandle<Rc<ScrollState>>, usize)>, scroll_state: Option<(ElementStateHandle<Rc<ScrollState>>, usize)>,
child_alignment: f32,
} }
impl Flex { impl Flex {
@ -30,6 +31,7 @@ impl Flex {
axis, axis,
children: Default::default(), children: Default::default(),
scroll_state: None, scroll_state: None,
child_alignment: -1.,
} }
} }
@ -41,6 +43,15 @@ impl Flex {
Self::new(Axis::Vertical) Self::new(Axis::Vertical)
} }
/// Render children centered relative to the cross-axis of the parent flex.
///
/// If this is a flex row, children will be centered vertically. If this is a
/// flex column, children will be centered horizontally.
pub fn align_children_center(mut self) -> Self {
self.child_alignment = 0.;
self
}
pub fn scrollable<Tag, V>( pub fn scrollable<Tag, V>(
mut self, mut self,
element_id: usize, element_id: usize,
@ -309,7 +320,26 @@ impl Element for Flex {
} }
} }
child.paint(child_origin, visible_bounds, cx); // We use the child_alignment f32 to determine a point along the cross axis of the
// overall flex element and each child. We then align these points. So 0 would center
// each child relative to the overall height/width of the flex. -1 puts children at
// the start. 1 puts children at the end.
let cross_axis = self.axis.invert();
let my_center = bounds.size().along(cross_axis) / 2.;
let my_target = my_center + my_center * self.child_alignment;
let child_center = child.size().along(cross_axis) / 2.;
let child_target = child_center + child_center * self.child_alignment;
let mut aligned_child_origin = child_origin;
match self.axis {
Axis::Horizontal => aligned_child_origin
.set_y(aligned_child_origin.y() - (child_target - my_target)),
Axis::Vertical => aligned_child_origin
.set_x(aligned_child_origin.x() - (child_target - my_target)),
}
child.paint(aligned_child_origin, visible_bounds, cx);
match self.axis { match self.axis {
Axis::Horizontal => child_origin += vec2f(child.size().x(), 0.0), Axis::Horizontal => child_origin += vec2f(child.size().x(), 0.0),

View file

@ -859,6 +859,8 @@ pub struct WelcomeStyle {
#[derive(Clone, Deserialize, Default)] #[derive(Clone, Deserialize, Default)]
pub struct CheckboxStyle { pub struct CheckboxStyle {
pub icon: String,
pub icon_color: Color,
pub width: f32, pub width: f32,
pub height: f32, pub height: f32,
pub default: ContainerStyle, pub default: ContainerStyle,

View file

@ -1,7 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use gpui::{ use gpui::{
elements::{Canvas, Empty, Flex, Image, Label, MouseEventHandler, ParentElement, Stack}, elements::{Canvas, Empty, Flex, Image, Label, MouseEventHandler, ParentElement, Stack, Svg},
geometry::rect::RectF, geometry::rect::RectF,
Action, Element, ElementBox, Entity, MouseButton, MouseRegion, MutableAppContext, Action, Element, ElementBox, Entity, MouseButton, MouseRegion, MutableAppContext,
RenderContext, Subscription, View, ViewContext, RenderContext, Subscription, View, ViewContext,
@ -104,6 +104,7 @@ impl View for WelcomePage {
) )
.boxed(), .boxed(),
]) ])
.align_children_center()
.boxed(), .boxed(),
Flex::row() Flex::row()
.with_children([ .with_children([
@ -119,9 +120,9 @@ impl View for WelcomePage {
) )
.boxed(), .boxed(),
]) ])
.align_children_center()
.boxed(), .boxed(),
]) ])
.aligned()
.boxed(), .boxed(),
) )
.boxed() .boxed()
@ -177,8 +178,15 @@ impl WelcomePage {
set_value: fn(&mut SettingsFileContent, checked: bool) -> (), set_value: fn(&mut SettingsFileContent, checked: bool) -> (),
) -> ElementBox { ) -> ElementBox {
MouseEventHandler::<T>::new(0, cx, |state, _| { MouseEventHandler::<T>::new(0, cx, |state, _| {
Empty::new() let indicator = if checked {
.constrained() Svg::new(style.icon.clone())
.with_color(style.icon_color)
.constrained()
} else {
Empty::new().constrained()
};
indicator
.with_width(style.width) .with_width(style.width)
.with_height(style.height) .with_height(style.height)
.contained() .contained()

View file

@ -1,6 +1,6 @@
import { ColorScheme } from "../themes/common/colorScheme"; import { ColorScheme } from "../themes/common/colorScheme";
import { border, background, text } from "./components"; import { border, background, foreground, text } from "./components";
export default function welcome(colorScheme: ColorScheme) { export default function welcome(colorScheme: ColorScheme) {
@ -10,15 +10,18 @@ export default function welcome(colorScheme: ColorScheme) {
let checkboxBase = { let checkboxBase = {
cornerRadius: 4, cornerRadius: 4,
padding: { padding: {
left: 8, left: 3,
right: 8, right: 3,
top: 4, top: 3,
bottom: 4, bottom: 3,
}, },
shadow: colorScheme.popoverShadow, shadow: colorScheme.popoverShadow,
border: border(layer), border: border(layer),
margin: { margin: {
left: -8, left: 8,
right: 8,
top: 5,
bottom: 5
}, },
}; };
@ -44,30 +47,40 @@ export default function welcome(colorScheme: ColorScheme) {
}, },
}, },
checkbox: { checkbox: {
width: 9, width: 12,
height: 9, height: 12,
icon: "icons/check_12.svg",
iconColor: foreground(layer, "on"),
default: { default: {
...checkboxBase, ...checkboxBase,
background: colorScheme.ramps.blue(0.5).hex(), background: background(layer, "default"),
border: {
color: foreground(layer, "hovered"),
width: 1,
}
}, },
checked: { checked: {
...checkboxBase, ...checkboxBase,
background: colorScheme.ramps.red(0.5).hex(), background: background(layer, "hovered"),
border: {
color: foreground(layer, "hovered"),
width: 1,
}
}, },
hovered: { hovered: {
...checkboxBase, ...checkboxBase,
background: colorScheme.ramps.blue(0.5).hex(), background: background(layer, "hovered"),
border: { border: {
color: colorScheme.ramps.green(0.5).hex(), color: foreground(layer, "hovered"),
width: 1, width: 1,
} }
}, },
hoveredAndChecked: { hoveredAndChecked: {
...checkboxBase, ...checkboxBase,
background: colorScheme.ramps.red(0.5).hex(), background: background(layer, "hovered"),
border: { border: {
color: colorScheme.ramps.green(0.5).hex(), color: foreground(layer, "hovered"),
width: 1, width: 1,
} }
} }