Cleanup first version impls (#132)

This commit is contained in:
Jason Lee 2024-08-11 14:46:55 +08:00 committed by GitHub
parent 8f71b807aa
commit bb6d8d8f60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 152 additions and 300 deletions

View file

@ -14,7 +14,7 @@ use ui::{
popover::Popover,
popup_menu::PopupMenu,
theme::{ActiveTheme, Theme},
Clickable as _, IconName, Sizable,
IconName, Sizable,
};
use crate::app_state::AppState;

View file

@ -9,7 +9,7 @@ use ui::{
h_flex,
prelude::FluentBuilder,
theme::ActiveTheme,
v_flex, Clickable, Disableable as _, Icon, IconName, Selectable as _, Sizable as _,
v_flex, Disableable as _, Icon, IconName, Selectable as _, Sizable as _,
};
use crate::section;

View file

@ -7,7 +7,7 @@ use ui::{
dropdown::{Dropdown, DropdownEvent, DropdownItem, SearchableVec},
h_flex,
theme::ActiveTheme,
v_flex, IconName, Selection, Sizable,
v_flex, IconName, Sizable,
};
struct Country {
@ -129,11 +129,6 @@ impl DropdownStory {
})
}
#[allow(unused)]
fn on_click(sel: &Selection, cx: &mut WindowContext) {
println!("Check value changed: {}", sel);
}
fn on_dropdown_event(
&mut self,
_: View<Dropdown<Vec<Country>>>,

View file

@ -10,7 +10,7 @@ use ui::{
h_flex,
input::{InputEvent, OtpInput, TextInput},
prelude::FluentBuilder as _,
v_flex, Clickable, FocusableCycle, IconName, Selection, Sizable,
v_flex, FocusableCycle, IconName, Sizable,
};
use crate::section;
@ -170,7 +170,7 @@ impl InputStory {
};
}
fn toggle_opt_masked(&mut self, _: &Selection, cx: &mut ViewContext<Self>) {
fn toggle_opt_masked(&mut self, _: &bool, cx: &mut ViewContext<Self>) {
self.otp_masked = !self.otp_masked;
self.otp_input
.update(cx, |input, cx| input.set_masked(self.otp_masked, cx));

View file

@ -12,7 +12,7 @@ use ui::{
h_flex,
list::{List, ListDelegate, ListItem},
theme::ActiveTheme as _,
v_flex, Clickable as _, Icon, IconName, StyledExt,
v_flex, Icon, IconName, StyledExt,
};
pub struct ListItemDeletegate {
@ -272,7 +272,11 @@ impl Render for PickerStory {
.occlude()
.w(px(450.))
.h(px(350.))
.elevation_3(cx)
.bg(cx.theme().popover)
.border_1()
.border_color(cx.theme().border)
.shadow_lg()
.rounded_lg()
.child(self.list.clone())
.on_mouse_down_out(cx.listener(|this, _, cx| {
this.open = false;

View file

@ -13,7 +13,7 @@ use ui::{
popup_menu::PopupMenuExt,
prelude::FluentBuilder,
switch::Switch,
v_flex, Clickable as _, IconName, Sizable,
v_flex, IconName, Sizable,
};
actions!(

View file

@ -10,7 +10,7 @@ use ui::{
progress::Progress,
skeleton::Skeleton,
slider::{Slider, SliderEvent},
v_flex, Clickable, IconName, Sizable,
v_flex, IconName, Sizable,
};
pub struct ProgressStory {

View file

@ -9,7 +9,7 @@ use ui::button::Button;
use ui::divider::Divider;
use ui::scroll::{Scrollbar, ScrollbarAxis, ScrollbarState};
use ui::theme::ActiveTheme;
use ui::{h_flex, v_flex, Clickable, StyledExt as _};
use ui::{h_flex, v_flex, StyledExt as _};
pub struct ScrollableStory {
scroll_handle: ScrollHandle,

View file

@ -9,7 +9,7 @@ use ui::{
label::Label,
table::{ColSort, Table, TableDelegate, TableEvent},
theme::ActiveTheme as _,
v_flex, Icon, IconName, Selectable, Selection,
v_flex, Icon, IconName, Selectable,
};
struct Customer {
@ -226,10 +226,18 @@ impl TableDelegate for CustomerTableDelegate {
}
fn col_sort(&self, col_ix: usize) -> Option<ColSort> {
if !self.col_sort {
return None;
}
self.columns.get(col_ix).and_then(|c| c.sort)
}
fn perform_sort(&mut self, col_ix: usize, sort: ColSort, _: &mut ViewContext<Table<Self>>) {
if !self.col_sort {
return;
}
if let Some(col) = self.columns.get_mut(col_ix) {
col.sort = Some(sort);
let asc = matches!(sort, ColSort::Ascending);
@ -328,34 +336,35 @@ impl TableStory {
Self { table }
}
fn toggle_loop_selection(&mut self, s: &Selection, cx: &mut ViewContext<Self>) {
fn toggle_loop_selection(&mut self, checked: &bool, cx: &mut ViewContext<Self>) {
let table = self.table.clone();
table.update(cx, |table, cx| {
table.delegate_mut().loop_selection = s.is_selected();
table.delegate_mut().loop_selection = *checked;
cx.notify();
});
}
fn toggle_col_resize(&mut self, s: &Selection, cx: &mut ViewContext<Self>) {
fn toggle_col_resize(&mut self, checked: &bool, cx: &mut ViewContext<Self>) {
let table = self.table.clone();
table.update(cx, |table, cx| {
table.delegate_mut().col_resize = s.is_selected();
table.delegate_mut().col_resize = *checked;
cx.notify();
});
}
fn toggle_col_order(&mut self, s: &Selection, cx: &mut ViewContext<Self>) {
fn toggle_col_order(&mut self, checked: &bool, cx: &mut ViewContext<Self>) {
let table = self.table.clone();
table.update(cx, |table, cx| {
table.delegate_mut().col_order = s.is_selected();
table.delegate_mut().col_order = *checked;
cx.notify();
});
}
fn toggle_col_sort(&mut self, s: &Selection, cx: &mut ViewContext<Self>) {
fn toggle_col_sort(&mut self, checked: &bool, cx: &mut ViewContext<Self>) {
let table = self.table.clone();
table.update(cx, |table, cx| {
table.delegate_mut().col_sort = s.is_selected();
println!("- toggle_col_sort: {}", checked);
table.delegate_mut().col_sort = *checked;
cx.notify();
});
}

View file

@ -11,28 +11,28 @@ use ui::{
label::Label,
link::Link,
radio::Radio,
v_flex, Clickable, Disableable as _, IconName, Selection, StyledExt,
v_flex, Disableable as _, IconName, StyledExt,
};
use crate::section;
pub struct TextStory {
check1: Selection,
check2: Selection,
check3: Selection,
select1: bool,
select2: bool,
check1: bool,
check2: bool,
check3: bool,
radio_check1: bool,
radio_check2: bool,
masked: bool,
}
impl TextStory {
pub(crate) fn new(_cx: &mut WindowContext) -> Self {
Self {
check1: Selection::Unselected,
check2: Selection::Indeterminate,
check3: Selection::Selected,
select1: false,
select2: true,
check1: false,
check2: false,
check3: true,
radio_check1: false,
radio_check2: true,
masked: false,
}
}
@ -42,8 +42,8 @@ impl TextStory {
}
#[allow(unused)]
fn on_click(sel: &Selection, cx: &mut WindowContext) {
println!("Check value changed: {}", sel);
fn on_click(checked: &bool, cx: &mut WindowContext) {
println!("Check value changed: {}", checked);
}
}
@ -122,7 +122,7 @@ impl Render for TextStory {
Checkbox::new("check1")
.checked(self.check1)
.on_click(cx.listener(|v, _, _| {
v.check1 = v.check1.inverse();
v.check1 = !v.check1;
})),
)
.child(
@ -130,7 +130,7 @@ impl Render for TextStory {
.checked(self.check2)
.label("Subscribe to newsletter")
.on_click(cx.listener(|v, _, _| {
v.check2 = v.check2.inverse();
v.check2 = !v.check2;
})),
)
.child(
@ -138,7 +138,7 @@ impl Render for TextStory {
.checked(self.check3)
.label("Remember me")
.on_click(cx.listener(|v, _, _| {
v.check3 = v.check3.inverse();
v.check3 = !v.check3;
})),
)
.child(
@ -158,21 +158,15 @@ impl Render for TextStory {
.child(
Checkbox::new("check3")
.label("Disabled Checked")
.checked(Selection::Selected)
.checked(true)
.disabled(true),
)
.child(
Checkbox::new("check3_1")
.label("Disabled Unchecked")
.checked(Selection::Unselected)
.checked(false)
.disabled(true),
)
.child(
Checkbox::new("check3_2")
.label("Disabled Indeterminate")
.checked(Selection::Indeterminate)
.disabled(true),
),
),
)
.child(
@ -183,30 +177,30 @@ impl Render for TextStory {
.items_start()
.child(
Radio::new("radio1")
.selected(self.select1)
.checked(self.radio_check1)
.on_click(cx.listener(|this, v, _cx| {
this.select1 = *v;
this.radio_check1 = *v;
})),
)
.child(
Radio::new("radio2")
.label("Radio")
.selected(self.select2)
.checked(self.radio_check2)
.on_click(cx.listener(|this, v, _cx| {
this.select2 = *v;
this.radio_check2 = *v;
})),
)
.child(
Radio::new("radio3")
.label("Disabled Radio")
.selected(true)
.checked(true)
.disabled(true),
)
.child(
div().w(px(200.)).child(
Radio::new("radio3")
.label("Warp: A long long long text radio label")
.selected(true)
.checked(true)
.disabled(true),
),
)

View file

@ -9,7 +9,7 @@ use ui::{
h_flex,
label::Label,
tooltip::Tooltip,
v_flex, Selection,
v_flex,
};
pub struct TooltipStory;
@ -51,11 +51,7 @@ impl Render for TooltipStory {
.child(
div()
.cursor(CursorStyle::PointingHand)
.child(
Checkbox::new("check")
.label("Remember me")
.checked(Selection::Selected),
)
.child(Checkbox::new("check").label("Remember me").checked(true))
.id("tooltip-4")
.tooltip(|cx| Tooltip::new("Checked!", cx)),
)

View file

@ -9,7 +9,7 @@ use ui::{
theme::ActiveTheme,
v_flex,
webview::WebView,
Clickable, IconName,
IconName,
};
pub struct WebViewStory {

View file

@ -1,9 +1,8 @@
use crate::{
h_flex,
indicator::Indicator,
styled_ext::Sizable,
theme::{ActiveTheme, Colorize as _},
Clickable, Disableable, Icon, Selectable, Size,
Disableable, Icon, Selectable, Sizable, Size,
};
use gpui::{
div, prelude::FluentBuilder as _, px, AnyElement, ClickEvent, Div, ElementId, FocusHandle,
@ -226,6 +225,11 @@ impl Button {
self.compact = true;
self
}
pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
self.on_click = Some(Box::new(handler));
self
}
}
impl Disableable for Button {
@ -242,13 +246,6 @@ impl Selectable for Button {
}
}
impl Clickable for Button {
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
self.on_click = Some(Box::new(handler));
self
}
}
impl Sizable for Button {
fn with_size(mut self, size: impl Into<Size>) -> Self {
self.size = size.into();

View file

@ -5,29 +5,25 @@ use gpui::{
};
use crate::{
disableable::Disableable,
selectable::{Selectable, Selection},
stack::{h_flex, v_flex},
h_flex,
theme::{ActiveTheme, Colorize as _},
IconName,
v_flex, Disableable, IconName, Selectable,
};
type OnClick = Box<dyn Fn(&Selection, &mut WindowContext) + 'static>;
#[derive(IntoElement)]
pub struct Checkbox {
id: ElementId,
checked: Selection,
checked: bool,
disabled: bool,
label: Option<SharedString>,
on_click: Option<OnClick>,
on_click: Option<Box<dyn Fn(&bool, &mut WindowContext) + 'static>>,
}
impl Checkbox {
pub fn new(id: impl Into<ElementId>) -> Self {
Self {
id: id.into(),
checked: Selection::Unselected,
checked: false,
disabled: false,
label: None,
on_click: None,
@ -39,12 +35,12 @@ impl Checkbox {
self
}
pub fn checked(mut self, checked: impl Into<Selection>) -> Self {
self.checked = checked.into();
pub fn checked(mut self, checked: bool) -> Self {
self.checked = checked;
self
}
pub fn on_click(mut self, handler: impl Fn(&Selection, &mut WindowContext) + 'static) -> Self {
pub fn on_click(mut self, handler: impl Fn(&bool, &mut WindowContext) + 'static) -> Self {
self.on_click = Some(Box::new(handler));
self
}
@ -59,11 +55,7 @@ impl Disableable for Checkbox {
impl Selectable for Checkbox {
fn selected(self, selected: bool) -> Self {
self.checked(if selected {
Selection::Selected
} else {
Selection::Unselected
})
self.checked(selected)
}
}
@ -96,7 +88,7 @@ impl RenderOnce for Checkbox {
.size_4()
.flex_shrink_0()
.map(|this| match self.checked {
Selection::Unselected => this.bg(theme.transparent),
false => this.bg(theme.transparent),
_ => this.bg(color),
})
.group_hover(group_id, |this| {
@ -114,8 +106,7 @@ impl RenderOnce for Checkbox {
.size_3()
.text_color(icon_color)
.map(|this| match self.checked {
Selection::Selected => this.path(IconName::Check.path()),
Selection::Indeterminate => this.path(IconName::Minus.path()),
true => this.path(IconName::Check.path()),
_ => this,
}),
),
@ -138,7 +129,8 @@ impl RenderOnce for Checkbox {
self.on_click.filter(|_| !self.disabled),
|this, on_click| {
this.on_click(move |_, cx| {
on_click(&self.checked.inverse(), cx);
let checked = !self.checked;
on_click(&checked, cx);
cx.refresh()
})
},

View file

@ -1,5 +0,0 @@
use gpui::{ClickEvent, WindowContext};
pub trait Clickable {
fn on_click(self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self;
}

View file

@ -3,7 +3,7 @@ use gpui::{
RenderOnce, SharedString, Styled, WindowContext,
};
use crate::{button::Button, h_flex, Clickable, IconName, Sizable};
use crate::{button::Button, h_flex, IconName, Sizable};
#[derive(IntoElement)]
pub struct Clipboard {

View file

@ -7,7 +7,7 @@ use gpui::{
Position, Stateful, Style, Styled as _, View, WindowContext,
};
use crate::{popup_menu::PopupMenu, theme::ActiveTheme as _, StyledExt as _};
use crate::{popup_menu::PopupMenu, theme::ActiveTheme};
pub fn init(_cx: &mut AppContext) {}
@ -128,10 +128,11 @@ impl Element for ContextMenu {
this.child(
div()
.elevation_2(cx)
.bg(cx.theme().popover)
.border_1()
.border_color(cx.theme().border)
.shadow_lg()
.rounded_lg()
.child(menu)
.on_mouse_down_out(move |_, cx| {
*open.borrow_mut() = false;

View file

@ -1,3 +0,0 @@
pub trait Disableable {
fn disabled(self, disabled: bool) -> Self;
}

View file

@ -46,7 +46,7 @@ impl RenderOnce for Divider {
self.base
.map(|this| match self.axis {
Axis::Vertical => this.v_flex().h_full(),
Axis::Vertical => this.flex().flex_row().items_center().h_full(),
Axis::Horizontal => this.h_flex().w_full(),
})
.child(

View file

@ -10,9 +10,8 @@ use crate::{
h_flex,
input::ClearButton,
list::{self, List, ListDelegate, ListItem},
styled_ext::StyleSized,
theme::ActiveTheme,
Clickable, Icon, IconName, Sizable, Size, StyledExt,
Icon, IconName, Sizable, Size, StyleSized, StyledExt,
};
actions!(dropdown, [Up, Down, Enter, Escape]);

View file

@ -1,4 +1,4 @@
use crate::{styled_ext::Sizable, theme::ActiveTheme, Size};
use crate::{theme::ActiveTheme, Sizable, Size};
use gpui::{
prelude::FluentBuilder as _, svg, AnyElement, Hsla, IntoElement, Render, RenderOnce,
SharedString, StyleRefinement, Styled, Svg, View, VisualContext, WindowContext,

View file

@ -9,10 +9,10 @@ use super::blink_cursor::BlinkCursor;
use super::history::History;
use super::ClearButton;
use crate::indicator::Indicator;
use crate::styled_ext::{Sizable, StyleSized};
use crate::theme::ActiveTheme;
use crate::StyledExt as _;
use crate::{event::InteractiveElementExt as _, Size};
use crate::{Clickable as _, StyledExt as _};
use crate::{Sizable, StyleSized};
use gpui::prelude::FluentBuilder as _;
use gpui::{
actions, div, fill, point, px, relative, rems, size, AnyElement, AppContext, Bounds,

View file

@ -17,7 +17,6 @@ pub enum TextAlign {
pub struct Label {
base: Div,
label: SharedString,
multiple_lines: bool,
align: TextAlign,
marked: bool,
}
@ -27,17 +26,11 @@ impl Label {
Self {
base: h_flex().line_height(rems(1.25)),
label: label.into(),
multiple_lines: true,
align: TextAlign::default(),
marked: false,
}
}
pub fn multiple_lines(mut self) -> Self {
self.multiple_lines = true;
self
}
pub fn text_align(mut self, align: TextAlign) -> Self {
self.align = align;
self
@ -74,11 +67,7 @@ const MASKED: &'static str = "•";
impl RenderOnce for Label {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let text = if !self.multiple_lines {
SharedString::from(self.label.replace('\n', ""))
} else {
self.label
};
let text = self.label;
let text_display = if self.marked {
MASKED.repeat(text.chars().count())

View file

@ -1,13 +1,9 @@
mod clickable;
mod colors;
mod disableable;
mod event;
mod focusable;
mod icon;
mod selectable;
mod stack;
mod styled_ext;
mod styled;
mod svg_img;
mod time;
@ -43,17 +39,14 @@ use std::ops::Deref;
// re-export
pub use wry;
pub use clickable::Clickable;
pub use disableable::Disableable;
pub use crate::Disableable;
pub use event::InteractiveElementExt;
pub use focusable::FocusableCycle;
pub use selectable::{Selectable, Selection};
pub use styled_ext::{Sizable, Size, StyledExt};
pub use styled::*;
pub use time::*;
pub use colors::*;
pub use icon::*;
pub use stack::*;
pub use svg_img::*;
rust_i18n::i18n!("locales", fallback = "en");

View file

@ -5,9 +5,7 @@ use gpui::{
};
use smallvec::SmallVec;
use crate::{
h_flex, styled_ext::Sizable as _, theme::ActiveTheme, Disableable, Icon, IconName, Selectable,
};
use crate::{h_flex, theme::ActiveTheme, Disableable, Icon, IconName, Selectable, Sizable as _};
#[derive(IntoElement)]
pub struct ListItem {

View file

@ -9,7 +9,7 @@ use gpui::{
};
use std::{cell::RefCell, rc::Rc};
use crate::{theme::ActiveTheme, Selectable, StyledExt as _};
use crate::{theme::ActiveTheme, Selectable};
actions!(popover, [Open, Dismiss]);
@ -247,10 +247,11 @@ impl<M: ManagedView> Element for Popover<M> {
div()
.size_full()
.occlude()
.elevation_2(cx)
.bg(bg_color)
.border_1()
.border_color(cx.theme().border)
.shadow_lg()
.rounded_lg()
.bg(bg_color)
.map(|this| match anchor {
AnchorCorner::TopLeft | AnchorCorner::TopRight => this.top_2(),
AnchorCorner::BottomLeft | AnchorCorner::BottomRight => {
@ -627,7 +628,8 @@ where
this.bg(cx.theme().popover)
.border_1()
.border_color(cx.theme().border)
.elevation_2(cx)
.shadow_lg()
.rounded_lg()
})
.bg(cx.theme().popover)
.child(self.view.clone())

View file

@ -8,8 +8,8 @@ use gpui::{
};
use crate::{
button::Button, h_flex, list::ListItem, popover::Popover, styled_ext::Sizable as _,
theme::ActiveTheme, v_flex, Icon, IconName, Selectable,
button::Button, h_flex, list::ListItem, popover::Popover, theme::ActiveTheme, v_flex, Icon,
IconName, Selectable, Sizable as _,
};
actions!(menu, [Confirm, Dismiss, SelectNext, SelectPrev]);

View file

@ -14,7 +14,7 @@ use crate::{
pub struct Radio {
id: ElementId,
label: Option<SharedString>,
selected: bool,
checked: bool,
disabled: bool,
on_click: Option<Box<dyn Fn(&bool, &mut WindowContext) + 'static>>,
}
@ -24,7 +24,7 @@ impl Radio {
Self {
id: id.into(),
label: None,
selected: false,
checked: false,
disabled: false,
on_click: None,
}
@ -35,8 +35,8 @@ impl Radio {
self
}
pub fn selected(mut self, selected: bool) -> Self {
self.selected = selected;
pub fn checked(mut self, checked: bool) -> Self {
self.checked = checked;
self
}
@ -73,7 +73,7 @@ impl RenderOnce for Radio {
.rounded_full()
.border_1()
.border_color(color)
.when(self.selected, |this| this.bg(color))
.when(self.checked, |this| this.bg(color))
.child(
svg()
.absolute()
@ -81,10 +81,10 @@ impl RenderOnce for Radio {
.left_px()
.size_3()
.text_color(color)
.when(self.selected, |this| {
.when(self.checked, |this| {
this.text_color(cx.theme().primary_foreground)
})
.map(|this| match self.selected {
.map(|this| match self.checked {
true => this.path(IconName::Check.path()),
false => this,
}),
@ -103,7 +103,7 @@ impl RenderOnce for Radio {
self.on_click.filter(|_| !self.disabled),
|this, on_click| {
this.on_click(move |_event, cx| {
on_click(&!self.selected, cx);
on_click(&!self.checked, cx);
})
},
)

View file

@ -6,7 +6,7 @@ use gpui::{
StatefulInteractiveElement, Styled, View, ViewContext, VisualContext as _, WindowContext,
};
use crate::{h_flex, styled_ext::AxisExt, theme::ActiveTheme, v_flex};
use crate::{h_flex, theme::ActiveTheme, v_flex, AxisExt};
#[derive(Clone, Render)]
pub struct DragPanel(pub (EntityId, usize, Axis));

View file

@ -1,57 +0,0 @@
use std::fmt::Display;
/// A trait for elements that can be selected.
///
/// Generally used to enable "toggle" or "active" behavior and styles on an element through the [`Selection`] status.
pub trait Selectable {
/// Sets whether the element is selected.
fn selected(self, selected: bool) -> Self;
}
/// Represents the selection status of an element.
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Selection {
/// The element is not selected.
#[default]
Unselected,
/// The selection state of the element is indeterminate.
Indeterminate,
/// The element is selected.
Selected,
}
impl From<bool> for Selection {
fn from(selected: bool) -> Self {
if selected {
Self::Selected
} else {
Self::Unselected
}
}
}
impl Display for Selection {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Unselected => write!(f, "Unselected"),
Self::Indeterminate => write!(f, "Indeterminate"),
Self::Selected => write!(f, "Selected"),
}
}
}
impl Selection {
/// Returns the inverse of the current selection status.
///
/// Indeterminate states become selected if inverted.
pub fn inverse(&self) -> Self {
match self {
Self::Unselected | Self::Indeterminate => Self::Selected,
Self::Selected => Self::Unselected,
}
}
pub fn is_selected(&self) -> bool {
matches!(self, Self::Selected)
}
}

View file

@ -1,19 +0,0 @@
use crate::StyledExt as _;
use gpui::{div, Div, Styled};
/// Horizontally stacks elements. Sets `flex()`, `flex_row()`, `items_center()`
#[track_caller]
pub fn h_flex() -> Div {
div().h_flex()
}
/// Vertically stacks elements. Sets `flex()`, `flex_col()`
#[track_caller]
pub fn v_flex() -> Div {
div().v_flex()
}
/// A horizontal divider. Sets `h_0.5()`, `bg()`, `bg_gray()`
pub fn span() -> Div {
div().w_auto()
}

View file

@ -3,53 +3,17 @@ use crate::{
theme::{ActiveTheme, Colorize},
};
use gpui::{
hsla, point, px, rems, AnyView, Axis, BoxShadow, Element, Fill, FocusHandle, Pixels, Styled,
WindowContext,
div, px, rems, AnyView, Axis, Div, Element, Fill, FocusHandle, Pixels, Styled, WindowContext,
};
use smallvec::{smallvec, SmallVec};
pub enum ElevationIndex {
Surface,
PopoverSurface,
ModalSurface,
/// Returns a `Div` as horizontal flex layout.
pub fn h_flex() -> Div {
div().h_flex()
}
impl ElevationIndex {
pub fn shadow(self) -> SmallVec<[BoxShadow; 2]> {
match self {
ElevationIndex::Surface => smallvec![],
ElevationIndex::PopoverSurface => smallvec![BoxShadow {
color: hsla(0., 0., 0., 0.12),
offset: point(px(0.), px(2.)),
blur_radius: px(3.),
spread_radius: px(0.),
}],
ElevationIndex::ModalSurface => smallvec![
BoxShadow {
color: hsla(0., 0., 0., 0.1),
offset: point(px(0.), px(4.)),
blur_radius: px(6.),
spread_radius: px(-1.),
},
BoxShadow {
color: hsla(0., 0., 0., 0.1),
offset: point(px(0.), px(2.)),
blur_radius: px(4.),
spread_radius: px(-2.),
}
],
}
}
}
fn elevated<E: Styled>(this: E, cx: &WindowContext, index: ElevationIndex) -> E {
this.bg(cx.theme().popover)
.rounded(px(8.))
.border_1()
.border_color(cx.theme().border)
.shadow(index.shadow())
/// Returns a `Div` as vertical flex layout.
pub fn v_flex() -> Div {
div().v_flex()
}
macro_rules! font_weight {
@ -63,35 +27,16 @@ macro_rules! font_weight {
/// Extends [`gpui::Styled`] with specific styling methods.
pub trait StyledExt: Styled + Sized {
/// Horizontally stacks elements.
///
/// Sets `flex()`, `flex_row()`, `items_center()`
/// Apply self into a horizontal flex layout.
fn h_flex(self) -> Self {
self.flex().flex_row().items_center()
}
/// Vertically stacks elements.
///
/// Sets `flex()`, `flex_col()`
/// Apply self into a vertical flex layout.
fn v_flex(self) -> Self {
self.flex().flex_col()
}
/// Located above the app background
fn elevation_1(self, cx: &WindowContext) -> Self {
elevated(self, cx, ElevationIndex::Surface)
}
/// Appear above most UI elements
fn elevation_2(self, cx: &WindowContext) -> Self {
elevated(self, cx, ElevationIndex::PopoverSurface)
}
// Above all other UI elements and are located above the wash layer
fn elevation_3(self, cx: &WindowContext) -> Self {
elevated(self, cx, ElevationIndex::ModalSurface)
}
/// Render a border with a width of 1px, color red
fn debug_red(self) -> Self {
if cfg!(debug_assertions) {
@ -227,6 +172,18 @@ impl From<Pixels> for Size {
}
}
/// A trait for defining element that can be selected.
pub trait Selectable: Sized {
/// Set the selected state of the element.
fn selected(self, selected: bool) -> Self;
}
/// A trait for defining element that can be disabled.
pub trait Disableable {
/// Set the disabled state of the element.
fn disabled(self, disabled: bool) -> Self;
}
/// A trait for setting the size of an element.
pub trait Sizable: Sized {
/// Set the ui::Size of this element.

View file

@ -1,7 +1,7 @@
use std::time::Duration;
use crate::{
stack::h_flex,
h_flex,
theme::{ActiveTheme, Colorize},
Disableable, Sizable, Size,
};

View file

@ -1,5 +1,5 @@
use crate::selectable::Selectable;
use crate::theme::{ActiveTheme, Colorize};
use crate::Selectable;
use gpui::prelude::FluentBuilder as _;
use gpui::{
div, AnyElement, Div, ElementId, InteractiveElement, IntoElement, ParentElement as _,

View file

@ -1,4 +1,4 @@
use crate::stack::h_flex;
use crate::h_flex;
use crate::theme::ActiveTheme;
use gpui::prelude::FluentBuilder as _;
use gpui::{

View file

@ -521,7 +521,7 @@ where
col_ix: usize,
cx: &mut ViewContext<Self>,
) -> Option<impl IntoElement> {
let sort = self.col_groups.get(col_ix).and_then(|g| g.sort);
let sort = self.delegate().col_sort(col_ix);
if sort.is_none() {
return None;
}

View file

@ -12,7 +12,7 @@ use crate::{
button::Button,
h_flex,
theme::{ActiveTheme, Colorize},
v_flex, Clickable, Disableable, IconName, Selectable,
v_flex, Disableable as _, IconName, Selectable,
};
use super::utils::days_in_month;

View file

@ -7,8 +7,8 @@ use gpui::{
use rust_i18n::t;
use crate::{
dropdown::Escape, h_flex, input::ClearButton, styled_ext::StyleSized as _,
theme::ActiveTheme as _, Clickable, Icon, IconName, Sizable, Size, StyledExt as _,
dropdown::Escape, h_flex, input::ClearButton, theme::ActiveTheme as _, Icon, IconName, Sizable,
Size, StyleSized as _, StyledExt as _,
};
use super::calendar::{Calendar, CalendarEvent, Date};
@ -223,7 +223,10 @@ impl Render for DatePicker {
.rounded_lg()
.p_3()
.w(px(popover_width))
.elevation_2(cx)
.border_1()
.border_color(cx.theme().border)
.shadow_lg()
.rounded_lg()
.on_mouse_up_out(
MouseButton::Left,
cx.listener(|view, _, cx| view.escape(&Escape, cx)),

View file

@ -3,7 +3,7 @@ use gpui::{
VisualContext, WindowContext,
};
use crate::{theme::ActiveTheme, StyledExt};
use crate::theme::ActiveTheme;
pub struct Tooltip {
text: SharedString,
@ -23,7 +23,10 @@ impl Render for Tooltip {
.m_3()
.bg(cx.theme().popover)
.text_color(cx.theme().popover_foreground)
.elevation_1(cx)
.bg(cx.theme().popover)
.border_1()
.border_color(cx.theme().border)
.shadow_md()
.rounded(px(6.))
.pt_1()
.pb_0p5()

View file

@ -8,7 +8,7 @@ use gpui::{
ViewContext, VisualContext, WindowContext,
};
use ui::{h_flex, label::Label, theme::ActiveTheme, v_flex, Icon, IconName, StyledExt};
use ui::{h_flex, label::Label, theme::ActiveTheme, v_flex, Icon, IconName};
use crate::Workspace;
@ -210,7 +210,11 @@ impl MessageNotification {
impl Render for MessageNotification {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_flex()
.elevation_3(cx)
.bg(cx.theme().popover)
.border_1()
.border_color(cx.theme().border)
.shadow_xl()
.rounded_xl()
.p_4()
.max_w_80()
.bg(cx.theme().background)