tooltip: Add action, key_binding method to Tooltip. (#787)
This commit is contained in:
parent
8ef4e2eb17
commit
9a6a0f4421
3 changed files with 63 additions and 21 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, App, AppContext, Context, Entity, Focusable, InteractiveElement, KeyBinding,
|
actions, div, App, AppContext, Context, Entity, Focusable, InteractiveElement, KeyBinding,
|
||||||
ParentElement, Render, StatefulInteractiveElement, Styled, Window,
|
Keystroke, ParentElement, Render, StatefulInteractiveElement, Styled, Window,
|
||||||
};
|
};
|
||||||
|
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
|
|
@ -10,7 +10,7 @@ use gpui_component::{
|
||||||
h_flex,
|
h_flex,
|
||||||
label::Label,
|
label::Label,
|
||||||
tooltip::Tooltip,
|
tooltip::Tooltip,
|
||||||
v_flex, ActiveTheme, IconName,
|
v_flex, ActiveTheme, IconName, Kbd,
|
||||||
};
|
};
|
||||||
|
|
||||||
actions!(tooltip, [Info]);
|
actions!(tooltip, [Info]);
|
||||||
|
|
@ -56,7 +56,7 @@ impl Focusable for TooltipStory {
|
||||||
impl Render for TooltipStory {
|
impl Render for TooltipStory {
|
||||||
fn render(
|
fn render(
|
||||||
&mut self,
|
&mut self,
|
||||||
window: &mut gpui::Window,
|
_: &mut gpui::Window,
|
||||||
_cx: &mut gpui::Context<Self>,
|
_cx: &mut gpui::Context<Self>,
|
||||||
) -> impl gpui::IntoElement {
|
) -> impl gpui::IntoElement {
|
||||||
v_flex()
|
v_flex()
|
||||||
|
|
@ -75,7 +75,6 @@ impl Render for TooltipStory {
|
||||||
"This is a tooltip with Action for display keybinding.",
|
"This is a tooltip with Action for display keybinding.",
|
||||||
&Info,
|
&Info,
|
||||||
Some("Tooltip"),
|
Some("Tooltip"),
|
||||||
window,
|
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
|
|
@ -83,13 +82,21 @@ impl Render for TooltipStory {
|
||||||
.justify_center()
|
.justify_center()
|
||||||
.child(Label::new("Hover me"))
|
.child(Label::new("Hover me"))
|
||||||
.id("tooltip-2")
|
.id("tooltip-2")
|
||||||
.tooltip(|window, cx| Tooltip::new("This is a Label").build(window, cx)),
|
.tooltip(|window, cx| {
|
||||||
|
Tooltip::new("This is a Label")
|
||||||
|
.action(&Info, Some("Tooltip"))
|
||||||
|
.build(window, cx)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.child(Checkbox::new("check").label("Remember me").checked(true))
|
.child(Checkbox::new("check").label("Remember me").checked(true))
|
||||||
.id("tooltip-3")
|
.id("tooltip-3")
|
||||||
.tooltip(|window, cx| Tooltip::new("Checked!").build(window, cx)),
|
.tooltip(|window, cx| {
|
||||||
|
Tooltip::new("Checked!")
|
||||||
|
.key_binding(Some(Kbd::new(Keystroke::parse("cmd-shift-u").unwrap())))
|
||||||
|
.build(window, cx)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
h_flex, indicator::Indicator, tooltip::Tooltip, ActiveTheme, Colorize as _, Disableable, Icon,
|
h_flex, indicator::Indicator, tooltip::Tooltip, ActiveTheme, Colorize as _, Disableable, Icon,
|
||||||
Kbd, Selectable, Sizable, Size, StyleSized,
|
Selectable, Sizable, Size, StyleSized,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, prelude::FluentBuilder as _, relative, Action, AnyElement, App, ClickEvent, Corners, Div,
|
div, prelude::FluentBuilder as _, relative, Action, AnyElement, App, ClickEvent, Corners, Div,
|
||||||
|
|
@ -183,8 +185,10 @@ pub struct Button {
|
||||||
border_edges: Edges<bool>,
|
border_edges: Edges<bool>,
|
||||||
size: Size,
|
size: Size,
|
||||||
compact: bool,
|
compact: bool,
|
||||||
tooltip: Option<SharedString>,
|
tooltip: Option<(
|
||||||
key_binding: Option<Kbd>,
|
SharedString,
|
||||||
|
Option<(Rc<Box<dyn Action>>, Option<SharedString>)>,
|
||||||
|
)>,
|
||||||
on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||||
pub(crate) stop_propagation: bool,
|
pub(crate) stop_propagation: bool,
|
||||||
loading: bool,
|
loading: bool,
|
||||||
|
|
@ -212,7 +216,6 @@ impl Button {
|
||||||
border_edges: Edges::all(true),
|
border_edges: Edges::all(true),
|
||||||
size: Size::Medium,
|
size: Size::Medium,
|
||||||
tooltip: None,
|
tooltip: None,
|
||||||
key_binding: None,
|
|
||||||
on_click: None,
|
on_click: None,
|
||||||
stop_propagation: true,
|
stop_propagation: true,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
|
@ -261,7 +264,7 @@ impl Button {
|
||||||
|
|
||||||
/// Set the tooltip of the button.
|
/// Set the tooltip of the button.
|
||||||
pub fn tooltip(mut self, tooltip: impl Into<SharedString>) -> Self {
|
pub fn tooltip(mut self, tooltip: impl Into<SharedString>) -> Self {
|
||||||
self.tooltip = Some(tooltip.into());
|
self.tooltip = Some((tooltip.into(), None));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,10 +273,14 @@ impl Button {
|
||||||
tooltip: impl Into<SharedString>,
|
tooltip: impl Into<SharedString>,
|
||||||
action: &dyn Action,
|
action: &dyn Action,
|
||||||
context: Option<&str>,
|
context: Option<&str>,
|
||||||
window: &Window,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.tooltip = Some(tooltip.into());
|
self.tooltip = Some((
|
||||||
self.key_binding = Kbd::binding_for_action(action, context, window);
|
tooltip.into(),
|
||||||
|
Some((
|
||||||
|
Rc::new(action.boxed_clone()),
|
||||||
|
context.map(|c| c.to_string().into()),
|
||||||
|
)),
|
||||||
|
));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -497,10 +504,15 @@ impl RenderOnce for Button {
|
||||||
.children(self.children)
|
.children(self.children)
|
||||||
})
|
})
|
||||||
.when(self.loading, |this| this.bg(normal_style.bg.opacity(0.8)))
|
.when(self.loading, |this| this.bg(normal_style.bg.opacity(0.8)))
|
||||||
.when_some(self.tooltip, |this, tooltip| {
|
.when_some(self.tooltip, |this, (tooltip, action)| {
|
||||||
this.tooltip(move |window, cx| {
|
this.tooltip(move |window, cx| {
|
||||||
Tooltip::new(tooltip.clone())
|
Tooltip::new(tooltip.clone())
|
||||||
.key_binding(self.key_binding.clone())
|
.when_some(action.clone(), |this, (action, context)| {
|
||||||
|
this.action(
|
||||||
|
action.boxed_clone().as_ref(),
|
||||||
|
context.as_ref().map(|c| c.as_ref()),
|
||||||
|
)
|
||||||
|
})
|
||||||
.build(window, cx)
|
.build(window, cx)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, prelude::FluentBuilder, px, AnyElement, AnyView, App, AppContext, Context, IntoElement,
|
div, prelude::FluentBuilder, px, Action, AnyElement, AnyView, App, AppContext, Context,
|
||||||
ParentElement, Render, Styled, Window,
|
IntoElement, ParentElement, Render, SharedString, Styled, Window,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{h_flex, text::Text, ActiveTheme, Kbd};
|
use crate::{h_flex, text::Text, ActiveTheme, Kbd};
|
||||||
|
|
@ -13,6 +13,7 @@ enum TooltipContext {
|
||||||
pub struct Tooltip {
|
pub struct Tooltip {
|
||||||
content: TooltipContext,
|
content: TooltipContext,
|
||||||
key_binding: Option<Kbd>,
|
key_binding: Option<Kbd>,
|
||||||
|
action: Option<(Box<dyn Action>, Option<SharedString>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tooltip {
|
impl Tooltip {
|
||||||
|
|
@ -21,6 +22,7 @@ impl Tooltip {
|
||||||
Self {
|
Self {
|
||||||
content: TooltipContext::Text(text.into()),
|
content: TooltipContext::Text(text.into()),
|
||||||
key_binding: None,
|
key_binding: None,
|
||||||
|
action: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,15 +34,22 @@ impl Tooltip {
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
key_binding: None,
|
key_binding: None,
|
||||||
|
action: None,
|
||||||
content: TooltipContext::Element(Box::new(move |window, cx| {
|
content: TooltipContext::Element(Box::new(move |window, cx| {
|
||||||
builder(window, cx).into_any_element()
|
builder(window, cx).into_any_element()
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set Action to display key binding information for the tooltip if it exists.
|
||||||
|
pub fn action(mut self, action: &dyn Action, context: Option<&str>) -> Self {
|
||||||
|
self.action = Some((action.boxed_clone(), context.map(SharedString::new)));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set KeyBinding information for the tooltip.
|
/// Set KeyBinding information for the tooltip.
|
||||||
pub(crate) fn key_binding(mut self, kbd: Option<impl Into<Kbd>>) -> Self {
|
pub fn key_binding(mut self, key_binding: Option<Kbd>) -> Self {
|
||||||
self.key_binding = kbd.map(Into::into);
|
self.key_binding = key_binding;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,6 +63,20 @@ impl FluentBuilder for Tooltip {}
|
||||||
|
|
||||||
impl Render for Tooltip {
|
impl Render for Tooltip {
|
||||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
|
let key_binding = if let Some(key_binding) = &self.key_binding {
|
||||||
|
Some(key_binding.clone())
|
||||||
|
} else {
|
||||||
|
if let Some((action, context)) = &self.action {
|
||||||
|
Kbd::binding_for_action(
|
||||||
|
action.as_ref(),
|
||||||
|
context.as_ref().map(|s| s.as_ref()),
|
||||||
|
window,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
div().child(
|
div().child(
|
||||||
// Wrap in a child, to ensure the left margin is applied to the tooltip
|
// Wrap in a child, to ensure the left margin is applied to the tooltip
|
||||||
h_flex()
|
h_flex()
|
||||||
|
|
@ -77,7 +100,7 @@ impl Render for Tooltip {
|
||||||
TooltipContext::Element(ref builder) => this.child(builder(window, cx)),
|
TooltipContext::Element(ref builder) => this.child(builder(window, cx)),
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.when_some(self.key_binding.clone(), |this, kbd| {
|
.when_some(key_binding, |this, kbd| {
|
||||||
this.child(
|
this.child(
|
||||||
div()
|
div()
|
||||||
.text_xs()
|
.text_xs()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue