From 4a8527478df335c27bf1cd601676d82fb73e535f Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 6 Mar 2023 11:51:58 -0800 Subject: [PATCH] Add child item alignment to flex implementation Fix checkbox styling co-authored-by: Nathan --- crates/gpui/src/elements/flex.rs | 32 ++++++++++++++++++++++++- crates/theme/src/theme.rs | 2 ++ crates/welcome/src/welcome.rs | 16 +++++++++---- styles/src/styleTree/welcome.ts | 41 +++++++++++++++++++++----------- 4 files changed, 72 insertions(+), 19 deletions(-) diff --git a/crates/gpui/src/elements/flex.rs b/crates/gpui/src/elements/flex.rs index ce595222f3f8a3c2e95019f19f790114f05653fd..b1427269949d050c2972bd1096601c902bdbabce 100644 --- a/crates/gpui/src/elements/flex.rs +++ b/crates/gpui/src/elements/flex.rs @@ -22,6 +22,7 @@ pub struct Flex { axis: Axis, children: Vec, scroll_state: Option<(ElementStateHandle>, usize)>, + child_alignment: f32, } impl Flex { @@ -30,6 +31,7 @@ impl Flex { axis, children: Default::default(), scroll_state: None, + child_alignment: -1., } } @@ -41,6 +43,15 @@ impl Flex { 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( mut self, 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 { Axis::Horizontal => child_origin += vec2f(child.size().x(), 0.0), diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index ded5c54f832ba53cbcc9c4ab998ed38122b38631..9442f08d24704af9d4f2309aeadd512cb114e3f5 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -859,6 +859,8 @@ pub struct WelcomeStyle { #[derive(Clone, Deserialize, Default)] pub struct CheckboxStyle { + pub icon: String, + pub icon_color: Color, pub width: f32, pub height: f32, pub default: ContainerStyle, diff --git a/crates/welcome/src/welcome.rs b/crates/welcome/src/welcome.rs index 232fd1bcb732aeda9cdace32a48e303f2dd36e78..f787a6cf24b038f370a6344c031f78b4d8e9664d 100644 --- a/crates/welcome/src/welcome.rs +++ b/crates/welcome/src/welcome.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; use gpui::{ - elements::{Canvas, Empty, Flex, Image, Label, MouseEventHandler, ParentElement, Stack}, + elements::{Canvas, Empty, Flex, Image, Label, MouseEventHandler, ParentElement, Stack, Svg}, geometry::rect::RectF, Action, Element, ElementBox, Entity, MouseButton, MouseRegion, MutableAppContext, RenderContext, Subscription, View, ViewContext, @@ -104,6 +104,7 @@ impl View for WelcomePage { ) .boxed(), ]) + .align_children_center() .boxed(), Flex::row() .with_children([ @@ -119,9 +120,9 @@ impl View for WelcomePage { ) .boxed(), ]) + .align_children_center() .boxed(), ]) - .aligned() .boxed(), ) .boxed() @@ -177,8 +178,15 @@ impl WelcomePage { set_value: fn(&mut SettingsFileContent, checked: bool) -> (), ) -> ElementBox { MouseEventHandler::::new(0, cx, |state, _| { - Empty::new() - .constrained() + let indicator = if checked { + Svg::new(style.icon.clone()) + .with_color(style.icon_color) + .constrained() + } else { + Empty::new().constrained() + }; + + indicator .with_width(style.width) .with_height(style.height) .contained() diff --git a/styles/src/styleTree/welcome.ts b/styles/src/styleTree/welcome.ts index 114ff0b7df69e12a0229698c3232c995e1edde2f..02e3c11f914f1b15b8cdd190589147f242217b70 100644 --- a/styles/src/styleTree/welcome.ts +++ b/styles/src/styleTree/welcome.ts @@ -1,6 +1,6 @@ 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) { @@ -10,15 +10,18 @@ export default function welcome(colorScheme: ColorScheme) { let checkboxBase = { cornerRadius: 4, padding: { - left: 8, - right: 8, - top: 4, - bottom: 4, + left: 3, + right: 3, + top: 3, + bottom: 3, }, shadow: colorScheme.popoverShadow, border: border(layer), margin: { - left: -8, + left: 8, + right: 8, + top: 5, + bottom: 5 }, }; @@ -44,30 +47,40 @@ export default function welcome(colorScheme: ColorScheme) { }, }, checkbox: { - width: 9, - height: 9, + width: 12, + height: 12, + icon: "icons/check_12.svg", + iconColor: foreground(layer, "on"), default: { ...checkboxBase, - background: colorScheme.ramps.blue(0.5).hex(), + background: background(layer, "default"), + border: { + color: foreground(layer, "hovered"), + width: 1, + } }, checked: { ...checkboxBase, - background: colorScheme.ramps.red(0.5).hex(), + background: background(layer, "hovered"), + border: { + color: foreground(layer, "hovered"), + width: 1, + } }, hovered: { ...checkboxBase, - background: colorScheme.ramps.blue(0.5).hex(), + background: background(layer, "hovered"), border: { - color: colorScheme.ramps.green(0.5).hex(), + color: foreground(layer, "hovered"), width: 1, } }, hoveredAndChecked: { ...checkboxBase, - background: colorScheme.ramps.red(0.5).hex(), + background: background(layer, "hovered"), border: { - color: colorScheme.ramps.green(0.5).hex(), + color: foreground(layer, "hovered"), width: 1, } }