Split out Interactive<T> into Toggle<T> and Interactive<T>
This commit is contained in:
parent
6ed86781b2
commit
e92015b12f
35 changed files with 223 additions and 144 deletions
|
@ -1233,19 +1233,19 @@ impl AssistantEditor {
|
||||||
cx,
|
cx,
|
||||||
|state, _| match message.role {
|
|state, _| match message.role {
|
||||||
Role::User => {
|
Role::User => {
|
||||||
let style = style.user_sender.style_for(state, false);
|
let style = style.user_sender.style_for(state);
|
||||||
Label::new("You", style.text.clone())
|
Label::new("You", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
}
|
}
|
||||||
Role::Assistant => {
|
Role::Assistant => {
|
||||||
let style = style.assistant_sender.style_for(state, false);
|
let style = style.assistant_sender.style_for(state);
|
||||||
Label::new("Assistant", style.text.clone())
|
Label::new("Assistant", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
}
|
}
|
||||||
Role::System => {
|
Role::System => {
|
||||||
let style = style.system_sender.style_for(state, false);
|
let style = style.system_sender.style_for(state);
|
||||||
Label::new("System", style.text.clone())
|
Label::new("System", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -1484,7 +1484,7 @@ impl View for AssistantEditor {
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Model, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<Model, _>::new(0, cx, |state, _| {
|
||||||
let style = theme.model.style_for(state, false);
|
let style = theme.model.style_for(state);
|
||||||
Label::new(model, style.text.clone())
|
Label::new(model, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl View for UpdateNotification {
|
||||||
)
|
)
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
||||||
let style = theme.dismiss_button.style_for(state, false);
|
let style = theme.dismiss_button.style_for(state);
|
||||||
Svg::new("icons/x_mark_8.svg")
|
Svg::new("icons/x_mark_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -74,7 +74,7 @@ impl View for UpdateNotification {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.with_child({
|
.with_child({
|
||||||
let style = theme.action_message.style_for(state, false);
|
let style = theme.action_message.style_for(state);
|
||||||
Text::new("View the release notes", style.text.clone())
|
Text::new("View the release notes", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -83,7 +83,7 @@ impl View for Breadcrumbs {
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEventHandler::<Breadcrumbs, Breadcrumbs>::new(0, cx, |state, _| {
|
MouseEventHandler::<Breadcrumbs, Breadcrumbs>::new(0, cx, |state, _| {
|
||||||
let style = style.style_for(state, false);
|
let style = style.style_for(state);
|
||||||
crumbs.with_style(style.container)
|
crumbs.with_style(style.container)
|
||||||
})
|
})
|
||||||
.on_click(MouseButton::Left, |_, this, cx| {
|
.on_click(MouseButton::Left, |_, this, cx| {
|
||||||
|
|
|
@ -299,7 +299,7 @@ impl CollabTitlebarItem {
|
||||||
pub fn toggle_user_menu(&mut self, _: &ToggleUserMenu, cx: &mut ViewContext<Self>) {
|
pub fn toggle_user_menu(&mut self, _: &ToggleUserMenu, cx: &mut ViewContext<Self>) {
|
||||||
let theme = theme::current(cx).clone();
|
let theme = theme::current(cx).clone();
|
||||||
let avatar_style = theme.workspace.titlebar.leader_avatar.clone();
|
let avatar_style = theme.workspace.titlebar.leader_avatar.clone();
|
||||||
let item_style = theme.context_menu.item.disabled_style().clone();
|
let item_style = theme.context_menu.item.off_state().disabled_style().clone();
|
||||||
self.user_menu.update(cx, |user_menu, cx| {
|
self.user_menu.update(cx, |user_menu, cx| {
|
||||||
let items = if let Some(user) = self.user_store.read(cx).current_user() {
|
let items = if let Some(user) = self.user_store.read(cx).current_user() {
|
||||||
vec![
|
vec![
|
||||||
|
@ -361,8 +361,20 @@ impl CollabTitlebarItem {
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(titlebar.toggle_contacts_badge)
|
.with_style(titlebar.toggle_contacts_badge)
|
||||||
.contained()
|
.contained()
|
||||||
.with_margin_left(titlebar.toggle_contacts_button.default.icon_width)
|
.with_margin_left(
|
||||||
.with_margin_top(titlebar.toggle_contacts_button.default.icon_width)
|
titlebar
|
||||||
|
.toggle_contacts_button
|
||||||
|
.off_state()
|
||||||
|
.default
|
||||||
|
.icon_width,
|
||||||
|
)
|
||||||
|
.with_margin_top(
|
||||||
|
titlebar
|
||||||
|
.toggle_contacts_button
|
||||||
|
.off_state()
|
||||||
|
.default
|
||||||
|
.icon_width,
|
||||||
|
)
|
||||||
.aligned(),
|
.aligned(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -372,7 +384,8 @@ impl CollabTitlebarItem {
|
||||||
MouseEventHandler::<ToggleContactsMenu, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<ToggleContactsMenu, Self>::new(0, cx, |state, _| {
|
||||||
let style = titlebar
|
let style = titlebar
|
||||||
.toggle_contacts_button
|
.toggle_contacts_button
|
||||||
.style_for(state, self.contacts_popover.is_some());
|
.in_state(self.contacts_popover.is_some())
|
||||||
|
.style_for(state);
|
||||||
Svg::new("icons/user_plus_16.svg")
|
Svg::new("icons/user_plus_16.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -419,7 +432,7 @@ impl CollabTitlebarItem {
|
||||||
|
|
||||||
let titlebar = &theme.workspace.titlebar;
|
let titlebar = &theme.workspace.titlebar;
|
||||||
MouseEventHandler::<ToggleScreenSharing, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<ToggleScreenSharing, Self>::new(0, cx, |state, _| {
|
||||||
let style = titlebar.call_control.style_for(state, false);
|
let style = titlebar.call_control.style_for(state);
|
||||||
Svg::new(icon)
|
Svg::new(icon)
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -473,7 +486,7 @@ impl CollabTitlebarItem {
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<ShareUnshare, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<ShareUnshare, Self>::new(0, cx, |state, _| {
|
||||||
//TODO: Ensure this button has consistent width for both text variations
|
//TODO: Ensure this button has consistent width for both text variations
|
||||||
let style = titlebar.share_button.style_for(state, false);
|
let style = titlebar.share_button.style_for(state);
|
||||||
Label::new(label, style.text.clone())
|
Label::new(label, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -511,7 +524,7 @@ impl CollabTitlebarItem {
|
||||||
Stack::new()
|
Stack::new()
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<ToggleUserMenu, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<ToggleUserMenu, Self>::new(0, cx, |state, _| {
|
||||||
let style = titlebar.call_control.style_for(state, false);
|
let style = titlebar.call_control.style_for(state);
|
||||||
Svg::new("icons/ellipsis_14.svg")
|
Svg::new("icons/ellipsis_14.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -549,7 +562,7 @@ impl CollabTitlebarItem {
|
||||||
fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||||
let titlebar = &theme.workspace.titlebar;
|
let titlebar = &theme.workspace.titlebar;
|
||||||
MouseEventHandler::<SignIn, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<SignIn, Self>::new(0, cx, |state, _| {
|
||||||
let style = titlebar.sign_in_prompt.style_for(state, false);
|
let style = titlebar.sign_in_prompt.style_for(state);
|
||||||
Label::new("Sign In", style.text.clone())
|
Label::new("Sign In", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -117,7 +117,8 @@ impl PickerDelegate for ContactFinderDelegate {
|
||||||
.contact_finder
|
.contact_finder
|
||||||
.picker
|
.picker
|
||||||
.item
|
.item
|
||||||
.style_for(mouse_state, selected);
|
.in_state(selected)
|
||||||
|
.style_for(mouse_state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_children(user.avatar.clone().map(|avatar| {
|
.with_children(user.avatar.clone().map(|avatar| {
|
||||||
Image::from_data(avatar)
|
Image::from_data(avatar)
|
||||||
|
|
|
@ -774,7 +774,8 @@ impl ContactList {
|
||||||
.with_style(
|
.with_style(
|
||||||
*theme
|
*theme
|
||||||
.contact_row
|
.contact_row
|
||||||
.style_for(&mut Default::default(), is_selected),
|
.in_state(is_selected)
|
||||||
|
.style_for(&mut Default::default()),
|
||||||
)
|
)
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
|
@ -797,7 +798,7 @@ impl ContactList {
|
||||||
.width
|
.width
|
||||||
.or(theme.contact_avatar.height)
|
.or(theme.contact_avatar.height)
|
||||||
.unwrap_or(0.);
|
.unwrap_or(0.);
|
||||||
let row = &theme.project_row.default;
|
let row = &theme.project_row.off_state().default;
|
||||||
let tree_branch = theme.tree_branch;
|
let tree_branch = theme.tree_branch;
|
||||||
let line_height = row.name.text.line_height(font_cache);
|
let line_height = row.name.text.line_height(font_cache);
|
||||||
let cap_height = row.name.text.cap_height(font_cache);
|
let cap_height = row.name.text.cap_height(font_cache);
|
||||||
|
@ -810,8 +811,11 @@ impl ContactList {
|
||||||
};
|
};
|
||||||
|
|
||||||
MouseEventHandler::<JoinProject, Self>::new(project_id as usize, cx, |mouse_state, _| {
|
MouseEventHandler::<JoinProject, Self>::new(project_id as usize, cx, |mouse_state, _| {
|
||||||
let tree_branch = *tree_branch.style_for(mouse_state, is_selected);
|
let tree_branch = *tree_branch.in_state(is_selected).style_for(mouse_state);
|
||||||
let row = theme.project_row.style_for(mouse_state, is_selected);
|
let row = theme
|
||||||
|
.project_row
|
||||||
|
.in_state(is_selected)
|
||||||
|
.style_for(mouse_state);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
@ -893,7 +897,7 @@ impl ContactList {
|
||||||
.width
|
.width
|
||||||
.or(theme.contact_avatar.height)
|
.or(theme.contact_avatar.height)
|
||||||
.unwrap_or(0.);
|
.unwrap_or(0.);
|
||||||
let row = &theme.project_row.default;
|
let row = &theme.project_row.off_state().default;
|
||||||
let tree_branch = theme.tree_branch;
|
let tree_branch = theme.tree_branch;
|
||||||
let line_height = row.name.text.line_height(font_cache);
|
let line_height = row.name.text.line_height(font_cache);
|
||||||
let cap_height = row.name.text.cap_height(font_cache);
|
let cap_height = row.name.text.cap_height(font_cache);
|
||||||
|
@ -904,8 +908,11 @@ impl ContactList {
|
||||||
peer_id.as_u64() as usize,
|
peer_id.as_u64() as usize,
|
||||||
cx,
|
cx,
|
||||||
|mouse_state, _| {
|
|mouse_state, _| {
|
||||||
let tree_branch = *tree_branch.style_for(mouse_state, is_selected);
|
let tree_branch = *tree_branch.in_state(is_selected).style_for(mouse_state);
|
||||||
let row = theme.project_row.style_for(mouse_state, is_selected);
|
let row = theme
|
||||||
|
.project_row
|
||||||
|
.in_state(is_selected)
|
||||||
|
.style_for(mouse_state);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
@ -989,7 +996,8 @@ impl ContactList {
|
||||||
|
|
||||||
let header_style = theme
|
let header_style = theme
|
||||||
.header_row
|
.header_row
|
||||||
.style_for(&mut Default::default(), is_selected);
|
.in_state(is_selected)
|
||||||
|
.style_for(&mut Default::default());
|
||||||
let text = match section {
|
let text = match section {
|
||||||
Section::ActiveCall => "Collaborators",
|
Section::ActiveCall => "Collaborators",
|
||||||
Section::Requests => "Contact Requests",
|
Section::Requests => "Contact Requests",
|
||||||
|
@ -999,7 +1007,7 @@ impl ContactList {
|
||||||
let leave_call = if section == Section::ActiveCall {
|
let leave_call = if section == Section::ActiveCall {
|
||||||
Some(
|
Some(
|
||||||
MouseEventHandler::<LeaveCallContactList, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<LeaveCallContactList, Self>::new(0, cx, |state, _| {
|
||||||
let style = theme.leave_call.style_for(state, false);
|
let style = theme.leave_call.style_for(state);
|
||||||
Label::new("Leave Call", style.text.clone())
|
Label::new("Leave Call", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -1110,8 +1118,7 @@ impl ContactList {
|
||||||
contact.user.id as usize,
|
contact.user.id as usize,
|
||||||
cx,
|
cx,
|
||||||
|mouse_state, _| {
|
|mouse_state, _| {
|
||||||
let button_style =
|
let button_style = theme.contact_button.style_for(mouse_state);
|
||||||
theme.contact_button.style_for(mouse_state, false);
|
|
||||||
render_icon_button(button_style, "icons/x_mark_8.svg")
|
render_icon_button(button_style, "icons/x_mark_8.svg")
|
||||||
.aligned()
|
.aligned()
|
||||||
.flex_float()
|
.flex_float()
|
||||||
|
@ -1146,7 +1153,8 @@ impl ContactList {
|
||||||
.with_style(
|
.with_style(
|
||||||
*theme
|
*theme
|
||||||
.contact_row
|
.contact_row
|
||||||
.style_for(&mut Default::default(), is_selected),
|
.in_state(is_selected)
|
||||||
|
.style_for(&mut Default::default()),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||||
|
@ -1204,7 +1212,7 @@ impl ContactList {
|
||||||
let button_style = if is_contact_request_pending {
|
let button_style = if is_contact_request_pending {
|
||||||
&theme.disabled_button
|
&theme.disabled_button
|
||||||
} else {
|
} else {
|
||||||
theme.contact_button.style_for(mouse_state, false)
|
theme.contact_button.style_for(mouse_state)
|
||||||
};
|
};
|
||||||
render_icon_button(button_style, "icons/x_mark_8.svg").aligned()
|
render_icon_button(button_style, "icons/x_mark_8.svg").aligned()
|
||||||
})
|
})
|
||||||
|
@ -1227,7 +1235,7 @@ impl ContactList {
|
||||||
let button_style = if is_contact_request_pending {
|
let button_style = if is_contact_request_pending {
|
||||||
&theme.disabled_button
|
&theme.disabled_button
|
||||||
} else {
|
} else {
|
||||||
theme.contact_button.style_for(mouse_state, false)
|
theme.contact_button.style_for(mouse_state)
|
||||||
};
|
};
|
||||||
render_icon_button(button_style, "icons/check_8.svg")
|
render_icon_button(button_style, "icons/check_8.svg")
|
||||||
.aligned()
|
.aligned()
|
||||||
|
@ -1250,7 +1258,7 @@ impl ContactList {
|
||||||
let button_style = if is_contact_request_pending {
|
let button_style = if is_contact_request_pending {
|
||||||
&theme.disabled_button
|
&theme.disabled_button
|
||||||
} else {
|
} else {
|
||||||
theme.contact_button.style_for(mouse_state, false)
|
theme.contact_button.style_for(mouse_state)
|
||||||
};
|
};
|
||||||
render_icon_button(button_style, "icons/x_mark_8.svg")
|
render_icon_button(button_style, "icons/x_mark_8.svg")
|
||||||
.aligned()
|
.aligned()
|
||||||
|
@ -1277,7 +1285,8 @@ impl ContactList {
|
||||||
.with_style(
|
.with_style(
|
||||||
*theme
|
*theme
|
||||||
.contact_row
|
.contact_row
|
||||||
.style_for(&mut Default::default(), is_selected),
|
.in_state(is_selected)
|
||||||
|
.style_for(&mut Default::default()),
|
||||||
)
|
)
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ where
|
||||||
)
|
)
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Dismiss, V>::new(user.id as usize, cx, |state, _| {
|
MouseEventHandler::<Dismiss, V>::new(user.id as usize, cx, |state, _| {
|
||||||
let style = theme.dismiss_button.style_for(state, false);
|
let style = theme.dismiss_button.style_for(state);
|
||||||
Svg::new("icons/x_mark_8.svg")
|
Svg::new("icons/x_mark_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -93,7 +93,7 @@ where
|
||||||
.with_children(buttons.into_iter().enumerate().map(
|
.with_children(buttons.into_iter().enumerate().map(
|
||||||
|(ix, (message, handler))| {
|
|(ix, (message, handler))| {
|
||||||
MouseEventHandler::<Button, V>::new(ix, cx, |state, _| {
|
MouseEventHandler::<Button, V>::new(ix, cx, |state, _| {
|
||||||
let button = theme.button.style_for(state, false);
|
let button = theme.button.style_for(state);
|
||||||
Label::new(message, button.text.clone())
|
Label::new(message, button.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(button.container)
|
.with_style(button.container)
|
||||||
|
|
|
@ -185,8 +185,12 @@ impl PickerDelegate for CommandPaletteDelegate {
|
||||||
let mat = &self.matches[ix];
|
let mat = &self.matches[ix];
|
||||||
let command = &self.actions[mat.candidate_id];
|
let command = &self.actions[mat.candidate_id];
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
let key_style = &theme.command_palette.key.style_for(mouse_state, selected);
|
let key_style = &theme
|
||||||
|
.command_palette
|
||||||
|
.key
|
||||||
|
.in_state(selected)
|
||||||
|
.style_for(mouse_state);
|
||||||
let keystroke_spacing = theme.command_palette.keystroke_spacing;
|
let keystroke_spacing = theme.command_palette.keystroke_spacing;
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
|
|
|
@ -9,6 +9,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use menu::*;
|
use menu::*;
|
||||||
use std::{any::TypeId, borrow::Cow, sync::Arc, time::Duration};
|
use std::{any::TypeId, borrow::Cow, sync::Arc, time::Duration};
|
||||||
|
use theme::ToggleState;
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
cx.add_action(ContextMenu::select_first);
|
cx.add_action(ContextMenu::select_first);
|
||||||
|
@ -328,10 +329,13 @@ impl ContextMenu {
|
||||||
Flex::column().with_children(self.items.iter().enumerate().map(|(ix, item)| {
|
Flex::column().with_children(self.items.iter().enumerate().map(|(ix, item)| {
|
||||||
match item {
|
match item {
|
||||||
ContextMenuItem::Item { label, .. } => {
|
ContextMenuItem::Item { label, .. } => {
|
||||||
let style = style.item.style_for(
|
let toggle_state = if Some(ix) == self.selected_index {
|
||||||
&mut Default::default(),
|
ToggleState::On
|
||||||
Some(ix) == self.selected_index,
|
} else {
|
||||||
);
|
ToggleState::Off
|
||||||
|
};
|
||||||
|
let style = style.item.in_state(toggle_state);
|
||||||
|
let style = style.style_for(&mut Default::default());
|
||||||
|
|
||||||
match label {
|
match label {
|
||||||
ContextMenuItemLabel::String(label) => {
|
ContextMenuItemLabel::String(label) => {
|
||||||
|
@ -363,10 +367,13 @@ impl ContextMenu {
|
||||||
.with_children(self.items.iter().enumerate().map(|(ix, item)| {
|
.with_children(self.items.iter().enumerate().map(|(ix, item)| {
|
||||||
match item {
|
match item {
|
||||||
ContextMenuItem::Item { action, .. } => {
|
ContextMenuItem::Item { action, .. } => {
|
||||||
let style = style.item.style_for(
|
let toggle_state = if Some(ix) == self.selected_index {
|
||||||
&mut Default::default(),
|
ToggleState::On
|
||||||
Some(ix) == self.selected_index,
|
} else {
|
||||||
);
|
ToggleState::Off
|
||||||
|
};
|
||||||
|
let style = style.item.in_state(toggle_state);
|
||||||
|
let style = style.style_for(&mut Default::default());
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
ContextMenuItemAction::Action(action) => KeystrokeLabel::new(
|
ContextMenuItemAction::Action(action) => KeystrokeLabel::new(
|
||||||
|
@ -412,8 +419,13 @@ impl ContextMenu {
|
||||||
let action = action.clone();
|
let action = action.clone();
|
||||||
let view_id = self.parent_view_id;
|
let view_id = self.parent_view_id;
|
||||||
MouseEventHandler::<MenuItem, ContextMenu>::new(ix, cx, |state, _| {
|
MouseEventHandler::<MenuItem, ContextMenu>::new(ix, cx, |state, _| {
|
||||||
let style =
|
let toggle_state = if Some(ix) == self.selected_index {
|
||||||
style.item.style_for(state, Some(ix) == self.selected_index);
|
ToggleState::On
|
||||||
|
} else {
|
||||||
|
ToggleState::Off
|
||||||
|
};
|
||||||
|
let style = style.item.in_state(toggle_state);
|
||||||
|
let style = style.style_for(state);
|
||||||
let keystroke = match &action {
|
let keystroke = match &action {
|
||||||
ContextMenuItemAction::Action(action) => Some(
|
ContextMenuItemAction::Action(action) => Some(
|
||||||
KeystrokeLabel::new(
|
KeystrokeLabel::new(
|
||||||
|
|
|
@ -127,16 +127,16 @@ impl CopilotCodeVerification {
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(
|
Label::new(
|
||||||
if copied { "Copied!" } else { "Copy" },
|
if copied { "Copied!" } else { "Copy" },
|
||||||
device_code_style.cta.style_for(state, false).text.clone(),
|
device_code_style.cta.style_for(state).text.clone(),
|
||||||
)
|
)
|
||||||
.aligned()
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(*device_code_style.right_container.style_for(state, false))
|
.with_style(*device_code_style.right_container.style_for(state))
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_width(device_code_style.right),
|
.with_width(device_code_style.right),
|
||||||
)
|
)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(device_code_style.cta.style_for(state, false).container)
|
.with_style(device_code_style.cta.style_for(state).container)
|
||||||
})
|
})
|
||||||
.on_click(gpui::platform::MouseButton::Left, {
|
.on_click(gpui::platform::MouseButton::Left, {
|
||||||
let user_code = data.user_code.clone();
|
let user_code = data.user_code.clone();
|
||||||
|
|
|
@ -71,7 +71,8 @@ impl View for CopilotButton {
|
||||||
.status_bar
|
.status_bar
|
||||||
.panel_buttons
|
.panel_buttons
|
||||||
.button
|
.button
|
||||||
.style_for(state, active);
|
.in_state(active)
|
||||||
|
.style_for(state);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
@ -255,7 +256,7 @@ impl CopilotButton {
|
||||||
move |state: &mut MouseState, style: &theme::ContextMenuItem| {
|
move |state: &mut MouseState, style: &theme::ContextMenuItem| {
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(Label::new("Copilot Settings", style.label.clone()))
|
.with_child(Label::new("Copilot Settings", style.label.clone()))
|
||||||
.with_child(theme::ui::icon(icon_style.style_for(state, false)))
|
.with_child(theme::ui::icon(icon_style.style_for(state)))
|
||||||
.align_children_center()
|
.align_children_center()
|
||||||
.into_any()
|
.into_any()
|
||||||
},
|
},
|
||||||
|
|
|
@ -100,7 +100,7 @@ impl View for DiagnosticIndicator {
|
||||||
.workspace
|
.workspace
|
||||||
.status_bar
|
.status_bar
|
||||||
.diagnostic_summary
|
.diagnostic_summary
|
||||||
.style_for(state, false);
|
.style_for(state);
|
||||||
|
|
||||||
let mut summary_row = Flex::row();
|
let mut summary_row = Flex::row();
|
||||||
if self.summary.error_count > 0 {
|
if self.summary.error_count > 0 {
|
||||||
|
@ -198,7 +198,7 @@ impl View for DiagnosticIndicator {
|
||||||
MouseEventHandler::<Message, _>::new(1, cx, |state, _| {
|
MouseEventHandler::<Message, _>::new(1, cx, |state, _| {
|
||||||
Label::new(
|
Label::new(
|
||||||
diagnostic.message.split('\n').next().unwrap().to_string(),
|
diagnostic.message.split('\n').next().unwrap().to_string(),
|
||||||
message_style.style_for(state, false).text.clone(),
|
message_style.style_for(state).text.clone(),
|
||||||
)
|
)
|
||||||
.aligned()
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
|
|
|
@ -3320,15 +3320,21 @@ impl Editor {
|
||||||
pub fn render_code_actions_indicator(
|
pub fn render_code_actions_indicator(
|
||||||
&self,
|
&self,
|
||||||
style: &EditorStyle,
|
style: &EditorStyle,
|
||||||
active: bool,
|
is_active: bool,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Option<AnyElement<Self>> {
|
) -> Option<AnyElement<Self>> {
|
||||||
if self.available_code_actions.is_some() {
|
if self.available_code_actions.is_some() {
|
||||||
enum CodeActions {}
|
enum CodeActions {}
|
||||||
Some(
|
Some(
|
||||||
MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
|
||||||
Svg::new("icons/bolt_8.svg")
|
Svg::new("icons/bolt_8.svg").with_color(
|
||||||
.with_color(style.code_actions.indicator.style_for(state, active).color)
|
style
|
||||||
|
.code_actions
|
||||||
|
.indicator
|
||||||
|
.in_state(is_active)
|
||||||
|
.style_for(state)
|
||||||
|
.color,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.with_padding(Padding::uniform(3.))
|
.with_padding(Padding::uniform(3.))
|
||||||
|
@ -3378,10 +3384,8 @@ impl Editor {
|
||||||
.with_color(
|
.with_color(
|
||||||
style
|
style
|
||||||
.indicator
|
.indicator
|
||||||
.style_for(
|
.in_state(fold_status == FoldStatus::Folded)
|
||||||
mouse_state,
|
.style_for(mouse_state)
|
||||||
fold_status == FoldStatus::Folded,
|
|
||||||
)
|
|
||||||
.color,
|
.color,
|
||||||
)
|
)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
|
|
@ -2090,7 +2090,7 @@ impl Element<Editor> for EditorElement {
|
||||||
.folds
|
.folds
|
||||||
.ellipses
|
.ellipses
|
||||||
.background
|
.background
|
||||||
.style_for(&mut cx.mouse_state::<FoldMarkers>(id as usize), false)
|
.style_for(&mut cx.mouse_state::<FoldMarkers>(id as usize))
|
||||||
.color;
|
.color;
|
||||||
|
|
||||||
(id, fold, color)
|
(id, fold, color)
|
||||||
|
|
|
@ -41,7 +41,8 @@ impl View for DeployFeedbackButton {
|
||||||
.status_bar
|
.status_bar
|
||||||
.panel_buttons
|
.panel_buttons
|
||||||
.button
|
.button
|
||||||
.style_for(state, active);
|
.in_state(active)
|
||||||
|
.style_for(state);
|
||||||
|
|
||||||
Svg::new("icons/feedback_16.svg")
|
Svg::new("icons/feedback_16.svg")
|
||||||
.with_color(style.icon_color)
|
.with_color(style.icon_color)
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl View for SubmitFeedbackButton {
|
||||||
let theme = theme::current(cx).clone();
|
let theme = theme::current(cx).clone();
|
||||||
enum SubmitFeedbackButton {}
|
enum SubmitFeedbackButton {}
|
||||||
MouseEventHandler::<SubmitFeedbackButton, Self>::new(0, cx, |state, _| {
|
MouseEventHandler::<SubmitFeedbackButton, Self>::new(0, cx, |state, _| {
|
||||||
let style = theme.feedback.submit_button.style_for(state, false);
|
let style = theme.feedback.submit_button.style_for(state);
|
||||||
Label::new("Submit as Markdown", style.text.clone())
|
Label::new("Submit as Markdown", style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -546,7 +546,7 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
.get(ix)
|
.get(ix)
|
||||||
.expect("Invalid matches state: no element for index {ix}");
|
.expect("Invalid matches state: no element for index {ix}");
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
let (file_name, file_name_positions, full_path, full_path_positions) =
|
let (file_name, file_name_positions, full_path, full_path_positions) =
|
||||||
self.labels_for_match(path_match, cx, ix);
|
self.labels_for_match(path_match, cx, ix);
|
||||||
Flex::column()
|
Flex::column()
|
||||||
|
|
|
@ -55,7 +55,7 @@ impl View for ActiveBufferLanguage {
|
||||||
|
|
||||||
MouseEventHandler::<Self, Self>::new(0, cx, |state, cx| {
|
MouseEventHandler::<Self, Self>::new(0, cx, |state, cx| {
|
||||||
let theme = &theme::current(cx).workspace.status_bar;
|
let theme = &theme::current(cx).workspace.status_bar;
|
||||||
let style = theme.active_language.style_for(state, false);
|
let style = theme.active_language.style_for(state);
|
||||||
Label::new(active_language_text, style.text.clone())
|
Label::new(active_language_text, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -180,7 +180,7 @@ impl PickerDelegate for LanguageSelectorDelegate {
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let mat = &self.matches[ix];
|
let mat = &self.matches[ix];
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
let buffer_language_name = self.buffer.read(cx).language().map(|l| l.name());
|
let buffer_language_name = self.buffer.read(cx).language().map(|l| l.name());
|
||||||
let mut label = mat.string.clone();
|
let mut label = mat.string.clone();
|
||||||
if buffer_language_name.as_deref() == Some(mat.string.as_str()) {
|
if buffer_language_name.as_deref() == Some(mat.string.as_str()) {
|
||||||
|
|
|
@ -681,7 +681,7 @@ impl LspLogToolbarItemView {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| "No server selected".into());
|
.unwrap_or_else(|| "No server selected".into());
|
||||||
let style = theme.toolbar_dropdown_menu.header.style_for(state, false);
|
let style = theme.toolbar_dropdown_menu.header.style_for(state);
|
||||||
Label::new(label, style.text.clone())
|
Label::new(label, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -722,7 +722,8 @@ impl LspLogToolbarItemView {
|
||||||
let style = theme
|
let style = theme
|
||||||
.toolbar_dropdown_menu
|
.toolbar_dropdown_menu
|
||||||
.item
|
.item
|
||||||
.style_for(state, logs_selected);
|
.in_state(logs_selected)
|
||||||
|
.style_for(state);
|
||||||
Label::new(SERVER_LOGS, style.text.clone())
|
Label::new(SERVER_LOGS, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -739,7 +740,8 @@ impl LspLogToolbarItemView {
|
||||||
let style = theme
|
let style = theme
|
||||||
.toolbar_dropdown_menu
|
.toolbar_dropdown_menu
|
||||||
.item
|
.item
|
||||||
.style_for(state, rpc_trace_selected);
|
.in_state(rpc_trace_selected)
|
||||||
|
.style_for(state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(RPC_MESSAGES, style.text.clone())
|
Label::new(RPC_MESSAGES, style.text.clone())
|
||||||
|
|
|
@ -565,7 +565,7 @@ impl SyntaxTreeToolbarItemView {
|
||||||
) -> impl Element<Self> {
|
) -> impl Element<Self> {
|
||||||
enum ToggleMenu {}
|
enum ToggleMenu {}
|
||||||
MouseEventHandler::<ToggleMenu, Self>::new(0, cx, move |state, _| {
|
MouseEventHandler::<ToggleMenu, Self>::new(0, cx, move |state, _| {
|
||||||
let style = theme.toolbar_dropdown_menu.header.style_for(state, false);
|
let style = theme.toolbar_dropdown_menu.header.style_for(state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(active_layer.language.name().to_string(), style.text.clone())
|
Label::new(active_layer.language.name().to_string(), style.text.clone())
|
||||||
|
@ -601,7 +601,8 @@ impl SyntaxTreeToolbarItemView {
|
||||||
let style = theme
|
let style = theme
|
||||||
.toolbar_dropdown_menu
|
.toolbar_dropdown_menu
|
||||||
.item
|
.item
|
||||||
.style_for(state, is_selected);
|
.in_state(is_selected)
|
||||||
|
.style_for(state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(layer.language.name().to_string(), style.text.clone())
|
Label::new(layer.language.name().to_string(), style.text.clone())
|
||||||
|
|
|
@ -204,7 +204,7 @@ impl PickerDelegate for OutlineViewDelegate {
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
let string_match = &self.matches[ix];
|
let string_match = &self.matches[ix];
|
||||||
let outline_item = &self.outline.items[string_match.candidate_id];
|
let outline_item = &self.outline.items[string_match.candidate_id];
|
||||||
|
|
||||||
|
|
|
@ -1253,7 +1253,10 @@ impl ProjectPanel {
|
||||||
let show_editor = details.is_editing && !details.is_processing;
|
let show_editor = details.is_editing && !details.is_processing;
|
||||||
|
|
||||||
MouseEventHandler::<Self, _>::new(entry_id.to_usize(), cx, |state, cx| {
|
MouseEventHandler::<Self, _>::new(entry_id.to_usize(), cx, |state, cx| {
|
||||||
let mut style = entry_style.style_for(state, details.is_selected).clone();
|
let mut style = entry_style
|
||||||
|
.in_state(details.is_selected)
|
||||||
|
.style_for(state)
|
||||||
|
.clone();
|
||||||
|
|
||||||
if cx
|
if cx
|
||||||
.global::<DragAndDrop<Workspace>>()
|
.global::<DragAndDrop<Workspace>>()
|
||||||
|
@ -1264,7 +1267,7 @@ impl ProjectPanel {
|
||||||
.filter(|destination| details.path.starts_with(destination))
|
.filter(|destination| details.path.starts_with(destination))
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
style = entry_style.active.clone().unwrap();
|
style = entry_style.on_state().default.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
let row_container_style = if show_editor {
|
let row_container_style = if show_editor {
|
||||||
|
@ -1405,9 +1408,9 @@ impl View for ProjectPanel {
|
||||||
let button_style = theme.open_project_button.clone();
|
let button_style = theme.open_project_button.clone();
|
||||||
let context_menu_item_style = theme::current(cx).context_menu.item.clone();
|
let context_menu_item_style = theme::current(cx).context_menu.item.clone();
|
||||||
move |state, cx| {
|
move |state, cx| {
|
||||||
let button_style = button_style.style_for(state, false).clone();
|
let button_style = button_style.style_for(state).clone();
|
||||||
let context_menu_item =
|
let context_menu_item =
|
||||||
context_menu_item_style.style_for(state, true).clone();
|
context_menu_item_style.on_state().style_for(state).clone();
|
||||||
|
|
||||||
theme::ui::keystroke_label(
|
theme::ui::keystroke_label(
|
||||||
"Open a project",
|
"Open a project",
|
||||||
|
|
|
@ -196,7 +196,7 @@ impl PickerDelegate for ProjectSymbolsDelegate {
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = &theme.picker.item;
|
let style = &theme.picker.item;
|
||||||
let current_style = style.style_for(mouse_state, selected);
|
let current_style = style.in_state(selected).style_for(mouse_state);
|
||||||
|
|
||||||
let string_match = &self.matches[ix];
|
let string_match = &self.matches[ix];
|
||||||
let symbol = &self.symbols[string_match.candidate_id];
|
let symbol = &self.symbols[string_match.candidate_id];
|
||||||
|
@ -229,7 +229,7 @@ impl PickerDelegate for ProjectSymbolsDelegate {
|
||||||
.with_child(
|
.with_child(
|
||||||
// Avoid styling the path differently when it is selected, since
|
// Avoid styling the path differently when it is selected, since
|
||||||
// the symbol's syntax highlighting doesn't change when selected.
|
// the symbol's syntax highlighting doesn't change when selected.
|
||||||
Label::new(path.to_string(), style.default.label.clone()),
|
Label::new(path.to_string(), style.off_state().default.label.clone()),
|
||||||
)
|
)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(current_style.container)
|
.with_style(current_style.container)
|
||||||
|
|
|
@ -173,7 +173,7 @@ impl PickerDelegate for RecentProjectsDelegate {
|
||||||
cx: &gpui::AppContext,
|
cx: &gpui::AppContext,
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
|
|
||||||
let string_match = &self.matches[ix];
|
let string_match = &self.matches[ix];
|
||||||
|
|
||||||
|
|
|
@ -328,7 +328,11 @@ impl BufferSearchBar {
|
||||||
Some(
|
Some(
|
||||||
MouseEventHandler::<Self, _>::new(option as usize, cx, |state, cx| {
|
MouseEventHandler::<Self, _>::new(option as usize, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.search.option_button.style_for(state, is_active);
|
let style = theme
|
||||||
|
.search
|
||||||
|
.option_button
|
||||||
|
.in_state(is_active)
|
||||||
|
.style_for(state);
|
||||||
Label::new(icon, style.text.clone())
|
Label::new(icon, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -371,7 +375,7 @@ impl BufferSearchBar {
|
||||||
enum NavButton {}
|
enum NavButton {}
|
||||||
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| {
|
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.search.option_button.style_for(state, false);
|
let style = theme.search.option_button.off_state().style_for(state);
|
||||||
Label::new(icon, style.text.clone())
|
Label::new(icon, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -403,7 +407,7 @@ impl BufferSearchBar {
|
||||||
|
|
||||||
enum CloseButton {}
|
enum CloseButton {}
|
||||||
MouseEventHandler::<CloseButton, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<CloseButton, _>::new(0, cx, |state, _| {
|
||||||
let style = theme.dismiss_button.style_for(state, false);
|
let style = theme.dismiss_button.style_for(state);
|
||||||
Svg::new("icons/x_mark_8.svg")
|
Svg::new("icons/x_mark_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
|
|
@ -896,7 +896,7 @@ impl ProjectSearchBar {
|
||||||
enum NavButton {}
|
enum NavButton {}
|
||||||
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| {
|
MouseEventHandler::<NavButton, _>::new(direction as usize, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.search.option_button.style_for(state, false);
|
let style = theme.search.option_button.off_state().style_for(state);
|
||||||
Label::new(icon, style.text.clone())
|
Label::new(icon, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -927,7 +927,11 @@ impl ProjectSearchBar {
|
||||||
let is_active = self.is_option_enabled(option, cx);
|
let is_active = self.is_option_enabled(option, cx);
|
||||||
MouseEventHandler::<Self, _>::new(option as usize, cx, |state, cx| {
|
MouseEventHandler::<Self, _>::new(option as usize, cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.search.option_button.style_for(state, is_active);
|
let style = theme
|
||||||
|
.search
|
||||||
|
.option_button
|
||||||
|
.in_state(is_active)
|
||||||
|
.style_for(state);
|
||||||
Label::new(icon, style.text.clone())
|
Label::new(icon, style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
|
|
@ -132,7 +132,7 @@ pub struct Titlebar {
|
||||||
pub outdated_warning: ContainedText,
|
pub outdated_warning: ContainedText,
|
||||||
pub share_button: Interactive<ContainedText>,
|
pub share_button: Interactive<ContainedText>,
|
||||||
pub call_control: Interactive<IconButton>,
|
pub call_control: Interactive<IconButton>,
|
||||||
pub toggle_contacts_button: Interactive<IconButton>,
|
pub toggle_contacts_button: Toggleable<Interactive<IconButton>>,
|
||||||
pub user_menu_button: Interactive<IconButton>,
|
pub user_menu_button: Interactive<IconButton>,
|
||||||
pub toggle_contacts_badge: ContainerStyle,
|
pub toggle_contacts_badge: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
@ -204,12 +204,12 @@ pub struct ContactList {
|
||||||
pub user_query_editor: FieldEditor,
|
pub user_query_editor: FieldEditor,
|
||||||
pub user_query_editor_height: f32,
|
pub user_query_editor_height: f32,
|
||||||
pub add_contact_button: IconButton,
|
pub add_contact_button: IconButton,
|
||||||
pub header_row: Interactive<ContainedText>,
|
pub header_row: Toggleable<Interactive<ContainedText>>,
|
||||||
pub leave_call: Interactive<ContainedText>,
|
pub leave_call: Interactive<ContainedText>,
|
||||||
pub contact_row: Interactive<ContainerStyle>,
|
pub contact_row: Toggleable<Interactive<ContainerStyle>>,
|
||||||
pub row_height: f32,
|
pub row_height: f32,
|
||||||
pub project_row: Interactive<ProjectRow>,
|
pub project_row: Toggleable<Interactive<ProjectRow>>,
|
||||||
pub tree_branch: Interactive<TreeBranch>,
|
pub tree_branch: Toggleable<Interactive<TreeBranch>>,
|
||||||
pub contact_avatar: ImageStyle,
|
pub contact_avatar: ImageStyle,
|
||||||
pub contact_status_free: ContainerStyle,
|
pub contact_status_free: ContainerStyle,
|
||||||
pub contact_status_busy: ContainerStyle,
|
pub contact_status_busy: ContainerStyle,
|
||||||
|
@ -251,7 +251,7 @@ pub struct DropdownMenu {
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub header: Interactive<DropdownMenuItem>,
|
pub header: Interactive<DropdownMenuItem>,
|
||||||
pub section_header: ContainedText,
|
pub section_header: ContainedText,
|
||||||
pub item: Interactive<DropdownMenuItem>,
|
pub item: Toggleable<Interactive<DropdownMenuItem>>,
|
||||||
pub row_height: f32,
|
pub row_height: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ pub struct DropdownMenuItem {
|
||||||
pub struct TabBar {
|
pub struct TabBar {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub pane_button: Interactive<IconButton>,
|
pub pane_button: Toggleable<Interactive<IconButton>>,
|
||||||
pub pane_button_container: ContainerStyle,
|
pub pane_button_container: ContainerStyle,
|
||||||
pub active_pane: TabStyles,
|
pub active_pane: TabStyles,
|
||||||
pub inactive_pane: TabStyles,
|
pub inactive_pane: TabStyles,
|
||||||
|
@ -339,7 +339,7 @@ pub struct Toolbar {
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
pub item_spacing: f32,
|
pub item_spacing: f32,
|
||||||
pub nav_button: Interactive<IconButton>,
|
pub nav_button: Toggleable<Interactive<IconButton>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default)]
|
||||||
|
@ -359,7 +359,7 @@ pub struct Search {
|
||||||
pub include_exclude_editor: FindEditor,
|
pub include_exclude_editor: FindEditor,
|
||||||
pub invalid_include_exclude_editor: ContainerStyle,
|
pub invalid_include_exclude_editor: ContainerStyle,
|
||||||
pub include_exclude_inputs: ContainedText,
|
pub include_exclude_inputs: ContainedText,
|
||||||
pub option_button: Interactive<ContainedText>,
|
pub option_button: Toggleable<Interactive<ContainedText>>,
|
||||||
pub match_background: Color,
|
pub match_background: Color,
|
||||||
pub match_index: ContainedText,
|
pub match_index: ContainedText,
|
||||||
pub results_status: TextStyle,
|
pub results_status: TextStyle,
|
||||||
|
@ -395,7 +395,7 @@ pub struct StatusBarPanelButtons {
|
||||||
pub group_left: ContainerStyle,
|
pub group_left: ContainerStyle,
|
||||||
pub group_bottom: ContainerStyle,
|
pub group_bottom: ContainerStyle,
|
||||||
pub group_right: ContainerStyle,
|
pub group_right: ContainerStyle,
|
||||||
pub button: Interactive<PanelButton>,
|
pub button: Toggleable<Interactive<PanelButton>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default)]
|
||||||
|
@ -444,10 +444,10 @@ pub struct PanelButton {
|
||||||
pub struct ProjectPanel {
|
pub struct ProjectPanel {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub entry: Interactive<ProjectPanelEntry>,
|
pub entry: Toggleable<Interactive<ProjectPanelEntry>>,
|
||||||
pub dragged_entry: ProjectPanelEntry,
|
pub dragged_entry: ProjectPanelEntry,
|
||||||
pub ignored_entry: Interactive<ProjectPanelEntry>,
|
pub ignored_entry: Toggleable<Interactive<ProjectPanelEntry>>,
|
||||||
pub cut_entry: Interactive<ProjectPanelEntry>,
|
pub cut_entry: Toggleable<Interactive<ProjectPanelEntry>>,
|
||||||
pub filename_editor: FieldEditor,
|
pub filename_editor: FieldEditor,
|
||||||
pub indent_width: f32,
|
pub indent_width: f32,
|
||||||
pub open_project_button: Interactive<ContainedText>,
|
pub open_project_button: Interactive<ContainedText>,
|
||||||
|
@ -481,7 +481,7 @@ pub struct GitProjectStatus {
|
||||||
pub struct ContextMenu {
|
pub struct ContextMenu {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub item: Interactive<ContextMenuItem>,
|
pub item: Toggleable<Interactive<ContextMenuItem>>,
|
||||||
pub keystroke_margin: f32,
|
pub keystroke_margin: f32,
|
||||||
pub separator: ContainerStyle,
|
pub separator: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
@ -498,7 +498,7 @@ pub struct ContextMenuItem {
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Default)]
|
#[derive(Debug, Deserialize, Default)]
|
||||||
pub struct CommandPalette {
|
pub struct CommandPalette {
|
||||||
pub key: Interactive<ContainedLabel>,
|
pub key: Toggleable<Interactive<ContainedLabel>>,
|
||||||
pub keystroke_spacing: f32,
|
pub keystroke_spacing: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,7 +565,7 @@ pub struct Picker {
|
||||||
pub input_editor: FieldEditor,
|
pub input_editor: FieldEditor,
|
||||||
pub empty_input_editor: FieldEditor,
|
pub empty_input_editor: FieldEditor,
|
||||||
pub no_matches: ContainedLabel,
|
pub no_matches: ContainedLabel,
|
||||||
pub item: Interactive<ContainedLabel>,
|
pub item: Toggleable<Interactive<ContainedLabel>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default)]
|
||||||
|
@ -771,13 +771,13 @@ pub struct InteractiveColor {
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default)]
|
||||||
pub struct CodeActions {
|
pub struct CodeActions {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub indicator: Interactive<InteractiveColor>,
|
pub indicator: Toggleable<Interactive<InteractiveColor>>,
|
||||||
pub vertical_scale: f32,
|
pub vertical_scale: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default)]
|
||||||
pub struct Folds {
|
pub struct Folds {
|
||||||
pub indicator: Interactive<InteractiveColor>,
|
pub indicator: Toggleable<Interactive<InteractiveColor>>,
|
||||||
pub ellipses: FoldEllipses,
|
pub ellipses: FoldEllipses,
|
||||||
pub fold_background: Color,
|
pub fold_background: Color,
|
||||||
pub icon_margin_scale: f32,
|
pub icon_margin_scale: f32,
|
||||||
|
@ -806,29 +806,52 @@ pub struct DiffStyle {
|
||||||
pub struct Interactive<T> {
|
pub struct Interactive<T> {
|
||||||
pub default: T,
|
pub default: T,
|
||||||
pub hover: Option<T>,
|
pub hover: Option<T>,
|
||||||
pub hover_and_active: Option<T>,
|
|
||||||
pub clicked: Option<T>,
|
pub clicked: Option<T>,
|
||||||
pub click_and_active: Option<T>,
|
|
||||||
pub active: Option<T>,
|
|
||||||
pub disabled: Option<T>,
|
pub disabled: Option<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Deserialize)]
|
||||||
|
pub struct Toggleable<T> {
|
||||||
|
on: T,
|
||||||
|
off: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
|
pub enum ToggleState {
|
||||||
|
Off,
|
||||||
|
On,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: std::borrow::Borrow<bool>> From<T> for ToggleState {
|
||||||
|
fn from(item: T) -> Self {
|
||||||
|
match *item.borrow() {
|
||||||
|
true => Self::On,
|
||||||
|
false => Self::Off,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Toggleable<T> {
|
||||||
|
pub fn new(on: T, off: T) -> Self {
|
||||||
|
Self { on, off }
|
||||||
|
}
|
||||||
|
pub fn in_state(&self, state: impl Into<ToggleState>) -> &T {
|
||||||
|
match state.into() {
|
||||||
|
ToggleState::Off => &self.off,
|
||||||
|
ToggleState::On => &self.on,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn on_state(&self) -> &T {
|
||||||
|
self.in_state(ToggleState::On)
|
||||||
|
}
|
||||||
|
pub fn off_state(&self) -> &T {
|
||||||
|
self.in_state(ToggleState::Off)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Interactive<T> {
|
impl<T> Interactive<T> {
|
||||||
pub fn style_for(&self, state: &mut MouseState, active: bool) -> &T {
|
pub fn style_for(&self, state: &mut MouseState) -> &T {
|
||||||
if active {
|
if state.clicked() == Some(platform::MouseButton::Left) && self.clicked.is_some() {
|
||||||
if state.hovered() {
|
|
||||||
self.hover_and_active
|
|
||||||
.as_ref()
|
|
||||||
.unwrap_or(self.active.as_ref().unwrap_or(&self.default))
|
|
||||||
} else if state.clicked() == Some(platform::MouseButton::Left) && self.clicked.is_some()
|
|
||||||
{
|
|
||||||
self.click_and_active
|
|
||||||
.as_ref()
|
|
||||||
.unwrap_or(self.active.as_ref().unwrap_or(&self.default))
|
|
||||||
} else {
|
|
||||||
self.active.as_ref().unwrap_or(&self.default)
|
|
||||||
}
|
|
||||||
} else if state.clicked() == Some(platform::MouseButton::Left) && self.clicked.is_some() {
|
|
||||||
self.clicked.as_ref().unwrap()
|
self.clicked.as_ref().unwrap()
|
||||||
} else if state.hovered() {
|
} else if state.hovered() {
|
||||||
self.hover.as_ref().unwrap_or(&self.default)
|
self.hover.as_ref().unwrap_or(&self.default)
|
||||||
|
@ -836,7 +859,6 @@ impl<T> Interactive<T> {
|
||||||
&self.default
|
&self.default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disabled_style(&self) -> &T {
|
pub fn disabled_style(&self) -> &T {
|
||||||
self.disabled.as_ref().unwrap_or(&self.default)
|
self.disabled.as_ref().unwrap_or(&self.default)
|
||||||
}
|
}
|
||||||
|
@ -852,10 +874,7 @@ impl<'de, T: DeserializeOwned> Deserialize<'de> for Interactive<T> {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
default: Value,
|
default: Value,
|
||||||
hover: Option<Value>,
|
hover: Option<Value>,
|
||||||
hover_and_active: Option<Value>,
|
|
||||||
clicked: Option<Value>,
|
clicked: Option<Value>,
|
||||||
click_and_active: Option<Value>,
|
|
||||||
active: Option<Value>,
|
|
||||||
disabled: Option<Value>,
|
disabled: Option<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,20 +900,14 @@ impl<'de, T: DeserializeOwned> Deserialize<'de> for Interactive<T> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let hover = deserialize_state(json.hover)?;
|
let hover = deserialize_state(json.hover)?;
|
||||||
let hover_and_active = deserialize_state(json.hover_and_active)?;
|
|
||||||
let clicked = deserialize_state(json.clicked)?;
|
let clicked = deserialize_state(json.clicked)?;
|
||||||
let click_and_active = deserialize_state(json.click_and_active)?;
|
|
||||||
let active = deserialize_state(json.active)?;
|
|
||||||
let disabled = deserialize_state(json.disabled)?;
|
let disabled = deserialize_state(json.disabled)?;
|
||||||
let default = serde_json::from_value(json.default).map_err(serde::de::Error::custom)?;
|
let default = serde_json::from_value(json.default).map_err(serde::de::Error::custom)?;
|
||||||
|
|
||||||
Ok(Interactive {
|
Ok(Interactive {
|
||||||
default,
|
default,
|
||||||
hover,
|
hover,
|
||||||
hover_and_active,
|
|
||||||
clicked,
|
clicked,
|
||||||
click_and_active,
|
|
||||||
active,
|
|
||||||
disabled,
|
disabled,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ where
|
||||||
F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
|
F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
|
||||||
{
|
{
|
||||||
MouseEventHandler::<Tag, V>::new(0, cx, |state, _| {
|
MouseEventHandler::<Tag, V>::new(0, cx, |state, _| {
|
||||||
let style = style.style_for(state, false);
|
let style = style.style_for(state);
|
||||||
Label::new(label, style.text.to_owned())
|
Label::new(label, style.text.to_owned())
|
||||||
.aligned()
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
|
@ -220,13 +220,13 @@ where
|
||||||
title,
|
title,
|
||||||
style
|
style
|
||||||
.title_text
|
.title_text
|
||||||
.style_for(&mut MouseState::default(), false)
|
.style_for(&mut MouseState::default())
|
||||||
.clone(),
|
.clone(),
|
||||||
))
|
))
|
||||||
.with_child(
|
.with_child(
|
||||||
// FIXME: Get a better tag type
|
// FIXME: Get a better tag type
|
||||||
MouseEventHandler::<Tag, V>::new(999999, cx, |state, _cx| {
|
MouseEventHandler::<Tag, V>::new(999999, cx, |state, _cx| {
|
||||||
let style = style.close_icon.style_for(state, false);
|
let style = style.close_icon.style_for(state);
|
||||||
icon(style)
|
icon(style)
|
||||||
})
|
})
|
||||||
.on_click(platform::MouseButton::Left, move |_, _, cx| {
|
.on_click(platform::MouseButton::Left, move |_, _, cx| {
|
||||||
|
|
|
@ -208,7 +208,7 @@ impl PickerDelegate for ThemeSelectorDelegate {
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
|
|
||||||
let theme_match = &self.matches[ix];
|
let theme_match = &self.matches[ix];
|
||||||
Label::new(theme_match.string.clone(), style.label.clone())
|
Label::new(theme_match.string.clone(), style.label.clone())
|
||||||
|
|
|
@ -141,7 +141,7 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
|
||||||
) -> gpui::AnyElement<Picker<Self>> {
|
) -> gpui::AnyElement<Picker<Self>> {
|
||||||
let theme = &theme::current(cx);
|
let theme = &theme::current(cx);
|
||||||
let keymap_match = &self.matches[ix];
|
let keymap_match = &self.matches[ix];
|
||||||
let style = theme.picker.item.style_for(mouse_state, selected);
|
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
||||||
|
|
||||||
Label::new(keymap_match.string.clone(), style.label.clone())
|
Label::new(keymap_match.string.clone(), style.label.clone())
|
||||||
.with_highlights(keymap_match.positions.clone())
|
.with_highlights(keymap_match.positions.clone())
|
||||||
|
|
|
@ -6,7 +6,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use theme::ThemeSettings;
|
use theme::{ThemeSettings, ToggleState};
|
||||||
|
|
||||||
pub trait Panel: View {
|
pub trait Panel: View {
|
||||||
fn position(&self, cx: &WindowContext) -> DockPosition;
|
fn position(&self, cx: &WindowContext) -> DockPosition;
|
||||||
|
@ -498,7 +498,14 @@ impl View for PanelButtons {
|
||||||
Stack::new()
|
Stack::new()
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Self, _>::new(panel_ix, cx, |state, cx| {
|
MouseEventHandler::<Self, _>::new(panel_ix, cx, |state, cx| {
|
||||||
let style = button_style.style_for(state, is_active);
|
let toggle_state = if is_active {
|
||||||
|
ToggleState::On
|
||||||
|
} else {
|
||||||
|
ToggleState::Off
|
||||||
|
};
|
||||||
|
let style = button_style.in_state(toggle_state);
|
||||||
|
|
||||||
|
let style = style.style_for(state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Svg::new(view.icon_path(cx))
|
Svg::new(view.icon_path(cx))
|
||||||
|
|
|
@ -291,7 +291,7 @@ pub mod simple_message_notification {
|
||||||
)
|
)
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<Cancel, _>::new(0, cx, |state, _| {
|
||||||
let style = theme.dismiss_button.style_for(state, false);
|
let style = theme.dismiss_button.style_for(state);
|
||||||
Svg::new("icons/x_mark_8.svg")
|
Svg::new("icons/x_mark_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -323,7 +323,7 @@ pub mod simple_message_notification {
|
||||||
0,
|
0,
|
||||||
cx,
|
cx,
|
||||||
|state, _| {
|
|state, _| {
|
||||||
let style = theme.action_message.style_for(state, false);
|
let style = theme.action_message.style_for(state);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
|
|
@ -1410,7 +1410,7 @@ impl Pane {
|
||||||
pub fn render_tab_bar_button<F: 'static + Fn(&mut Pane, &mut EventContext<Pane>)>(
|
pub fn render_tab_bar_button<F: 'static + Fn(&mut Pane, &mut EventContext<Pane>)>(
|
||||||
index: usize,
|
index: usize,
|
||||||
icon: &'static str,
|
icon: &'static str,
|
||||||
active: bool,
|
is_active: bool,
|
||||||
tooltip: Option<(String, Option<Box<dyn Action>>)>,
|
tooltip: Option<(String, Option<Box<dyn Action>>)>,
|
||||||
cx: &mut ViewContext<Pane>,
|
cx: &mut ViewContext<Pane>,
|
||||||
on_click: F,
|
on_click: F,
|
||||||
|
@ -1420,7 +1420,7 @@ impl Pane {
|
||||||
|
|
||||||
let mut button = MouseEventHandler::<TabBarButton, _>::new(index, cx, |mouse_state, cx| {
|
let mut button = MouseEventHandler::<TabBarButton, _>::new(index, cx, |mouse_state, cx| {
|
||||||
let theme = &settings::get::<ThemeSettings>(cx).theme.workspace.tab_bar;
|
let theme = &settings::get::<ThemeSettings>(cx).theme.workspace.tab_bar;
|
||||||
let style = theme.pane_button.style_for(mouse_state, active);
|
let style = theme.pane_button.in_state(is_active).style_for(mouse_state);
|
||||||
Svg::new(icon)
|
Svg::new(icon)
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
|
|
@ -219,7 +219,7 @@ impl View for Toolbar {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>)>(
|
fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>)>(
|
||||||
svg_path: &'static str,
|
svg_path: &'static str,
|
||||||
style: theme::Interactive<theme::IconButton>,
|
style: theme::Toggleable<theme::Interactive<theme::IconButton>>,
|
||||||
nav_button_height: f32,
|
nav_button_height: f32,
|
||||||
tooltip_style: TooltipStyle,
|
tooltip_style: TooltipStyle,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
|
@ -231,9 +231,9 @@ fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>
|
||||||
) -> AnyElement<Toolbar> {
|
) -> AnyElement<Toolbar> {
|
||||||
MouseEventHandler::<A, _>::new(0, cx, |state, _| {
|
MouseEventHandler::<A, _>::new(0, cx, |state, _| {
|
||||||
let style = if enabled {
|
let style = if enabled {
|
||||||
style.style_for(state, false)
|
style.off_state().style_for(state)
|
||||||
} else {
|
} else {
|
||||||
style.disabled_style()
|
style.off_state().disabled_style()
|
||||||
};
|
};
|
||||||
Svg::new(svg_path)
|
Svg::new(svg_path)
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue